Docfile commited on
Commit
de01232
·
verified ·
1 Parent(s): 520b8ab

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +301 -0
app.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify, redirect, url_for
2
+ import aiohttp
3
+ import asyncio
4
+ from bs4 import BeautifulSoup
5
+ import random
6
+ import string
7
+ import json
8
+ import threading
9
+ import os
10
+ import time
11
+ from datetime import datetime
12
+ from concurrent.futures import ThreadPoolExecutor
13
+
14
+ app = Flask(__name__)
15
+
16
+ # Configuration globale
17
+ config = {
18
+ 'base_url': "https://ivoire-startup-tracker-edithbrou.replit.app",
19
+ 'accounts_file': "accounts_data.json",
20
+ 'is_running': False,
21
+ 'batch_size': 10, # Nombre de requêtes parallèles
22
+ 'progress': {
23
+ 'total': 0,
24
+ 'current': 0,
25
+ 'success': 0,
26
+ 'failed': 0,
27
+ 'last_username': '',
28
+ 'last_status': '',
29
+ 'start_time': None,
30
+ 'end_time': None
31
+ }
32
+ }
33
+
34
+ # Fonction pour générer un nom d'utilisateur aléatoire
35
+ def generate_random_username(min_length=8, max_length=12):
36
+ """Génère un nom d'utilisateur aléatoire d'une longueur raisonnable"""
37
+ length = random.randint(min_length, max_length)
38
+ return ''.join(random.choice(string.ascii_lowercase) for _ in range(length))
39
+
40
+ # Fonction pour générer une adresse email aléatoire
41
+ def generate_random_email():
42
+ """Génère une adresse email aléatoire"""
43
+ username = ''.join(random.choice(string.ascii_lowercase) for _ in range(12))
44
+ domains = ["gmail.com", "yahoo.com", "outlook.com", "example.com"]
45
+ return f"{username}@{random.choice(domains)}"
46
+
47
+ # Fonction pour générer un mot de passe aléatoire
48
+ def generate_random_password(length=10):
49
+ """Génère un mot de passe aléatoire avec un mélange de caractères"""
50
+ chars = string.ascii_letters + string.digits + "!@#$%^&*()-_=+" # Éviter certains caractères spéciaux qui pourraient causer des problèmes
51
+ return ''.join(random.choice(chars) for _ in range(length))
52
+
53
+ # Fonction asynchrone pour créer un compte
54
+ async def create_account_async(session, is_startup_rep=False):
55
+ """Crée un compte sur le site web de manière asynchrone"""
56
+ register_url = f"{config['base_url']}/register"
57
+
58
+ try:
59
+ # Première requête pour récupérer le token CSRF
60
+ async with session.get(register_url, timeout=10) as response:
61
+ if response.status != 200:
62
+ return {'success': False, 'error': f"Erreur lors de l'accès à la page: {response.status}"}
63
+
64
+ html = await response.text()
65
+
66
+ # Extraire le token CSRF
67
+ soup = BeautifulSoup(html, 'html.parser')
68
+ csrf_token_input = soup.find('input', {'id': 'csrf_token'})
69
+
70
+ if not csrf_token_input:
71
+ return {'success': False, 'error': "Impossible de trouver le token CSRF"}
72
+
73
+ csrf_token = csrf_token_input.get('value')
74
+
75
+ # Générer des informations de compte aléatoires
76
+ username = generate_random_username()
77
+ email = generate_random_email()
78
+ password = generate_random_password()
79
+
80
+ # Préparer les données du formulaire
81
+ form_data = {
82
+ 'csrf_token': csrf_token,
83
+ 'username': username,
84
+ 'email': email,
85
+ 'password': password,
86
+ 'confirm_password': password,
87
+ 'submit': 'Register'
88
+ }
89
+
90
+ # Ajouter l'option startup rep si nécessaire
91
+ if is_startup_rep:
92
+ form_data['is_startup_rep'] = 'y'
93
+
94
+ # Envoyer le formulaire
95
+ headers = {
96
+ 'Referer': register_url,
97
+ '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'
98
+ }
99
+
100
+ async with session.post(register_url, data=form_data, headers=headers, timeout=15) as response:
101
+ result = {
102
+ 'success': response.status == 200 or response.status == 302,
103
+ 'username': username,
104
+ 'email': email,
105
+ 'password': password,
106
+ 'is_startup_rep': is_startup_rep,
107
+ 'created_at': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
108
+ 'status_code': response.status
109
+ }
110
+
111
+ return result
112
+
113
+ except asyncio.TimeoutError:
114
+ return {'success': False, 'error': "Timeout lors de la requête"}
115
+ except Exception as e:
116
+ return {'success': False, 'error': str(e)}
117
+
118
+ # Fonction pour traiter un lot de comptes en parallèle
119
+ async def process_batch(batch_indices, startup_ratio, accounts):
120
+ """Traite un lot de comptes en parallèle"""
121
+ async with aiohttp.ClientSession() as session:
122
+ tasks = []
123
+ for i in batch_indices:
124
+ if not config['is_running']:
125
+ break
126
+
127
+ is_startup = random.random() < startup_ratio
128
+ tasks.append(create_account_async(session, is_startup_rep=is_startup))
129
+
130
+ if not tasks:
131
+ return []
132
+
133
+ results = await asyncio.gather(*tasks, return_exceptions=True)
134
+
135
+ # Traiter les résultats
136
+ batch_results = []
137
+ for idx, result in zip(batch_indices, results):
138
+ if isinstance(result, Exception):
139
+ config['progress']['failed'] += 1
140
+ config['progress']['last_status'] = f"Échec de la création du compte {idx+1}: {str(result)}"
141
+ elif result.get('success', False):
142
+ config['progress']['success'] += 1
143
+ config['progress']['last_username'] = result['username']
144
+ config['progress']['last_status'] = f"Compte {idx+1} créé avec succès"
145
+ accounts.append(result)
146
+ batch_results.append(result)
147
+ else:
148
+ config['progress']['failed'] += 1
149
+ config['progress']['last_status'] = f"Échec de la création du compte {idx+1}: {result.get('error', 'Erreur inconnue')}"
150
+
151
+ config['progress']['current'] = idx + 1
152
+
153
+ return batch_results
154
+
155
+ # Fonction principale pour créer des comptes de manière asynchrone
156
+ async def create_accounts_async(num_accounts, startup_ratio=0.3):
157
+ """Crée plusieurs comptes en parallèle de manière asynchrone"""
158
+ # Charger les comptes existants
159
+ accounts = []
160
+ if os.path.exists(config['accounts_file']):
161
+ try:
162
+ with open(config['accounts_file'], 'r') as f:
163
+ accounts = json.load(f)
164
+ except:
165
+ accounts = []
166
+
167
+ # Traiter les comptes par lots
168
+ batch_size = config['batch_size']
169
+ for start_idx in range(0, num_accounts, batch_size):
170
+ if not config['is_running']:
171
+ break
172
+
173
+ end_idx = min(start_idx + batch_size, num_accounts)
174
+ batch_indices = list(range(start_idx, end_idx))
175
+
176
+ # Traiter un lot de comptes
177
+ await process_batch(batch_indices, startup_ratio, accounts)
178
+
179
+ # Enregistrer les données après chaque lot
180
+ with open(config['accounts_file'], 'w') as f:
181
+ json.dump(accounts, f, indent=2)
182
+
183
+ # Petite pause pour éviter de surcharger le serveur
184
+ await asyncio.sleep(1)
185
+
186
+ return accounts
187
+
188
+ # Fonction pour lancer la création de comptes en arrière-plan
189
+ def create_accounts_background(num_accounts, startup_ratio=0.3):
190
+ config['progress'] = {
191
+ 'total': num_accounts,
192
+ 'current': 0,
193
+ 'success': 0,
194
+ 'failed': 0,
195
+ 'last_username': '',
196
+ 'last_status': 'Démarrage...',
197
+ 'start_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
198
+ 'end_time': None
199
+ }
200
+
201
+ # Créer une boucle asyncio dans un nouveau thread
202
+ loop = asyncio.new_event_loop()
203
+ asyncio.set_event_loop(loop)
204
+
205
+ try:
206
+ accounts = loop.run_until_complete(create_accounts_async(num_accounts, startup_ratio))
207
+
208
+ # Mise à jour finale
209
+ config['progress']['end_time'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
210
+ config['progress']['last_status'] = "Terminé"
211
+
212
+ # Enregistrement final
213
+ with open(config['accounts_file'], 'w') as f:
214
+ json.dump(accounts, f, indent=2)
215
+
216
+ except Exception as e:
217
+ config['progress']['last_status'] = f"Erreur: {str(e)}"
218
+ finally:
219
+ config['is_running'] = False
220
+ loop.close()
221
+
222
+ # Routes Flask
223
+ @app.route('/')
224
+ def index():
225
+ return render_template('index.html', config=config)
226
+
227
+ @app.route('/start', methods=['POST'])
228
+ def start():
229
+ if config['is_running']:
230
+ return jsonify({"status": "error", "message": "Une génération est déjà en cours"})
231
+
232
+ num_accounts = int(request.form.get('num_accounts', 10))
233
+ startup_ratio = float(request.form.get('startup_ratio', 0.3))
234
+ batch_size = int(request.form.get('batch_size', config['batch_size']))
235
+
236
+ # Mettre à jour la taille du lot
237
+ config['batch_size'] = min(batch_size, 20) # Limiter à 20 pour éviter de surcharger le serveur
238
+ config['is_running'] = True
239
+
240
+ # Démarrer le processus en arrière-plan
241
+ thread = threading.Thread(target=create_accounts_background, args=(num_accounts, startup_ratio))
242
+ thread.daemon = True
243
+ thread.start()
244
+
245
+ return jsonify({"status": "success", "message": "Génération démarrée"})
246
+
247
+ @app.route('/stop', methods=['POST'])
248
+ def stop():
249
+ config['is_running'] = False
250
+ return jsonify({"status": "success", "message": "Arrêt demandé"})
251
+
252
+ @app.route('/progress')
253
+ def progress():
254
+ return jsonify(config['progress'])
255
+
256
+ @app.route('/accounts')
257
+ def view_accounts():
258
+ page = int(request.args.get('page', 1))
259
+ per_page = 20
260
+
261
+ accounts = []
262
+ if os.path.exists(config['accounts_file']):
263
+ try:
264
+ with open(config['accounts_file'], 'r') as f:
265
+ accounts = json.load(f)
266
+ except:
267
+ accounts = []
268
+
269
+ total_accounts = len(accounts)
270
+ total_pages = (total_accounts + per_page - 1) // per_page
271
+
272
+ start_idx = (page - 1) * per_page
273
+ end_idx = start_idx + per_page
274
+
275
+ current_accounts = accounts[start_idx:end_idx]
276
+
277
+ return render_template(
278
+ 'accounts.html',
279
+ accounts=current_accounts,
280
+ page=page,
281
+ total_pages=total_pages,
282
+ total_accounts=total_accounts
283
+ )
284
+
285
+ @app.route('/script.js')
286
+ def serve_js():
287
+ return render_template('script.js'), 200, {'Content-Type': 'application/javascript'}
288
+
289
+ @app.route('/clear', methods=['POST'])
290
+ def clear_accounts():
291
+ """Supprime tous les comptes enregistrés"""
292
+ if os.path.exists(config['accounts_file']):
293
+ try:
294
+ os.remove(config['accounts_file'])
295
+ return jsonify({"status": "success", "message": "Données des comptes supprimées"})
296
+ except Exception as e:
297
+ return jsonify({"status": "error", "message": f"Erreur lors de la suppression: {str(e)}"})
298
+ return jsonify({"status": "success", "message": "Aucun fichier à supprimer"})
299
+
300
+ if __name__ == '__main__':
301
+ app.run(debug=True)