254 lines
11 KiB
PHP

<?php
/**
* FavMasToKey - Traitement des favoris
*/
// Définir la constante pour inclure les fichiers
define('FAVMASTOKEY', true);
// Forcer les en-têtes JSON dès le début pour éviter tout conflit
header('Content-Type: application/json');
// Activer la capture d'erreurs
set_error_handler(function($errno, $errstr, $errfile, $errline) {
echo json_encode([
'success' => false,
'message' => "Erreur PHP: $errstr (ligne $errline dans $errfile)",
]);
exit;
});
try {
// Inclure les fichiers requis
require_once 'includes/config.php';
require_once 'includes/functions.php';
// Vérifier que la requête est en POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']);
exit;
}
// Vérifier que l'utilisateur est authentifié
if (!isset($_SESSION['misskey_token']) || empty($_SESSION['misskey_token'])) {
http_response_code(401);
echo json_encode(['success' => false, 'message' => 'Non authentifié']);
exit;
}
// Récupérer l'instance Misskey
$misskey_instance = isset($_SESSION['misskey_instance']) ? $_SESSION['misskey_instance'] : '';
if (empty($misskey_instance)) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Instance Misskey non définie']);
exit;
}
// Récupérer le token d'accès
$token = $_SESSION['misskey_token'];
// Récupérer les données envoyées
$input_data = file_get_contents('php://input');
$input = json_decode($input_data, true);
if (!$input || !isset($input['batch']) || !is_array($input['batch'])) {
http_response_code(400);
echo json_encode([
'success' => false,
'message' => 'Données invalides',
'debug' => [
'received' => $input_data ? substr($input_data, 0, 200) . '...' : 'Aucune donnée reçue'
]
]);
exit;
}
// Récupérer le lot à traiter
$batch = $input['batch'];
$currentIndex = isset($input['currentIndex']) ? (int)$input['currentIndex'] : 0;
$totalItems = isset($input['totalItems']) ? (int)$input['totalItems'] : count($batch);
$slowMode = isset($input['slowMode']) ? (bool)$input['slowMode'] : false;
$delaySeconds = isset($input['delaySeconds']) ? (int)$input['delaySeconds'] : 30;
// Ajuster le délai entre les requêtes selon le mode et la valeur personnalisée
if ($slowMode) {
$delayMs = $delaySeconds * 1000; // Convertir en millisecondes
} else {
$delayMs = $config['delay_between_requests'];
}
// Résultats du traitement
$results = [];
// Traiter chaque URL du lot
foreach ($batch as $index => $url) {
// Extraire les informations de l'URL
$urlParts = parse_url($url);
// Vérifier que l'URL est valide
if (!$urlParts || !isset($urlParts['host']) || !isset($urlParts['path'])) {
$results[] = [
'status' => 'error',
'message' => "URL invalide: $url",
'error_type' => 'invalid_url'
];
continue;
}
// Ajouter un log pour déboguer
error_log("Recherche de l'URL: " . $url . " sur l'instance: " . $misskey_instance);
// Rechercher la note sur Misskey à partir de l'URL
$searchResult = search_federated_note($misskey_instance, $url, $token);
// Vérifier si la recherche a réussi ET si les données contiennent un ID valide
if ($searchResult['success'] && isset($searchResult['data']) && !empty($searchResult['data'])) {
// Vérifier et extraire l'ID de manière sécurisée
if (isset($searchResult['data']['id']) && !empty($searchResult['data']['id'])) {
$noteId = $searchResult['data']['id'];
// Tenter d'ajouter la note aux favoris
$favoriteResult = add_to_favorites($misskey_instance, $noteId, $token);
if ($favoriteResult['success']) {
$results[] = [
'status' => 'success',
'message' => "Ajouté aux favoris: $url"
];
} else {
// Vérifier si c'est une erreur de "déjà ajouté aux favoris"
$errorMessage = isset($favoriteResult['data']['error']['message'])
? $favoriteResult['data']['error']['message']
: (isset($favoriteResult['message']) ? $favoriteResult['message'] : 'Erreur inconnue');
// Extraire le code d'erreur si disponible
$errorCode = isset($favoriteResult['data']['error']['code'])
? $favoriteResult['data']['error']['code']
: '';
// Déterminer le type d'erreur
$errorType = 'api_error';
if (strpos($errorMessage, 'already') !== false) {
$errorType = 'already_favorited';
} elseif (strpos($errorMessage, 'rate limit') !== false || strpos($errorMessage, 'limit exceeded') !== false || $errorCode == 'RATE_LIMIT_EXCEEDED') {
$errorType = 'rate_limit';
} elseif (strpos($errorMessage, 'permission') !== false || $errorCode == 'NO_PERMISSION') {
$errorType = 'permission_denied';
}
if ($errorType === 'already_favorited') {
$results[] = [
'status' => 'info',
'message' => "Déjà dans vos favoris: $url",
'error_type' => $errorType
];
} else if ($errorType === 'rate_limit') {
$results[] = [
'status' => 'warning',
'message' => "Limite d'API atteinte pour: $url. " . ($slowMode ? "Essayez d'augmenter le délai." : "Activez le mode ultra-lent."),
'error_type' => $errorType,
'details' => $errorMessage
];
} else {
$results[] = [
'status' => 'error',
'message' => "Erreur lors de l'ajout aux favoris: $errorMessage",
'error_type' => $errorType,
'details' => $errorCode ? "Code: $errorCode" : ""
];
}
}
} else {
// L'ID est manquant ou vide dans la réponse
$dataKeys = is_array($searchResult['data']) ? array_keys($searchResult['data']) : ['non_array'];
$results[] = [
'status' => 'error',
'message' => "Note trouvée mais sans ID valide: $url",
'error_type' => 'invalid_response',
'details' => "Clés disponibles: " . implode(', ', $dataKeys)
];
// Log pour déboguer
error_log("Structure de données reçue: " . json_encode($searchResult['data']));
}
} else {
// Note non trouvée ou erreur de recherche
$errorMessage = isset($searchResult['message']) ? $searchResult['message'] : "Publication introuvable";
$errorCode = isset($searchResult['error_code']) ? $searchResult['error_code'] : '';
$httpCode = isset($searchResult['http_code']) ? $searchResult['http_code'] : '';
// Déterminer le type d'erreur
$errorType = 'not_found';
if (strpos($errorMessage, 'rate limit') !== false || $httpCode == 429 ||
(isset($searchResult['data']['error']) &&
(isset($searchResult['data']['error']['code']) && $searchResult['data']['error']['code'] == 'RATE_LIMIT_EXCEEDED'))) {
$errorType = 'rate_limit';
$errorMessage = $slowMode
? "Limite d'API atteinte malgré le mode ultra-lent. Essayez d'augmenter le délai ou attendez quelques minutes."
: "Limite d'API atteinte. Activez le mode ultra-lent ou attendez quelques minutes.";
} elseif ($httpCode >= 500) {
$errorType = 'server_error';
$errorMessage = "L'instance Misskey rencontre des problèmes. Statut HTTP: $httpCode";
} elseif ($httpCode == 401 || $httpCode == 403) {
$errorType = 'auth_error';
$errorMessage = "Problème d'authentification ou de permission. Vérifiez votre token.";
} elseif ($httpCode == 0) {
$errorType = 'network_error';
$errorMessage = "Problème de connexion réseau. Vérifiez votre connectivité.";
}
$results[] = [
'status' => $errorType == 'rate_limit' ? 'warning' : 'error',
'message' => "Publication non trouvée sur le réseau fédéré: $url ($errorMessage)",
'error_type' => $errorType,
'details' => $httpCode ? "HTTP: $httpCode" : ""
];
// Ajouter des infos de debug
if (isset($searchResult['data']) && is_array($searchResult['data'])) {
error_log("Données reçues pour URL $url: " . json_encode($searchResult['data']));
}
}
// Pause pour éviter le rate limiting - utilise le délai approprié selon le mode
usleep($delayMs * 1000);
}
// Si au moins une erreur de rate limit a été détectée, suggérer le mode lent
$hasRateLimitErrors = false;
foreach ($results as $result) {
if (isset($result['error_type']) && $result['error_type'] === 'rate_limit') {
$hasRateLimitErrors = true;
break;
}
}
// Renvoyer les résultats
echo json_encode([
'success' => true,
'results' => $results,
'progress' => [
'current' => $currentIndex + count($batch),
'total' => $totalItems,
'percentage' => round((($currentIndex + count($batch)) / $totalItems) * 100, 2)
],
'suggestions' => [
'use_slow_mode' => $hasRateLimitErrors && !$slowMode,
'increase_delay' => $hasRateLimitErrors && $slowMode && $delaySeconds < 60
],
'config' => [
'slow_mode' => $slowMode,
'delay_seconds' => $delaySeconds
]
]);
} catch (Exception $e) {
// Capturer toutes les exceptions et renvoyer un message d'erreur formaté en JSON
echo json_encode([
'success' => false,
'message' => 'Exception: ' . $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
}