?
| Current Path : /home/w/e/b/webyoo/www/nathan-ai/site/ |
| Current File : /home/w/e/b/webyoo/www/nathan-ai/site/publish.php |
<?php
/**
* publish.php — publie LE prochain post de la file sur LinkedIn.
* Appelé par le cron (3x/jour). Publie 1 post par exécution.
*
* Usage manuel de test : php publish.php
*/
require __DIR__ . '/lib.php';
$c = cfg();
// --- Sécurités de base ---
if (empty($c['access_token']) || empty($c['author_urn'])) {
logline("ABANDON: access_token ou author_urn manquant dans config.php.");
exit(1);
}
// --- Charger la file de posts ---
if (!file_exists($c['queue_file'])) { logline("ABANDON: posts.json introuvable."); exit(1); }
$posts = json_decode(file_get_contents($c['queue_file']), true);
if (!is_array($posts) || count($posts) === 0) { logline("ABANDON: posts.json vide ou invalide."); exit(1); }
// --- Charger l'état (index du prochain post) ---
$state = ['next' => 0];
if (file_exists($c['state_file'])) {
$s = json_decode(file_get_contents($c['state_file']), true);
if (is_array($s) && isset($s['next'])) $state = $s;
}
$idx = (int)$state['next'];
// Fin de file ?
if ($idx >= count($posts)) {
if (!empty($c['loop_queue'])) {
$idx = 0; // on recommence
} else {
logline("File terminée ($idx/" . count($posts) . "). Réalimente posts.json puis remets state.json à {\"next\":0}.");
exit(0);
}
}
// --- Le texte à publier ---
$post = $posts[$idx];
$commentary = is_array($post) ? ($post['text'] ?? '') : (string)$post;
$commentary = trim($commentary);
if ($commentary === '') { logline("Post #$idx vide, on saute."); $state['next'] = $idx + 1; file_put_contents($c['state_file'], json_encode($state)); exit(0); }
// --- Appel API LinkedIn (Posts API versionnée) ---
$payload = [
'author' => $c['author_urn'],
'commentary' => $commentary,
'visibility' => 'PUBLIC',
'distribution'=> [
'feedDistribution' => 'MAIN_FEED',
'targetEntities' => [],
'thirdPartyDistributionChannels'=> [],
],
'lifecycleState' => 'PUBLISHED',
'isReshareDisabledByAuthor'=> false,
];
$headers = [
'Authorization: Bearer ' . $c['access_token'],
'Content-Type: application/json',
'X-Restli-Protocol-Version: 2.0.0',
'LinkedIn-Version: ' . $c['linkedin_version'],
];
list($code, $resp) = http_request('POST', 'https://api.linkedin.com/rest/posts', $headers, json_encode($payload));
if ($code >= 200 && $code < 300) {
// LinkedIn renvoie l'ID du post dans l'en-tête x-restli-id, ici on log le succès simple.
$preview = mb_substr(str_replace("\n", ' ', $commentary), 0, 70);
logline("OK (#$idx) publié [$code] : \"$preview...\"");
$state['next'] = $idx + 1;
file_put_contents($c['state_file'], json_encode($state));
exit(0);
} else {
logline("ECHEC (#$idx) [$code] : $resp");
// On n'incrémente PAS : le prochain cron réessaiera le même post.
// Si erreur 401 -> jeton expiré (voir guide, renouvellement).
exit(1);
}