From e7e9a20993831a25e78c8b7ac117b8b16d8ac44e Mon Sep 17 00:00:00 2001 From: BlackSnowDot <95581741+BlackSnowDot@users.noreply.github.com> Date: Tue, 27 Sep 2022 20:33:07 -0700 Subject: [PATCH] __commit__ First Commit of OutlookGen --- README.md | 111 +++++++++++++++++++ Utils.py | 56 ++++++++++ account.txt | 14 +++ anycaptcha.py | 271 +++++++++++++++++++++++++++++++++++++++++++++++ config.json | 33 ++++++ main.py | 232 ++++++++++++++++++++++++++++++++++++++++ proxy.txt | 0 requirements.txt | 8 ++ 8 files changed, 725 insertions(+) create mode 100644 README.md create mode 100644 Utils.py create mode 100644 account.txt create mode 100644 anycaptcha.py create mode 100644 config.json create mode 100644 main.py create mode 100644 proxy.txt create mode 100644 requirements.txt diff --git a/README.md b/README.md new file mode 100644 index 0000000..47bf881 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +

outlook

+
+

Outlook Generator

+

Dont Skid 👀

+
+
(Programming Language - Python 3)
+

+OutlookGen forks +Repo stars +OutlookGen License +issues +

View

+ +--- + +

outlook

