[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text eol=lf\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n\n# Standard to msysgit\n*.doc\t diff=astextplain\n*.DOC\t diff=astextplain\n*.docx diff=astextplain\n*.DOCX diff=astextplain\n*.dot  diff=astextplain\n*.DOT  diff=astextplain\n*.pdf  diff=astextplain\n*.PDF\t diff=astextplain\n*.rtf\t diff=astextplain\n*.RTF\t diff=astextplain\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Dependency directories\nnode_modules\njspm_packages\n\n# Optional npm cache directory\n.npm\n\noutput/screenshots/*.png\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"PogoPlayer\"]\n\tpath = PogoPlayer\n\turl = https://github.com/sebastienvercammen/PogoPlayer.git\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"node\"\n  - \"6.1\"\ninstall:\n  - npm install\n  - npm install jshint\nnotifications:\n  email: false\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2017 Frost The Fox and Sébastien Vercammen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Nintendo PTC Account Generator [![Build Status](https://travis-ci.org/sebastienvercammen/ptc-acc-gen.svg?branch=master)](https://travis-ci.org/sebastienvercammen/ptc-acc-gen)\n\n***Supported once again! Please use the [PokemonGo-Map Discord](https://discord.gg/g6k7w83) for questions.***\n\n***It seems Nintendo has patched the + e-mail trick for Gmail. Some users on our Discord have tested and reported that Gmail now requires a 220+ second cooldown period between creation of accounts. Using another e-mail provider (tested with hotmail) still works. For automatic validation, forward all PTC account e-mails to a Gmail account and use our auto-verifier.***\n\n**Please be sure to clone RECURSIVELY**\nexample: git clone --recursive https://github.com/sebastienvercammen/ptc-acc-gen.git\n\nAn automation script based on Nightmare.js that can create any number of Nintendo Pokémon Trainer Club accounts with a single  e-mail address. This only works because Nintendo doesn't check for \"email+1@domain.com\" e-mail tricks, where the e-mail host completely ignores any part after (and including) the plus sign and sends it to \"email@domain.com\".\n\nThis project was started as a proof of concept: even multi-billion dollar companies that just released the single most popular mobile game (Pokémon Go) sometimes miss the details.\n\nMore about plus signs in e-mail addresses [on StackExchange](http://security.stackexchange.com/questions/65244/what-are-the-security-reasons-for-disallowing-the-plus-sign-in-email-addresses).\n\nIf you're using Gmail and want to automatically verify all accounts, use https://gist.github.com/sebastienvercammen/e7e0e9e57db246d7f941b789d8508186\nThe instructions are at the top of the file.\n\n\nThe new version on Nightmare.js now:\n\n* Checks for usernames/e-mails that are already taken\n* Can screenshot the result page (both on success and on failure)\n* Handles server issues better\n* Doesn't require PhantomJS/CasperJS or fiddling with the PATH environment variable\n\n## Requirements\n### Prerequisites\n* [Node.js](https://nodejs.org/en/)\n\n## Usage\nWindows Instructions:\n\n1. Make sure you clone recursively (git clone --recursive [origin])\n  - if you download the zip, make sure you also download the submodule PogoPlayer.\n  - if you cloned non-recursively, be sure to run `git submodule init && git submodule update` or ToS verification will not work.\n2. Install requirements with `npm install`\n3. Run config.py or edit config.js manually. (you will have to edit manually for 2captcha)\n4. Run using `makeaccounts.bat`.\n5. Wait for the generator to fill in the second page, then accept the captcha and hit submit.\n6. Repeat for all accounts\n7. Find the generated accounts in PogoPlayer/accounts.csv.\n\nIt is recommended to keep the username set in your config to around 6 characters.\n\nLinux Instructions:  \n***Headless systems will no longer be able to use the gen due to the captcha requirement, unless you use the autovalidation using 2captcha service (see below)***\n\n1. Run `npm install`\n2. Run config.py or edit config.js manually. (you will need to edit manually for 2captcha)\n2. Run using `makeaccounts.sh`.\n3. Wait for the generator to fill in the second page, then accept the captcha and hit submit.\n4. Repeat for all accounts\n5. Find the generated accounts in PogoPlayer/accounts.csv.\n\nThere is a few command line arguments for index.js if you run manually. `node index.js -h` for more info.\n\nIt is recommended to keep the username set in your config to around 6 characters.\n\nAuto-validation Instructions:\n\n1. Create a 2Captcha account at http://2captcha.com/\n2. Make a deposit or start working to have a positive balance\n3. Navigate to \"2Captcha API\" page and copy the API KEY\n4. Update config.js to enable autovalidation and paste your API KEY\n5. That's it, run the script as usual. You will be switched back to headless mode automatically\n\n## Configuration\n### 1. Generate 10 accounts in the format USERx, where x is 0 to 9.\nThis example corresponds to the default settings. It will generate 10 accounts in the same format: user0, user1, ...\n\nIn [config.js](config.js):\n\n// Starts gen from startNumber to endNumber, determining how many accounts are made\n\tstartNum: 0,\n\tendNum: 10,\n\n\t// Creation Options\n\tnicknameFile: false, // Use nicknames file, or just append numbers to username?\n\trandomPassword: false, // If true generate a random password, If false set \"password\" field below\n\tscreenshotResult: true, // Saves a screenshot per account creation when set to true\n\tscreenshotOnFailure: true, // Saves a screenshot even if registration fails when set to true\n\n\t// Creation Requirements\n\tusername: 'CHANGEME', // Keep the '', User- & display name. Make sure any \"(username + number)@domain.com\" is 100% unique, and is 6 characters minimum, but under 14 characters after the numbers are applied.\n\tpassword: 'CHANGEME', // If you set randomPassword to 'false' above change this to your chosen password (so you have same password for all accounts)\n\temailUser: 'email', // Enter your email address name. If your address is email@domain.com you'd enter 'email'\n\temailDomain: 'domain.com', // Domain of email address. If your address is email@domain.com  you'd enter 'domain.com'\n\tlatitude: 'LATITUDE', // Location Latitude for initial login\n\tlongitude: 'LONGITUDE' // Location Longitude for initial login\n\n### 2. Generate random passwords per account.\n\n Set randomPassword: true, in [config.js](config.js).\n\n Password for accounts will be random, aftyer finished find usernames and passwords in /PogoPlayer/accounts.csv\n\n### 3. Save screenshots (Default directory is /output/screenshots)\n\n\tscreenshotResult: true, // Saves a screenshot per account creation when set to true\n\tscreenshotOnFailure: true, // Saves a screenshot even if registration fails when set to true\n\n### 4. Use a list of unique usernames instead of USERx combinations.\n\n  To create a number of accounts with custom usernames instead of user + number combinations, change [index.js](index.js):\n\n  Set nicknameFile: true, in [config.js](config.js).\n\n  The list of unique usernames must be stored in [nicknames.json](nicknames.json). An example is available on the repo.\n"
  },
  {
    "path": "config.js",
    "content": "var config = {\n    // Starts gen from startNumber to endNumber, determining how many accounts are made\n    startNum: 0,\n    endNum: 10,\n\n    // Creation Options\n    // Use nicknames file, or just append numbers to username?\n    nicknameFile: false,\n    // If true generate a random password, If false set \"password\" field below\n    randomPassword: true,\n    // Saves a screenshot per account creation when set to true\n    screenshotResult: true,\n    // Saves a screenshot even if registration fails when set to true\n    screenshotOnFailure: true,\n\n    // Creation Requirements\n    // Keep the '', User- & display name. It is recommended to keep the username set in your config to around 6 characters.\n    username: \"CHANGEME\",\n    // If you set randomPassword to 'false' above change this to your chosen password (so you have same password for all accounts)\n    password: \"NOSTATIC\",\n    // Enter your email address name. If your address is email@domain.com you'd enter 'email'\n    emailUser: \"CHANGEME\",\n    // Domain of email address. If your address is email@domain.com  you'd enter 'domain.com'\n    emailDomain: \"CHANGEME\",\n    // Location Latitude for initial login\n    latitude: \"CHANGEME\",\n    // Location Longitude for initial login\n    longitude: \"CHANGEME\",\n    // Country code (e.g. BE, FR, US, CA)\n    country: \"US\",\n\n    // 2Captcha API key\n    useAutoCatcha: false,\n    captchaApiKey: \"YOUR_2CAPTCHA_API_KEY_HERE\",\n    // turn on debug logging\n    debug: false\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "config.py",
    "content": "#!/usr/bin/python\n# Version 1\n\nimport os\nimport sys\nimport signal\nimport re\nfrom os import fsync\n\n\ndef signal_handler(signal, frame):\n        print('You pressed Ctrl+C!')\n        sys.exit(0)\n\ndef printmenu():\n    os.system('cls' if os.name == 'nt' else 'clear')\n    #os.system('cls') # for Windows\n    #os.system('clear')\n\n    print (30 * '-')\n    print (\"PTC-ACC-GEN Config Builder\")\n    print (\"Lets set you up!\")\n    print (30 * '-')\n    print (\"1. Build Your Config\")\n    print (\"0. Quit\")\n    print (30 * '-')\n    choice = raw_input('Enter your choice [0-1] : ')\n    try:\n        choice = int(choice)\n    except:\n        printmenu()\n    print (30 * '-')\n\n    if choice == 1:\n        configBuilder()\n    elif choice == 0:\n        cleanExit(\"bye\")\n    else:\n        printmenu()\n\n\ndef configBuilder():\n\n    \"Calculates the number of accounts needed for a specific step value to achiece a specific scan time\"\n    startNum = raw_input(\"Number for Accounts to Start at (recommend 0): \")\n    endNum = raw_input(\"Number for Accounts to End at (recommend 10): \")\n    nicknameFile = raw_input(\"Use Nickname File? (recommend: false): \")\n    randomPassword = raw_input(\"Use Random Password? (recommend: true): \")\n    screenshotResult = raw_input(\"Save Screenshot of each Success? (recommend: true): \")\n    screenshotOnFailure = raw_input(\"Save Screenshot of each Failure? (recommend: true): \")\n    username = raw_input(\"Choose User/Display name, at least 6 chars (recommended) and less than 15: \")\n    if randomPassword.lower() in (\"false\"):\n            password = raw_input(\"Choose Static Password for Accounts: \")\n    else:\n            password = \"NOSTATIC\"\n    emailUser = raw_input(\"Email Address Name (whats before the @ in your email address? ex: yoloswag420): \")\n    emailDomain = raw_input(\"Email Domain (whats after the @ in your email address? ex: hotmail.com): \")\n    latitude = raw_input(\"Latitude for Registration (example: 36.54596): \")\n    longitude = raw_input(\"Longitude for Registration (example: -79.22247): \")\n    country = raw_input(\"Country Code for Registration (example: US, BE, FR, CA): \")\n\n    #Now lets check what people input vs what is valid\n    flag = 1\n    while flag == 1:\n            try:\n                int(startNum)\n            except ValueError:\n                try:\n                    float(startNum)\n                except ValueError:\n                    print (30 * '-')\n                    print \"Your Number for Accounts to Start at is not a number\"\n                    print \"Your Current Start Number: %s\" %(startNum)\n                    startNum = raw_input(\"Number for Accounts to Start at (recommend 0): \")\n                    flag = 1\n            try:\n                int(endNum)\n            except ValueError:\n                try:\n                    float(endNum)\n                except ValueError:\n                    print (30 * '-')\n                    print \"Your Number for Accounts to End at is not a number\"\n                    print \"Your Current End Number: %s\" %(endNum)\n                    startNum = raw_input(\"Number for Accounts to End at (recommend 10): \")\n                    flag = 1\n            try:\n                int(latitude)\n            except ValueError:\n                try:\n                    float(latitude)\n                except ValueError:\n                    print (30 * '-')\n                    print \"Your Latitude is not a number\"\n                    print \"Your Current Latitude: %s\" %(latitude)\n                    latitude = raw_input(\"Latitude for Registration (example: 36.54596): \")\n                    flag = 1\n            try:\n                int(longitude)\n            except ValueError:\n                try:\n                    float(longitude)\n                except ValueError:\n                    print (30 * '-')\n                    print \"Your Longitude is not a number\"\n                    print \"Your Current Longitude: %s\" %(longitude)\n                    startNum = raw_input(\"Longitude for Registration (example: -79.22247): \")\n                    flag = 1\n\n            if startNum > endNum:\n                    print (30 * '-')\n                    print \"Your Number for Accounts to End at must be greater than Number for Accounts to Start at\"\n                    print \"Your Current End Number: %s Your Current Start Number: %s\" %(startNum, endNum)\n                    startNum = raw_input(\"Number for Accounts to Start at (recommend 0): \")\n                    endNum = raw_input(\"Number for Accounts to End at (recommend 10): \")\n                    flag = 1\n            else:\n                    flag = 0\n            if nicknameFile.lower() not in (\"true\", \"false\"):\n                    print (30 * '-')\n                    print \"You didn't type 'true' or 'false' for Use Nickname File: %s\" %(nicknameFile)\n                    nicknameFile = raw_input(\"Use Nickname File? (recommend: false): \")\n                    flag = 1\n            else:\n                    flag = 0\n            if randomPassword.lower() not in (\"true\", \"false\"):\n                    print (30 * '-')\n                    print \"You didn't type 'true' or 'false' for Use Random Password: %s\" %(randomPassword)\n                    randomPassword = raw_input(\"Use Random Password? (recommend: false): \")\n                    flag = 1\n            else:\n                    flag = 0\n            if screenshotResult.lower() not in (\"true\", \"false\"):\n                    print (30 * '-')\n                    print \"You didn't type 'true' or 'false' for Save Screenshot of each Success: %s\" %(screenshotResult)\n                    screenshotResult = raw_input(\"Save Screenshot of each Success? (recommend: true): \")\n                    flag = 1\n            else:\n                    flag = 0\n            if screenshotOnFailure.lower() not in (\"true\", \"false\"):\n                    print (30 * '-')\n                    print \"You didn't type 'true' or 'false' for Save Screenshot of each Failure: %s\" %(screenshotOnFailure)\n                    screenshotOnFailure = raw_input(\"Save Screenshot of each Failure? (recommend: true): \")\n                    flag = 1\n            else:\n                    flag = 0\n            if len(username) < 6:\n                    print (30 * '-')\n                    print \"You chose a username that was less than 6 chars: %s\" %(username)\n                    username = raw_input(\"Choose User/Display name, at least 6 chars and less than 15: \")\n                    flag = 1\n            elif len(username) > 15:\n                    print (30 * '-')\n                    print \"You chose a username that was more than 15 chars: %s\" %(username)\n                    username = raw_input(\"Choose User/Display name, at least 6 chars and less than 15: \")\n                    flag = 1\n            else:\n                    flag = 0\n\n    vars = ['startNum', 'endNum','nicknameFile','randomPassword','screenshotResult','screenshotOnFailure','username','password','emailUser','emailDomain','latitude','longitude','country']\n    new_values = [startNum + ',',endNum + ',',nicknameFile + ',',randomPassword + ',',screenshotResult + ',',screenshotOnFailure + ',','\"' + username + '\",','\"' + password + '\",','\"' + emailUser + '\",','\"' + emailDomain + '\",','\"' + latitude + '\",','\"' + longitude + '\",','\"' + country + '\",','\"']\n    what_to_change = dict(zip(vars,new_values))\n\n    updating('config.js',what_to_change)\n\n    raw_input(\"Config Built Successfully! Press Enter\")\n    printmenu()\n\ndef updating(filename,dico):\n\n    RE = '(('+'|'.join(dico.keys())+')\\s*:)[^\\r\\n]*?(\\r?\\n|\\r)'\n    pat = re.compile(RE)\n\n    def jojo(mat,dic = dico ):\n        return dic[mat.group(2)].join(mat.group(1,3))\n\n    with open(filename,'rb') as f:\n        content = f.read()\n\n    with open(filename,'wb') as f:\n        f.write(pat.sub(jojo,content))\n\ndef cleanExit(message):\n    sys.exit(message)\n\n\nsignal.signal(signal.SIGINT, signal_handler)\nprintmenu()\n"
  },
  {
    "path": "gmailverify.js",
    "content": "/*\n  Automatically click all \"Verify your email\" links in the welcome e-mail from\n  Nintendo Pokémon Trainer Club's signup e-mails.\n\n  All verified e-mails will be moved to trash unless you set \"moveToTrash\" to false.\n\n  How to use:\n   1. Login to Gmail\n   2. Go to https://script.google.com/\n   3. Enter the code, save, run.\n   4. Wait until fully completed, DO NOT LEAVE THE PAGE! (When finished, the text \"running...\" at the top will disappear.)\n   5. Click View > Logs. At the bottom you'll see the total accounts verified.\n   6. Enjoy\n\n   Note: The script will stop after about 98 emails. This is a limitation of Google Scripts, not the script itself. Simply run again and it will process the remaining emails.\n*/\n\nfunction myFunction() {\n  var verified = 0;\n  var moveToTrash = true;\n\n  var threads = GmailApp.search('in:inbox subject:\"Pokémon Trainer Club Activation\"');\n  Logger.log(\"Found \" + threads.length + \" threads.\");\n\n  threads.forEach(function(thread) {\n    var messages = thread.getMessages();\n    Logger.log(\"Found \" + messages.length + \" messages.\");\n\n    messages.forEach(function(msg) {\n      var value = msg.getBody()\n                     .match(/verify your email/m);\n\n      if(msg.isInInbox() && value) {\n        var link = msg.getBody().match(/<a href=\"https:\\/\\/club.pokemon.com\\/us\\/pokemon-trainer-club\\/activated\\/([\\w\\d]+)\"/);\n\n        if(link) {\n          var url = 'https://club.pokemon.com/us/pokemon-trainer-club/activated/' + link[1];\n          var options = {\n            \"muteHttpExceptions\": true\n          };\n\n          var status = UrlFetchApp.fetch(url, options).getResponseCode();\n          Logger.log(\"[#] Verified (\" + status + \"): \" + url);\n\n          if(status == 200) {\n            verified++;\n            msg.markRead();\n\n            if(moveToTrash) { msg.moveToTrash(); }\n          }\n        }\n      }\n    });\n  });\n\n  Logger.log(\"Completed \" + verified + \" verifications.\");\n}\n"
  },
  {
    "path": "index.js",
    "content": "/*jshint sub:true*/\n// Requires\nvar Nightmare = require('nightmare');\nvar nicknames = require('./nicknames.json');\nvar fs = require('fs');\nvar request = require('request');\n\n// Settings\nvar showWindow = true;\n\n// Start Config File Imports\nvar configFile = require('./config');\nvar start = configFile.startNum;\nvar end = configFile.endNum;\nvar useNicknamesFile = configFile.nicknameFile;\nvar useRandomPassword = configFile.randomPassword;\nvar screenshotResult = configFile.screenshotResult;\nvar screenshotFail = configFile.screenshotOnFailure;\nvar username = configFile.username;\nvar password = configFile.password;\nvar email_user = configFile.emailUser;\nvar email_domain = configFile.emailDomain;\nvar lat = configFile.latitude;\nvar lon = configFile.longitude;\nvar country = configFile.country;\nvar useAutoCatcha = configFile.useAutoCatcha;\nvar captchaApiKey = configFile.captchaApiKey;\nvar debug = configFile.debug;\n// End Config File Imports\n\nif (useAutoCatcha)\n    showWindow = false;\n\n// argv parse\nvar argv = require('minimist')(process.argv.slice(2));\nif (argv['h']) {\n    console.log(\"usage: index.js [-h] [-u USERNAME] [-s START] [-e END]\");\n    console.log(\"\");\n    console.log(\"An automation script based on Nightmare.js.\");\n    console.log(\"Can create any number of Nintendo Pokémon Trainer Club accounts,\");\n    console.log(\"with a single e-mail address.\");\n    console.log(\"\");\n    console.log(\"optional arguments:\");\n    console.log(\"\t-u\tThe username used.\");\n    console.log(\"\t-s\tStarting number.\");\n    console.log(\"\t-e\tEnding number.\");\n    process.exit();\n}\nif (argv['u']) {\n    username = argv['u'];\n}\nif (argv['s']) {\n    start = argv['s'];\n}\nif (argv['e']) {\n    end = argv['e'];\n}\n\nvar outputFile = \"PogoPlayer/accounts.csv\"; // File which will contain the generated \"username password\" combinations.\nvar outputFormat = \"ptc,%NICK%,%PASS%,%LAT%,%LON%,%UN%\\r\\n\"; // Format used to save the account data in outputFile. Supports %NICK%, %PASS%.\nvar screenshotFolder = \"output/screenshots/\";\n\n// App data\nvar url_ptc = \"https://club.pokemon.com/us/pokemon-trainer-club/sign-up/\";\nvar useragent = \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36\";\nvar symbols = [\"#\", \"?\", \"!\", \"@\", \"$\", \"%\", \"^\", \"&\", \">\", \"<\", \"+\", \"`\", \"*\", \"(\", \")\", \"-\", \"[\", \"]\"];\nvar nightmare_opts = {\n    show: showWindow,\n    waitTimeout: 10000,\n    gotoTimeout: 5000,\n    loadTimeout: 5000\n};\n// Prints nice little message\nconsole.log(\"ptc-acc-gen v2.8.0 by Sébastien Vercammen and Frost The Fox (and Github contribs)\");\n\n\n// Settings check\nif (!useNicknamesFile && (username + end).length > 16) {\n    console.log(\"Error: length of username + number can't be longer than 16 characters.\");\n    console.log(\"Please use a shorter nickname.\");\n    process.exit();\n}\n\nif ((email_user + '+' + username + end + '@' + email_domain).length > 75) {\n    console.log(\"Error: length of e-mail address including the + trick can't be longer than 75 characters.\");\n    console.log(\"Please use a shorter e-mail address and/or nickname.\");\n    process.exit();\n}\n\nif (!useRandomPassword && (password.length > 15 || !containsSymbol(password) || !containsUppercase(password))) {\n    console.log(\"Error: length of password can't be longer than 15 characters, requires a symbol and uppercase characters.\");\n    process.exit();\n}\n\n// LETSAHGO\nvar nightmare = Nightmare(nightmare_opts);\nnightmare.useragent(useragent);\n\ncreateAccount(start);\n\n// Helpers\n\nfunction containsUppercase(txt) {\n    return txt.toLowerCase() !== txt;\n}\n\nfunction containsSymbol(txt) {\n    return symbols.some(function(s) {\n        return txt.indexOf(s) > -1;\n    });\n}\n\nfunction handleError(err) {\n    if (debug) {\n        console.log(\"[DEBUG] Error:\" + JSON.stringify(err));\n    }\n\n    return err;\n}\n\nfunction getRandomInt(min, max) {\n    return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\nfunction getRandomNumbers(length) {\n    return Math.random().toString().substr(2, length);\n}\n\nfunction getRandomSymbols(length) {\n    var str = \"\";\n\n    for (var i = 0; i < length; i++) {\n        str += symbols[getRandomInt(0, symbols.length - 1)];\n    }\n\n    return str;\n}\n\nfunction randomPassword() {\n    // Your password must include upper and lower case letters, numbers and symbols (such as #?!@$%%^&><+`*()-])\n    return (Math.random().toString(36) + '00000000000000000').slice(2, 8) + getRandomNumbers(3) + getRandomSymbols(3) + \"ABC\";\n}\n\nfunction prepareNightmare(nightmare) {\n    nightmare.useragent(useragent);\n}\n\n// Pages\nfunction createAccount(ctr) {\n    console.log(\"Creating account \" + ctr + \" of \" + end);\n\n    // Launch instance\n    handleFirstPage(ctr);\n}\n\n// First page\nfunction handleFirstPage(ctr) {\n    if (debug) {\n        console.log(\"[DEBUG] Handle first page #\" + ctr);\n    }\n\n    nightmare.goto(url_ptc)\n        .evaluate(evaluateDobPage)\n        .then(function(validated) {\n            if (!validated) {\n                // Missing form data, loop over itself\n                console.log(\"[\" + ctr + \"] Unable to evaluate PTC DOB signup page... Trying again.\");\n                return function() {\n                    nightmare.wait(500).refresh().wait();\n                    handleFirstPage(ctr);\n                };\n            } else {\n                return function() {\n                    fillFirstPage(ctr);\n                };\n            }\n        })\n        .then(function(next) {\n            // Handle next step: either a loop to first page in case of error, or form fill on success\n            return next();\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleFirstPage(ctr);\n            }\n        });\n}\n\nfunction fillFirstPage(ctr) {\n    if (debug) {\n        console.log(\"[DEBUG] Fill first page #\" + ctr);\n    }\n\n    nightmare.evaluate(function(data) {\n            var dob = new Date((new Date()).getTime() - (Math.random() * (new Date()).getTime()) - 18 * 365 * 24 * 60 * 60 * 1000);\n            document.getElementById(\"id_dob\").value = dob.getFullYear() + \"-\" + (dob.getMonth() + 1) + \"-\" + dob.getDate();\n\n            var els = document.getElementsByName(\"country\");\n            for (var i = 0; i < els.length; i++) {\n                els[i].value = data.country;\n            }\n\n            return document.getElementById(\"id_dob\").value;\n        }, {\n            country: country\n        })\n        .click(\"form[name='verify-age'] [type=submit]\")\n        .wait(\"#id_username\")\n        .then(function() {\n            handleSignupPage(ctr);\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleFirstPage(ctr);\n            }\n        });\n}\n\n// Signup page\nfunction handleSignupPage(ctr) {\n    if (debug) {\n        console.log(\"[DEBUG] Handle second page #\" + ctr);\n    }\n\n    nightmare.evaluate(evaluateSignupPage)\n        .then(function(validated) {\n            if (!validated) {\n                // Missing form data, loop over itself\n                console.log(\"[\" + ctr + \"] Unable to evaluate PTC signup page... Trying again.\");\n                return function() {\n                    nightmare.wait(500).refresh().wait();\n                    handleFirstPage(ctr);\n                };\n            } else {\n                return function() {\n                    fillSignupPage(ctr);\n                };\n            }\n        }).then(function(next) {\n            // Handle next step: either a loop to first page in case of error, or form fill on success\n            return next();\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleSignupPage(ctr);\n            }\n        });\n}\n\nfunction fillSignupPage(ctr) {\n    if (debug) {\n        console.log(\"[DEBUG] Fill signup page #\" + ctr);\n    }\n\n    var _pass = password;\n    var _nick = username + ctr;\n\n    if (useRandomPassword) {\n        _pass = randomPassword();\n    }\n\n    // Use nicknames list, or (username + number) combo?\n    if (useNicknamesFile) {\n        // Make sure we have a nickname left\n        if (nicknames.length < 1) {\n            throw Error(\"We're out of nicknames to use!\");\n        }\n\n        // Get the first nickname off the list & use it\n        _nick = nicknames.shift();\n        console.log(\"Using next account from nicknames file: \" + _nick);\n    }\n\n    // Fill it all in\n    if (useAutoCatcha) {\n        nightmare.evaluate(function(data) {\n                document.getElementById(\"id_password\").value = data.pass;\n                document.getElementById(\"id_confirm_password\").value = data.pass;\n                document.getElementById(\"id_email\").value = data.email_user === \"\" ? data.nick + \"@\" + data.email_domain : data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n                document.getElementById(\"id_confirm_email\").value = data.email_user === \"\" ? data.nick + \"@\" + data.email_domain : data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n                document.getElementById(\"id_screen_name\").value = data.nick;\n                document.getElementById(\"id_username\").value = data.nick;\n                window.scrollTo(0, document.body.scrollHeight);\n            }, {\n                \"pass\": _pass,\n                \"nick\": _nick,\n                \"email_user\": email_user,\n                \"email_domain\": email_domain\n            })\n            .check(\"#id_terms\");\n\n\n        nightmare.evaluate(function() {\n            return document.getElementsByClassName(\"g-recaptcha\")[0].getAttribute('data-sitekey');\n        }).then(function(result) {\n            console.log(\"Start recaptcha solving\");\n\n            request('http://2captcha.com/in.php?key=' + captchaApiKey + '&method=userrecaptcha&googlekey=' + result + '&pageurl=club.pokemon.com', function(error, response, body) {\n                if (error) throw error;\n                \n                console.log(\"Checking status of captcha id: \" + body.substring(3));\n\n                var checkCaptcha = function() {\n                    request('http://2captcha.com/res.php?key=' + captchaApiKey + '&action=get&id=' + body.substring(3), function(error, response, body) {\n                        if (error) throw error;\n\n                        if (body.substring(0, 2) == \"OK\") {\n                            var captchaValidation = body.substring(3);\n                            nightmare.evaluate(function(data) {\n                                    document.getElementById(\"g-recaptcha-response\").value = data.captchaValidation;\n                                }, {\n                                    captchaValidation: captchaValidation\n                                })\n                                .click('.button-green[value=\" Continue\"]')\n                                .then(function() {\n                                    nightmare.wait(function() {\n                                            return (document.getElementById(\"signup-signin\") !== null || document.getElementById(\"btn-reset\") !== null || document.body.textContent.indexOf(\"That username already exists\") > -1);\n                                        })\n                                        .evaluate(function() {\n                                            return (document.body.textContent.indexOf(\"Hello! Thank you for creating an account!\") > -1);\n                                        })\n                                        .then(function(success) {\n                                            if (success) {\n                                                // Log it in the file of used nicknames\n                                                var content = outputFormat.replace('%NICK%', _nick).replace('%PASS%', _pass).replace('%LAT%', lat).replace('%LON%', lon).replace('%UN%', _nick);\n                                                fs.appendFile(outputFile, content, function(err) {\n                                                    if (err) throw err;\n                                                });\n                                            } else {\n                                                console.log(\"[x] Failed username \" + _nick);\n                                            }\n\n                                            if ((success && screenshotResult) || screenshotFail) {\n                                                // Screenshot\n                                                nightmare.screenshot(screenshotFolder + _nick + \".png\");\n                                            }\n\n                                            // Next one, or stop\n                                            if (ctr < end) {\n                                                return function() {\n                                                    createAccount(ctr + 1);\n                                                };\n                                            } else {\n                                                return nightmare.end();\n                                            }\n                                        }).then(function(next) {\n                                            return next();\n                                        }).catch(handleError)\n                                        .then(function(err) {\n                                            if (typeof err !== \"undefined\") {\n                                                return handleSignupPage(ctr);\n                                            }\n                                        });\n                                });\n                        } else {\n                            // Not ready yet...\n                            setTimeout(checkCaptcha, 2000);\n                        }\n                    });\n                };\n                setTimeout(checkCaptcha, 2000);\n            });\n        });\n    } else {\n        nightmare.evaluate(function(data) {\n                document.getElementById(\"id_password\").value = data.pass;\n                document.getElementById(\"id_confirm_password\").value = data.pass;\n                document.getElementById(\"id_email\").value = data.email_user === \"\" ? data.nick + \"@\" + data.email_domain : data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n                document.getElementById(\"id_confirm_email\").value = data.email_user === \"\" ? data.nick + \"@\" + data.email_domain : data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n                document.getElementById(\"id_screen_name\").value = data.nick;\n                document.getElementById(\"id_username\").value = data.nick;\n                window.scrollTo(0, document.body.scrollHeight);\n            }, {\n                \"pass\": _pass,\n                \"nick\": _nick,\n                \"email_user\": email_user,\n                \"email_domain\": email_domain\n            })\n            .check(\"#id_terms\")\n            .wait(function() {\n                return (document.getElementById(\"signup-signin\") !== null || document.getElementById(\"btn-reset\") !== null || document.body.textContent.indexOf(\"That username already exists\") > -1);\n            })\n            .evaluate(function() {\n                return (document.body.textContent.indexOf(\"Hello! Thank you for creating an account!\") > -1);\n            })\n            .then(function(success) {\n                if (success) {\n                    // Log it in the file of used nicknames\n                    var content = outputFormat.replace('%NICK%', _nick).replace('%PASS%', _pass).replace('%LAT%', lat).replace('%LON%', lon).replace('%UN%', _nick);\n                    fs.appendFile(outputFile, content, function(err) {\n                        if (err) throw err;\n                    });\n                } else {\n                    console.log(\"[x] Failed username \" + _nick);\n                }\n\n                if ((success && screenshotResult) || screenshotFail) {\n                    // Screenshot\n                    nightmare.screenshot(screenshotFolder + _nick + \".png\");\n                }\n\n                // Next one, or stop\n                if (ctr < end) {\n                    return function() {\n                        createAccount(ctr + 1);\n                    };\n                } else {\n                    return nightmare.end();\n                }\n            }).then(function(next) {\n                return next();\n            }).catch(handleError)\n            .then(function(err) {\n                if (typeof err !== \"undefined\") {\n                    return handleSignupPage(ctr);\n                }\n            });\n    }\n}\n\n// Evaluations\nfunction evaluateDobPage() {\n    var dob_value = document.getElementById(\"id_dob\");\n    return ((document.title === \"The Official Pokémon Website | Pokemon.com\") && (dob_value !== null));\n}\n\nfunction evaluateSignupPage() {\n    var username_field = document.getElementById(\"id_username\");\n    return ((document.title === \"The Official Pokémon Website | Pokemon.com\") && (username_field !== null));\n}\n"
  },
  {
    "path": "index.js.original",
    "content": "// Requires\nvar Nightmare = require('nightmare');\nvar nicknames = require('./nicknames.json');\nvar fs = require('fs');\n\n// Settings\nvar debug = false;\nvar showWindow = true;\n\nvar start = START_NUM; // Start from x (NAMEx, EMAIL+x@domain.com)\nvar end = END_NUM;\n\nvar useNicknamesFile = false; // Use nicknames file, or just append numbers to username?\nvar useRandomPassword = false; // Generate a random password?\nvar screenshotResult = true; // Saves a screenshot per account creation if set to true\nvar screenshotOnFailure = true; // Saves a screenshot even if registration failed\n\nvar outputFile = \"PogoPlayer/accounts.csv\"; // File which will contain the generated \"username password\" combinations.\nvar outputFormat = \"ptc,%NICK%,%PASS%,%LAT%,%LON%,%UN%\\r\\n\"; // Format used to save the account data in outputFile. Supports %NICK%, %PASS%.\nvar screenshotFolder = \"output/screenshots/\";\n\nvar country = \"US\"; // Country code (e.g. BE, FR, US, CA)\nvar dob = \"1990-01-01\"; // Date of birth, yyyy-mm-dd\nvar username = \"USERNAME_PH\"; // User- & display name. Make sure any \"(username + number)@domain.com\" is 100% unique, and is 6 characters minimum, but under 14 characters after the numbers are applied.\nvar password = \"PASSWORD_PH\"; // Static password for all accounts. Ignored if useRandomPassword is true.\nvar email_user = \"EMAIL_PH\"; // If your email is email@domain.com, enter \"email\"\nvar email_domain = \"DOMAIN_PH\"; // Domain of e-mail host\nvar lat = \"LATITUDE_PH\" // Location Latitude for initial login\nvar lon = \"LONGITUDE_PH\" // Location Longitude for initial login\n\n// App data\nvar url_ptc = \"https://club.pokemon.com/us/pokemon-trainer-club/sign-up/\";\nvar useragent = \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36\";\nvar nightmare_opts = {\n    show: showWindow,\n    waitTimeout: 10000,\n    gotoTimeout: 5000,\n    loadTimeout: 5000\n};\n// Prints nice little message\nconsole.log(\"ptc-acc-gen v1.4.1 by Sébastien Vercammen and Frost The Fox (and Github contribs)\")\n\n\n// Settings check\nif (!useNicknamesFile && (username + end).length > 16) {\n    console.log(\"Error: length of username + number can't be longer than 16 characters.\");\n    console.log(\"Please use a shorter nickname.\");\n    process.exit();\n}\n\nif ((email_user + '+' + username + end + '@' + email_domain).length > 75) {\n    console.log(\"Error: length of e-mail address including the + trick can't be longer than 75 characters.\");\n    console.log(\"Please use a shorter e-mail address and/or nickname.\");\n    process.exit();\n}\n\nif (!useRandomPassword && password.length > 15) {\n    console.log(\"Error: length of password can't be longer than 15 characters.\");\n    console.log(\"Please use a shorter password.\");\n    process.exit();\n}\n\n// LETSAHGO\nvar nightmare = Nightmare(nightmare_opts);\nnightmare.useragent(useragent);\n\ncreateAccount(start);\n\n// Helpers\n\nfunction handleError(err) {\n    if(debug) {\n        console.log(\"[DEBUG] Error:\" + JSON.stringify(err));\n    }\n    \n    return err;\n}\n\nfunction randomPassword() {\n    return Math.random().toString(36).substr(2, 8);\n}\n\nfunction prepareNightmare(nightmare) {\n    nightmare.useragent(useragent);\n}\n\nfunction randomPassword() {\n    return Math.random().toString(36).substr(2, 8);\n}\n\n// Pages\nfunction createAccount(ctr) {\n    console.log(\"Creating account \" + ctr + \" of \" + end);\n    \n    // Launch instance\n    handleFirstPage(ctr);\n}\n\n// First page\nfunction handleFirstPage(ctr) {\n    if(debug) {\n        console.log(\"[DEBUG] Handle first page #\" + ctr);\n    }\n    \n    nightmare.goto(url_ptc)\n        .evaluate(evaluateDobPage)\n        .then(function(validated)  {\n            if(!validated) {\n                // Missing form data, loop over itself\n                console.log(\"[\" + ctr + \"] Servers are acting up... Trying again.\");\n                return function() { nightmare.wait(500).refresh().wait(); handleFirstPage(ctr); };\n            } else {\n                return function() { fillFirstPage(ctr); };\n            }\n        })\n        .then(function(next) {\n            // Handle next step: either a loop to first page in case of error, or form fill on success\n            return next();\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleFirstPage(ctr);\n            }\n        });\n}\n\nfunction fillFirstPage(ctr) {\n    if(debug) {\n        console.log(\"[DEBUG] Fill first page #\" + ctr);\n    }\n    \n    nightmare.evaluate(function(data) {\n            document.getElementById(\"id_dob\").value = data.dob;\n            \n            var els = document.getElementsByName(\"id_country\");\n            for(var i = 0; i < els.length; i++) {\n                els[i].value = data.country;\n            }\n            \n            return document.getElementById(\"id_dob\").value;\n        }, { dob: dob, country: country })\n        .click(\"form[name='verify-age'] [type=submit]\")\n        .wait(\"#id_username\")\n        .then(function() {\n            handleSignupPage(ctr);\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleFirstPage(ctr);\n            }\n        });\n}\n\n// Signup page\nfunction handleSignupPage(ctr) {\n    if(debug) {\n        console.log(\"[DEBUG] Handle second page #\" + ctr);\n    }\n    \n    nightmare.evaluate(evaluateSignupPage)\n        .then(function(validated) {\n            if(!validated) {\n                // Missing form data, loop over itself\n                console.log(\"[\" + ctr + \"] Servers are acting up... Trying again.\");\n                return function() { nightmare.wait(500).refresh().wait(); handleFirstPage(ctr); };\n            } else {\n                return function() { fillSignupPage(ctr); };\n            }\n        }).then(function(next) {\n            // Handle next step: either a loop to first page in case of error, or form fill on success\n            return next();\n        })\n        .catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleSignupPage(ctr);\n            }\n        });\n}\n\nfunction fillSignupPage(ctr) {\n    if(debug) {\n        console.log(\"[DEBUG] Fill signup page #\" + ctr);\n    }\n    \n    var _pass = password;\n    var _nick = username + ctr;\n    \n    if(useRandomPassword) {\n        _pass = randomPassword();\n    }\n    \n    // Use nicknames list, or (username + number) combo?\n    if(useNicknamesFile) {\n        // Make sure we have a nickname left\n        if(nicknames.length < 1) {\n            throw Error(\"We're out of nicknames to use!\");\n        }\n        \n        // Get the first nickname off the list & use it\n        _nick = nicknames.shift();\n    }\n    \n    // Fill it all in\n    nightmare.evaluate(function(data) {\n            document.getElementById(\"id_password\").value = data.pass;\n            document.getElementById(\"id_confirm_password\").value = data.pass;\n            document.getElementById(\"id_email\").value = data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n            document.getElementById(\"id_confirm_email\").value = data.email_user + \"+\" + data.nick + \"@\" + data.email_domain;\n            document.getElementById(\"id_screen_name\").value = data.nick;\n            document.getElementById(\"id_username\").value = data.nick;\n\t\twindow.scrollTo(0,document.body.scrollHeight);\n        }, { \"pass\": _pass, \"nick\": _nick, \"email_user\": email_user, \"email_domain\": email_domain })\n        .check(\"#id_terms\")\n        .wait(function() {\n            return (document.getElementById(\"signup-signin\") !== null || document.getElementById(\"btn-reset\") !== null || document.body.textContent.indexOf(\"That username already exists\") > -1);\n        })\n        .evaluate(function() {\n            return (document.body.textContent.indexOf(\"Hello! Thank you for creating an account!\") > -1);\n        })\n        .then(function(success) {\n            if(success) {\n                // Log it in the file of used nicknames\n                var content = outputFormat.replace('%NICK%', _nick).replace('%PASS%', _pass).replace('%LAT%', lat).replace('%LON%', lon).replace('%UN%', _nick);\n                fs.appendFile(outputFile, content, function(err) {\n                    //\n                });\n            }\n            \n            if((success && screenshotResult) || screenshotOnFailure) {\n                // Screenshot\n                nightmare.screenshot(screenshotFolder + _nick + \".png\");\n            }\n            \n            // Next one, or stop\n            if(ctr < end) {\n                return function() { createAccount(ctr + 1); };\n            } else {\n                return nightmare.end();\n            }\n        }).then(function(next) {\n            return next();\n        }).catch(handleError)\n        .then(function(err) {\n            if (typeof err !== \"undefined\") {\n                return handleSignupPage(ctr);\n            }\n        });\n}\n\n// Evaluations\nfunction evaluateDobPage() {\n    var dob_value = document.getElementById(\"id_dob\");\n    return ((document.title === \"The Official Pokémon Website | Pokemon.com\") && (dob_value !== null));\n}\n\nfunction evaluateSignupPage() {\n    var username_field = document.getElementById(\"id_username\");\n    return ((document.title === \"The Official Pokémon Website | Pokemon.com\") && (username_field !== null));\n}\n"
  },
  {
    "path": "install.bat",
    "content": "@echo off\ngit --version\nif not \"%errorlevel%\" == \"0\" (\n\techo git is currently not installed, or has not been added to your system PATH\n\techo please install git, or if git is already installed, run:\n\techo setx PATH \"%PATH%,C:\\Program Files\\Git\\mingw64\\libexec\\git-core\"\n\techo If using 32-bit or alternate install path, replace your git path in the above command\n\tpause\n) else (\n\techo attempting to clone PogoPlayer\n\tgit submodule init 2>&1 >NUL\n\tgit submodule update 2>&1 >NUL\n\tif not \"%errorlevel%\" == \"0\" (\n\t\techo submodule install failed.\n\t\techo Maybe try cloning recursively?\n\t\techo git clone --recursive https://github.com/sebastienvercammen/ptc-acc-gen.git\n\t) else (\n\t\tnode --version >NUL\n\t\tif \"%errorlevel%\" == \"9009\" (\n\t\t\techo NodeJS is not currently installed correctly. Please install that, then run \"npm install\" from your PokemonGo-Map folder.\n\t\t) else (\n\t\t\techo NodeJS installed, proceeding with installation\n\t\t\tnpm install\n\t\t)\n\t)\n)\npython config.py\npause\n"
  },
  {
    "path": "install.sh",
    "content": "#!/bin/bash\ncurl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -\nsudo apt-get install -y libnss3-dev libxss1 git\nwhich git 2>&1 >/dev/null\nif [ $? -ne 0 ] ; then\n        echo git is not currently installed\n        echo Please install git before proceeding\n\telse\n\t\tgit submodule init\n\t\tgit submodule update\n\tif [ $? -ne 0 ] ; then\n\t\t\techo submodule install failed.\n\t\t\techo Maybe try cloning recursively?\n\t\t\techo git clone --recursive https://github.com/sebastienvercammen/ptc-acc-gen.git\n\tfi\n\t\tsudo apt-get update 2> /dev/null\n\t\tsudo apt-get install -y nodejs nodejs-legacy\n\tif [ $? -ne 0 ] ; then\n\t\t\techo depenencies install failed. Please use the installer of your choice to grab them\n\t\t\techo examples:\n\t\t\techo apt-get install npm nodejs\n\t\t\techo yum install npm nodejs\n\t\telse\n\t\t\tsudo npm install\n\tfi\nfi\npython config.py\n"
  },
  {
    "path": "makeaccounts.bat",
    "content": "@echo off\nnode index.js\ncd PogoPlayer\nnode pogo.js\necho \"Find the generated accounts in PogoPlayer/accounts.csv\"\npause\n"
  },
  {
    "path": "makeaccounts.sh",
    "content": "#!/bin/bash\n# fuck headless systems, we got a captcha now\nnode index.js\ncd PogoPlayer\nnode pogo.js\necho \"Find the generated accounts in PogoPlayer/accounts.csv\"\n"
  },
  {
    "path": "nicknames.json",
    "content": "[\n    \"uniqueuser159\",\n    \"betteruser933\"\n]"
  },
  {
    "path": "output/screenshots/.gitkeep",
    "content": "\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"nintendo-ptc-account-generator\",\n  \"version\": \"2.8.0\",\n  \"description\": \"An automation script based on NodeJS that can create any number of Nintendo Pokémon Trainer Club (PTC) accounts with a single e-mail address.\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"jshint index.js config.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/sebastienvercammen/ptc-acc-gen.git\"\n  },\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"nintendo\",\n    \"ptc\",\n    \"pokemon\",\n    \"pokemongo\",\n    \"accounts\",\n    \"generator\"\n  ],\n  \"author\": \"Frost The Fox, originally Sébastien Vercammen\",\n  \"dependencies\": {\n    \"minimist\": \"^1.2.0\",\n    \"nightmare\": \"^2.6.0\",\n    \"pogobuf\": \"^1.8.0\",\n    \"request\": \"^2.79.0\"\n  }\n}\n"
  }
]