[
  {
    "path": ".gitignore",
    "content": "config.json\ngs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n\npackage-lock.json\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules\njspm_packages\n\n# Optional npm cache directory\n.npm\n\n# Optional REPL history\n.node_repl_history\n\ndist\nout\n\n# macOS\n.DS_Store\n\npackage-lock.json\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2017 Peter Soboyejo <http://petersoboyejo.com/>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# easy-proxy\nMass proxy distribution made easy with the DigitalOcean API\n\n![screen](https://i.imgur.com/ZIabShH.png)\n\n[DOWNLOADS CAN BE FOUND HERE](https://github.com/dzt/easy-proxy/releases)\n\n[Community Discord Server](https://discord.gg/BkDxcjT)\n\n### Setup (for development)\n\neasy-proxy requires [Node.js](http://nodejs.org/).\n\nDevelopment Setup:\n\n```sh\n$ git clone https://github.com/dzt/easy-proxy.git\n$ cd easy-proxy\n$ npm install # sudo npm install if you're on macOS\n$ npm run dev\n```\n\n# Videos\n[Preview & Explanation Video](https://youtu.be/Uy0EpcAgaAs)\n\n[RSA ID Setup on macOS](https://streamable.com/6gnpe)\n\n### Who\n\nWritten by <a href=\"http://petersoboyejo.com/\">@dzt</a>, made better by you.\n\n\n## License\n\n```\nThe MIT License (MIT)\n\nCopyright (c) 2017 Peter Soboyejo <http://petersoboyejo.com/>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n"
  },
  {
    "path": "confg/nouserpass/squid.conf",
    "content": "http_port 3128\ncache deny all\nhierarchy_stoplist cgi-bin ?\n\naccess_log none\ncache_store_log none\ncache_log /dev/null\n\nrefresh_pattern ^ftp: 1440 20% 10080\nrefresh_pattern ^gopher: 1440 0% 1440\nrefresh_pattern -i (/cgi-bin/|\\?) 0 0% 0\nrefresh_pattern . 0 20% 4320\n\nacl localhost src 127.0.0.1/32 ::1\nacl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1\n\nacl SSL_ports port 1-65535\nacl Safe_ports port 1-65535\nacl CONNECT method CONNECT\nacl siteblacklist dstdomain \"/etc/squid/blacklist.acl\"\nhttp_access allow manager localhost\nhttp_access deny manager\n\nhttp_access deny !Safe_ports\n\nhttp_access deny CONNECT !SSL_ports\nhttp_access deny siteblacklist\n#auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwd\n\n#auth_param basic children 5\n#auth_param basic realm Squid proxy-caching web server\n#auth_param basic credentialsttl 2 hours\n#acl password proxy_auth REQUIRED\nhttp_access allow localhost\nhttp_access allow password\nhttp_access allow all\n\nforwarded_for off\nrequest_header_access Allow allow all\nrequest_header_access Authorization allow all\nrequest_header_access WWW-Authenticate allow all\nrequest_header_access Proxy-Authorization allow all\nrequest_header_access Proxy-Authenticate allow all\nrequest_header_access Cache-Control allow all\nrequest_header_access Content-Encoding allow all\nrequest_header_access Content-Length allow all\nrequest_header_access Content-Type allow all\nrequest_header_access Date allow all\nrequest_header_access Expires allow all\nrequest_header_access Host allow all\nrequest_header_access If-Modified-Since allow all\nrequest_header_access Last-Modified allow all\nrequest_header_access Location allow all\nrequest_header_access Pragma allow all\nrequest_header_access Accept allow all\nrequest_header_access Accept-Charset allow all\nrequest_header_access Accept-Encoding allow all\nrequest_header_access Accept-Language allow all\nrequest_header_access Content-Language allow all\nrequest_header_access Mime-Version allow all\nrequest_header_access Retry-After allow all\nrequest_header_access Title allow all\nrequest_header_access Connection allow all\nrequest_header_access Proxy-Connection allow all\nrequest_header_access User-Agent allow all\nrequest_header_access Cookie allow all\nrequest_header_access All deny all\n"
  },
  {
    "path": "confg/userpass/squid.conf",
    "content": "http_port 3128\ncache deny all\nhierarchy_stoplist cgi-bin ?\n\naccess_log none\ncache_store_log none\ncache_log /dev/null\n\nrefresh_pattern ^ftp: 1440 20% 10080\nrefresh_pattern ^gopher: 1440 0% 1440\nrefresh_pattern -i (/cgi-bin/|\\?) 0 0% 0\nrefresh_pattern . 0 20% 4320\n\nacl localhost src 127.0.0.1/32 ::1\nacl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1\n\nacl SSL_ports port 1-65535\nacl Safe_ports port 1-65535\nacl CONNECT method CONNECT\nacl siteblacklist dstdomain \"/etc/squid/blacklist.acl\"\nhttp_access allow manager localhost\nhttp_access deny manager\n\nhttp_access deny !Safe_ports\n\nhttp_access deny CONNECT !SSL_ports\nhttp_access deny siteblacklist\nauth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwd\n\nauth_param basic children 5\nauth_param basic realm Squid proxy-caching web server\nauth_param basic credentialsttl 2 hours\nacl password proxy_auth REQUIRED\nhttp_access allow localhost\nhttp_access allow password\nhttp_access deny all\n\nforwarded_for off\nrequest_header_access Allow allow all\nrequest_header_access Authorization allow all\nrequest_header_access WWW-Authenticate allow all\nrequest_header_access Proxy-Authorization allow all\nrequest_header_access Proxy-Authenticate allow all\nrequest_header_access Cache-Control allow all\nrequest_header_access Content-Encoding allow all\nrequest_header_access Content-Length allow all\nrequest_header_access Content-Type allow all\nrequest_header_access Date allow all\nrequest_header_access Expires allow all\nrequest_header_access Host allow all\nrequest_header_access If-Modified-Since allow all\nrequest_header_access Last-Modified allow all\nrequest_header_access Location allow all\nrequest_header_access Pragma allow all\nrequest_header_access Accept allow all\nrequest_header_access Accept-Charset allow all\nrequest_header_access Accept-Encoding allow all\nrequest_header_access Accept-Language allow all\nrequest_header_access Content-Language allow all\nrequest_header_access Mime-Version allow all\nrequest_header_access Retry-After allow all\nrequest_header_access Title allow all\nrequest_header_access Connection allow all\nrequest_header_access Proxy-Connection allow all\nrequest_header_access User-Agent allow all\nrequest_header_access Cookie allow all\nrequest_header_access All deny all\n"
  },
  {
    "path": "create.js",
    "content": "const randomstring = require('randomstring')\nconst DigitalOcean = require('do-wrapper').default\nconst eSettings = require('electron-settings')\nconst request = require('request')\nconst _ = require('underscore')\nconst ipcMain = require('electron').ipcMain\n\nvar task = function(win, info, settings, no, callback) {\n    var sender = win.webContents;\n    var ssh_key_id = null;\n    var id = null;\n    var stopped = false;\n\n    api = new DigitalOcean(eSettings.getSync('do_api_key'), '9999')\n    var host = null;\n\n    ipcMain.on('stopTasks', function(event) {\n        if (stopped == false) {\n            sender.send('updateMonitor', {\n                no: no,\n                msg: 'Cancelled',\n                username: info.username,\n                password: info.password,\n                ip: 'n/a',\n                error: true\n            });\n            stopped = true\n        }\n    });\n\n    sender.send('updateMonitor', {\n        no: no,\n        msg: 'Started',\n        username: info.username,\n        password: info.password,\n        ip: 'n/a',\n        error: false\n    });\n\n    createDroplet();\n\n    function createDroplet() {\n\n        sender.send('updateMonitor', {\n            no: no,\n            msg: `Creating Droplet`,\n            username: info.username,\n            password: info.password,\n            ip: 'n/a',\n            error: false\n        });\n\n        var dropletName = randomstring.generate(14) + '-ep';\n\n        var dropletData = {\n            name: dropletName,\n            region: info.region,\n            size: '512mb',\n            image: parseInt(info.slug),\n            ssh_keys: [ssh_key_id],\n            monitoring: true,\n            user_data:\n              '#!/bin/bash \\n' +\n              'yum install squid wget httpd-tools -y &&' +\n              'touch /etc/squid/passwd &&' +\n              `htpasswd -b /etc/squid/passwd ${info.username} ${info.password} &&` +\n              'wget -O /etc/squid/squid.conf https://raw.githubusercontent.com/dzt/easy-proxy/master/confg/userpass/squid.conf --no-check-certificate &&' +\n              'touch /etc/squid/blacklist.acl &&' +\n              'systemctl restart squid.service && systemctl enable squid.service &&' +\n              'iptables -I INPUT -p tcp --dport 3128 -j ACCEPT &&' +\n              'iptables-save'\n        };\n\n/*\n        var dropletData = {\n            name: dropletName,\n            region: info.region,\n            size: '512mb',\n            image: parseInt(info.slug),\n            ssh_keys: [ssh_key_id],\n            monitoring: true,\n            user_data:\n              '#!/bin/bash \\n' +\n              'yum install squid wget httpd-tools -y &&' +\n              //'touch /etc/squid/passwd &&' +\n              //`htpasswd -b /etc/squid/passwd ${info.username} ${info.password} &&` +\n              'wget -O /etc/squid/squid.conf https://raw.githubusercontent.com/dzt/easy-proxy/master/confg/nouserpass/squid.conf --no-check-certificate &&' +\n              'touch /etc/squid/blacklist.acl &&' +\n              'systemctl restart squid.service && systemctl enable squid.service &&' +\n              'iptables -I INPUT -p tcp --dport 3128 -j ACCEPT &&' +\n              'iptables-save'\n        };\n\n*/\n        console.log(dropletData);\n\n        api.dropletsCreate(dropletData, function(err, resp, body) {\n            if (err) {\n                sender.send('updateMonitor', {\n                    no: no,\n                    msg: 'An error occured while trying to create your droplet.',\n                    username: info.username,\n                    password: info.password,\n                    ip: 'n/a',\n                    error: true\n                });\n                console.log(`[${no}] Error creating droplet.`);\n                console.log(err);\n                return callback(null, true);\n            }\n\n            setTimeout(function() {\n\n                if (stopped) {\n                    destroyDroplet(id, api, function(err, resp) {\n                        if (err) {\n                            return callback(null, true);\n                        }\n                        return callback(null, true);\n                    });\n                }\n\n                api.dropletsGetAll({}, function(err, resp, body) {\n\n                    id = _.findWhere(resp.body.droplets, {\n                        name: dropletName\n                    }).id\n\n                    host = _.findWhere(resp.body.droplets, {\n                        name: dropletName\n                    }).networks.v4[0].ip_address\n\n                    var para = null;\n\n                    if (eSettings.getSync('ssh_passphrase') != null) {\n                        para = eSettings.getSync('ssh_passphrase');\n                    }\n\n                    if (stopped) {\n                        destroyDroplet(id, api, function(err, resp) {\n                            if (err) {\n                                return callback(null, true);\n                            }\n                            return callback(null, true);\n                        });\n                    }\n\n                    if (stopped) {\n                        destroyDroplet(id, api, function(err, resp) {\n                            if (err) {\n                                return callback(null, true);\n                            }\n                            return callback(null, true);\n                        });\n                    } else {\n                        sender.send('updateMonitor', {\n                            no: no,\n                            msg: `Droplet Created`,\n                            username: info.username,\n                            password: info.password,\n                            ip: host,\n                            error: false\n                        });\n                    }\n\n                        console.log(\"http://\" + info.username + \":\" + info.password + \"@\" + host + \":\" + '3128')\n\n\n                        var count = 119;\n                        for (var i = 0; i < 119; i++) {\n\n                          setTimeout(function() {\n                            sender.send('updateMonitor', {\n                                no: no,\n                                msg: `Testing Proxy in ${count}s`,\n                                username: info.username,\n                                password: info.password,\n                                ip: host,\n                                error: false\n                            });\n                            count--;\n                          }, 1000*i);\n\n                        }\n\n\n                        setTimeout(function() {\n                            request({\n                                method: 'get',\n                                url: 'https://google.com/',\n                                proxy: \"http://\" + info.username + \":\" + info.password + \"@\" + host + \":\" + '3128',\n                                gzip: true,\n                                headers: {\n                                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3107.4 Safari/537.36'\n                                }\n                            }, (error, resp, body) => {\n\n                                if (error) {\n                                    console.log(error);\n                                    sender.send('updateMonitor', {\n                                        no: no,\n                                        msg: `Proxy Invalid, destroying droplet.`,\n                                        username: info.username,\n                                        password: info.password,\n                                        ip: host,\n                                        error: true\n                                    });\n\n                                    destroyDroplet(id, api, function(err, resp) {\n                                        if (err) {\n                                            sender.send('updateMonitor', {\n                                                no: no,\n                                                msg: `Error Occured while destroying droplet due to bad proxy Connection.`,\n                                                username: info.username,\n                                                password: info.password,\n                                                ip: host,\n                                                error: true\n                                            });\n                                            return callback(null, true);\n                                        }\n\n                                        sender.send('updateMonitor', {\n                                            no: no,\n                                            msg: `Droplet Destroyed due to bad proxy connection.`,\n                                            username: info.username,\n                                            password: info.password,\n                                            ip: host,\n                                            error: true\n                                        });\n\n                                        return callback(null, true);\n\n                                    });\n\n                                } else {\n                                    sender.send('updateMonitor', {\n                                        no: no,\n                                        msg: `Created!`,\n                                        username: info.username,\n                                        password: info.password,\n                                        ip: host,\n                                        error: false\n                                    });\n\n                                    console.log(`[${no}] Created!`);\n                                    return callback(null, true);\n                                }\n\n                            });\n                        }, 120000);\n\n                });\n\n\n            }, 60000);\n\n        });\n\n\n    }\n\n}\n\nfunction destroyDroplet(id, api, cb) {\n    api.dropletsDelete(id, function(err, resp, body) {\n        if (err) {\n            return cb(true, null);\n        }\n        return cb(null, true)\n    });\n}\n\nmodule.exports = {\n    task: task\n};\n"
  },
  {
    "path": "index.js",
    "content": "const electron = require('electron')\nconst {\n    app,\n    BrowserWindow,\n    Menu\n} = electron\nconst settings = require('./settings-manager')\nconst eSettings = require('electron-settings')\nconst create = require('./create')\nconst path = require('path')\nconst async = require('async')\nconst ChildProcess = require('child_process')\nvar DigitalOcean = require('do-wrapper').default,\n    api = null;\n\nvar win, settingsWin;\n\nconst debug = /--debug/.test(process.argv[2])\n\n// Launch Menu Spawn System\n\nvar createShortcut = function(callback) {\n    spawnUpdate([\n        '--createShortcut',\n        path.basename(process.execPath),\n        '--shortcut-locations',\n        'StartMenu'\n    ], callback)\n}\n\nvar removeShortcut = function(callback) {\n    spawnUpdate([\n        '--removeShortcut',\n        path.basename(process.execPath)\n    ], callback)\n}\n\nvar spawnUpdate = function(args, callback) {\n    var updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe')\n    var stdout = ''\n    var spawned = null\n\n    try {\n        spawned = ChildProcess.spawn(updateExe, args)\n    } catch (error) {\n        if (error && error.stdout == null)\n            error.stdout = stdout\n        process.nextTick(function() {\n            callback(error)\n        })\n        return\n    }\n\n    var error = null\n\n    spawned.stdout.on('data', function(data) {\n        stdout += data\n    })\n\n    spawned.on('error', function(processError) {\n        if (!error)\n            error = processError\n    })\n\n    spawned.on('close', function(code, signal) {\n        if (!error && code !== 0) {\n            error = new Error('Command failed: ' + code + ' ' + signal)\n        }\n        if (error && error.code == null)\n            error.code = code\n        if (error && error.stdout == null)\n            error.stdout = stdout\n        callback(error)\n    })\n}\n\nswitch (process.argv[1]) {\n    case '--squirrel-install':\n        createShortcut(function() {\n            app.quit()\n        });\n        break;\n    case '--squirrel-uninstall':\n        removeShortcut(function() {\n            app.quit();\n        });\n        break;\n    case '--squirrel-obsolete':\n    case '--squirrel-updated':\n        app.quit();\n        break;\n    default:\n        init();\n}\n\nfunction init() {\n    app.on('ready', () => {\n\n        settings.init()\n        app.ep = {\n            settings\n        }\n\n        win = new BrowserWindow({\n            width: 750,\n            height: 670,\n            minWidth: 750,\n            minHeight: 670,\n            resizable: true,\n            maxWidth: 750,\n            maxHeight: 640,\n            fullscreenable: false,\n            frame: true,\n            show: true,\n            icon: `${__dirname}/static/icon.png`\n        })\n        const menuTemplate = [{\n                label: 'File',\n                submenu: [{\n                        label: 'Settings',\n                        click() {\n                            initSettings()\n                        },\n                        accelerator: 'CmdOrCtrl+,',\n                    },\n                    {\n                        label: 'Quit',\n                        click() {\n                            app.quit()\n                        },\n                        accelerator: 'CmdOrCtrl+Q',\n                    }\n                ]\n            },\n            {\n                label: 'Edit',\n                submenu: [{\n                        role: 'copy'\n                    },\n                    {\n                        role: 'paste'\n                    },\n                    {\n                        role: 'pasteandmatchstyle'\n                    },\n                    {\n                        role: 'delete'\n                    },\n                    {\n                        role: 'selectall'\n                    }\n                ]\n            },\n            {\n                label: 'View',\n                submenu: [{\n                    label: 'Reload',\n                    accelerator: 'CmdOrCtrl+R',\n                    click(item, focusedWindow) {\n                        if (focusedWindow) focusedWindow.reload()\n                    }\n                }]\n            },\n            {\n                role: 'window',\n                submenu: [{\n                        role: 'minimize'\n                    },\n                    {\n                        role: 'close'\n                    }\n                ]\n            },\n            {\n                role: 'help',\n                submenu: [{\n                        label: 'Learn More about EasyProxy',\n                        click() {\n                            require('electron').shell.openExternal('github.com/dzt/easy-proxy')\n                        }\n                    },\n                    {\n                        label: 'Toggle Developer Tools',\n                        accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',\n                        click(item, focusedWindow) {\n                            if (focusedWindow) focusedWindow.webContents.toggleDevTools()\n                        }\n                    }\n                ]\n            }\n        ]\n\n        // If the platform is Mac OS, make some changes to the window management portion of the menu\n        if (process.platform === 'darwin') {\n            menuTemplate[2].submenu = [{\n                    label: 'Close',\n                    accelerator: 'CmdOrCtrl+W',\n                    role: 'close'\n                },\n                {\n                    label: 'Minimize',\n                    accelerator: 'CmdOrCtrl+M',\n                    role: 'minimize'\n                },\n                {\n                    label: 'Zoom',\n                    role: 'zoom'\n                },\n                {\n                    type: 'separator'\n                },\n                {\n                    label: 'Bring All to Front',\n                    role: 'front'\n                }\n            ]\n        }\n\n        // Set menu template just created as the application menu\n        const mainMenu = Menu.buildFromTemplate(menuTemplate)\n        Menu.setApplicationMenu(mainMenu)\n        win.setMenu(null);\n        win.loadURL(`file://${__dirname}/static/index.html`);\n    })\n}\n\nelectron.ipcMain.on('create', function(event, args) {\n    var tasks = []\n    args.map(function(task, i) {\n        tasks.push(function(cb) {\n            create.task(win, task, settings, i + 1, (err, response) => {\n                if (err) {\n                    return (err)\n                }\n                return cb(null, response)\n            })\n        })\n    })\n    async.parallel(tasks, function(err, res) {\n        if (err) {\n            console.log('err', err)\n        } else {\n            console.log(res)\n            // TODO: When Session Ends\n            win.webContents.send('tasksEnded');\n        }\n    });\n});\n\nelectron.ipcMain.on('openSettings', function(event, args) {\n    initSettings();\n});\n\nelectron.ipcMain.on('open-file-dialog', function(event) {\n    require('electron').dialog.showOpenDialog({\n        properties: ['openFile'],\n        filters: [{\n            name: 'All Files',\n            extensions: ['*']\n        }]\n    }, function(filename) {\n        if (filename) {\n            console.log(filename[0]);\n            event.sender.send('selected-file', filename[0]);\n        }\n    })\n});\n\nelectron.ipcMain.on('wipeDroplets', function(event) {\n    api = new DigitalOcean(eSettings.getSync('do_api_key'));\n    var droplets = [];\n    api.dropletsGetAll({}, function(err, resp, body) {\n        if (err) {\n            console.log(err);\n            event.sender.send('errDestroy');\n        }\n\n        for (var i = 0; i < body.droplets.length; i++) {\n            var id = body.droplets[i].id;\n            var dropletName = body.droplets[i].name;\n            if (dropletName.endsWith('-ep')) {\n                api.dropletsDelete(id, function(err, resp, body) {});\n            }\n        }\n\n        event.sender.send('wipe-complete');\n\n        //console.log(body);\n    });\n});\n\nelectron.ipcMain.on('resetApp', (event, args) => {\n    win.close()\n    settingsWin.close()\n    app.quit();\n})\n\nelectron.ipcMain.on('refreshMainWindow', (event, args) => {\n    win.webContents.send('refreshMain');\n})\n\nelectron.ipcMain.on('fetchForImages', function(event) {\n\n    var options = [];\n    var regionDict = [];\n\n    api = new DigitalOcean(eSettings.getSync('do_api_key'));\n\n    function fetchFullRegionName(shortName) {\n        for (var i = 0; i < regionDict.length; i++) {\n            if (regionDict[i].slug == shortName) {\n                return regionDict[i].fullName;\n            }\n        }\n    }\n\n    // Fetch for Regions and Slug Names\n    api.regionsGetAll({}, function(err, resp, body) {\n        if (err) {\n            // Return Error to Window\n            console.log('err', err);\n            win.webContents.send('initError');\n            return\n        }\n\n        for (var i = 0; i < body.regions.length; i++) {\n            regionDict.push({\n                fullName: body.regions[i].name,\n                slug: body.regions[i].slug\n            })\n        }\n\n        api.imagesGetAll({type: 'distribution'}, function(err, resp, body) {\n            if (err) {\n                // Return Error to Window\n                win.webContents.send('initError');\n                return\n            }\n\n            for (var i = 0; i < body.images.length; i++) {\n                // Look for 64bit versions of CentOS 7\n                if (body.images[i].distribution.indexOf('CentOS') > -1) {\n                    if (body.images[i].name.split(' ')[0].startsWith('7')) {\n                        for (var x = 0; x < body.images[i].regions.length; x++) {\n\n                            if (fetchFullRegionName(body.images[i].regions[x]) != undefined) {\n                                options.push({\n                                    title: `CentOS ${body.images[i].name} - ${body.images[i].id} - (${fetchFullRegionName(body.images[i].regions[x])})`,\n                                    region: body.images[i].regions[x],\n                                    slug: body.images[i].id\n                                })\n                            }\n                        }\n\n                    }\n                }\n            }\n\n            win.webContents.send('updateOptionList', options);\n\n        });\n    });\n\n});\n\nfunction initSettings() {\n    settingsWin = new electron.BrowserWindow({\n        backgroundColor: '#ffffff',\n        center: true,\n        fullscreen: false,\n        height: 700,\n        icon: `${__dirname}/static/icon.png`,\n        maximizable: false,\n        minimizable: false,\n        resizable: false,\n        show: false,\n        skipTaskbar: true,\n        title: 'Settings',\n        useContentSize: true,\n        width: 550\n    })\n\n    settingsWin.loadURL(`file://${__dirname}/static/settings.html`);\n    // No menu on the About settingsWindow\n    settingsWin.setMenu(null);\n    //settingsWin.webContents.openDevTools()\n    settingsWin.once('ready-to-show', function() {\n        settingsWin.show()\n    })\n\n    settingsWin.once('closed', function() {\n        aboutWin = null\n    })\n\n    return settingsWin.show()\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"EasyProxy\",\n    \"version\": \"2.1.2\",\n    \"description\": \"Easy Proxy Creation\",\n    \"main\": \"index.js\",\n    \"scripts\": {\n        \"start\": \"electron .\",\n        \"dev\": \"electron . --debug\",\n        \"dist:win\": \"build --windows --x64 --dir\",\n        \"dist:mac\": \"build --mac\",\n        \"installer\": \"node scripts/installer.js\"\n    },\n    \"author\": \"Peter Soboyejo <thepcmrtim@gmail.com>\",\n    \"license\": \"MIT\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"git://github.com/dzt/easy-proxy.git\"\n    },\n    \"bugs\": {\n        \"url\": \"https://github.com/dzt/easy-proxy/issues\"\n    },\n    \"dependencies\": {\n        \"async\": \"^2.6.0\",\n        \"bootstrap\": \"^3.3.7\",\n        \"console.table\": \"^0.8.0\",\n        \"copy-paste\": \"^1.3.0\",\n        \"do-wrapper\": \"^3.11.1\",\n        \"electron-config\": \"^1.0.0\",\n        \"electron-settings\": \"^2.2.2\",\n        \"font-awesome\": \"^4.7.0\",\n        \"jquery\": \"^3.2.1\",\n        \"object-path\": \"^0.11.4\",\n        \"path\": \"^0.12.7\",\n        \"prompt\": \"^1.0.0\",\n        \"randomstring\": \"^1.1.5\",\n        \"request\": \"^2.83.0\",\n        \"rimraf\": \"^2.5.4\",\n        \"underscore\": \"^1.8.3\"\n    },\n    \"devDependencies\": {\n        \"electron\": \"1.3.4\",\n        \"electron-winstaller\": \"^2.5.0\",\n        \"electron-builder\": \"^19.13.0\"\n    },\n    \"build\": {\n        \"productName\": \"EasyProxy\",\n        \"appId\": \"com.petersoboyejo.easyproxy\",\n        \"mac\": {\n            \"target\": \"default\",\n            \"icon\": \"static/icons/logo.icns\",\n            \"identity\": null\n        },\n        \"win\": {\n            \"publisherName\": \"EasyProxy\",\n            \"target\": \"squirrel\",\n            \"icon\": \"static/icons/logo.ico\"\n        }\n    }\n}\n"
  },
  {
    "path": "scripts/installer.js",
    "content": "const createWindowsInstaller = require('electron-winstaller').createWindowsInstaller\nconst path = require('path')\nconst rimraf = require('rimraf')\n\ndeleteOutputFolder()\n  .then(getInstallerConfig)\n  .then(createWindowsInstaller)\n  .catch((error) => {\n    console.log('err')\n    console.error(error.message || error)\n    process.exit(1)\n  })\n\nfunction getInstallerConfig () {\n  const rootPath = path.join(__dirname, '..')\n  const outPath = path.join(rootPath, 'dist')\n  return Promise.resolve({\n    appDirectory: path.join(outPath, 'win-unpacked'),\n    noMsi: true,\n    outputDirectory: path.join(outPath, 'windows-installer'),\n    setupExe: 'EasyProxySetup.exe',\n    setupIcon: path.join(rootPath, 'static', 'icons', 'logo.ico'),\n    skipUpdateIcon: true\n  })\n}\n\nfunction deleteOutputFolder () {\n  return new Promise((resolve, reject) => {\n    rimraf(path.join(__dirname, '..', 'out', 'windows-installer'), (error) => {\n      error ? reject(error) : resolve()\n    })\n  })\n}"
  },
  {
    "path": "settings-manager.js",
    "content": "const homedir = require('os').homedir\nconst app = require('electron').app\nconst settings = require('electron-settings')\nconst objectPath = require('object-path')\n\nconst DEFAULTS = {\n    filePath: null,\n    do_api_key: null,\n    ip_auth: false,\n    ips: null\n};\n\n// we need to sync every setting that can be modified externally\n// e.g. the `openOnStartup` setting can be modified via\n// macOS' System Preferences.app\n\nfunction sync() {\n  settings.setSync('openOnStartup', app.getLoginItemSettings().openAtLogin);\n}\n\nfunction init() {\n  settings.defaults(DEFAULTS);\n  settings.applyDefaultsSync();\n  sync();\n}\n\nfunction get(key) {\n  sync();\n  return objectPath.get(key) || settings.getSync(key);\n}\n\nfunction getAll() {\n  sync();\n  return settings.getSync();\n}\n\nfunction set(key, value) {\n  settings.setSync(key, value);\n}\n\nfunction observe(keyPath, handler) {\n  return settings.observe(keyPath, handler);\n}\n\nmodule.exports = {\n  get: get,\n  getAll: getAll,\n  set: set,\n  observe: observe,\n  init: init\n};\n"
  },
  {
    "path": "static/app.js",
    "content": "require(\"copy-paste\").global()\n\nconst remote = require('electron').remote\nconst app = remote.app\nconst $ = require('jquery')\nconst ipcRenderer = require('electron').ipcRenderer\nconst settings = require('electron-settings')\nconst randomstring = require('randomstring')\n\nvar settingsValues = app.ep.settings.getAll();\n\n// Fetch for Images as soon as Window is loaded\n\nif (settingsValues.do_api_key == null || settingsValues.do_api_key == \"\") {\n    $(\"#fetching\").html('<option value=\"fetching\" id=\"fetching\">Digital Ocean API Key Missing</option>');\n} else {\n    ipcRenderer.send('fetchForImages');\n}\n\nipcRenderer.on('initError', function(event, data) {\n\n    $(\"#fetching\").html('<option value=\"fetching\" id=\"fetching\">An error has occured while trying to fetch data from DigitalOcean, try checking your API Key or refresh.</option>');\n\n});\n\n// When Images are Fetched return data to DOM\nipcRenderer.on('updateOptionList', function(event, data) {\n\n    if (data.length == 0) {\n        $(\"#fetching\").html('<option value=\"fetching\" id=\"fetching\">No CentOS 7 Servers are available at the time.</option>');\n    } else {\n        for (var i = 0; i < data.length; i++) {\n            $('#sel1').append(`<option value=\"${data[i].title}\" region=\"${data[i].region}\" slug=\"${data[i].slug}\">${data[i].title}</option>`);\n        }\n\n        $(\"#fetching\").remove();\n        $(\"#sel1\").prop(\"disabled\", false);\n        $(\"#createButton\").prop(\"disabled\", false);\n    }\n\n});\n\nipcRenderer.on('refreshMain', function(event) {\n  remote.getCurrentWindow().reload();\n});\n\n// Create Proxies Button\n$('#createButton').click(() => {\n\n    if ($(\"#count\").val() == \"\") {\n\n        alert(\"You must set the number of proxies you want to create before performing this action.\");\n\n    } else if (settingsValues.do_api_key == null) {\n\n        alert(\"You're missing crutial settings required to create proxies, please check your settings and try again.\");\n\n    } else {\n\n\n        $(\"#results\").empty();\n\n        $(\"#createButton\").prop(\"disabled\", true);\n        $(\"#sel1\").prop(\"disabled\", true);\n        $(\"#count\").prop(\"disabled\", true);\n        $(\"#clearLogsButton\").prop(\"disabled\", true);\n        $(\"#createButton\").text('Creating...');\n\n        var proxyCount = parseInt($('#count').val())\n\n        var tasks = [];\n\n        for (var i = 0; i < proxyCount; i++) {\n\n            var username = randomstring.generate({\n                length: 6,\n                charset: 'alphabetic',\n                capitalization: 'lowercase'\n            });\n\n            var password = randomstring.generate({\n                length: 6,\n                charset: 'alphabetic',\n                capitalization: 'lowercase'\n            });\n\n            tasks.push({\n                username: username,\n                password: password,\n                slug: $('#sel1').find(\":selected\").attr('slug'),\n                region: $('#sel1').find(\":selected\").attr('region')\n            })\n        }\n\n        ipcRenderer.send('create', tasks);\n    }\n});\n\n// Update List Items in realtime\n\nipcRenderer.on('updateMonitor', function(event, data) {\n    // TODO: Add Timestamp\n    if ($(`#${data.username}`).length) {\n        // update exisiting item\n\n        if (data.error) {\n            var newlyAddedUpdate = `\n            <tr id=\"${data.username}\">\n            <td id=\"no\">#${data.no}</td>\n            <td>${data.ip}</td>\n            <td>3128</td>\n            <td>${data.username}</td>\n            <td>${data.password}</td>\n            <td style=\"color: red;\">${data.msg}</td>\n          </tr>`\n        } else {\n            var newlyAddedUpdate = `\n            <tr id=\"${data.username}\">\n            <td id=\"no\">#${data.no}</td>\n            <td>${data.ip}</td>\n            <td>3128</td>\n            <td>${data.username}</td>\n            <td>${data.password}</td>\n            <td style=\"color: green;\">${data.msg}</td>\n          </tr>`\n        }\n        $(`#${data.username}`).replaceWith(newlyAddedUpdate);\n    } else {\n        var newlyAddedUpdate = `\n      <tr id=\"${data.username}\">\n        <td id=\"no\">#${data.no}</td>\n        <td>${data.ip}</td>\n        <td>3128</td>\n        <td>${data.username}</td>\n        <td>${data.password}</td>\n        <td style=\"color: green;\">${data.msg}</td>\n      </tr>\n    `\n        $('#results').append(newlyAddedUpdate);\n    }\n});\n\n$('#refresh').click(() => {\n    remote.getCurrentWindow().reload();\n});\n\n$('#copyToClipboardButton').click(() => {\n\n    var content = [];\n    $(\"tr\").each(function(i) {\n        if (i != 0) {\n            if ($(this).has(`td:contains('Created!')`).length) {\n                var ip = $(this).find('td').eq(1).text();\n                var user = $(this).find('td').eq(3).text();\n                var pass = $(this).find('td').eq(4).text();\n                content.push(`${ip}:3128:${user}:${pass}`);\n            }\n        }\n    });\n    // use join function\n    copy(content.join('\\n'))\n});\n\n$('#clearLogsButton').click(() => {\n    $(\"#results\").empty();\n});\n\n$('#cancelTasksButton').click(() => {\n    ipcRenderer.send('stopTasks');\n});\n\n$('#settingsButton').click(() => {\n    ipcRenderer.send('openSettings');\n});\n\n// When all tasks are done doing there thing bring everything back to normal and purge old stuff\n\nipcRenderer.on('tasksEnded', function(event, data) {\n    $(\"#createButton\").prop(\"disabled\", false);\n    $(\"#sel1\").prop(\"disabled\", false);\n    $(\"#count\").prop(\"disabled\", false);\n    $(\"#clearLogsButton\").prop(\"disabled\", false);\n    $(\"#createButton\").text('Create');\n});\n"
  },
  {
    "path": "static/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n   <head>\n      <meta charset=\"utf-8\">\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n      <title>EasyProxy</title>\n      <link rel=\"stylesheet\" href=\"../node_modules/bootstrap/dist/css/bootstrap.min.css\">\n      <link href=\"../node_modules/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" type=\"text/css\" />\n      <link rel=\"stylesheet\" href=\"main.css\">\n   </head>\n   <body>\n      <div class=\"main\">\n         <center>\n            <br>\n            <hr width=\"100%\">\n            <div style=\"width: 80%;\">\n               <div class=\"form-group\">\n                  <label>Number of Proxies:</label>\n                  <input type=\"number\" placeholder=\"Example: 5\" class=\"form-control\" id=\"count\">\n               </div>\n               <div class=\"form-group\">\n                  <select class=\"form-control\" id=\"sel1\" disabled>\n                     <option value=\"fetching\" id=\"fetching\">Fetching Images...</option>\n                  </select>\n               </div>\n               <button type=\"submit\" class=\"btn btn-success\" id=\"createButton\" style=\"width: 100%; outline: none;\" disabled>Create</button>\n               <br><br>\n               <div class=\"btn-group\">\n                  <button type=\"button\" id=\"copyToClipboardButton\" class=\"btn btn-default\" aria-label=\"Left Align\">Copy to Clipboard</button>\n                  <button type=\"button\" id=\"clearLogsButton\" class=\"btn btn-default\" aria-label=\"Center Align\">Clear Logs</button>\n                  <button type=\"button\" id=\"cancelTasksButton\" class=\"btn btn-default\" aria-label=\"Right Align\">Cancel Task(s)</button>\n                  <button type=\"button\" id=\"settingsButton\" class=\"btn btn-default\" aria-label=\"Justify\">Settings</button> \n               </div>\n               <hr style=\"width: 80%;\">\n            </div>\n            <br>\n            </hr>\n            <table class=\"table table-condensed\" style=\"width: 80%;\">\n               <thead>\n                  <tr>\n                     <th>#</th>\n                     <th>IP/Host</th>\n                     <th>Port</th>\n                     <th>Username</th>\n                     <th>Password</th>\n                     <th>Status</th>\n                  </tr>\n               </thead>\n               <tbody id=\"results\">\n                  <!-- <tr>\n                     <td>1</td>\n                     <td>108.20.181.185</td>\n                     <td>3128</td>\n                     <td>Z2IoAD0Wec</td>\n                     <td>5095131428</td>\n                     <td style=\"color: green;\">Creating Instance</td>\n                     </tr> -->\n               </tbody>\n            </table>\n            <br><br>\n         </center>\n         <footer>\n            <div class=\"status\">\n               <a class=\"fa fa-refresh\" id=\"refresh\" style=\"text-decoration: none; cursor: pointer;\"></a>&nbsp;&nbsp; Refresh\n            </div>\n         </footer>\n      </div>\n      <script>require('./app.js')</script>\n   </body>\n</html>"
  },
  {
    "path": "static/main.css",
    "content": "body {\n  background: white;\n}\n:not(input):not(textarea),\n:not(input):not(textarea)::after,\n:not(input):not(textarea)::before {\n    -webkit-user-select: none;\n    user-select: none;\n    cursor: default;\n}\ninput, button, textarea, :focus {\n    outline: none; // You should add some other style for :focus to help UX/a11y\n}\n\na:not([draggable=true]), img:not([draggable=true]) {\n    -webkit-user-drag: none;\n    user-drag: none; /* Technically not supported in Electron yet */\n}\na[href^=\"http://\"],\na[href^=\"https://\"],\na[href^=\"ftp://\"] {\n    -webkit-user-drag: auto;\n    user-drag: auto; /* Technically not supported in Electron yet */\n}\n\n.main footer {\n    position: fixed;\n    right: 0px;\n    bottom: 0px;\n    left: 0px;\n    background-color: #EEEEEE;\n    color: #666;\n    border-style: solid;\n    border-width: 1px;\n    border-color: #fff #fff #fff #fff;\n    font-size: 12px;\n    padding: 9px 24px;\n    overflow: hidden;\n    z-index: 999;\n}\n.main footer .status div {\n    display: none;\n}\n.main footer .status div:before {\n    content: '';\n    display: inline-block;\n    width: 9px;\n    height: 9px;\n    background-color: #ccc;\n    border-radius: 100px;\n    margin-right: 6px;\n}\n.main footer .status .connected:before {\n    background-color: #66bc66;\n}\n.main footer .status .connecting:before, .main footer .status .updating:before {\n    background-color: #f04646;\n    -webkit-animation: 3s indicator infinite;\n}\n.main footer .status .disconnected:before {\n    background-color: #de7b7b;\n}\n.main footer .update {\n    float: right;\n}\n.main footer .update a {\n    display: inline;\n    padding: 3px 9px;\n}\n"
  },
  {
    "path": "static/settings.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"stylesheet\" href=\"../node_modules/bootstrap/dist/css/bootstrap.min.css\">\n\n    <link href=\"../node_modules/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" type=\"text/css\" />\n    <style>\n      body {\n        background-color: white;\n        font-family: BlinkMacSystemFont, 'Helvetica Neue', Helvetica, sans-serif;\n        text-align: center;\n        overflow: hidden;\n        outline: none;\n        font-size: 16px;\n        -webkit-user-select: none;\n      }\n      img {\n        width: 100px;\n        height: 100px;\n      }\n      h1 {\n        font-size: 0.9em;\n        -webkit-user-select: text;\n      }\n      p {\n        font-size: 0.8em;\n        -webkit-user-select: text;\n      }\n      input[type=\"radio\"] {\n        font-size: 0.8em;\n      }\n      input {\n        outline: none;\n      }\n      a {\n        text-decoration: none;\n      }\n\n      .btn-file {\n        position: relative;\n        overflow: hidden;\n      }\n      .btn-file input[type=file] {\n        position: absolute;\n        top: 0;\n        right: 0;\n        min-width: 100%;\n        min-height: 100%;\n        font-size: 100px;\n        text-align: right;\n        filter: alpha(opacity=0);\n        opacity: 0;\n        background: red;\n        cursor: inherit;\n        display: block;\n      }\n      input[readonly] {\n        background-color: white !important;\n        cursor: text !important;\n      }\n\n    </style>\n  </head>\n  <body>\n\n    <hr>\n\n    <img src=\"./icon.png\">\n    <p>\n      Version <script>document.write(require('../package.json').version)</script>\n      (<script>document.write(process.arch === 'x64' ? '64-bit' : '32-bit')</script>)\n      <br><br>\n      Written by <a href=\"https://github.com/dzt\">@dzt</a></a>\n    </p>\n\n    <hr>\n\n    <center>\n\n        <ul class=\"nav nav-tabs\" style=\"width: 400px;\">\n            <li role=\"presentation\" class=\"active\">\n              <a data-toggle=\"pill\" href=\"#menu1\">General</a>\n            </li>\n            <li role=\"presentation\">\n              <a data-toggle=\"pill\" href=\"#menu2\">Forwarding</a>\n            </li>\n          </ul>\n\n      <div class=\"tab-content\">\n        <div id=\"menu1\" class=\"tab-pane fade in active\">\n\n            <h5>Digital Ocean API Key</h5>\n            <input type=\"text\" style=\"width: 400px;\" class=\"form-control\" id=\"doKey\">\n\n            <h5>Authorized IPs</h5>\n            <textarea class=\"form-control\" style=\"width: 400px;\" rows=\"3\" disabled>Coming Soon...</textarea>\n\n            <br>\n\n            <!-- <div class=\"form-check\" style=\"font-size: 14px;\">\n              <input class=\"form-check-input\" type=\"checkbox\" value=\"\" id=\"defaultCheck1\">\n              Enable IP Authorization\n            </div> -->\n\n            <!-- <div class=\"form-check\" style=\"font-size: 14px;\">\n              <input class=\"form-check-input\" type=\"checkbox\" value=\"\" id=\"defaultCheck1\">\n              Disable User/Pass\n            </div> -->\n\n            <br>\n\n            <button type=\"submit\" class=\"btn btn-success\" id=\"saveSettings\" style=\"width: 400px; outline: none;\">Save</button>\n            <br><br>\n            <button type=\"submit\" class=\"btn btn-danger\" id=\"destroy\" style=\"width: 400px; outline: none;\">Destroy All Droplets</button>\n            <br><br>\n            <button type=\"submit\" class=\"btn btn-warning\" id=\"reset\" style=\"width: 400px; outline: none;\">Reset to Defaults</button>\n\n          </div>\n\n          <div id=\"menu2\" class=\"tab-pane fade\">\n              <h3>Coming Soon...</h3>\n          </div>\n\n        </div>\n\n      </center>\n\n  </body>\n  <script>\n      if (typeof module === 'object') {\n        window.module = module;\n        module = undefined;\n      }\n   </script>\n  <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js\"></script>\n  <script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\"></script>\n  <script>require('./settings.js')</script>\n</html>\n"
  },
  {
    "path": "static/settings.js",
    "content": "const remote = require('electron').remote;\nconst app = remote.app;\nconst settings = require('electron-settings');\nconst $ = require('jquery')\nconst Config = require('electron-config');\nconst config = new Config();\nconst dialog = remote.dialog;\nconst ipcRenderer = require('electron').ipcRenderer\n\nvar settingsValues = app.ep.settings.getAll();\nvar settingsVal = config.get('settingsVal')\nvar shell = require('electron').shell;\n\n\n$(\"#filePathBtn\").click(function(event){\n    event.preventDefault();\n    ipcRenderer.send('open-file-dialog');\n});\n\n$('#passphrase').val(settingsValues.ssh_passphrase);\n$('#doKey').val(settingsValues.do_api_key);\n$('#filePath').val(settingsValues.filePath);\n$('#keyName').val(settingsValues.do_ssh_key_name);\n\nipcRenderer.on('selected-file', function(event, filename) {\n    $('#filePath').val(filename);\n    settingsValues.filePath = filename\n    app.ep.settings.set('filePath', filename);\n});\n\n$('#passphrase').change(function() {\n    settingsValues.ssh_passphrase = $(this).val()\n    app.ep.settings.set('ssh_passphrase', $(this).val());\n});\n\n$('#keyName').change(function() {\n    settingsValues.do_ssh_key_name = $(this).val()\n    app.ep.settings.set('do_ssh_key_name', $(this).val());\n});\n\n$('#doKey').change(function() {\n    settingsValues.do_api_key = $(this).val()\n    app.ep.settings.set('do_api_key', $(this).val());\n});\n\n$('#saveSettings').click(() => {\n    ipcRenderer.send('refreshMainWindow');\n});\n\n$('#destroy').click(() => {\n  $(\"#destroy\").prop(\"disabled\", true);\n  if (settingsValues.do_api_key == null || settingsValues.do_api_ke == \"\") {\n    $('#destroy').text('No API Key was found');\n    setTimeout(function(){\n      $('#destroy').text('Destroy');\n      $(\"#destroy\").prop(\"disabled\", false);\n    }, 5000);\n  } else {\n    $('#destroy').text('Destroying...');\n    ipcRenderer.send('wipeDroplets');\n  }\n});\n\n$('#reset').click(() => {\n  dialog.showMessageBox({\n      \"message\": `Are you sure you want to reset?`,\n      \"detail\": \"You will not be able to recover any task data after you perform this action.\",\n      \"buttons\": [\"Ok\", \"Cancel\"],\n  }, function(response) {\n      switch (response) {\n          case 0:\n              ok();\n          case 1:\n              break;\n      }\n  });\n  function ok() {\n    settings.resetToDefaults()\n    ipcRenderer.send('resetApp');\n  }\n});\n\nipcRenderer.on('errDestroy', function(event, data) {\n\n  $('#destroy').text('Error Occured while destroying');\n\n  setTimeout(function(){\n    $('#destroy').text('Destroy');\n    $(\"#destroy\").prop(\"disabled\", false);\n  }, 5000);\n\n});\n\nipcRenderer.on('wipe-complete', function(event, data) {\n  $('#destroy').text('All Droplets have been destroyed');\n\n  setTimeout(function(){\n    $('#destroy').text('Destroy');\n    $(\"#destroy\").prop(\"disabled\", false);\n  }, 5000);\n});\n"
  }
]