Eps2 / app.py
Docfile's picture
Update app.py
414ae53 verified
raw
history blame
22.8 kB
from flask import Flask, render_template, request, jsonify, redirect, url_for
import requests
from bs4 import BeautifulSoup
import random
import string
import json
import threading
import os
import time
from datetime import datetime
app = Flask(__name__)
# Configuration globale
config = {
'base_url': "https://ivoire-startup-tracker-edithbrou.replit.app",
'accounts_file': "accounts_data.json",
'is_running': False,
'progress': {
'total': 0,
'current': 0,
'success': 0,
'failed': 0,
'last_username': '',
'last_status': '',
'start_time': None,
'end_time': None
}
}
# Fonction pour générer un nom d'utilisateur aléatoire (min 80 caractères)
def generate_random_username(min_length=80, max_length=100):
"""Génère un nom d'utilisateur aléatoire d'au moins 80 caractères"""
length = random.randint(min_length, max_length)
return ''.join(random.choice(string.ascii_lowercase) for _ in range(length))
# Fonction pour générer une adresse email aléatoire
def generate_random_email():
"""Génère une adresse email aléatoire"""
username = ''.join(random.choice(string.ascii_lowercase) for _ in range(12))
domains = ["gmail.com", "yahoo.com", "outlook.com", "example.com"]
return f"{username}@{random.choice(domains)}"
# Fonction pour générer un mot de passe aléatoire
def generate_random_password(length=12):
"""Génère un mot de passe aléatoire"""
chars = string.ascii_letters + string.digits + "!@#$%^&*"
return ''.join(random.choice(chars) for _ in range(length))
# Fonction pour créer un compte
def create_account(is_startup_rep=False):
"""Crée un compte sur le site web"""
register_url = f"{config['base_url']}/register"
# Première requête pour récupérer le token CSRF
session = requests.Session()
try:
response = session.get(register_url)
if response.status_code != 200:
return {'success': False, 'error': f"Erreur lors de l'accès à la page: {response.status_code}"}
# Extraire le token CSRF
soup = BeautifulSoup(response.text, 'html.parser')
csrf_token = soup.find('input', {'id': 'csrf_token'}).get('value')
if not csrf_token:
return {'success': False, 'error': "Impossible de trouver le token CSRF"}
# Générer des informations de compte aléatoires
username = generate_random_username()
email = generate_random_email()
password = generate_random_password()
# Préparer les données du formulaire
form_data = {
'csrf_token': csrf_token,
'username': username,
'email': email,
'password': password,
'confirm_password': password,
'submit': 'Register'
}
# Ajouter l'option startup rep si nécessaire
if is_startup_rep:
form_data['is_startup_rep'] = 'y'
# Envoyer le formulaire
headers = {
'Referer': register_url,
'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'
}
response = session.post(register_url, data=form_data, headers=headers)
result = {
'success': response.status_code == 200 or response.status_code == 302,
'username': username,
'email': email,
'password': password,
'is_startup_rep': is_startup_rep,
'created_at': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'status_code': response.status_code
}
return result
except Exception as e:
return {'success': False, 'error': str(e)}
# Fonction pour créer plusieurs comptes en arrière-plan
def create_accounts_background(num_accounts, startup_ratio=0.3):
config['progress'] = {
'total': num_accounts,
'current': 0,
'success': 0,
'failed': 0,
'last_username': '',
'last_status': 'Démarrage...',
'start_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'end_time': None
}
# Charger les comptes existants
accounts = []
if os.path.exists(config['accounts_file']):
try:
with open(config['accounts_file'], 'r') as f:
accounts = json.load(f)
except:
accounts = []
for i in range(num_accounts):
if not config['is_running']:
break
is_startup = random.random() < startup_ratio
config['progress']['current'] = i + 1
config['progress']['last_status'] = f"Création du compte {i+1}/{num_accounts}..."
result = create_account(is_startup_rep=is_startup)
if result.get('success', False):
config['progress']['success'] += 1
config['progress']['last_username'] = result['username']
config['progress']['last_status'] = f"Compte {i+1} créé avec succès"
accounts.append(result)
else:
config['progress']['failed'] += 1
config['progress']['last_status'] = f"Échec de la création du compte {i+1}: {result.get('error', 'Erreur inconnue')}"
# Enregistrer les données régulièrement
with open(config['accounts_file'], 'w') as f:
json.dump(accounts, f, indent=2)
# Petite pause pour éviter de surcharger le serveur
time.sleep(1)
config['is_running'] = False
config['progress']['end_time'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
config['progress']['last_status'] = "Terminé"
# Enregistrement final
with open(config['accounts_file'], 'w') as f:
json.dump(accounts, f, indent=2)
# Routes Flask
@app.route('/')
def index():
return render_template('index.html', config=config)
@app.route('/start', methods=['POST'])
def start():
if config['is_running']:
return jsonify({"status": "error", "message": "Une génération est déjà en cours"})
num_accounts = int(request.form.get('num_accounts', 10))
startup_ratio = float(request.form.get('startup_ratio', 0.3))
config['is_running'] = True
# Démarrer le processus en arrière-plan
thread = threading.Thread(target=create_accounts_background, args=(num_accounts, startup_ratio))
thread.daemon = True
thread.start()
return jsonify({"status": "success", "message": "Génération démarrée"})
@app.route('/stop', methods=['POST'])
def stop():
config['is_running'] = False
return jsonify({"status": "success", "message": "Arrêt demandé"})
@app.route('/progress')
def progress():
return jsonify(config['progress'])
@app.route('/accounts')
def view_accounts():
page = int(request.args.get('page', 1))
per_page = 20
accounts = []
if os.path.exists(config['accounts_file']):
try:
with open(config['accounts_file'], 'r') as f:
accounts = json.load(f)
except:
accounts = []
total_accounts = len(accounts)
total_pages = (total_accounts + per_page - 1) // per_page
start_idx = (page - 1) * per_page
end_idx = start_idx + per_page
current_accounts = accounts[start_idx:end_idx]
return render_template(
'accounts.html',
accounts=current_accounts,
page=page,
total_pages=total_pages,
total_accounts=total_accounts
)
if __name__ == '__main__':
# Get the directory of the current script
current_dir = os.path.dirname(os.path.abspath(__file__))
# Create the templates directory if it doesn't exist
templates_dir = os.path.join(current_dir, 'templates')
if not os.path.exists(templates_dir):
os.makedirs(templates_dir)
# Create the HTML template files using absolute paths
index_html_path = os.path.join(templates_dir, 'index.html')
accounts_html_path = os.path.join(templates_dir, 'accounts.html')
with open(index_html_path, 'w') as f:
f.write('''
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Générateur de comptes automatique</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f5f5f5; }
.card { box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
.progress { height: 25px; }
#status-display { height: 200px; overflow-y: auto; }
</style>
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
<div class="card-header bg-primary text-white">
<h3 class="card-title mb-0">Générateur de comptes - Startup Côte d'Ivoire</h3>
</div>
<div class="card-body">
<form id="generator-form">
<div class="row mb-3">
<div class="col-md-6">
<label for="num_accounts" class="form-label">Nombre de comptes à créer</label>
<input type="number" class="form-control" id="num_accounts" name="num_accounts" min="1" max="1000" value="10">
</div>
<div class="col-md-6">
<label for="startup_ratio" class="form-label">Ratio de représentants de startup (%)</label>
<input type="number" class="form-control" id="startup_ratio" name="startup_ratio" min="0" max="100" value="30">
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button type="submit" id="start-btn" class="btn btn-success btn-lg">
<i class="fas fa-play"></i> Démarrer
</button>
<button type="button" id="stop-btn" class="btn btn-danger btn-lg">
<i class="fas fa-stop"></i> Arrêter
</button>
<a href="/accounts" class="btn btn-primary btn-lg">
<i class="fas fa-list"></i> Voir les comptes
</a>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-12">
<div class="card">
<div class="card-header bg-info text-white">
<h4 class="card-title mb-0">Progression</h4>
</div>
<div class="card-body">
<div class="progress mb-3">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%">0%</div>
</div>
<div class="row text-center mb-3">
<div class="col">
<div class="card bg-light">
<div class="card-body">
<h5>Total</h5>
<h3 id="total-count">0</h3>
</div>
</div>
</div>
<div class="col">
<div class="card bg-success text-white">
<div class="card-body">
<h5>Réussis</h5>
<h3 id="success-count">0</h3>
</div>
</div>
</div>
<div class="col">
<div class="card bg-danger text-white">
<div class="card-body">
<h5>Échecs</h5>
<h3 id="failed-count">0</h3>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<h5>Dernier statut</h5>
</div>
<div class="card-body">
<p id="last-status">-</p>
<p>Dernier compte créé: <span id="last-username" class="text-primary fw-bold">-</span></p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<p>Heure de début: <span id="start-time">-</span></p>
</div>
<div class="col-md-6 text-end">
<p>Heure de fin: <span id="end-time">-</span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Formulaire de génération
document.getElementById('generator-form').addEventListener('submit', function(e) {
e.preventDefault();
const numAccounts = document.getElementById('num_accounts').value;
const startupRatio = document.getElementById('startup_ratio').value / 100;
fetch('/start', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `num_accounts=${numAccounts}&startup_ratio=${startupRatio}`
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
startProgressUpdates();
} else {
alert(data.message);
}
});
});
// Bouton d'arrêt
document.getElementById('stop-btn').addEventListener('click', function() {
fetch('/stop', {
method: 'POST'
})
.then(response => response.json())
.then(data => {
alert(data.message);
});
});
// Mettre à jour la progression
function updateProgress() {
fetch('/progress')
.then(response => response.json())
.then(data => {
const progressPercent = data.total > 0 ? Math.round((data.current / data.total) * 100) : 0;
document.getElementById('progress-bar').style.width = `${progressPercent}%`;
document.getElementById('progress-bar').textContent = `${progressPercent}%`;
document.getElementById('total-count').textContent = data.total;
document.getElementById('success-count').textContent = data.success;
document.getElementById('failed-count').textContent = data.failed;
document.getElementById('last-status').textContent = data.last_status;
document.getElementById('last-username').textContent = data.last_username || '-';
document.getElementById('start-time').textContent = data.start_time || '-';
document.getElementById('end-time').textContent = data.end_time || '-';
});
}
let progressInterval;
function startProgressUpdates() {
// Arrêter l'intervalle précédent s'il existe
if (progressInterval) {
clearInterval(progressInterval);
}
// Mettre à jour immédiatement
updateProgress();
// Puis toutes les 2 secondes
progressInterval = setInterval(updateProgress, 2000);
}
// Vérifier si une génération est déjà en cours au chargement de la page
updateProgress();
});
</script>
</body>
</html>
''')
with open(accounts_html_path, 'w') as f:
f.write('''
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Liste des comptes générés</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f5f5f5; }
.card { box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
.username-cell {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.pagination { margin-bottom: 0; }
</style>
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
<h3 class="mb-0">Liste des comptes générés</h3>
<a href="/" class="btn btn-light">Retour au générateur</a>
</div>
<div class="card-body">
<div class="alert alert-info">
Total des comptes générés: {{ total_accounts }}
</div>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>#</th>
<th>Nom d'utilisateur</th>
<th>Email</th>
<th>Mot de passe</th>
<th>Startup Rep</th>
<th>Date de création</th>
<th>Statut</th>
</tr>
</thead>
<tbody>
{% for account in accounts %}
<tr>
<td>{{ (page - 1) * 20 + loop.index }}</td>
<td class="username-cell" title="{{ account.username }}">{{ account.username }}</td>
<td>{{ account.email }}</td>
<td>{{ account.password }}</td>
<td>{% if account.is_startup_rep %}Oui{% else %}Non{% endif %}</td>
<td>{{ account.created_at }}</td>
<td>
{% if account.success %}
<span class="badge bg-success">Succès</span>
{% else %}
<span class="badge bg-danger">Échec</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if total_pages > 1 %}
<div class="d-flex justify-content-center mt-4">
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item {% if page == 1 %}disabled{% endif %}">
<a class="page-link" href="{{ url_for('view_accounts', page=page-1) if page > 1 else '#' }}">Précédent</a>
</li>
{% for p in range(1, total_pages + 1) %}
{% if p == page %}
<li class="page-item active"><span class="page-link">{{ p }}</span></li>
{% else %}
<li class="page-item"><a class="page-link" href="{{ url_for('view_accounts', page=p) }}">{{ p }}</a></li>
{% endif %}
{% endfor %}
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
<a class="page-link" href="{{ url_for('view_accounts', page=page+1) if page < total_pages else '#' }}">Suivant</a>
</li>
</ul>
</nav>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
''')
app.run(debug=True)