Esenjin e39e76fd06 ajout du "mode filou"
permet de faire tourner différents jetons d'accès pour outrepasser les limitations vraiment beaucoup trop stricts de certaines api
2025-03-22 13:42:21 +01:00

570 lines
32 KiB
PHP

<?php
/**
* FavMasToKey - Mode Filou (multiple tokens)
*/
// Définir la constante pour inclure les fichiers
define('FAVMASTOKEY', true);
// Inclure les fichiers requis
require_once 'includes/config.php';
require_once 'includes/functions.php';
// Vérifier si l'utilisateur est authentifié (au moins avec un token)
$has_primary_token = isset($_SESSION['misskey_token']) && !empty($_SESSION['misskey_token']);
$instance = isset($_SESSION['misskey_instance']) ? $_SESSION['misskey_instance'] : '';
// Traiter le formulaire de connexion Misskey (pour le token principal)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'connect_token') {
if (isset($_POST['misskey_instance']) && isset($_POST['misskey_token'])) {
$instance = trim($_POST['misskey_instance']);
$token = trim($_POST['misskey_token']);
// Vérifier que l'instance et le token sont valides
if (empty($instance) || empty($token)) {
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Veuillez renseigner à la fois l\'instance Misskey et le jeton d\'accès.'
];
} else {
// Valider le format de l'instance
$instance = preg_replace('/^https?:\/\//', '', $instance);
$instance = rtrim($instance, '/');
if (!preg_match('/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/', $instance)) {
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'L\'URL de l\'instance Misskey semble invalide.'
];
} else {
// Vérifier la validité du token en effectuant une requête test
$validate_result = validate_misskey_token($instance, $token);
if ($validate_result['success']) {
// Stocker le token et l'instance dans la session
$_SESSION['misskey_token'] = $token;
$_SESSION['misskey_instance'] = $instance;
// Initialiser le tableau des tokens supplémentaires s'il n'existe pas
if (!isset($_SESSION['additional_tokens'])) {
$_SESSION['additional_tokens'] = [];
}
$_SESSION['messages'][] = [
'type' => 'success',
'text' => 'Connecté avec succès à ' . $instance . ' (token principal).'
];
// Rediriger vers la section des tokens multiples
header('Location: multitokens.php#tokens');
exit;
} else {
// Formater le message d'erreur correctement
$errorDetails = isset($validate_result['message']) ? $validate_result['message'] : 'Erreur inconnue';
// Si le message est un tableau, le convertir en chaîne JSON
if (is_array($errorDetails)) {
$errorDetails = json_encode($errorDetails, JSON_PRETTY_PRINT);
}
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Le jeton d\'accès semble invalide ou a expiré.',
'details' => $errorDetails
];
}
}
}
} else {
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Données manquantes.'
];
}
}
// Traiter l'ajout d'un token supplémentaire
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add_token') {
if (isset($_POST['token_name']) && isset($_POST['token_value'])) {
$name = trim($_POST['token_name']);
$token = trim($_POST['token_value']);
// Vérifier que le nom et le token sont valides
if (empty($name) || empty($token)) {
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Veuillez renseigner à la fois un nom et un jeton d\'accès.'
];
} else {
// Vérifier la validité du token en effectuant une requête test
$validate_result = validate_misskey_token($instance, $token);
if ($validate_result['success']) {
// Ajouter le token au tableau des tokens supplémentaires
if (!isset($_SESSION['additional_tokens'])) {
$_SESSION['additional_tokens'] = [];
}
// Générer un ID unique pour ce token
$token_id = uniqid('token_');
$_SESSION['additional_tokens'][$token_id] = [
'name' => $name,
'token' => $token,
'added_at' => time(),
'last_used' => null,
'usage_count' => 0
];
$_SESSION['messages'][] = [
'type' => 'success',
'text' => 'Token supplémentaire "' . $name . '" ajouté avec succès.'
];
// Rediriger pour éviter la soumission multiple
header('Location: multitokens.php#tokens');
exit;
} else {
$errorDetails = isset($validate_result['message']) ? $validate_result['message'] : 'Erreur inconnue';
if (is_array($errorDetails)) {
$errorDetails = json_encode($errorDetails, JSON_PRETTY_PRINT);
}
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Le jeton d\'accès supplémentaire "' . $name . '" semble invalide ou a expiré.',
'details' => $errorDetails
];
}
}
} else {
$_SESSION['messages'][] = [
'type' => 'danger',
'text' => 'Données manquantes pour l\'ajout du token.'
];
}
}
// Traiter la suppression d'un token
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'remove_token') {
if (isset($_POST['token_id']) && isset($_SESSION['additional_tokens'][$_POST['token_id']])) {
$token_id = $_POST['token_id'];
$token_name = $_SESSION['additional_tokens'][$token_id]['name'];
// Supprimer le token
unset($_SESSION['additional_tokens'][$token_id]);
$_SESSION['messages'][] = [
'type' => 'info',
'text' => 'Token "' . $token_name . '" supprimé avec succès.'
];
// Rediriger pour éviter la soumission multiple
header('Location: multitokens.php#tokens');
exit;
}
}
// Traitement de la déconnexion complète
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
// Supprimer les informations d'authentification
unset($_SESSION['misskey_token']);
unset($_SESSION['misskey_instance']);
unset($_SESSION['additional_tokens']);
$_SESSION['messages'][] = [
'type' => 'info',
'text' => 'Vous avez été déconnecté (tous les tokens ont été supprimés).'
];
// Rediriger vers la page d'accueil
header('Location: multitokens.php');
exit;
}
// Initialiser les messages
$messages = [];
if (isset($_SESSION['messages'])) {
$messages = $_SESSION['messages'];
unset($_SESSION['messages']);
}
// Récupérer le nombre de tokens supplémentaires
$additional_tokens_count = isset($_SESSION['additional_tokens']) ? count($_SESSION['additional_tokens']) : 0;
$total_tokens_count = $has_primary_token ? 1 + $additional_tokens_count : $additional_tokens_count;
// Récupérer les favoris du localStorage
$has_favorites = false;
?>
<!DOCTYPE html>
<html lang="fr" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#7e57c2">
<link rel="icon" href="images/favicon.svg" type="image/svg+xml">
<meta name="description" content="FavMasToKey Mode Filou - Accélérez le transfert de vos favoris de Mastodon vers Misskey avec plusieurs jetons">
<title>Mode Filou - FavMasToKey</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="css/styles.css">
<style>
.token-card {
transition: all 0.3s ease;
border-left: 4px solid #7e57c2;
}
.token-card.active {
border-left-color: #4caf50;
background-color: rgba(76, 175, 80, 0.1);
}
.token-card.cooldown {
border-left-color: #ffb74d;
background-color: rgba(255, 183, 77, 0.1);
}
.token-card.error {
border-left-color: #f44336;
background-color: rgba(244, 67, 54, 0.1);
}
.token-status {
width: 10px;
height: 10px;
border-radius: 50%;
display: inline-block;
margin-right: 5px;
}
.token-status.ready {
background-color: #4caf50;
}
.token-status.cooldown {
background-color: #ffb74d;
}
.token-status.error {
background-color: #f44336;
}
.token-status.idle {
background-color: #9e9e9e;
}
#tokens-container {
max-height: 400px;
overflow-y: auto;
}
</style>
</head>
<body>
<div class="container py-5">
<header class="text-center mb-5">
<h1>FavMasToKey - Mode Filou</h1>
<p class="lead">Accélérez le transfert de vos favoris avec plusieurs jetons d'accès</p>
<div class="mt-3">
<a href="index.php" class="btn btn-sm btn-outline-primary">Mode Standard</a>
<a href="doc.php" class="btn btn-sm btn-outline-primary">Documentation</a>
<a href="diagnostic.php" class="btn btn-sm btn-outline-primary">Diagnostic</a>
</div>
</header>
<!-- Messages d'alerte -->
<?php if (!empty($messages)): ?>
<?php foreach ($messages as $message): ?>
<div class="alert alert-<?php echo $message['type']; ?> alert-dismissible fade show" role="alert">
<?php echo $message['text']; ?>
<?php if (isset($message['details']) && ENVIRONMENT === 'development'): ?>
<hr>
<details>
<summary>Détails techniques (mode développement)</summary>
<pre class="mt-2 p-2 bg-dark text-light"><?php echo htmlspecialchars($message['details']); ?></pre>
</details>
<?php endif; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Fermer"></button>
</div>
<?php endforeach; ?>
<?php endif; ?>
<div class="row justify-content-center">
<div class="col-md-10">
<div class="card shadow-sm mb-4">
<div class="card-body">
<h2 class="card-title">Comment ça marche ?</h2>
<p>Le <strong>Mode Filou</strong> permet d'accélérer le transfert de vos favoris en utilisant plusieurs jetons d'accès en rotation. Cela permet de contourner les limites d'API de certaines instances Misskey très strictes.</p>
<div class="alert alert-info">
<h5><i class="bi bi-info-circle"></i> Principe de fonctionnement</h5>
<p>Au lieu d'utiliser un seul jeton avec un long délai entre chaque requête, le mode filou va :</p>
<ol>
<li>Utiliser plusieurs jetons en rotation</li>
<li>Distribuer les requêtes entre ces jetons</li>
<li>Respecter un délai suffisant avant de réutiliser un même jeton</li>
</ol>
<p class="mb-0">Par exemple, avec 10 jetons et un délai de 15 secondes entre chaque requête, vous pourrez traiter un favori toutes les 15 secondes tout en n'utilisant chaque jeton qu'une fois toutes les 150 secondes.</p>
</div>
<div class="alert alert-warning">
<h5><i class="bi bi-exclamation-triangle"></i> Utilisation responsable</h5>
<p>Bien que cette méthode soit efficace, veuillez l'utiliser de manière responsable :</p>
<ul>
<li>Utilisez uniquement vos propres jetons (n'empruntez pas les jetons d'autres personnes)</li>
<li>Respectez un délai raisonnable entre les requêtes pour ne pas surcharger l'instance</li>
<li>Limitez le nombre de jetons à ce qui est nécessaire pour votre migration</li>
</ul>
</div>
</div>
</div>
<!-- Étape 1: Téléchargement du fichier JSON -->
<div class="card shadow-sm mb-4" id="step1">
<div class="card-header text-white">
<h3 class="card-title h5 mb-0">1. Importer vos favoris Mastodon</h3>
</div>
<div class="card-body">
<p>Téléchargez d'abord votre fichier d'export de favoris depuis Mastodon.</p>
<div class="card bg-light mb-3">
<div class="card-body">
<h5>Comment obtenir mon fichier de favoris ?</h5>
<ol>
<li>Connectez-vous à votre compte Mastodon</li>
<li>Allez dans <strong>Préférences</strong> > <strong>Exporter et importer</strong></li>
<li>Dans la section <strong>Exporter</strong>, cliquez sur <strong>Demander vos favoris</strong></li>
<li>Une fois le fichier prêt, téléchargez-le</li>
</ol>
</div>
</div>
<form id="upload-form" class="mt-4">
<div class="mb-3">
<label for="json-file" class="form-label">Fichier JSON des favoris</label>
<input type="file" class="form-control" id="json-file" name="json_file" accept=".json" required>
</div>
<button type="submit" class="btn btn-primary">Analyser le fichier</button>
</form>
<div id="file-summary" class="alert alert-info mt-3 d-none"></div>
</div>
</div>
<!-- Étape 2: Gestion des tokens -->
<div class="card shadow-sm mb-4" id="tokens">
<div class="card-header text-white">
<h3 class="card-title h5 mb-0">2. Configurer vos jetons d'accès</h3>
</div>
<div class="card-body">
<?php if (!$has_primary_token): ?>
<!-- Formulaire de connexion pour le token principal -->
<div class="card bg-light mb-4">
<div class="card-body">
<h4>Token principal</h4>
<p>Commencez par configurer votre jeton d'accès principal en vous connectant à votre instance Misskey.</p>
<form id="misskey-form" method="post" class="mt-3">
<input type="hidden" name="action" value="connect_token">
<div class="mb-3">
<label for="misskey-instance" class="form-label">Instance Misskey</label>
<input type="text" class="form-control" id="misskey-instance" name="misskey_instance"
placeholder="misskey.io" required>
<div class="form-text">Entrez le nom de domaine de votre instance Misskey (ex: misskey.io)</div>
</div>
<div class="mb-3">
<label for="misskey-token" class="form-label">Jeton d'accès</label>
<input type="password" class="form-control" id="misskey-token" name="misskey_token"
placeholder="Votre jeton d'accès Misskey" required>
<div class="form-text">Collez le jeton d'accès généré dans les paramètres de votre compte Misskey</div>
</div>
<button type="submit" class="btn btn-primary">Se connecter à Misskey</button>
</form>
</div>
</div>
<?php else: ?>
<!-- Informations sur l'instance connectée -->
<div class="alert alert-success mb-4">
<strong>Connecté à <?php echo htmlspecialchars($instance); ?></strong>
<p class="mb-0">Vous êtes authentifié avec votre token principal.</p>
<div class="mt-2">
<a href="multitokens.php?action=logout" class="btn btn-sm btn-outline-dark">Déconnexion complète</a>
</div>
</div>
<!-- Gestion des tokens supplémentaires -->
<div class="card mb-4">
<div class="card-header">
<h4 class="h5 mb-0">Tokens supplémentaires</h4>
</div>
<div class="card-body">
<p>Pour accélérer le transfert, ajoutez des jetons d'accès supplémentaires de votre compte Misskey.</p>
<div class="alert alert-info">
<strong>Conseil :</strong> Pour créer plusieurs jetons, connectez-vous à votre instance Misskey, allez dans <strong>Paramètres > API</strong> et générez plusieurs jetons d'accès avec les mêmes permissions que votre token principal.
</div>
<form method="post" class="mb-4">
<input type="hidden" name="action" value="add_token">
<div class="row g-3 align-items-end">
<div class="col-md-4">
<label for="token-name" class="form-label">Nom du jeton</label>
<input type="text" class="form-control" id="token-name" name="token_name" placeholder="Token 1" required>
</div>
<div class="col-md-6">
<label for="token-value" class="form-label">Valeur du jeton</label>
<input type="password" class="form-control" id="token-value" name="token_value" placeholder="Jeton d'accès supplémentaire" required>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary w-100">Ajouter</button>
</div>
</div>
</form>
<h5>Tokens configurés (<?php echo $total_tokens_count; ?>)</h5>
<div id="tokens-container">
<!-- Token principal -->
<div class="card mb-2 token-card">
<div class="card-body py-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<span class="token-status ready"></span>
<strong>Token principal</strong>
<span class="badge bg-primary ms-2">Principal</span>
</div>
<div>
<span class="text-muted small">Prêt</span>
</div>
</div>
</div>
</div>
<!-- Tokens supplémentaires -->
<?php if (isset($_SESSION['additional_tokens']) && !empty($_SESSION['additional_tokens'])): ?>
<?php foreach ($_SESSION['additional_tokens'] as $token_id => $token_data): ?>
<div class="card mb-2 token-card" data-token-id="<?php echo $token_id; ?>">
<div class="card-body py-2">
<div class="d-flex justify-content-between align-items-center">
<div>
<span class="token-status ready"></span>
<strong><?php echo htmlspecialchars($token_data['name']); ?></strong>
<?php if (isset($token_data['usage_count']) && $token_data['usage_count'] > 0): ?>
<span class="badge bg-secondary ms-2"><?php echo $token_data['usage_count']; ?> utilisations</span>
<?php endif; ?>
</div>
<div class="d-flex align-items-center">
<span class="text-muted small me-3">Prêt</span>
<form method="post" onsubmit="return confirm('Êtes-vous sûr de vouloir supprimer ce jeton ?');">
<input type="hidden" name="action" value="remove_token">
<input type="hidden" name="token_id" value="<?php echo $token_id; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger">Supprimer</button>
</form>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="alert alert-warning">
<p class="mb-0">Aucun token supplémentaire configuré. Ajoutez-en pour accélérer le processus.</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
<!-- Étape 3: Migration avec tokens multiples -->
<div class="card shadow-sm mb-4" id="step3">
<div class="card-header text-white">
<h3 class="card-title h5 mb-0">3. Migration avec rotation des jetons</h3>
</div>
<div class="card-body">
<?php if ($has_primary_token && $total_tokens_count > 0): ?>
<!-- Configuration de la migration -->
<div class="mb-4">
<h4>Configuration</h4>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="delay-between-tokens" class="form-label">Délai entre deux jetons (secondes)</label>
<input type="range" class="form-range" id="delay-between-tokens" min="5" max="60" value="15" step="5">
<div class="d-flex justify-content-between">
<span class="small">5s</span>
<span id="delay-value">15s</span>
<span class="small">60s</span>
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="token-cooldown" class="form-label">Délai avant réutilisation d'un jeton (secondes)</label>
<input type="range" class="form-range" id="token-cooldown" min="60" max="300" value="150" step="30">
<div class="d-flex justify-content-between">
<span class="small">60s</span>
<span id="cooldown-value">150s</span>
<span class="small">5min</span>
</div>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="auto-adjust" checked>
<label class="form-check-label" for="auto-adjust">Ajustement automatique des délais en cas d'erreur</label>
</div>
</div>
<!-- Barre de progression -->
<div class="mb-4">
<h4>Progression</h4>
<div class="mb-3">
<label class="form-label">Progression globale</label>
<div class="progress" style="height: 20px;">
<div id="global-progress" class="progress-bar" role="progressbar"
style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div>
</div>
<div class="mb-3">
<label class="form-label d-flex justify-content-between">
<span>Statistiques</span>
<span id="stats-display">-</span>
</label>
<div class="progress" style="height: 10px;">
<div id="success-progress" class="progress-bar bg-success" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<div id="skip-progress" class="progress-bar bg-info" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<div id="warn-progress" class="progress-bar bg-warning" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<div id="error-progress" class="progress-bar bg-danger" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<label class="form-label mb-0">Journal des opérations</label>
<button type="button" class="btn btn-sm btn-outline-secondary" id="clear-log">Effacer</button>
</div>
<div id="log-container" class="border p-3 bg-light" style="max-height: 200px; overflow-y: auto;">
<div id="operation-log"></div>
</div>
</div>
</div>
<!-- Contrôles de la migration -->
<div class="d-flex justify-content-between">
<button type="button" class="btn btn-primary" id="start-migration">Démarrer la migration</button>
<div>
<button type="button" class="btn btn-warning d-none" id="pause-migration">Pause</button>
<button type="button" class="btn btn-danger" id="cancel-migration">Annuler</button>
</div>
</div>
<?php else: ?>
<div class="alert alert-warning">
<h5>Configuration incomplète</h5>
<p>Pour démarrer la migration, vous devez :</p>
<ol>
<li>Télécharger votre fichier d'export de favoris</li>
<li>Configurer au moins un jeton d'accès</li>
</ol>
<p class="mb-0">Complétez les étapes précédentes avant de continuer.</p>
</div>
<?php endif; ?>
</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="js/multitokens.js"></script>
</body>
</html>