+ +## 📝 Document + +**Install Requirements** + +``` +pip3 install -r requirements.txt +``` + +**Install Chrome Driver** + +##### Windows + +###### Alos You Can Watch [This Video](https://youtube.com) + +- Go [Here](https://chromedriver.chromium.org/downloads) And Download chromedriver Windows Version +- Put chromedriver.exe into Script folder + +##### Linux + +*Run This Command* + +```shell script +sudo apt install chromium-chromedriver +``` + +- Go [Here](https://chromedriver.chromium.org/downloads) And Download chromedriver Linux Version +- Put chromedriver into Script folder + +--- + +## ⚙️ Config Document + +| Name | Descripton | +| ------------- | ------------- | +| Prefix | Log Prefix (Default: &beGen&5>> ) | +| ProxyFile | proxy file path (Default: proxy.txt) | +| OutputFile | output file path (Default: account.txt) | +| Timer | Generate Timer (Default: true) | +| driverPath | path of chromedriver (Default: ./chromedriver) | +| providers | Captcha Providers (Default: anycaptcha/twocaptcha) | +| api_key | Your Api Key (Default: ) | +| site_key | outlook site key (Default: B7D8911C-5CC8-A9A3-35B0-554ACEE604DA) | +| Domain | Email Domain (Default: @hotmail.com/@outlook.com) | +| minBirthDate | Minimum BirthDate (Default: 1980) | +| maxBirthDate | Maximum BirthDate (Default: 1999) | +| PasswordLength | Password Length (Default: 10) | +| FirstNameLength | First Name Length (Default: 5) | +| LastNameLength | Last Name Length (Default: 5) | +| DriverArguments | driver argument list (Default: ...) | + +#### Change this configs + +- driverPath +- providers +- api_key +- Domain + +**`config.json` Example** + +```json +{ + "Common": { + "Prefix": "&beGen&5>> ", + "ProxyFile": "proxy.txt", + "OutputFile": "account.txt", + "Timer": true, + "driverPath": "./chromedriver" + }, + "Captcha": { + "providers": "anycaptcha", + "api_key": "0dv3a5b276b347bxxxx12a6x8a9m862", + "site_key": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA" + }, + "EmailInfo": { + "Domain": "@outlook.com", + "minBirthDate": 1980, + "maxBirthDate": 1999, + "PasswordLength": 10, + "FirstNameLength": 5, + "LastNameLength": 5 + }, + "DriverArguments": [ + "--disable-logging", + "--disable-login-animations", + "--disable-notifications", + "--incognito", + "--ignore-certificate-errors", + "--disable-blink-features=AutomationControlled", + "--disable-gpu", + "--headless", + "--no-sandbox" + ] +} +``` diff --git a/Utils.py b/Utils.py new file mode 100644 index 0000000..eec298f --- /dev/null +++ b/Utils.py @@ -0,0 +1,56 @@ +import time +from contextlib import suppress +from random import choice, randint +from uuid import uuid4 + +from unique_names_generator import get_random_name +from unique_names_generator.data import ADJECTIVES, ANIMALS, COLORS, COUNTRIES, LANGUAGES, NAMES, STAR_WARS + + +class Utils: + @staticmethod + def replace(text: str, new: dict) -> str: + for old, new in new.items(): + text = text.replace(old, new) + return text + + @staticmethod + def makeString(string_length=8): + while True: + rnd = str(uuid4()) + rnd = rnd.upper() + rnd = rnd.replace("-", "") + if not rnd[0:string_length][:1].isdigit(): + return rnd[0:string_length] + + @staticmethod + def logger(email: str, password: str): + open('accounts.txt', 'a+').write(f'{email}:{password}\n') + + def eGen(self): + while True: + try: + return self.randomize(get_random_name( + combo=[NAMES, choice([ADJECTIVES, ANIMALS, COLORS, COUNTRIES, LANGUAGES, NAMES, STAR_WARS])], + separator="").replace(" ", "") + (str(randint(0, 999)) if randint(0, 1) else "")) + except: + continue + + def randomize(self, string: str): + return string.replace(string[randint(0, len(string))], self.makeString(1)) + + +class Timer: + def __init__(self): + self.start_time = float + self.now = float + + def start(self, t: time.time()): + self.start_time = t + + def reset(self, t: time.time()): + self.start_time = t + + def timer(self, t: time.time()): + self.now = t - self.start_time + return self.now diff --git a/account.txt b/account.txt new file mode 100644 index 0000000..a0e546c --- /dev/null +++ b/account.txt @@ -0,0 +1,14 @@ +BlythDPDria@hotmail.com:AD957250E3 +BinnieJocastanu98B@hotmail.com:F2F78569EC +HarmBnieQui-gBnjinn@hotmail.com:B02BB31DC5 +JuietaJellyfishD84@hotmail.com:B16645A016 +RBbinetNiennunb297@hotmail.com:EDA119E63D +BabitaSaraiFi866@hotmail.com:C99AADDD7F +DiRebeDa648@hotmail.com:A55A10F780 +EdelineSenegal4A0@hotmail.com:BF5A32609D +WenonCBermudC621@hotmail.com:C8A068A6F2 +DorellDKi-Ddi-mundi@hotmail.com:E65D3A3D12 +LynnellPersiEn986@hotmail.com:C322E914E8 +BariskaNormal@hotmail.com:EB8DC8FE8B +ShDDrDDTan473@hotmail.com:A3863870DB +DaElleenJade@hotmail.com:E61BCD6A75 diff --git a/anycaptcha.py b/anycaptcha.py new file mode 100644 index 0000000..0c5f37f --- /dev/null +++ b/anycaptcha.py @@ -0,0 +1,271 @@ +import warnings +from json import loads + +from six import PY3 +from six.moves.urllib_parse import urljoin +from requests import Session +import time + +SLEEP_EVERY_CHECK_FINISHED = 3 +MAXIMUM_JOIN_TIME = 200 + +if PY3: + + def split(value, sep, maxsplit): + return value.split(sep, maxsplit=maxsplit) + +else: + def split(value, sep, maxsplit): + parts = value.split(sep) + return parts[:maxsplit] + [sep.join(parts[maxsplit:]), ] + + +class Job(object): + client = None + task_id = None + _last_result = None + + def __init__(self, client, task_id, time_sleep=2, typecaptcha=None): + self.client = client + self.task_id = task_id + self.time_sleep = time_sleep + self.typecaptcha = typecaptcha + + def _update(self): + self._last_result = self.client.getTaskResult(self.task_id) + + def check_is_ready(self): + self._update() + if self._last_result['errorId'] != 0: + return 2 + if self._last_result["status"] == "ready": + return 1 + return 0 + + def get_solution_response(self): # Recaptcha + if self._last_result['errorId'] != 0: + return "ERROR|" + self._last_result['errorDescription'] + + if self.typecaptcha == "funcaptcha": + return self._last_result["solution"]["token"] + if self.typecaptcha == "text": + return self._last_result["solution"]["text"] + return self._last_result["solution"]["gRecaptchaResponse"] + + def get_token_response(self): # Funcaptcha + return self._last_result["solution"]["token"] + + def get_answers(self): + return self._last_result["solution"]["answers"] + + def get_captcha_text(self): # Image + return self._last_result["solution"]["text"] + + def get_cells_numbers(self): + return self._last_result["solution"]["cellNumbers"] + + def report_incorrect(self): + warnings.warn( + "report_incorrect is deprecated, use report_incorrect_image instead", + DeprecationWarning, + ) + return self.client.reportIncorrectImage() + + def report_incorrect_image(self): + return self.client.reportIncorrectImage(self.task_id) + + def report_incorrect_recaptcha(self): + return self.client.reportIncorrectRecaptcha(self.task_id) + + def join(self, maximum_time=200): + elapsed_time = 0 + maximum_time = maximum_time or MAXIMUM_JOIN_TIME + + while True: + time.sleep(self.time_sleep) + sts = self.check_is_ready() + + if sts == 0: + continue + elif sts == 1: + return + else: + return "ERROR" + + elapsed_time += SLEEP_EVERY_CHECK_FINISHED + if elapsed_time is not None and elapsed_time > maximum_time: + return "ERROR|TIMEOUT" + + while not self.check_is_ready(): + time.sleep(self.time_sleep) + elapsed_time += SLEEP_EVERY_CHECK_FINISHED + if elapsed_time is not None and elapsed_time > maximum_time: + return "ERROR|TIMEOUT" + + +class AnycaptchaClient(object): + client_key = None + CREATE_TASK_URL = "/createTask" + TASK_RESULT_URL = "/getTaskResult" + BALANCE_URL = "/getBalance" + REPORT_IMAGE_URL = "/reportIncorrectImageCaptcha" + REPORT_RECAPTCHA_URL = "/reportIncorrectRecaptcha" + APP_STAT_URL = "/getAppStats" + SOFT_ID = 847 + language_pool = "en" + response_timeout = 5 + + def __init__( + self, client_key, language_pool="en", host="api.anycaptcha.com", use_ssl=True + ): + self._client_ip = None + self.client_key = client_key + self.language_pool = language_pool + self.base_url = "{proto}://{host}/".format( + proto="https" if use_ssl else "http", host=host + ) + self.session = Session() + + @property + def client_ip(self): + if not hasattr(self, "_client_ip"): + self._client_ip = self.session.get( + "https://api.myip.com", timeout=self.response_timeout + ).json()["ip"] + return self._client_ip + + def _check_response(self, response): + pass + + def createTask(self, task, typecaptcha=None): + + request = { + "clientKey": self.client_key, + "task": task.serialize(), + "softId": self.SOFT_ID, + "languagePool": self.language_pool, + } + response = self.session.post( + urljoin(self.base_url, self.CREATE_TASK_URL), + json=request, + timeout=self.response_timeout, + ).json() + + self._check_response(response) + + return Job(self, response["taskId"], time_sleep=task.time_sleep, typecaptcha=typecaptcha) + + def createTaskSmee(self, task, timeout=MAXIMUM_JOIN_TIME): + """ + Beta method to stream response from smee.io + """ + response = self.session.head( + "https://smee.io/new", timeout=self.response_timeout + ) + smee_url = response.headers["Location"] + task = task.serialize() + request = { + "clientKey": self.client_key, + "task": task, + "softId": self.SOFT_ID, + "languagePool": self.language_pool, + "callbackUrl": smee_url, + } + r = self.session.get( + url=smee_url, + headers={"Accept": "text/event-stream"}, + stream=True, + timeout=(self.response_timeout, timeout), + ) + response = self.session.post( + url=urljoin(self.base_url, self.CREATE_TASK_URL), + json=request, + timeout=self.response_timeout, + ).json() + self._check_response(response) + for line in r.iter_lines(): + content = line.decode("utf-8") + if '"host":"smee.io"' not in content: + continue + payload = loads(split(content, ":", 1)[1].strip()) + if "taskId" not in payload["body"] or str(payload["body"]["taskId"]) != str( + response["taskId"] + ): + continue + r.close() + if task["type"] == "CustomCaptchaTask": + payload["body"]["solution"] = payload["body"]["data"][0] + job = Job(client=self, task_id=response["taskId"]) + job._last_result = payload["body"] + return job + + def getTaskResult(self, task_id): + request = {"clientKey": self.client_key, "taskId": task_id} + response = self.session.post( + urljoin(self.base_url, self.TASK_RESULT_URL), json=request + ).json() + self._check_response(response) + return response + + def getBalance(self): + request = { + "clientKey": self.client_key, + "softId": self.SOFT_ID, + } + response = self.session.post( + urljoin(self.base_url, self.BALANCE_URL), json=request + ).json() + self._check_response(response) + return response["balance"] + + def getAppStats(self, soft_id, mode): + request = {"clientKey": self.client_key, "softId": soft_id, "mode": mode} + response = self.session.post( + urljoin(self.base_url, self.APP_STAT_URL), json=request + ).json() + self._check_response(response) + return response + + def reportIncorrectImage(self, task_id): + request = {"clientKey": self.client_key, "taskId": task_id} + response = self.session.post( + urljoin(self.base_url, self.REPORT_IMAGE_URL), json=request + ).json() + self._check_response(response) + return response.get("status", False) != False + + def reportIncorrectRecaptcha(self, task_id): + request = {"clientKey": self.client_key, "taskId": task_id} + response = self.session.post( + urljoin(self.base_url, self.REPORT_RECAPTCHA_URL), json=request + ).json() + self._check_response(response) + return response["status"] == "success" + + +class BaseTask(object): + def serialize(self, **result): + return result + + +class FunCaptchaProxylessTask(BaseTask): + type = "FunCaptchaTaskProxyless" + websiteURL = None + websiteKey = None + time_sleep = 0.1 + + def __init__(self, website_url, website_key, *args, **kwargs): + self.websiteURL = website_url + self.websiteKey = website_key + super(FunCaptchaProxylessTask, self).__init__(*args, **kwargs) + + def serialize(self, **result): + result = super(FunCaptchaProxylessTask, self).serialize(**result) + result.update( + { + "type": self.type, + "websiteURL": self.websiteURL, + "websitePublicKey": self.websiteKey, + } + ) + return result diff --git a/config.json b/config.json new file mode 100644 index 0000000..09661cc --- /dev/null +++ b/config.json @@ -0,0 +1,33 @@ +{ + "Common": { + "Prefix": "&beGen&5>> ", + "ProxyFile": "proxy.txt", + "OutputFile": "account.txt", + "Timer": true, + "driverPath": "./chromedriver" + }, + "Captcha": { + "providers": "anycaptcha/twocaptcha", + "api_key": "", + "site_key": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA" + }, + "EmailInfo": { + "Domain": "@hotmail.com/@outlook.com", + "minBirthDate": 1980, + "maxBirthDate": 1999, + "PasswordLength": 10, + "FirstNameLength": 5, + "LastNameLength": 5 + }, + "DriverArguments": [ + "--disable-logging", + "--disable-login-animations", + "--disable-notifications", + "--incognito", + "--ignore-certificate-errors", + "--disable-blink-features=AutomationControlled", + "--disable-gpu", + "--headless", + "--no-sandbox" + ] +} \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..4db8003 --- /dev/null +++ b/main.py @@ -0,0 +1,232 @@ +import sys +import time +from contextlib import suppress +from json import load +from random import randint, choice +from typing import Any + +from PyTerm import Console +from colorama import Fore +from selenium import webdriver +from selenium.webdriver import Proxy +from selenium.webdriver.chrome.service import Service +from selenium.webdriver.chrome.webdriver import WebDriver +from selenium.webdriver.common.by import By +from selenium.webdriver.common.proxy import ProxyType +from selenium.webdriver.support.select import Select +from twocaptcha import TwoCaptcha +import anycaptcha +from Utils import Utils, Timer +from tqdm import tqdm + +# Some Value +eGenerated = 0 +solvedCaptcha = 0 + + +class eGen: + def __init__(self): + Console.clear() + self.Utils = Utils() # Utils Module + self.config: Any = load(open('config.json')) # Config File + self.checkConfig() # Check Config File + self.options = webdriver.ChromeOptions() # Driver Options + self.Timer = Timer() # Timer + + self.colors = { + '&a': Fore.LIGHTGREEN_EX, + '&4': Fore.RED, + '&2': Fore.GREEN, + '&b': Fore.LIGHTCYAN_EX, + '&c': Fore.LIGHTRED_EX, + '&6': Fore.LIGHTYELLOW_EX, + '&f': Fore.RESET, + '&e': Fore.LIGHTYELLOW_EX, + '&3': Fore.CYAN, + '&1': Fore.BLUE, + '&9': Fore.LIGHTBLUE_EX, + '&5': Fore.MAGENTA, + '&d': Fore.LIGHTMAGENTA_EX, + '&8': Fore.LIGHTBLACK_EX, + '&0': Fore.BLACK} # Colors + + self.driver = None + self.capabilities = None + self.first_name = None # Generate First Name + self.last_name = None # Generate Last Name + self.password = None # Generate Password + self.email = self.Utils.eGen() # Generate Email + + # Values About Captcha + self.providers = self.config['Captcha']['providers'] + self.api_key = self.config["Captcha"]["api_key"] + self.site_key = self.config["Captcha"]["site_key"] + + # Other + self.service = Service(self.config['Common']['driverPath']) + self.proxies = [i.strip() for i in open(self.config['Common']['ProxyFile']).readlines()] # Get Proxies + for arg in tqdm(self.config["DriverArguments"], desc='Loading Arguments', + bar_format='{desc} | {l_bar}{bar:15} | {percentage:3.0f}%'): # Get Driver Arguments + self.options.add_argument(arg) # Add Argument to option + time.sleep(0.2) + + # More Options + self.options.add_experimental_option("excludeSwitches", ["enable-automation"]) + self.options.add_experimental_option('excludeSwitches', ['enable-logging']) + self.options.add_experimental_option('useAutomationExtension', False) + + @staticmethod + def create_proxy(proxy: str): + # Make Proxy Function + proxy_core = Proxy() + proxy_core.proxyType = ProxyType.MANUAL + proxy_core.httpProxy = proxy + proxy_core.sslProxy = proxy + return proxy_core + + def solver(self, site_url, browser): + # Solve Captcha Function + global solvedCaptcha + # TwoCaptcha + if self.providers == 'twocaptcha': + try: + return TwoCaptcha(self.api_key).funcaptcha(sitekey=self.site_key, url=site_url)['code'] + except Exception as exp: + self.print(exp) + + # AnyCaptcha + elif self.providers == 'anycaptcha': + client = anycaptcha.AnycaptchaClient(self.api_key) + task = anycaptcha.FunCaptchaProxylessTask(site_url, self.site_key) + job = client.createTask(task, typecaptcha="funcaptcha") + self.print("Solving funcaptcha") + job.join() + result = job.get_solution_response() + if result.find("ERROR") != -1: + self.print(result) + browser.quit() + else: + solvedCaptcha += 1 + return result + + def fElement(self, driver: WebDriver, by: By = By.ID, value=None, delay: float = 0.3): + # Custom find Element Function + count = 0 + while count <= 100: + try: + return driver.find_element(by, value) + except: + time.sleep(delay) + count += 1 + self.print(f'tried 100 time to find element...') + driver.quit() + return + + def get_balance(self): + # Check provider Balance Function + if self.providers == 'twocaptcha': + return TwoCaptcha(self.api_key).balance() + elif self.providers == 'anycaptcha': + return anycaptcha.AnycaptchaClient(self.api_key).getBalance() + + def update(self): + # Update Title Function + global eGenerated, solvedCaptcha + Console.set_title( + f'Email Generated: {eGenerated} | Solved Captcha: {solvedCaptcha} | Balance: {self.get_balance()}') + + def generate_info(self): + # Generate Information Function + self.password = self.Utils.makeString(self.config["EmailInfo"]["PasswordLength"]) # Generate Password + self.first_name = self.Utils.makeString(self.config["EmailInfo"]["FirstNameLength"]) # Generate First Name + self.last_name = self.Utils.makeString(self.config["EmailInfo"]["LastNameLength"]) # Generate Last Name + + def checkConfig(self): + # Check Config Function + captcha_sec = self.config['Captcha'] + if captcha_sec['api_key'] == "" or captcha_sec['providers'] == "anycaptcha/twocaptcha" or \ + self.config['EmailInfo']['Domain'] == "@hotmail.com/@outlook.com": + self.print('Please Fix Config!') + sys.exit() + + def print(self, text: object, end: str = "\n"): + # Print With Prefix Function + print(self.Utils.replace(f"{self.config['Common']['Prefix']}&f{text}", self.colors), end=end) + + def CreateEmail(self, driver: WebDriver): + # Create Email Function + try: + global eGenerated, solvedCaptcha + self.update() + self.Timer.start(time.time()) if self.config["Common"]['Timer'] else '' + driver.get("https://outlook.live.com/owa/?nlp=1&signup=1") + assert 'Create' in driver.title + if self.config['EmailInfo']['Domain'] == "@hotmail.com": + domain = self.fElement(driver, By.ID, 'LiveDomainBoxList') + time.sleep(0.1) + domainObject = Select(domain) + domainObject.select_by_value('hotmail.com') + emailInput = self.fElement(driver, By.ID, 'MemberName') + emailInput.send_keys(self.email) + self.print(f"email: {self.email}{self.config['EmailInfo']['Domain']}") + self.fElement(driver, By.ID, 'iSignupAction').click() + with suppress(Exception): + self.print(driver.find_element(By.ID, 'MemberNameError').text) + self.print("email is already taken") + driver.quit() + return + passwordinput = self.fElement(driver, By.ID, 'PasswordInput') + passwordinput.send_keys(self.password) + self.print("Password: %s" % self.password) + self.fElement(driver, By.ID, 'iSignupAction').click() + first = self.fElement(driver, By.ID, "FirstName") + first.send_keys(self.first_name) + last = self.fElement(driver, By.ID, "LastName") + last.send_keys(self.last_name) + self.fElement(driver, By.ID, 'iSignupAction').click() + dropdown = self.fElement(driver, By.ID, "Country") + dropdown.find_element(By.XPATH, "//option[. = 'Turkey']").click() + birthMonth = self.fElement(driver, By.ID, "BirthMonth") + objectMonth = Select(birthMonth) + objectMonth.select_by_value(str(randint(1, 12))) + birthMonth = self.fElement(driver, By.ID, "BirthDay") + objectMonth = Select(birthMonth) + objectMonth.select_by_value(str(randint(1, 28))) + birthYear = self.fElement(driver, By.ID, "BirthYear") + birthYear.send_keys(str(randint(1980, 1999))) + self.fElement(driver, By.ID, 'iSignupAction').click() + driver.switch_to.frame(self.fElement(driver, By.ID, 'enforcementFrame')) + token = self.solver(driver.current_url, self.driver) + time.sleep(0.5) + driver.execute_script( + 'parent.postMessage(JSON.stringify({eventId:"challenge-complete",payload:{sessionToken:"' + token + '"}}),"*")') + self.update() + self.fElement(driver, By.ID, 'idBtn_Back').click() + self.print(f'Email Created in {str(self.Timer.timer(time.time())).split(".")[0]}s') if \ + self.config["Common"]['Timer'] else self.print('Email Created') + eGenerated += 1 + self.Utils.logger(self.email + self.config['EmailInfo']['Domain'], self.password) + self.update() + driver.quit() + except KeyboardInterrupt: + driver.quit() + sys.exit() + except Exception as exp: + self.print(exp) + + def run(self): + # Run Script Function + Console.clear() + self.print('Coded with <3 by MatrixTeam') + while True: + self.generate_info() + proxy = choice(self.proxies) # Select Proxy + self.print(proxy) + self.capabilities = webdriver.DesiredCapabilities.CHROME # Driver Capabilities + self.create_proxy(proxy).add_to_capabilities(self.capabilities) + self.CreateEmail(driver=webdriver.Chrome(options=self.options, desired_capabilities=self.capabilities, + service=self.service)) + + +if __name__ == '__main__': + eGen().run() diff --git a/proxy.txt b/proxy.txt new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ebbe6b4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +git+https://github.com/Its-Vichy/PyTerm.git +selenium==4.4.3 +six~=1.16.0 +requests~=2.28.1 +unique-names-generator~=1.0.2 +colorama==0.4.5 +tqdm==4.64.1 +twocaptcha==0.0.1 \ No newline at end of file