Files
zuevav e5a88665cd mailn
2026-04-30 15:14:09 +03:00

230 lines
8.3 KiB
PHP

<?php
/**
* Cron script to publish scheduled posts
* Run this every minute: * * * * * php /path/to/cron_publish.php
*/
// Set timezone to Moscow
date_default_timezone_set('Europe/Moscow');
// Prevent web access
if (php_sapi_name() !== 'cli' && !isset($_GET['cron_key'])) {
// Allow web access with secret key for hosts without cron
$configFile = __DIR__ . '/config.php';
if (file_exists($configFile)) {
$config = require $configFile;
$cronKey = $config['cron_key'] ?? '';
if (empty($cronKey) || $_GET['cron_key'] !== $cronKey) {
http_response_code(403);
die('Access denied');
}
} else {
http_response_code(403);
die('Access denied');
}
}
// Load config - must assign to $config variable
$config = require __DIR__ . '/config.php';
require_once __DIR__ . '/classes/VKAPI.php';
require_once __DIR__ . '/classes/TelegramBot.php';
// Log file for debugging
$logFile = __DIR__ . '/data/cron_log.txt';
function logMessage($msg) {
global $logFile;
$timestamp = date('Y-m-d H:i:s');
file_put_contents($logFile, "[$timestamp] $msg\n", FILE_APPEND);
echo $msg . "\n";
}
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
if (!file_exists($scheduledFile)) {
logMessage("No scheduled posts file");
exit;
}
$posts = json_decode(file_get_contents($scheduledFile), true) ?: [];
$now = time();
$updated = false;
logMessage("Starting cron run. Now: " . date('Y-m-d H:i:s', $now) . " (" . $now . ")");
$pendingCount = count(array_filter($posts, fn($p) => $p['status'] === 'pending'));
logMessage("Found $pendingCount pending posts");
foreach ($posts as &$post) {
// Skip if not pending
if ($post['status'] !== 'pending') {
continue;
}
$scheduledTime = strtotime($post['scheduled_time']);
logMessage("Post {$post['id']}: scheduled for " . date('Y-m-d H:i:s', $scheduledTime) . " ($scheduledTime)");
if ($scheduledTime > $now) {
$diff = $scheduledTime - $now;
logMessage(" -> Not yet time (in $diff seconds)");
continue;
}
logMessage(" -> Time to publish!");
// Prepare text with tags
$baseText = $post['text'] ?? '';
$tags = $post['tags'] ?? [];
if (!empty($tags)) {
$tagsString = implode(' ', array_map(function($t) { return '#' . $t; }, $tags));
$baseText = $baseText ? $baseText . "\n\n" . $tagsString : $tagsString;
}
// Collect all photo URLs
$photoUrls = $post['photos'] ?? [];
$uploadedFiles = $post['uploaded_files'] ?? [];
foreach ($uploadedFiles as $file) {
if (!empty($file['url'])) {
$photoUrls[] = $file['url'];
}
}
logMessage(" Photos: " . count($photoUrls));
// Check if cross-promo was enabled for this post
$crossPromoEnabled = $post['cross_promo'] ?? false;
logMessage(" Cross-promo enabled: " . ($crossPromoEnabled ? 'yes' : 'no'));
// Load cross-promo settings if enabled
$crossPromoFile = __DIR__ . '/data/cross_promo.json';
$crossPromo = [];
if ($crossPromoEnabled && file_exists($crossPromoFile)) {
$crossPromo = json_decode(file_get_contents($crossPromoFile), true) ?: [];
}
$hasCrossPromo = $crossPromoEnabled && (!empty($crossPromo['telegramLink']) || !empty($crossPromo['vkLink']));
// Check which platforms we're posting to
$platforms = $post['platforms'] ?? [];
$postingToTelegram = false;
$postingToVk = false;
foreach ($platforms as $p) {
$pType = $p['type'] ?? $p;
if ($pType === 'telegram') $postingToTelegram = true;
if ($pType === 'vk') $postingToVk = true;
}
// Prepare platform-specific texts with cross-promo
$textForTelegram = $baseText;
$textForVk = $baseText;
if ($hasCrossPromo) {
// Add VK link to Telegram posts
if (!empty($crossPromo['vkLink']) && $postingToTelegram) {
$linkText = $crossPromo['textForTg'] ?? 'Мой канал ВКонтакте';
$textForTelegram .= "\n\n<a href=\"{$crossPromo['vkLink']}\">{$linkText}</a>";
logMessage(" Cross-promo: VK link added to TG text");
}
// Add Telegram link to VK posts
if (!empty($crossPromo['telegramLink']) && $postingToVk) {
$linkText = $crossPromo['textForVk'] ?? 'Мой канал в Telegram';
$textForVk .= "\n\n{$linkText}: {$crossPromo['telegramLink']}";
logMessage(" Cross-promo: TG link added to VK text");
}
}
$results = [];
logMessage(" Platforms: " . json_encode($platforms));
logMessage(" TG token set: " . (!empty($config['telegram']['bot_token']) ? 'yes' : 'NO'));
logMessage(" VK token set: " . (!empty($config['vk']['access_token']) ? 'yes' : 'NO'));
if (empty($platforms)) {
logMessage(" WARNING: No platforms specified!");
}
foreach ($platforms as $platform) {
$type = $platform['type'] ?? $platform;
$target = $platform['target'] ?? '';
logMessage(" Processing platform: $type, target: $target");
if ($type === 'telegram') {
if (empty($config['telegram']['bot_token'])) {
logMessage(" Telegram: SKIPPED - no bot token in config");
continue;
}
try {
$telegram = new TelegramBot($config['telegram']['bot_token']);
// Get first channel if no target specified
if (empty($target)) {
$channels = $telegram->getChannels();
logMessage(" Telegram channels: " . count($channels));
if (!empty($channels)) {
$target = $channels[0]['id'];
}
}
if ($target) {
logMessage(" Posting to Telegram channel: $target");
$result = $telegram->post($target, $photoUrls, $textForTelegram, 'HTML');
$results['telegram'] = ['success' => true, 'result' => $result];
logMessage(" Telegram: OK");
} else {
$results['telegram'] = ['success' => false, 'error' => 'No target channel'];
logMessage(" Telegram: No target channel");
}
} catch (Exception $e) {
$results['telegram'] = ['success' => false, 'error' => $e->getMessage()];
logMessage(" Telegram: ERROR - {$e->getMessage()}");
}
}
if ($type === 'vk') {
if (empty($config['vk']['access_token'])) {
logMessage(" VK: SKIPPED - no access token in config");
continue;
}
try {
$vk = new VKAPI($config['vk']['access_token']);
// Get first group if no target specified
if (empty($target)) {
$validation = $vk->validateToken();
if ($validation['valid'] && ($validation['type'] ?? '') === 'community') {
$target = $validation['user_id'];
} else {
$groups = $vk->getGroups();
if (!empty($groups)) {
$target = $groups[0]['id'];
}
}
}
if ($target) {
logMessage(" Posting to VK group: $target");
$result = $vk->post($target, $photoUrls, strip_tags($textForVk));
$results['vk'] = ['success' => true, 'result' => $result];
logMessage(" VK: OK");
} else {
$results['vk'] = ['success' => false, 'error' => 'No target group'];
logMessage(" VK: No target group");
}
} catch (Exception $e) {
$results['vk'] = ['success' => false, 'error' => $e->getMessage()];
logMessage(" VK: ERROR - {$e->getMessage()}");
}
}
}
// Update post status
$post['status'] = 'published';
$post['published_at'] = date('Y-m-d H:i:s');
$post['results'] = $results;
$updated = true;
logMessage("Post {$post['id']} marked as published");
}
// Save updated posts
if ($updated) {
file_put_contents($scheduledFile, json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
logMessage("Posts file updated");
}
logMessage("Done\n---");