Spaces:
Sleeping
Sleeping
| import asyncio | |
| import aiohttp | |
| import json | |
| import time | |
| import random | |
| from typing import Dict, Optional, List, Any | |
| from urllib.parse import urljoin | |
| from faker import Faker | |
| from concurrent.futures import ThreadPoolExecutor | |
| from asyncio import Semaphore | |
| from tqdm.asyncio import tqdm as tqdm_asyncio | |
| import logging | |
| from dataclasses import dataclass | |
| from aiohttp import ClientTimeout | |
| from contextlib import asynccontextmanager | |
| # Configuration du logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| class AccountData: | |
| username: str | |
| password: str | |
| province_id: int | |
| ville_id: int | |
| registration_date: str = None | |
| class RateLimiter: | |
| def __init__(self, rate_limit: int, time_window: float = 1.0): | |
| self.rate_limit = rate_limit | |
| self.time_window = time_window | |
| self.tokens = rate_limit | |
| self.last_update = time.time() | |
| self._lock = asyncio.Lock() | |
| async def acquire(self): | |
| async with self._lock: | |
| now = time.time() | |
| time_passed = now - self.last_update | |
| self.tokens = min(self.rate_limit, | |
| self.tokens + time_passed * (self.rate_limit / self.time_window)) | |
| self.last_update = now | |
| if self.tokens < 1: | |
| wait_time = (1 - self.tokens) * (self.time_window / self.rate_limit) | |
| await asyncio.sleep(wait_time) | |
| self.tokens = 0 | |
| else: | |
| self.tokens -= 1 | |
| class AccountGenerator: | |
| def __init__(self): | |
| self.faker = Faker(['fr_FR']) | |
| self.locations = { | |
| 1: [1, 2, 3, 4, 5, 6], # Estuaire | |
| 2: [7, 8, 9, 10, 11], # Haut-Ogooué | |
| 3: [12, 13], # Moyen-Ogooué | |
| 4: [14, 15, 16, 17, 18],# Ngounié | |
| 5: [19, 20, 21], # Nyanga | |
| 6: [22, 23, 24], # Ogooué-Ivindo | |
| 7: [25, 26], # Ogooué-Lolo | |
| 8: [27, 28, 29], # Ogooué-Maritime | |
| 9: [30, 31, 32, 33, 34] # Woleu-Ntem | |
| } | |
| self._username_cache = set() | |
| self._lock = asyncio.Lock() | |
| async def generate_unique_username(self, min_length=10, max_length=20) -> str: | |
| async with self._lock: | |
| while True: | |
| username = self._generate_username(min_length, max_length) | |
| if username not in self._username_cache: | |
| self._username_cache.add(username) | |
| return username | |
| def _generate_username(self, min_length=10, max_length=20) -> str: | |
| patterns = [ | |
| lambda: self.faker.user_name()[:12], | |
| lambda: f"{self.faker.first_name().lower()}{random.randint(1, 999)}", | |
| lambda: f"{self.faker.last_name().lower()}{random.randint(1, 99)}", | |
| lambda: f"{self.faker.word()}{random.randint(1, 999)}" | |
| ] | |
| username = random.choice(patterns)() | |
| username = ''.join(c for c in username if c.isalnum()) | |
| if len(username) < min_length: | |
| username += str(random.randint(1000, 9999)) | |
| elif len(username) > max_length: | |
| username = username[:max_length] | |
| return username | |
| def generate_password(self, min_length=8, max_length=12) -> str: | |
| patterns = [ | |
| lambda: self.faker.password(length=random.randint(min_length, max_length)), | |
| lambda: f"{self.faker.word().capitalize()}{random.randint(100, 999)}!", | |
| lambda: f"{self.faker.color_name().capitalize()}{random.randint(100, 999)}@" | |
| ] | |
| return random.choice(patterns)() | |
| def generate_location(self) -> tuple: | |
| province_id = random.choice(list(self.locations.keys())) | |
| ville_id = random.choice(self.locations[province_id]) | |
| return province_id, ville_id | |
| async def generate_account_data(self) -> AccountData: | |
| province_id, ville_id = self.generate_location() | |
| return AccountData( | |
| username=await self.generate_unique_username(), | |
| password=self.generate_password(), | |
| province_id=province_id, | |
| ville_id=ville_id | |
| ) | |
| class AsyncGabaoHubAPI: | |
| def __init__(self, base_url: str, session: aiohttp.ClientSession, rate_limiter: RateLimiter): | |
| self.base_url = base_url.rstrip('/') | |
| self.session = session | |
| self.rate_limiter = rate_limiter | |
| self.timeout = ClientTimeout(total=30) | |
| self.headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
| 'Content-Type': 'application/x-www-form-urlencoded', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
| 'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3' | |
| } | |
| async def _make_request(self, endpoint: str, method: str = 'POST', data: Dict = None) -> Dict: | |
| await self.rate_limiter.acquire() | |
| url = urljoin(self.base_url, endpoint) | |
| try: | |
| async with self.session.request(method, url, data=data, timeout=self.timeout, headers=self.headers) as response: | |
| text = await response.text() | |
| return { | |
| 'success': response.status == 200, | |
| 'status_code': response.status, | |
| 'data': text | |
| } | |
| except asyncio.TimeoutError: | |
| logger.error(f"Timeout lors de la requête vers {endpoint}") | |
| return {'success': False, 'error': 'Timeout'} | |
| except Exception as e: | |
| logger.error(f"Erreur lors de la requête vers {endpoint}: {str(e)}") | |
| return {'success': False, 'error': str(e)} | |
| async def check_username_availability(self, username: str) -> bool: | |
| result = await self._make_request( | |
| '/assets/functions.php', | |
| data={'ajaxCall': 'isUsernameTaken', 'u': username} | |
| ) | |
| if not result['success']: | |
| raise ConnectionError(f"Erreur lors de la vérification du username: {result.get('error')}") | |
| return result['data'].strip() == "0" | |
| async def register_user(self, account_data: AccountData) -> Dict: | |
| if not 3 <= len(account_data.username) <= 32: | |
| return {'success': False, 'error': "Username length invalid"} | |
| if not account_data.username.isalnum(): | |
| return {'success': False, 'error': "Username must be alphanumeric"} | |
| if not 4 <= len(account_data.password) <= 32: | |
| return {'success': False, 'error': "Password length invalid"} | |
| init_result = await self._make_request('/register/index.php', method='GET') | |
| if not init_result['success']: | |
| return {'success': False, 'error': "Cannot access registration page"} | |
| if not await self.check_username_availability(account_data.username): | |
| return {'success': False, 'error': "Username already taken"} | |
| register_data = { | |
| 'username': account_data.username, | |
| 'password': account_data.password, | |
| 'password2': account_data.password, | |
| 'province': str(account_data.province_id), | |
| 'ville': str(account_data.ville_id), | |
| 'submit': "S'incrire" | |
| } | |
| result = await self._make_request('/register/register.php', data=register_data) | |
| if not result['success']: | |
| return {'success': False, 'error': f"Registration error: {result.get('error')}"} | |
| if "erreur" in result['data'].lower() or "error" in result['data'].lower(): | |
| return {'success': False, 'error': "Registration failed, check provided data"} | |
| return { | |
| 'success': True, | |
| 'message': "Registration successful", | |
| 'data': result['data'] | |
| } | |
| class AsyncAccountCreator: | |
| def __init__(self, base_url: str, max_concurrent: int = 3, rate_limit: int = 10): | |
| self.base_url = base_url | |
| self.generator = AccountGenerator() | |
| self.max_concurrent = max_concurrent | |
| self.rate_limiter = RateLimiter(rate_limit) | |
| self.successful_accounts: List[AccountData] = [] | |
| self.failed_accounts: List[Dict] = [] | |
| self._semaphore = Semaphore(max_concurrent) | |
| async def _get_session(self): | |
| conn = aiohttp.TCPConnector(limit=self.max_concurrent) | |
| async with aiohttp.ClientSession(connector=conn) as session: | |
| yield session | |
| async def create_account(self, session: aiohttp.ClientSession) -> Dict: | |
| async with self._semaphore: | |
| api = AsyncGabaoHubAPI(self.base_url, session, self.rate_limiter) | |
| max_retries = 3 | |
| retry_count = 0 | |
| while retry_count < max_retries: | |
| try: | |
| account_data = await self.generator.generate_account_data() | |
| result = await api.register_user(account_data) | |
| if result['success']: | |
| account_data.registration_date = time.strftime('%Y-%m-%d %H:%M:%S') | |
| self.successful_accounts.append(account_data) | |
| return {'success': True, 'account': account_data} | |
| retry_count += 1 | |
| await asyncio.sleep(random.uniform(1, 3)) | |
| except Exception as e: | |
| logger.error(f"Error creating account: {str(e)}") | |
| retry_count += 1 | |
| await asyncio.sleep(random.uniform(1, 3)) | |
| self.failed_accounts.append({ | |
| 'error': f"Failed after {max_retries} attempts", | |
| 'last_attempt': account_data | |
| }) | |
| return {'success': False, 'error': f"Failed after {max_retries} attempts"} | |
| async def create_multiple_accounts(self, count: int) -> Dict: | |
| start_time = time.time() | |
| results = {'success': [], 'failed': []} | |
| async with self._get_session() as session: | |
| tasks = [self.create_account(session) for _ in range(count)] | |
| for result in tqdm_asyncio( | |
| asyncio.as_completed(tasks), | |
| total=count, | |
| desc="Creating accounts" | |
| ): | |
| try: | |
| completed_result = await result | |
| if completed_result['success']: | |
| results['success'].append(completed_result['account']) | |
| else: | |
| results['failed'].append(completed_result['error']) | |
| except Exception as e: | |
| logger.error(f"Task error: {str(e)}") | |
| results['failed'].append(str(e)) | |
| end_time = time.time() | |
| return { | |
| 'duration': end_time - start_time, | |
| 'total_attempts': count, | |
| 'successful': len(results['success']), | |
| 'failed': len(results['failed']), | |
| 'accounts': results['success'], | |
| 'errors': results['failed'] | |
| } | |
| async def save_accounts(accounts: List[AccountData], filename: str): | |
| with open(filename, 'w', encoding='utf-8') as f: | |
| json.dump([vars(account) for account in accounts], f, ensure_ascii=False, indent=2) | |
| async def main(): | |
| try: | |
| creator = AsyncAccountCreator( | |
| 'https://gabaohub.alwaysdata.net', | |
| max_concurrent=10, | |
| rate_limit=20 | |
| ) | |
| num_accounts = 20000 | |
| logger.info(f"Creating {num_accounts} accounts...") | |
| results = await creator.create_multiple_accounts(num_accounts) | |
| logger.info(f"\nResults after {results['duration']:.2f} seconds:") | |
| logger.info(f"✅ Successfully created accounts: {results['successful']}") | |
| logger.info(f"❌ Failed attempts: {results['failed']}") | |
| if results['accounts']: | |
| filename = f"accounts_{time.strftime('%Y%m%d_%H%M%S')}.json" | |
| await save_accounts(results['accounts'], filename) | |
| logger.info(f"\nAccounts saved to {filename}") | |
| except Exception as e: | |
| logger.error(f"Main error: {str(e)}") | |
| raise | |
| if __name__ == "__main__": | |
| asyncio.run(main()) |