<!DOCTYPE html>
<html>

<head>
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"
        integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdn.jsdelivr.net/npm/bcryptjs@2.4.3/dist/bcrypt.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Query Export - Illicit Services</title>

    <meta name="description" content="Export from our database of leaked information.">
    <meta name="robots" content="index, follow">

    <meta property="og:type" content="article" />
    <meta property="og:title" content="Illict Services LTD" />
    <meta property="og:description" content="Export from our database of leaked information." />
    <meta property="og:url" content="https://search.illicit.services" />
    <meta property="og:site_name" content="Database Search" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="en" />


    <meta name="apple-mobile-web-app-status-bar" content="#000000" />
    <meta name="theme-color" content="#000000" />

    <style>
        html,
        body,
        {
        height: 100%;
        }

        #app {
            height: 100%;
        }

        html,
        body,
        #app,
        v-main__wrap {
            background-color: black;
        }

        /* */
    </style>
</head>

<body>
    <div id="app">
        <v-app>
            <v-main>
                <span>
                    <!-- Wallet goes in the top-right -->
                    <v-toolbar flat color="transparent" dark app
                        style="position: absolute; top: 0; right: 0; z-index: 1000">
                        <v-toolbar-title class="white--text">
                            <v-btn @click="showWallet = !showWallet" elevation="0" class="white--text" text><span
                                    id="creditCount" v-text="creditStr+' Credits'"></span><v-icon>
                                    mdi-wallet
                                </v-icon></v-btn>
                        </v-toolbar-title>
                    </v-toolbar>
                    <!-- Wallet Modal -->
                    <v-dialog v-model="showWallet" max-width="500px">
                        <v-card>
                            <v-card-title>
                                <span class="headline">Wallet Management</span>
                                <v-spacer></v-spacer>
                                <!-- About tooltip -->
                                <v-tooltip bottom>
                                    <template v-slot:activator="{ on }">
                                        <v-btn icon v-on="on" @click="showAbout = !showAbout">
                                            <v-icon>mdi-information</v-icon>
                                        </v-btn>
                                    </template>
                                    <span>Credits currently can be used for: <ul>
                                            <li>Bulk data exports (thousands to hundres of thousands of records)</li>
                                        </ul>Credits will soon be used for: <ul>
                                            <li>Mass-deletion of records (avoid crypto fees)</li>
                                            <li>Enrichment of your own data-sets (via CSV upload)</li>
                                            <li>Exporting data from the visualization tool as CSV or Relational JSON
                                            </li>
                                            <li>Any other resource intensive task</li>
                                        </ul><br />Of course, regular search will remain free, forever.</span>
                                </v-tooltip>
                            </v-card-title>
                            <v-card-text>
                                <v-row>
                                    <v-col cols="12">
                                        <!-- Allow user to copy their wallet ID -->
                                        <v-text-field id="walletId" v-model="walletId" label="Wallet ID" append
                                            append-icon="mdi-content-copy" @change="updateWalletID"></v-text-field>
                                        <!-- Subtle warning to user that anyone can use their credits if they have their wallet ID -->
                                        <v-alert dense type="warning" outlined>
                                            Your wallet ID is the key to your credits and exports. If you share it with
                                            someone,
                                            that person can use your credits. If you lose it, you lose your credits.
                                        </v-alert>
                                    </v-col>

                                    <v-col cols="12">
                                        <!-- Allow user to re-fill their wallet -->
                                        <v-row>
                                            <v-col cols="10">
                                                <v-text-field v-model="walletFill" label="Fill Wallet (1 USD = 100)"
                                                    append prepend-icon="mdi-currency-usd"></v-text-field>
                                            </v-col>
                                            <v-col cols="2">
                                                <v-btn class="my-0 mt-3" color="blue darken-1" block text
                                                    @click="doFillWallet">
                                                    Fill
                                                </v-btn>
                                            </v-col>
                                        </v-row>
                                    </v-col>
                                </v-row>
                            </v-card-text>
                            <v-card-actions>
                                <v-spacer></v-spacer>
                                <v-btn color="blue darken-1" text @click="showWallet = false">
                                    Close
                                </v-btn>
                            </v-card-actions>
                        </v-card>
                    </v-dialog>
                    <!-- Export Modal -->
                    <v-dialog v-model="showExport" max-width="500px">
                        <v-card>
                            <v-card-title>
                                <span class="headline">New Export</span>
                                <v-spacer></v-spacer>
                                <!-- About tooltip -->
                                <v-tooltip bottom>
                                    <template v-slot:activator="{ on }">
                                        <v-btn icon v-on="on" @click="showAbout = !showAbout">
                                            <v-icon>mdi-information</v-icon>
                                        </v-btn>
                                    </template>
                                    <span>Exports are a way to download your data. You can export your data as a CSV
                                        file, or as a JSON file. The JSON file will be in a relational format, so you
                                        can easily import it into a database. <br /><br />You can also export your data
                                        from the visualization tool as CSV or Relational JSON.</span>
                                </v-tooltip>
                            </v-card-title>
                            <v-card-text>
                                <!-- Allow user to paste in search url as input -->
                                <v-text-field id="exportUrl" v-model="exportUrl" label="Search URL" append
                                    append-icon="mdi-content-paste"></v-text-field>

                                <!-- Input how many records to export -->
                                <v-text-field id="exportCount" v-model="exportCount" label="Record Count" append
                                    append-icon="mdi-numeric"></v-text-field>

                            </v-card-text>
                            <v-card-actions>
                                <v-btn color="red darken-1" text @click="showExport = false">
                                    Close
                                </v-btn>
                                <v-spacer></v-spacer>
                                <v-btn color="blue darken-1" text @click="doExport">
                                    Export
                                </v-btn>


                            </v-card-actions>
                        </v-card>
                    </v-dialog>
                </span>
                <v-container flex pa-0>
                    <h1 style="margin-top: 5%">Database Exports</h1>
                    <!-- Lists exports for wallet -->
                    <v-card style="margin-top: 5%">
                        <v-card-title>
                            <span class="headline">Exports List</span>
                            <v-spacer></v-spacer>
                            <!-- New export button (plus icon) -->
                            <v-tooltip bottom>
                                <template v-slot:activator="{ on }">
                                    <v-btn icon v-on="on" @click="showExport = !showExport">
                                        <v-icon>mdi-plus</v-icon>
                                    </v-btn>
                                </template>
                                <span>Create a new export</span>
                            </v-tooltip>
                        </v-card-title>
                        <v-card-text>
                            <v-data-table :items="exports" :headers="exportsTableHeaders">
                                <!-- Download button slot -->
                                <template v-slot:item.download="{ item }">
                                    <v-btn :disabled="item.status != 'complete'" color="blue darken-1" text
                                        @click="downloadExport(item)">
                                        Download
                                    </v-btn>
                                </template>

                            </v-data-table>
                        </v-card-text>

                    </v-card>


                    <small>Copyright <a href="https://illicit.services">Illicit Services LTD</a>. Email: <a
                            href="mailto:miyakoyakota@riseup.com">miyakoyakota@riseup.com</a>. By using this service you agree with the <a
                            href="/terms">terms of use</a>. Also, treat these downloads as "hot" storage, don't expect
                        your download to stay up forever should MEGA delete it.</small>
                </v-container>
            </v-main>
        </v-app>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    <script>
        const creditCountElement = document.getElementById("creditCount")
        new Vue({
            el: '#app',
            vuetify: new Vuetify({
                theme: { dark: true },
                // Mdi icons
                icons: {
                    iconfont: 'mdi',
                },
            }),
            data: () => ({
                showWallet: false,
                balance: 0,
                exact: true,
                showExport: false,
                creditStr: '<loading>',
                exportUrl: '',
                walletFill: 0.0,
                exportCount: 200,
                walletId: '',
                exports: [],
                exportsTableHeaders: [
                    { text: 'Export ID', value: 'jobid' },
                    { text: 'Status', value: 'status' },
                    { text: 'Query', value: 'query' },
                    { text: 'Record Count', value: 'exportCount' },
                    { text: 'Download', value: 'download' }
                ],
                hashTypes: ['BCrypt', 'MD5', 'SHA1', 'SHA256', 'SHA512', 'RIPEMD160', 'SHA3', 'SHA224', 'SHA384'],
                queryOptions: [
                    'First Name',
                    'Last Name',
                    'Email',
                    'Username',
                    'Password',
                    'Domain',
                    'IP Address',
                    'ASN Number',
                    'ASN Name',
                    'Continent',
                    'Country',
                    'Phone',
                    'Address',
                    'License Plate Number',
                    'Birth Year',
                    'VIN',
                    'City',
                    'State',
                    'Zip',
                    'Source'
                ],
                queryFieldMap: {
                    'First Name': 'firstName',
                    'Last Name': 'lastName',
                    'Email': 'emails',
                    'Username': 'usernames',
                    'Password': 'passwords',
                    'Domain': 'domain',
                    'IP Address': 'ips',
                    'ASN Number': 'asn',
                    'ASN Name': 'asnOrg',
                    'Continent': 'continent',
                    'Country': 'country',
                    'Phone': 'phoneNumbers',
                    'Address': 'address',
                    'License Plate Number': 'VRN',
                    'Birth Year': 'birthYear',
                    'VIN': 'vin',
                    'City': 'city',
                    'State': 'state',
                    'Zip': 'zipCode',
                    'Source': 'source'
                }
            }),
            mounted() {
                // Check if ?url= is in the URL
                const urlParams = new URLSearchParams(window.location.search);
                if (urlParams.has('url')) {
                    this.exportUrl = decodeURIComponent(urlParams.get('url'));
                    this.showExport = true;
                }


                // Check if wallet is in local storage
                if (localStorage.getItem('walletId')) {
                    console.log('wallet found')
                    this.walletId = localStorage.getItem('walletId')
                    // Get balance
                    fetch(`/wallet/${this.walletId}`)
                        .then(response => response.json())
                        .then(data => {
                            console.log(`wallet balance: ${data.credits}`)
                            this.balance = data.credits
                            this.creditStr = data.credits.toString()
                        })

                    // Get exports
                    fetch(`/exports/${this.walletId}`)
                        .then(response => response.json())
                        .then(data => {
                            console.log(`wallet exports: ${data}`)
                            this.exports = data
                        })
                } else {
                    // Create a new wallet ID (uuid)
                    this.walletId = this.uuidv4()
                    console.log('wallet created: ' + this.walletId)
                    localStorage.setItem('walletId', this.walletId)
                    this.balance = 0
                    this.creditStr = '0.0'

                    // Get balance
                    fetch(`/wallet/${this.walletId}`)
                        .then(response => response.json())
                        .then(data => {
                            console.log(`wallet balance: ${data.credits}`)
                            this.balance = data.credits
                            this.creditStr = data.credits.toString()
                        })

                }
            },
            methods: {
                updateWalletID(id) {
                    if (typeof id === 'string') {
                        this.walletId = id
                        console.log('wallet updated: ' + id)
                        localStorage.setItem('walletId', id)
                    }
                },
                downloadExport(item) {
                    // Open item.link in new tab
                    window.open(item.link, '_blank')
                },
                goToMap() {
                    window.location.href = `/map`
                },
                isMobile() {
                    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
                        return true
                    } else {
                        return false
                    }
                },
                uuidv4() {
                    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
                        (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
                    );
                },
                doExport() {
                    // Check if wallet is valid
                    if (this.walletId.length !== 36) {
                        alert('Invalid wallet ID')
                        return
                    }

                    // Check if export count is valid
                    if (this.exportCount > 100000) {
                        alert('Max 100,000 records per export')
                        return
                    }

                    const exportUrlParams = new URL(this.exportUrl).searchParams;

                    // Construct the /export URL with the same query parameters
                    const exportUrl = new URL('/export', window.location.origin);
                    exportUrl.search = exportUrlParams.toString();

                    if (this.exportCount <= 100) {
                        return this.actuallyDoExport(exportUrl)
                    }

                    // Calculate cost. 1 credit = 10 records, first 100 records are free
                    const cost = (this.exportCount - 100) / 10

                    // Check if user has enough credits
                    if (this.balance < cost) {
                        alert('Not enough credits')
                        return
                    }

                    // Confirm export
                    if (!confirm(`Export ${this.exportCount} records for ${cost} credits?`)) {
                        return
                    }

                    this.actuallyDoExport(exportUrl)

                    // Deduct from local wallet
                    this.balance -= cost
                    this.creditStr = this.balance.toString()

                    // Close modal
                    this.showExport = false
                    // reset search url
                    this.exportUrl = ''
                    // reset export count
                    this.exportCount = 200

                    // If "url" is in the URL, remove it
                    const urlParams = new URLSearchParams(window.location.search);
                    if (urlParams.has('url')) {
                        urlParams.delete('url')
                        window.history.replaceState({}, document.title, `${window.location.pathname}?${urlParams.toString()}`);
                    }
                },
                actuallyDoExport(exportUrl) {
                    fetch(exportUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({
                            walletId: this.walletId,
                            exportCount: this.exportCount
                        })
                    })
                        .then(response => response.json())
                        .then(data => {
                            if (data.success) {
                                alert('Export started... check back soon')
                                this.exports.push({
                                    query: new URL(exportUrl).searchParams.toString(),
                                    exportCount: this.exportCount,
                                    status: 'pending',
                                    ...data
                                })
                                console.log(this.exports)
                            } else {
                                alert('Error exporting. Credits have not been deducted')
                            }
                        })
                },
                doFillWallet() {
                    const walletId = this.walletId
                    // 1USD = 100 Credits
                    const amount = this.walletFill * 100

                    // Check if amount is valid
                    if (amount < 100) {
                        alert('Minimum $1')
                        return
                    }

                    // Check if wallet is valid
                    if (walletId.length !== 36) {
                        alert('Invalid wallet ID')
                        return
                    }

                    window.location = `/fillWallet/${walletId}/${amount}`
                },
                copyWalletId() {
                    // Method 1
                    const el = document.createElement('textarea');
                    el.value = this.walletId;
                    document.body.appendChild(el);
                    el.select();
                    document.execCommand('copy');
                    document.body.removeChild(el);

                    // Method 2
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        navigator.clipboard.writeText(this.walletId)
                    }

                    // Method 3
                    const input = document.getElementById('walletId');
                    input.focus();
                    input.select();
                    document.execCommand('copy');
                },
                buildQuery() {
                    let query = ''
                    this.queries.forEach((q, idx) => {
                        const field = this.queryFieldMap[q.field];
                        const value = q.value;

                        if (q.not) {
                            if (idx === 0) {
                                query += `not${field}=${q.value}`;
                            } else {
                                query += `&not${field}=${q.value}`;
                            }
                        } else {
                            if (idx === 0) {
                                query += `${field}=${q.value}`;
                            } else {
                                query += `&${field}=${q.value}`;
                            }
                        }


                        if (this.exact) {
                            query += `&exact=true`;
                        }
                    });

                    return query
                }
            }
        })
    </script>
</body>

</html>
