Repository: GzGod/Dawn Branch: main Commit: 713a43396606 Files: 29 Total size: 60.7 KB Directory structure: gitextract_p0kopyhp/ ├── README.md ├── config/ │ ├── data/ │ │ ├── farm.txt │ │ ├── proxies.txt │ │ └── register.txt │ └── settings.yaml ├── console/ │ ├── __init__.py │ ├── logger.py │ └── main.py ├── core/ │ ├── api.py │ ├── bot.py │ ├── exceptions/ │ │ └── base.py │ └── solvers/ │ ├── __init__.py │ ├── anti_captcha.py │ └── two_captcha.py ├── database/ │ ├── __init__.py │ ├── models/ │ │ ├── __init__.py │ │ └── accounts.py │ └── settings.py ├── loader.py ├── models/ │ ├── __init__.py │ ├── bot.py │ └── config.py ├── requirements.txt ├── run.py └── utils/ ├── __init__.py ├── console.py ├── file_utils.py ├── imap_utils.py └── load_config.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # Dawn Extension Bot [1.5] # 原作者https://github.com/Jaammerr/The-Dawn-Bot 防止正义人士
Dawn Extension Bot Console
**我的推特: [@Hy78516012,如果觉得有用请给我点个关注吧)** --- ## 🚀 功能 - ✅ 自动账户注册和登录 - 📧 自动账户重新验证 - 🌾 自动完成所有任务 - 💰 自动获取积分 - 📊 导出账户统计数据 - 🔄 保持会话功能 - 🧩 高级跳码 --- ## 💻 环境及需要的账户 - Python >= 3.11 - 安装Python虚拟环境 - 能注册DAWN的邮箱号 - 代理IP(可选) --- ## 🛠️ 设置 1. 克隆仓库: ```bash git clone https://github.com/GzGod/Dawn ``` 2. 创建并激活虚拟环境: ```bash Windows系统: python -m venv venv cd venv/Scripts activate Linux(服务器): python3 -m venv venv cd venv/bin source activate cd ../.. ``` 3. 安装依赖: ```bash pip install -r requirements.txt ``` --- ## ⚙️ 配置 ### settings.yaml 该文件包含机器人的常规设置: ```yaml threads: 5 # 同时进行账户操作的线程数 keepalive_interval: 120 # 保持会话请求之间的延迟(秒) referral_code: "YOUR_REFERRAL_CODE" # 注册推荐码 captcha_service: "2captcha" # 验证码解决服务(2captcha或anticaptcha都可以) two_captcha_api_key: "YOUR_2CAPTCHA_API_KEY" anti_captcha_api_key: "YOUR_ANTICAPTCHA_API_KEY" imap_settings: # 电子邮件提供商的IMAP设置 gmail.com: imap.gmail.com outlook.com: imap-mail.outlook.com # 根据需要添加更多电子邮件提供商 ``` ### 其他配置文件 #### 📁 register.txt 包含注册账户信息。注意 这里的邮箱的password需要的是imap授权码,小白不建议用这种 老老实实注册然后填在farm.txt即可 ``` 格式: email:password email:password ... ``` #### 📁 farm.txt 包含用于获取积分和完成任务的账户信息。 ``` 格式: email:password email:password ... ``` #### 📁 proxies.txt 包含代理信息。 ``` 格式: http://user:pass@ip:port http://ip:port:user:pass http://ip:port@user:pass http://user:pass:ip:port ... ``` --- ## 🚀 使用 1. 确保所有配置文件已正确设置。 2. 运行机器人: ```bash python run.py ``` --- ## ⚠️ 重要提示 - 建议的保持会话请求之间的延迟为120秒。 - 如果有未验证的账户,可以再次使用`register`模块重新验证。 - 由于验证码复杂性的变化,现在使用外部服务(2captcha,anti-captcha)来解决验证码。 - 使用数据库来优化登录过程,通过存储授权令牌。 - 对于像Gmail这样的电子邮件服务,可能需要使用应用程序专用密码而不是常规电子邮件密码。 --- ## 🔧 问题排查 - **Email Verification Issues**:检查`settings.yaml`中的电子邮件提供商IMAP设置。 - **Captcha Problems**:验证您的验证码服务API密钥和账户余额。 - **Proxy Issues**:确保您的代理格式正确且代理功能正常。 --- ================================================ FILE: config/data/farm.txt ================================================ test@gmail.com:password ================================================ FILE: config/data/proxies.txt ================================================ http://proxy ================================================ FILE: config/data/register.txt ================================================ test@gmail.com:password ================================================ FILE: config/settings.yaml ================================================ # Application Configuration File # ============================= # Core Settings # ------------ threads: 10 # Number of concurrent threads to run (minimum: 1) keepalive_interval: 120 # How often to send keepalive signal (in seconds) referral_code: "hegbhf" # Your referral code for the application # Captcha Settings # --------------- captcha_module: 2captcha # Captcha service to use: '2captcha' or 'anticaptcha' two_captcha_api_key: "" # API key for 2captcha service anti_captcha_api_key: "" # API key for anti-captcha service # Startup Delay Configuration # ------------------------- delay_before_start: min: 2 # Minimum delay before starting (seconds) max: 3 # Maximum delay before starting (seconds) # Email Provider IMAP Settings # -------------------------- imap_settings: # Common email providers and their IMAP servers gmail.com: imap.gmail.com # Google Mail yahoo.com: imap.mail.yahoo.com # Yahoo Mail outlook.com: imap-mail.outlook.com # Microsoft Outlook hotmail.com: imap-mail.outlook.com # Microsoft Hotmail mail.ru: imap.mail.ru # Mail.ru rambler.ru: imap.rambler.ru # Rambler gmx.com: imap.gmx.com # GMX Mail gmx.net: imap.gmx.net # GMX Germany gmx.de: imap.gmx.net # GMX Germany (alternate domain) ================================================ FILE: console/__init__.py ================================================ from .main import Console ================================================ FILE: console/logger.py ================================================ from colorama import Fore def error_log(message: str): print(Fore.RED + ">> ERROR |" + Fore.LIGHTBLACK_EX + f" {message}") def success_log(message: str): print(Fore.GREEN + ">> SUCCESS |" + Fore.LIGHTBLACK_EX + f" {message}") def info_log(message: str): print(Fore.LIGHTBLACK_EX + f">> INFO | {message}") ================================================ FILE: console/main.py ================================================ import os import sys import inquirer from inquirer.themes import GreenPassion from art import text2art from colorama import Fore from loader import config from rich.console import Console as RichConsole from rich.panel import Panel from rich.table import Table from rich import box from rich.text import Text sys.path.append(os.path.realpath(".")) class Console: MODULES = ( "Register", "Farm", "Complete tasks", "Export statistics", "Exit", ) MODULES_DATA = { "Register": "register", "Farm": "farm", "Exit": "exit", "Export statistics": "export_stats", "Complete tasks": "complete_tasks", } def __init__(self): self.rich_console = RichConsole() def show_dev_info(self): os.system("cls" if os.name == "nt" else "clear") title = text2art("JamBit", font="small") styled_title = Text(title, style="bold cyan") version = Text("VERSION: 1.5", style="blue") telegram = Text("我的推特主页: https://x.com/Hy78516012", style="green") github = Text("我的GitHub: https://github.com/Gzgod", style="green") dev_panel = Panel( Text.assemble(styled_title, "\n", version, "\n", telegram, "\n", github), border_style="yellow", expand=False, title="[bold green]Welcome[/bold green]", subtitle="[italic]Powered by Jammer[/italic]", ) self.rich_console.print(dev_panel) print() @staticmethod def prompt(data: list): answers = inquirer.prompt(data, theme=GreenPassion()) return answers def get_module(self): questions = [ inquirer.List( "module", message=Fore.LIGHTBLACK_EX + "Select the module", choices=self.MODULES, ), ] answers = self.prompt(questions) return answers.get("module") def display_info(self): table = Table(title="Dawn Configuration", box=box.ROUNDED) table.add_column("Parameter", style="cyan") table.add_column("Value", style="magenta") table.add_row("Accounts to register", str(len(config.accounts_to_register))) table.add_row("Accounts to farm", str(len(config.accounts_to_farm))) table.add_row("Threads", str(config.threads)) table.add_row( "Delay before start", f"{config.delay_before_start.min} - {config.delay_before_start.max} sec", ) panel = Panel( table, expand=False, border_style="green", title="[bold yellow]System Information[/bold yellow]", subtitle="[italic]Use arrow keys to navigate[/italic]", ) self.rich_console.print(panel) def build(self) -> None: self.show_dev_info() self.display_info() module = self.get_module() config.module = self.MODULES_DATA[module] if config.module == "exit": exit(0) ================================================ FILE: core/api.py ================================================ import asyncio import json import names from datetime import datetime, timezone from typing import Literal, Tuple, Any from curl_cffi.requests import AsyncSession from models import Account from .exceptions.base import APIError, SessionRateLimited, ServerError from loader import captcha_solver, config class DawnExtensionAPI: API_URL = "https://www.aeropres.in/chromeapi/dawn" def __init__(self, account: Account): self.account_data = account self.wallet_data: dict[str, Any] = {} self.session = self.setup_session() def setup_session(self) -> AsyncSession: session = AsyncSession(impersonate="chrome124", verify=False) session.timeout = 30 session.headers = { "accept": "*/*", "accept-language": "en-US,en;q=0.9", "origin": "chrome-extension://fpdkjdnhkakefebpekbdhillbhonfjjp", "priority": "u=1, i", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", } if self.account_data.proxy: session.proxies = { "http": self.account_data.proxy.as_url, "https": self.account_data.proxy.as_url, } return session async def clear_request(self, url: str): session = AsyncSession(impersonate="chrome124", verify=False, timeout=30) session.proxies = self.session.proxies response = await session.get(url) return response async def send_request( self, request_type: Literal["POST", "GET", "OPTIONS"] = "POST", method: str = None, json_data: dict = None, params: dict = None, url: str = None, headers: dict = None, cookies: dict = None, verify: bool = True, max_retries: int = 3, retry_delay: float = 3.0, ): def verify_response(response_data: dict | list) -> dict | list: if "status" in str(response_data): if isinstance(response_data, dict): if response_data.get("status") is False: raise APIError( f"API returned an error: {response_data}", response_data ) elif "success" in str(response_data): if isinstance(response_data, dict): if response_data.get("success") is False: raise APIError( f"API returned an error: {response_data}", response_data ) return response_data for attempt in range(max_retries): try: if request_type == "POST": if not url: response = await self.session.post( f"{self.API_URL}{method}", json=json_data, params=params, headers=headers if headers else self.session.headers, cookies=cookies, ) else: response = await self.session.post( url, json=json_data, params=params, headers=headers if headers else self.session.headers, cookies=cookies, ) elif request_type == "OPTIONS": response = await self.session.options( url, headers=headers if headers else self.session.headers, cookies=cookies, ) else: if not url: response = await self.session.get( f"{self.API_URL}{method}", params=params, headers=headers if headers else self.session.headers, cookies=cookies, ) else: response = await self.session.get( url, params=params, headers=headers if headers else self.session.headers, cookies=cookies, ) if verify: if response.status_code == 403: raise SessionRateLimited("Session is rate limited") if response.status_code in (500, 502, 503, 504): raise ServerError(f"Server error - {response.status_code}") try: return verify_response(response.json()) except json.JSONDecodeError: return response.text return response.text except ServerError as error: if attempt == max_retries - 1: raise error await asyncio.sleep(retry_delay) except APIError: raise except SessionRateLimited: raise except Exception as error: if attempt == max_retries - 1: raise ServerError( f"Failed to send request after {max_retries} attempts: {error}" ) await asyncio.sleep(retry_delay) raise ServerError(f"Failed to send request after {max_retries} attempts") @staticmethod async def solve_puzzle( image: str, ) -> Tuple[str | int, bool, str | int] | Tuple[str, bool] | Tuple[str, bool, str]: response = await captcha_solver.solve(image) return response @staticmethod async def report_invalid_puzzle(task_id: int | str) -> None: await captcha_solver.report_bad(task_id) async def get_puzzle_id(self) -> str: if "Berear" in self.session.headers: del self.session.headers["Berear"] self.session.cookies.clear() params = { 'appid': 'undefined', } response = await self.send_request( method="/v1/puzzle/get-puzzle", request_type="GET", params=params, ) return response["puzzle_id"] async def get_puzzle_image(self, puzzle_id: str) -> str: response = await self.send_request( method="/v1/puzzle/get-puzzle-image", request_type="GET", params={"puzzle_id": puzzle_id, "appid": "undefined"}, ) return response.get("imgBase64") async def register(self, puzzle_id: str, answer: str) -> dict: json_data = { "firstname": names.get_first_name(), "lastname": names.get_last_name(), "email": self.account_data.email, "mobile": "", "password": self.account_data.password, "country": "+91", "referralCode": config.referral_code, "puzzle_id": puzzle_id, "ans": answer, } return await self.send_request( method="/v1/puzzle/validate-register", json_data=json_data, ) async def keepalive(self) -> dict | str: headers = { "accept": "*/*", "accept-language": "en-US,en;q=0.9,ru;q=0.8", "authorization": f'Berear {self.session.headers["Berear"]}', "content-type": "application/json", "origin": "chrome-extension://fpdkjdnhkakefebpekbdhillbhonfjjp", "user-agent": self.session.headers["user-agent"], } json_data = { "username": self.account_data.email, "extensionid": "fpdkjdnhkakefebpekbdhillbhonfjjp", "numberoftabs": 0, "_v": "1.0.9", } params = { 'appid': 'undefined', } return await self.send_request( method="/v1/userreward/keepalive", json_data=json_data, verify=False, headers=headers, params=params, ) async def user_info(self) -> dict: headers = self.session.headers.copy() headers["authorization"] = f'Berear {self.session.headers["Berear"]}' headers["content-type"] = "application/json" del headers["Berear"] params = { 'appid': 'undefined', } response = await self.send_request( url="https://www.aeropres.in/api/atom/v1/userreferral/getpoint", request_type="GET", headers=headers, params=params, ) return response["data"] async def complete_tasks(self, tasks: list[str] = None, delay: int = 1) -> None: if not tasks: tasks = ["telegramid", "discordid", "twitter_x_id"] headers = self.session.headers.copy() headers["authorization"] = f'Brearer {self.session.headers["Berear"]}' headers["content-type"] = "application/json" del headers["Berear"] for task in tasks: json_data = { task: task, } await self.send_request( method="/v1/profile/update", json_data=json_data, headers=headers, ) await asyncio.sleep(delay) async def verify_session(self) -> tuple[bool, str]: try: await self.user_info() return True, "Session is valid" except ServerError: return True, "Server error" except APIError as error: return False, str(error) async def login(self, puzzle_id: str, answer: str): current_time = datetime.now(timezone.utc) formatted_datetime_str = ( current_time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" ) params = { 'appid': 'undefined', } json_data = { "username": self.account_data.email, "password": self.account_data.password, "logindata": { "_v": "1.0.9", "datetime": formatted_datetime_str, }, "puzzle_id": puzzle_id, "ans": answer, } response = await self.send_request( method="/v1/user/login/v2", json_data=json_data, params=params, ) berear = response.get("data", {}).get("token") if berear: self.wallet_data = response.get("data", {}).get("wallet") self.session.headers.update({"Berear": berear}) else: raise APIError(f"Failed to login: {response}") ================================================ FILE: core/bot.py ================================================ from datetime import datetime, timedelta from typing import Tuple, Any, Optional import pytz from loguru import logger from loader import config, file_operations from models import Account, OperationResult, StatisticData from .api import DawnExtensionAPI from utils import check_email_for_link, check_if_email_valid from database import Accounts from .exceptions.base import APIError, SessionRateLimited, CaptchaSolvingFailed class Bot(DawnExtensionAPI): def __init__(self, account: Account): super().__init__(account) async def get_captcha_data(self) -> Tuple[str, Any, Optional[Any]]: for _ in range(5): try: puzzle_id = await self.get_puzzle_id() image = await self.get_puzzle_image(puzzle_id) logger.info( f"Account: {self.account_data.email} | Got puzzle image, solving..." ) answer, solved, *rest = await self.solve_puzzle(image) if solved and len(answer) == 6: logger.success( f"Account: {self.account_data.email} | Puzzle solved: {answer}" ) return puzzle_id, answer, rest[0] if rest else None if len(answer) != 6 and rest: await self.report_invalid_puzzle(rest[0]) logger.error( f"Account: {self.account_data.email} | Failed to solve puzzle: Incorrect answer | Retrying..." ) except SessionRateLimited: raise except Exception as e: logger.error( f"Account: {self.account_data.email} | Error occurred while solving captcha: {str(e)} | Retrying..." ) raise CaptchaSolvingFailed("Failed to solve captcha after 5 attempts") async def clear_account_and_session(self) -> None: if await Accounts.get_account(email=self.account_data.email): await Accounts.delete_account(email=self.account_data.email) self.session = self.setup_session() async def process_reverify_email(self) -> OperationResult: await self.clear_account_and_session() try: confirm_url = await check_email_for_link( imap_server=self.account_data.imap_server, email=self.account_data.email, password=self.account_data.password, ) if confirm_url is None: logger.error( f"Account: {self.account_data.email} | Confirmation link not found" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) logger.success( f"Account: {self.account_data.email} | Link found, confirming registration..." ) response = await self.clear_request(url=confirm_url) if response.status_code == 200: logger.success( f"Account: {self.account_data.email} | Successfully confirmed registration" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=True, ) logger.error( f"Account: {self.account_data.email} | Failed to confirm registration" ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to reverify email: {error}" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) async def process_registration(self) -> OperationResult: task_id = None try: if not await check_if_email_valid( self.account_data.imap_server, self.account_data.email, self.account_data.password, ): logger.error(f"Account: {self.account_data.email} | Invalid email") return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) logger.info(f"Account: {self.account_data.email} | Registering...") puzzle_id, answer, task_id = await self.get_captcha_data() await self.register(puzzle_id, answer) logger.info( f"Account: {self.account_data.email} | Successfully registered, waiting for email..." ) confirm_url = await check_email_for_link( imap_server=self.account_data.imap_server, email=self.account_data.email, password=self.account_data.password, ) if confirm_url is None: logger.error( f"Account: {self.account_data.email} | Confirmation link not found" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) logger.success( f"Account: {self.account_data.email} | Link found, confirming registration..." ) response = await self.clear_request(url=confirm_url) if response.status_code == 200: logger.success( f"Account: {self.account_data.email} | Successfully confirmed registration" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=True, ) logger.error( f"Account: {self.account_data.email} | Failed to confirm registration" ) except APIError as error: if error.error_message in error.BASE_MESSAGES: if error.error_message == "Incorrect answer. Try again!": logger.warning( f"Account: {self.account_data.email} | Captcha answer incorrect, re-solving..." ) if task_id: await self.report_invalid_puzzle(task_id) elif error.error_message == "email already exists": logger.warning(f"Account: {self.account_data.email} | Email already exists, re-verifying...") return await self.process_reverify_email() else: logger.warning( f"Account: {self.account_data.email} | Captcha expired, re-solving..." ) return await self.process_registration() logger.error( f"Account: {self.account_data.email} | Failed to register: {error}" ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to register: {error}" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) @staticmethod def get_sleep_until(blocked: bool = False) -> datetime: duration = ( timedelta(minutes=10) if blocked else timedelta(seconds=config.keepalive_interval) ) return datetime.now(pytz.UTC) + duration async def process_farming(self) -> None: try: db_account_data = await Accounts.get_account(email=self.account_data.email) if db_account_data and db_account_data.session_blocked_until: if await self.handle_sleep(db_account_data.session_blocked_until): return if not db_account_data or not db_account_data.headers: if not await self.login_new_account(): return elif not await self.handle_existing_account(db_account_data): return await self.perform_farming_actions() except SessionRateLimited: await self.handle_session_blocked() except APIError as error: logger.error( f"Account: {self.account_data.email} | Failed to farm: {error}" ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to farm: {error}" ) return async def process_get_user_info(self) -> StatisticData: try: db_account_data = await Accounts.get_account(email=self.account_data.email) if db_account_data and db_account_data.session_blocked_until: if await self.handle_sleep(db_account_data.session_blocked_until): return StatisticData( success=False, referralPoint=None, rewardPoint=None ) if not db_account_data or not db_account_data.headers: if not await self.login_new_account(): return StatisticData( success=False, referralPoint=None, rewardPoint=None ) elif not await self.handle_existing_account(db_account_data): return StatisticData( success=False, referralPoint=None, rewardPoint=None ) user_info = await self.user_info() logger.success( f"Account: {self.account_data.email} | Successfully got user info" ) return StatisticData( success=True, referralPoint=user_info["referralPoint"], rewardPoint=user_info["rewardPoint"], ) except SessionRateLimited: await self.handle_session_blocked() except APIError as error: logger.error( f"Account: {self.account_data.email} | Failed to get user info: {error}" ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to get user info: {error}" ) return StatisticData(success=False, referralPoint=None, rewardPoint=None) async def process_complete_tasks(self) -> OperationResult: try: db_account_data = await Accounts.get_account(email=self.account_data.email) if db_account_data is None: if not await self.login_new_account(): return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) else: await self.handle_existing_account(db_account_data) logger.info(f"Account: {self.account_data.email} | Completing tasks...") await self.complete_tasks() logger.success( f"Account: {self.account_data.email} | Successfully completed tasks" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=True, ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to complete tasks: {error}" ) return OperationResult( identifier=self.account_data.email, data=self.account_data.password, status=False, ) async def login_new_account(self): task_id = None try: logger.info(f"Account: {self.account_data.email} | Logging in...") puzzle_id, answer, task_id = await self.get_captcha_data() await self.login(puzzle_id, answer) logger.info(f"Account: {self.account_data.email} | Successfully logged in") await Accounts.create_account( email=self.account_data.email, headers=self.session.headers ) return True except APIError as error: if error.error_message in error.BASE_MESSAGES: if error.error_message == "Incorrect answer. Try again!": logger.warning( f"Account: {self.account_data.email} | Captcha answer incorrect, re-solving..." ) if task_id: await self.report_invalid_puzzle(task_id) elif error.error_message == "Email not verified , Please check spam folder incase you did not get email": logger.error( f"Account: {self.account_data.email} | Email not verified, run registration process again" ) await file_operations.export_unverified_email(self.account_data.email, self.account_data.password) for account in config.accounts_to_farm: if account.email == self.account_data.email: config.accounts_to_farm.remove(account) return False else: logger.warning( f"Account: {self.account_data.email} | Captcha expired, re-solving..." ) return await self.login_new_account() logger.error( f"Account: {self.account_data.email} | Failed to login: {error}" ) return False except CaptchaSolvingFailed: sleep_until = self.get_sleep_until() await Accounts.set_sleep_until(self.account_data.email, sleep_until) logger.error( f"Account: {self.account_data.email} | Failed to solve captcha after 5 attempts, sleeping..." ) return False except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to login: {error}" ) return False async def handle_existing_account(self, db_account_data) -> bool | None: if db_account_data.sleep_until and await self.handle_sleep( db_account_data.sleep_until ): return False self.session.headers = db_account_data.headers status, result = await self.verify_session() if not status: logger.warning( f"Account: {self.account_data.email} | Session is invalid, re-logging in: {result}" ) await self.clear_account_and_session() return await self.process_farming() logger.info(f"Account: {self.account_data.email} | Using existing session") return True async def handle_session_blocked(self): await self.clear_account_and_session() logger.error( f"Account: {self.account_data.email} | Session rate-limited | Sleeping..." ) sleep_until = self.get_sleep_until(blocked=True) await Accounts.set_session_blocked_until(self.account_data.email, sleep_until) async def handle_sleep(self, sleep_until): current_time = datetime.now(pytz.UTC) sleep_until = sleep_until.replace(tzinfo=pytz.UTC) if sleep_until > current_time: sleep_duration = (sleep_until - current_time).total_seconds() logger.debug( f"Account: {self.account_data.email} | Sleeping until {sleep_until} (duration: {sleep_duration:.2f} seconds)" ) return True return False async def close_session(self): try: await self.session.close() except Exception as error: logger.debug( f"Account: {self.account_data.email} | Failed to close session: {error}" ) async def perform_farming_actions(self): try: await self.keepalive() logger.success( f"Account: {self.account_data.email} | Sent keepalive request" ) user_info = await self.user_info() logger.info( f"Account: {self.account_data.email} | Total points earned: {user_info['rewardPoint']['points']}" ) except Exception as error: logger.error( f"Account: {self.account_data.email} | Failed to perform farming actions: {error}" ) finally: new_sleep_until = self.get_sleep_until() await Accounts.set_sleep_until( email=self.account_data.email, sleep_until=new_sleep_until ) ================================================ FILE: core/exceptions/base.py ================================================ class APIError(Exception): BASE_MESSAGES = ["refresh your captcha!!", "Incorrect answer. Try again!", "Email not verified , Please check spam folder incase you did not get email", "email already exists"] """Base class for API exceptions""" def __init__(self, error: str, response_data: dict = None): self.error = error self.response_data = response_data @property def error_message(self) -> str: if self.response_data and "message" in self.response_data: return self.response_data["message"] def __str__(self): return self.error class SessionRateLimited(Exception): """Raised when the session is rate limited""" pass class CaptchaSolvingFailed(Exception): """Raised when the captcha solving failed""" pass class ServerError(APIError): """Raised when the server returns an error""" pass ================================================ FILE: core/solvers/__init__.py ================================================ from .anti_captcha import AntiCaptchaImageSolver from .two_captcha import TwoCaptchaImageSolver ================================================ FILE: core/solvers/anti_captcha.py ================================================ import asyncio from typing import Any, Tuple import httpx class AntiCaptchaImageSolver: BASE_URL = "https://api.anti-captcha.com" def __init__(self, api_key: str): self.api_key = api_key self.client = httpx.AsyncClient(timeout=10) async def solve(self, image: str) -> Tuple[str, bool]: try: captcha_data = { "clientKey": self.api_key, "softId": 1201, "task": { "type": "ImageToTextTask", "body": image, "phrase": False, "case": True, "numeric": 0, "math": False, "minLength": 6, "maxLength": 6, "comment": "Pay close attention to the letter case.", }, } resp = await self.client.post( f"{self.BASE_URL}/createTask", json=captcha_data ) resp.raise_for_status() data = resp.json() if data.get("errorId") == 0: return await self.get_captcha_result(data.get("taskId")) return data.get("errorDescription"), False except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False except Exception as err: return f"An unexpected error occurred: {err}", False async def get_captcha_result(self, task_id: int | str) -> Tuple[Any, bool]: for _ in range(10): try: resp = await self.client.post( f"{self.BASE_URL}/getTaskResult", json={"clientKey": self.api_key, "taskId": task_id}, ) resp.raise_for_status() result = resp.json() if result.get("errorId") != 0: return result.get("errorDescription"), False if result.get("status") == "ready": return result["solution"].get("text", ""), True await asyncio.sleep(3) except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False except Exception as err: return f"An unexpected error occurred: {err}", False return "Max time for solving exhausted", False async def report_bad(self, task_id: int | str) -> Tuple[Any, bool]: try: resp = await self.client.post( f"{self.BASE_URL}/reportIncorrectImageCaptcha", json={"clientKey": self.api_key, "taskId": task_id}, ) resp.raise_for_status() return resp.json(), True except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False except Exception as err: return f"An unexpected error occurred: {err}", False ================================================ FILE: core/solvers/two_captcha.py ================================================ import asyncio from typing import Any, Tuple import httpx class TwoCaptchaImageSolver: BASE_URL = "https://api.2captcha.com" def __init__(self, api_key: str): self.api_key = api_key self.client = httpx.AsyncClient(timeout=10) async def solve(self, image: str) -> Tuple[str, bool]: try: captcha_data = { "clientKey": self.api_key, "softId": 4706, "task": { "type": "ImageToTextTask", "body": image, "phrase": False, "case": True, "numeric": 4, "math": False, "minLength": 6, "maxLength": 6, "comment": "Pay close attention to the letter case.", }, } resp = await self.client.post( f"{self.BASE_URL}/createTask", json=captcha_data ) resp.raise_for_status() data = resp.json() if data.get("errorId") == 0: return await self.get_captcha_result(data.get("taskId")) return data.get("errorDescription"), False except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False except Exception as err: return f"An unexpected error occurred: {err}", False async def get_captcha_result( self, task_id: int | str ) -> tuple[Any, bool, int | str] | tuple[str, bool, int | str] | tuple[str, bool]: for _ in range(10): try: resp = await self.client.post( f"{self.BASE_URL}/getTaskResult", json={"clientKey": self.api_key, "taskId": task_id}, ) resp.raise_for_status() result = resp.json() if result.get("errorId") != 0: return result.get("errorDescription"), False, task_id if result.get("status") == "ready": return result["solution"].get("text", ""), True, task_id await asyncio.sleep(3) except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False, task_id except Exception as err: return f"An unexpected error occurred: {err}", False, task_id return "Max time for solving exhausted", False async def report_bad(self, task_id: str | int) -> Tuple[Any, bool]: try: resp = await self.client.post( f"{self.BASE_URL}/reportIncorrect", json={"clientKey": self.api_key, "taskId": task_id}, ) resp.raise_for_status() return resp.json(), True except httpx.HTTPStatusError as err: return f"HTTP error occurred: {err}", False except Exception as err: return f"An unexpected error occurred: {err}", False ================================================ FILE: database/__init__.py ================================================ from .models import Accounts from .settings import initialize_database ================================================ FILE: database/models/__init__.py ================================================ from .accounts import Accounts ================================================ FILE: database/models/accounts.py ================================================ import pytz from datetime import datetime from tortoise import Model, fields from loguru import logger class Accounts(Model): email = fields.CharField(max_length=255, unique=True) headers = fields.JSONField(null=True) sleep_until = fields.DatetimeField(null=True) session_blocked_until = fields.DatetimeField(null=True) class Meta: table = "dawn_accounts_v1.4" @classmethod async def get_account(cls, email: str): return await cls.get_or_none(email=email) @classmethod async def get_accounts(cls): return await cls.all() @classmethod async def create_account(cls, email: str, headers: dict = None): account = await cls.get_account(email=email) if account is None: account = await cls.create(email=email, headers=headers) return account else: account.headers = headers await account.save() return account @classmethod async def delete_account(cls, email: str): account = await cls.get_account(email=email) if account is None: return False await account.delete() return True @classmethod async def set_sleep_until(cls, email: str, sleep_until: datetime): account = await cls.get_account(email=email) if account is None: return False if sleep_until.tzinfo is None: sleep_until = pytz.UTC.localize(sleep_until) else: sleep_until = sleep_until.astimezone(pytz.UTC) account.sleep_until = sleep_until await account.save() logger.info(f"Account: {email} | Set new sleep_until: {sleep_until}") return True @classmethod async def set_session_blocked_until( cls, email: str, session_blocked_until: datetime ): account = await cls.get_account(email=email) if account is None: account = await cls.create_account(email=email) account.session_blocked_until = session_blocked_until await account.save() logger.info( f"Account: {email} | Set new session_blocked_until: {session_blocked_until}" ) return if session_blocked_until.tzinfo is None: session_blocked_until = pytz.UTC.localize(session_blocked_until) else: session_blocked_until = session_blocked_until.astimezone(pytz.UTC) account.session_blocked_until = session_blocked_until await account.save() logger.info( f"Account: {email} | Set new session_blocked_until: {session_blocked_until}" ) ================================================ FILE: database/settings.py ================================================ from loguru import logger from tortoise import Tortoise async def initialize_database() -> None: try: await Tortoise.init( db_url="sqlite://database/database.sqlite3", modules={"models": ["database.models.accounts"]}, timezone="UTC", ) await Tortoise.generate_schemas(safe=True) except Exception as error: logger.error(f"Error while initializing database: {error}") exit(0) ================================================ FILE: loader.py ================================================ import asyncio from core.solvers import * from utils import load_config, FileOperations config = load_config() captcha_solver = ( AntiCaptchaImageSolver(config.anti_captcha_api_key) if config.captcha_module == "anticaptcha" else TwoCaptchaImageSolver(config.two_captcha_api_key) ) file_operations = FileOperations() semaphore = asyncio.Semaphore(config.threads) ================================================ FILE: models/__init__.py ================================================ from .config import * from .bot import * ================================================ FILE: models/bot.py ================================================ from typing import Literal, TypedDict ModuleType = Literal["register", "tasks", "stats", "accounts"] class OperationResult(TypedDict): identifier: str data: str status: bool class StatisticData(TypedDict): success: bool referralPoint: dict | None rewardPoint: dict | None ================================================ FILE: models/config.py ================================================ from typing import Literal from better_proxy import Proxy from pydantic import BaseModel, PositiveInt, ConfigDict class Account(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) email: str password: str imap_server: str = "" proxy: Proxy class Config(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) class DelayBeforeStart(BaseModel): min: int max: int accounts_to_register: list[Account] = [] accounts_to_farm: list[Account] = [] referral_code: str = "" two_captcha_api_key: str = "" anti_captcha_api_key: str = "" delay_before_start: DelayBeforeStart threads: PositiveInt imap_settings: dict[str, str] keepalive_interval: PositiveInt module: str = "" captcha_module: Literal["2captcha", "anticaptcha"] = "" ================================================ FILE: requirements.txt ================================================ names~=0.3.0 curl_cffi~=0.7.1 pytz~=2024.1 loguru~=0.7.2 httpx~=0.27.0 urllib3~=2.2.2 art~=6.2 PyYAML~=6.0.2 pydantic~=2.8.2 inquirer~=3.3.0 colorama~=0.4.6 better_proxy tortoise-orm imap_tools numpy~=1.26.4 aiofiles~=24.1.0 aiocsv~=1.3.2 rich~=13.9.2 ================================================ FILE: run.py ================================================ import asyncio import random import sys from typing import Callable, Coroutine, Any, List, Set from loguru import logger from loader import config, semaphore, file_operations from core.bot import Bot from models import Account from utils import setup from console import Console from database import initialize_database accounts_with_initial_delay: Set[str] = set() async def run_module_safe( account: Account, process_func: Callable[[Bot], Coroutine[Any, Any, Any]] ) -> Any: global accounts_with_initial_delay async with semaphore: bot = Bot(account) try: if config.delay_before_start.min > 0: if process_func == process_farming and account.email not in accounts_with_initial_delay: random_delay = random.randint(config.delay_before_start.min, config.delay_before_start.max) logger.info(f"Account: {account.email} | Initial farming delay: {random_delay} sec") await asyncio.sleep(random_delay) accounts_with_initial_delay.add(account.email) elif process_func != process_farming: random_delay = random.randint(config.delay_before_start.min, config.delay_before_start.max) logger.info(f"Account: {account.email} | Sleep for {random_delay} sec") await asyncio.sleep(random_delay) result = await process_func(bot) return result finally: await bot.close_session() async def process_registration(bot: Bot) -> None: operation_result = await bot.process_registration() await file_operations.export_result(operation_result, "register") async def process_farming(bot: Bot) -> None: await bot.process_farming() async def process_export_stats(bot: Bot) -> None: data = await bot.process_get_user_info() await file_operations.export_stats(data) async def process_complete_tasks(bot: Bot) -> None: operation_result = await bot.process_complete_tasks() await file_operations.export_result(operation_result, "tasks") async def run_module( accounts: List[Account], process_func: Callable[[Bot], Coroutine[Any, Any, Any]] ) -> tuple[Any]: tasks = [run_module_safe(account, process_func) for account in accounts] return await asyncio.gather(*tasks) async def farm_continuously(accounts: List[Account]) -> None: while True: random.shuffle(accounts) await run_module(accounts, process_farming) await asyncio.sleep(10) def reset_initial_delays(): global accounts_with_initial_delay accounts_with_initial_delay.clear() async def run() -> None: await initialize_database() await file_operations.setup_files() reset_initial_delays() module_map = { "register": (config.accounts_to_register, process_registration), "farm": (config.accounts_to_farm, farm_continuously), "complete_tasks": (config.accounts_to_farm, process_complete_tasks), "export_stats": (config.accounts_to_farm, process_export_stats), } while True: Console().build() if config.module not in module_map: logger.error(f"Unknown module: {config.module}") break accounts, process_func = module_map[config.module] if not accounts: logger.error(f"No accounts for {config.module}") break if config.module == "farm": await process_func(accounts) else: await run_module(accounts, process_func) input("\n\nPress Enter to continue...") if __name__ == "__main__": if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) setup() asyncio.run(run()) ================================================ FILE: utils/__init__.py ================================================ from .load_config import load_config from .console import * from .file_utils import * from .imap_utils import * ================================================ FILE: utils/console.py ================================================ import os import sys import urllib3 from art import tprint from loguru import logger def setup(): urllib3.disable_warnings() logger.remove() logger.add( sys.stdout, colorize=True, format="{time:HH:mm:ss} | {level: <8} | - {" "message}", ) logger.add("./logs/logs.log", rotation="1 day", retention="7 days") def show_dev_info(): os.system("cls") tprint("JamBit") print("\033[36m" + "我的推特主页: " + "\033[34m" + "https://x.com/Hy78516012" + "\033[34m") print( "\033[36m" + "我的GitHub: " + "\033[34m" + "https://github.com/Gzgod" + "\033[34m" ) print() ================================================ FILE: utils/file_utils.py ================================================ import asyncio import aiofiles from pathlib import Path from aiocsv import AsyncWriter from models import ModuleType, OperationResult, StatisticData class FileOperations: def __init__(self, base_path: str = "./results"): self.base_path = Path(base_path) self.lock = asyncio.Lock() self.module_paths: dict[ModuleType, dict[str, Path]] = { "register": { "success": self.base_path / "registration_success.txt", "failed": self.base_path / "registration_failed.txt", }, "tasks": { "success": self.base_path / "tasks_success.txt", "failed": self.base_path / "tasks_failed.txt", }, "stats": { "base": self.base_path / "accounts_stats.csv", }, "accounts": { "unverified": self.base_path / "unverified_accounts.txt", }, } async def setup_files(self): self.base_path.mkdir(exist_ok=True) for module_paths in self.module_paths.values(): for path in module_paths.values(): path.touch(exist_ok=True) async with aiofiles.open(self.module_paths["stats"]["base"], "w") as f: writer = AsyncWriter(f) await writer.writerow( [ "Email", "Referral Code", "Points", "Referral Points", "Total Points", "Registration Date", "Completed Tasks", ] ) async def export_result(self, result: OperationResult, module: ModuleType): if module not in self.module_paths: raise ValueError(f"Unknown module: {module}") file_path = self.module_paths[module][ "success" if result["status"] else "failed" ] async with self.lock: try: async with aiofiles.open(file_path, "a") as file: await file.write(f"{result['identifier']}:{result['data']}\n") except IOError as e: print(f"Error writing to file: {e}") async def export_unverified_email(self, email: str, password: str): file_path = self.module_paths["accounts"]["unverified"] async with self.lock: try: async with aiofiles.open(file_path, "a") as file: await file.write(f"{email}:{password}\n") except IOError as e: print(f"Error writing to file: {e}") async def export_stats(self, data: StatisticData): file_path = self.module_paths["stats"]["base"] async with self.lock: try: async with aiofiles.open(file_path, mode="a", newline="") as f: writer = AsyncWriter(f) if not data or not data["referralPoint"] or not data["rewardPoint"]: return await writer.writerow( [ data["referralPoint"]["email"], data["referralPoint"]["referralCode"], data["rewardPoint"]["points"], data["referralPoint"]["commission"], float(data["rewardPoint"]["points"]) + float(data["referralPoint"]["commission"]), data["rewardPoint"]["registerpointsdate"], ( True if data["rewardPoint"]["twitter_x_id_points"] == 5000 and data["rewardPoint"]["discordid_points"] == 5000 and data["rewardPoint"]["telegramid_points"] == 5000 else False ), ] ) except IOError as e: print(f"Error writing to file: {e}") ================================================ FILE: utils/imap_utils.py ================================================ import re from typing import Optional import asyncio from loguru import logger from imap_tools import MailBox, AND async def check_if_email_valid( imap_server: str, email: str, password: str, ) -> bool: logger.info(f"Account: {email} | Checking if email is valid...") try: await asyncio.to_thread(lambda: MailBox(imap_server).login(email, password)) return True except Exception as error: logger.error(f"Account: {email} | Email is invalid (IMAP): {error}") return False async def check_email_for_link( imap_server: str, email: str, password: str, max_attempts: int = 8, delay_seconds: int = 5, ) -> Optional[str]: link_pattern = ( r"https://www\.aeropres\.in/chromeapi/dawn/v1/user/verifylink\?key=[a-f0-9-]+" ) logger.info(f"Account: {email} | Checking email for link...") try: async def search_in_mailbox(): return await asyncio.to_thread( lambda: search_for_link_sync( MailBox(imap_server).login(email, password), link_pattern ) ) for attempt in range(max_attempts): link = await search_in_mailbox() if link: return link if attempt < max_attempts - 1: logger.info( f"Account: {email} | Link not found. Waiting {delay_seconds} seconds before next attempt..." ) await asyncio.sleep(delay_seconds) logger.warning( f"Account: {email} | Link not found after {max_attempts} attempts, searching in spam folder..." ) spam_folders = ("SPAM", "Spam", "spam", "Junk", "junk", "Spamverdacht") for spam_folder in spam_folders: async def search_in_spam(): return await asyncio.to_thread( lambda: search_for_link_in_spam_sync( MailBox(imap_server).login(email, password), link_pattern, spam_folder, ) ) link = await search_in_spam() if link: return link logger.error( f"Account: {email} | Link not found in spam folder after multiple attempts" ) return None except Exception as error: logger.error(f"Account: {email} | Failed to check email for link: {error}") return None def search_for_link_sync(mailbox: MailBox, link_pattern: str) -> Optional[str]: messages = mailbox.fetch() for msg in messages: if msg.from_ == "hello@dawninternet.com": body = msg.text or msg.html if body: match = re.search(link_pattern, body) if match: return match.group(0) return None def search_for_link_in_spam_sync( mailbox: MailBox, link_pattern: str, spam_folder: str ) -> Optional[str]: if mailbox.folder.exists(spam_folder): mailbox.folder.set(spam_folder) return search_for_link_sync(mailbox, link_pattern) return None ================================================ FILE: utils/load_config.py ================================================ import os import yaml from itertools import cycle from loguru import logger from models import Config, Account from better_proxy import Proxy from typing import List, Dict, Generator CONFIG_PATH = os.path.join(os.getcwd(), "config") CONFIG_DATA_PATH = os.path.join(CONFIG_PATH, "data") CONFIG_PARAMS = os.path.join(CONFIG_PATH, "settings.yaml") REQUIRED_DATA_FILES = ("accounts.txt", "proxies.txt") REQUIRED_PARAMS_FIELDS = ( "threads", "keepalive_interval", "imap_settings", "captcha_module", "delay_before_start", "referral_code", ) def read_file( file_path: str, check_empty: bool = True, is_yaml: bool = False ) -> List[str] | Dict: if not os.path.exists(file_path): raise FileNotFoundError(f"File not found: {file_path}") if check_empty and os.stat(file_path).st_size == 0: raise ValueError(f"File is empty: {file_path}") if is_yaml: with open(file_path, "r", encoding="utf-8") as file: return yaml.safe_load(file) with open(file_path, "r", encoding="utf-8") as file: return [line.strip() for line in file] def get_params() -> Dict: data = read_file(CONFIG_PARAMS, is_yaml=True) missing_fields = set(REQUIRED_PARAMS_FIELDS) - set(data.keys()) if missing_fields: raise ValueError(f"Missing fields in config file: {', '.join(missing_fields)}") return data def get_proxies() -> List[Proxy]: try: proxies = read_file( os.path.join(CONFIG_DATA_PATH, "proxies.txt"), check_empty=False ) return [Proxy.from_str(line) for line in proxies] if proxies else [] except Exception as exc: raise ValueError(f"Failed to parse proxy: {exc}") def get_accounts(file_name: str) -> Generator[Account, None, None]: proxies = get_proxies() proxy_cycle = cycle(proxies) if proxies else None accounts = read_file(os.path.join(CONFIG_DATA_PATH, file_name), check_empty=False) for account in accounts: try: email, password = account.split(":") yield Account( email=email, password=password, proxy=next(proxy_cycle) if proxy_cycle else None, ) except ValueError: logger.error(f"Failed to parse account: {account}") def validate_domains(accounts: List[Account], domains: Dict[str, str]) -> List[Account]: for account in accounts: domain = account.email.split("@")[1] if domain not in domains: raise ValueError( f"Domain '{domain}' is not supported, please add it to the config file" ) account.imap_server = domains[domain] return accounts def load_config() -> Config: try: reg_accounts = list(get_accounts("register.txt")) farm_accounts = list(get_accounts("farm.txt")) if not reg_accounts and not farm_accounts: raise ValueError("No accounts found in data files") params = get_params() config = Config( **params, accounts_to_farm=farm_accounts, accounts_to_register=reg_accounts ) if reg_accounts: config.accounts_to_register = validate_domains( reg_accounts, config.imap_settings ) if config.captcha_module == "2captcha" and not config.two_captcha_api_key: raise ValueError("2Captcha API key is missing") elif config.captcha_module == "anticaptcha" and not config.anti_captcha_api_key: raise ValueError("AntiCaptcha API key is missing") return config except Exception as exc: logger.error(f"Failed to load config: {exc}") exit(1)