mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-12 01:36:54 +02:00
Un jeton de page collé à la main meurt au bout de 60 jours — ou du jour au lendemain si le mot de passe change, si le compte perd son rôle d'admin ou si Meta révoque l'autorisation — et on ne l'apprenait qu'à la première publication en échec : le contrôle quotidien existant se contentait de marquer la page « expired ». On reprend la chaîne recommandée par Meta, comme dans PleinR : autorisation OAuth, échange du code contre un jeton utilisateur longue durée (~60 j), puis dérivation des jetons de page — qui n'expirent pas. Le jeton utilisateur est conservé chiffré sur chaque page : c'est lui qui permet au TokenManager de régénérer un jeton révoqué sans intervention humaine, et de se prolonger lui-même avant échéance. - facebook_config : App ID / App Secret de l'application, saisis dans les paramètres (chiffrés en base) ou par variables d'environnement. - /api/facebook : configuration, connexion OAuth, callback qui crée ou met à jour les pages, contrôle d'une page à la demande, contrôle global. - TokenManager : /debug_token pour connaître l'état réel du jeton, puis renouvellement automatique 15 jours avant l'échéance ou dès révocation ; repli sur le contrôle historique tant que l'application n'est pas configurée ou si Facebook est injoignable, pour ne pas passer l'UI au rouge sur une panne réseau. Le cron passe à deux fois par jour. - Les comptes Instagram professionnels rattachés à une page reçoivent le même traitement, puisqu'ils publient avec le jeton de cette page. - L'UI montre l'état constaté (jeton valide, bientôt expiré, révoqué), l'erreur à corriger et un bouton de contrôle immédiat ; un bandeau signale les pages à reconnecter. - /api/pages ne renvoie plus aucun jeton au navigateur, seulement un indicateur de renouvellement automatique. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qns6Gcpd95bCHWUxySh4Ew
52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
import cron from 'node-cron';
|
|
import { TokenManager } from './services/token_manager';
|
|
import { AnalyticsService } from './services/analytics';
|
|
import { purgeOldMedia } from './services/media-purge';
|
|
import { tiktokService } from './services/tiktok';
|
|
|
|
export function startTokenCron() {
|
|
// Toutes les 2 minutes — suivi des publications TikTok (API asynchrone)
|
|
cron.schedule('*/2 * * * *', async () => {
|
|
try {
|
|
await tiktokService.syncPendingPublications();
|
|
} catch (error) {
|
|
console.error('[Cron] TikTok publish status sync failed:', error);
|
|
}
|
|
});
|
|
console.log('[Cron] TikTok publish status job scheduled (*/2 * * * *).');
|
|
|
|
// Deux fois par jour (00:00 et 12:00) — contrôle et renouvellement des jetons.
|
|
// Un jeton révoqué par Meta ne prévient pas : passer deux fois par jour
|
|
// réduit d'autant la fenêtre pendant laquelle une publication échouerait.
|
|
cron.schedule('0 0,12 * * *', async () => {
|
|
console.log('[Cron] Running token check...');
|
|
const results = await TokenManager.checkAndRefreshTokens();
|
|
const renewed = results.filter(r => r.renewed).length;
|
|
const failing = results.filter(r => r.status === 'expired' || r.status === 'error').length;
|
|
console.log(`[Cron] Token check done: ${results.length} contrôlés, ${renewed} renouvelés, ${failing} en échec.`);
|
|
});
|
|
console.log('[Cron] Token refresh job scheduled (0 0,12 * * *).');
|
|
|
|
// Run twice daily (08:00 and 20:00) — Analytics sync for all pages
|
|
cron.schedule('0 8,20 * * *', async () => {
|
|
console.log('[Cron] Running analytics sync for all pages...');
|
|
try {
|
|
await AnalyticsService.syncAllPages();
|
|
} catch (error) {
|
|
console.error('[Cron] Analytics sync failed:', error);
|
|
}
|
|
});
|
|
console.log('[Cron] Analytics sync job scheduled (0 8,20 * * *).');
|
|
|
|
// Run every day at 03:00 AM — Cleanup old media from Cloudinary and DB
|
|
cron.schedule('0 3 * * *', async () => {
|
|
console.log('[Cron] Running daily media purge check...');
|
|
try {
|
|
await purgeOldMedia();
|
|
} catch (error) {
|
|
console.error('[Cron] Media purge check failed:', error);
|
|
}
|
|
});
|
|
console.log('[Cron] Media purge job scheduled (0 3 * * *).');
|
|
}
|