mailn
This commit is contained in:
@@ -0,0 +1,949 @@
|
||||
<?php
|
||||
/**
|
||||
* API endpoints for AJAX requests
|
||||
* VK, Telegram, Flickr integration
|
||||
*/
|
||||
|
||||
// Set timezone to Moscow
|
||||
date_default_timezone_set('Europe/Moscow');
|
||||
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Load configuration
|
||||
$configFile = __DIR__ . '/config.php';
|
||||
if (!file_exists($configFile)) {
|
||||
echo json_encode(['error' => 'Configuration not found']);
|
||||
exit;
|
||||
}
|
||||
$config = require $configFile;
|
||||
|
||||
// Autoload classes
|
||||
spl_autoload_register(function ($class) {
|
||||
$file = __DIR__ . '/classes/' . $class . '.php';
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create FlickrAPI instance with OAuth if available
|
||||
*/
|
||||
function createFlickrAPI($config) {
|
||||
$flickr = new FlickrAPI(
|
||||
$config['flickr']['api_key'],
|
||||
$config['flickr']['api_secret'] ?? '',
|
||||
$config['flickr_user_id'] ?? ''
|
||||
);
|
||||
|
||||
// Add OAuth if tokens exist
|
||||
if (!empty($config['flickr']['api_secret'])) {
|
||||
$oauth = new FlickrOAuth(
|
||||
$config['flickr']['api_key'],
|
||||
$config['flickr']['api_secret']
|
||||
);
|
||||
if ($oauth->isAuthorized()) {
|
||||
$flickr->setOAuth($oauth);
|
||||
}
|
||||
}
|
||||
|
||||
return $flickr;
|
||||
}
|
||||
|
||||
// Check authentication
|
||||
$auth = new Auth();
|
||||
if (!$auth->isAuthenticated()) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => 'Not authenticated']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get action
|
||||
$action = $_GET['action'] ?? $_POST['action'] ?? '';
|
||||
|
||||
try {
|
||||
switch ($action) {
|
||||
|
||||
// ============ CONVERTER ============
|
||||
|
||||
case 'convert':
|
||||
$urls = $_POST['urls'] ?? '';
|
||||
$size = $_POST['size'] ?? 'Large';
|
||||
$format = $_POST['format'] ?? 'bbcode';
|
||||
|
||||
$parser = new FlickrParser();
|
||||
$generator = new FormatGenerator();
|
||||
|
||||
$parsed = $parser->parseMultiple($urls);
|
||||
|
||||
if (empty($parsed)) {
|
||||
echo json_encode(['error' => 'No valid Flickr URLs found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$images = [];
|
||||
$flickr = null;
|
||||
|
||||
// Check if we need API to get full URLs
|
||||
$needApi = false;
|
||||
foreach ($parsed as $item) {
|
||||
if ($item['type'] === 'page' || $item['type'] === 'short') {
|
||||
$needApi = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($needApi && !empty($config['flickr']['api_key'])) {
|
||||
$flickr = createFlickrAPI($config);
|
||||
}
|
||||
|
||||
foreach ($parsed as $item) {
|
||||
$imageData = [
|
||||
'photo_id' => $item['photo_id'],
|
||||
'title' => 'Image',
|
||||
];
|
||||
|
||||
if ($item['type'] === 'direct') {
|
||||
// Direct URL - modify size suffix
|
||||
$imageData['url'] = $parser->buildImageUrl($item, $size);
|
||||
$imageData['original'] = $parser->buildImageUrl($item, 'Original');
|
||||
} elseif ($flickr) {
|
||||
// Need to fetch from API
|
||||
try {
|
||||
$info = $flickr->getPhotoInfo($item['photo_id']);
|
||||
$sizes = $flickr->getPhotoSizes($item['photo_id']);
|
||||
|
||||
$imageData['title'] = $info['title']['_content'] ?? 'Image';
|
||||
|
||||
// Get requested size
|
||||
$sizeMap = [
|
||||
'Large' => 'Large',
|
||||
'Large1600' => 'Large 1600',
|
||||
'Large2048' => 'Large 2048',
|
||||
'Original' => 'Original',
|
||||
'Medium640' => 'Medium 640',
|
||||
'Medium' => 'Medium',
|
||||
];
|
||||
|
||||
$sizeName = $sizeMap[$size] ?? 'Large';
|
||||
$imageData['url'] = $sizes[$sizeName]['url'] ?? $sizes['Large']['url'] ?? '';
|
||||
$imageData['original'] = $sizes['Original']['url'] ?? $sizes['Large']['url'] ?? '';
|
||||
|
||||
} catch (Exception $e) {
|
||||
$imageData['url'] = $item['original_url'];
|
||||
$imageData['original'] = $item['original_url'];
|
||||
}
|
||||
} else {
|
||||
// No API - use original URL
|
||||
$imageData['url'] = $item['original_url'];
|
||||
$imageData['original'] = $item['original_url'];
|
||||
}
|
||||
|
||||
$images[] = $imageData;
|
||||
}
|
||||
|
||||
$output = $generator->generateMultiple($format, $images);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'output' => $output,
|
||||
'count' => count($images),
|
||||
]);
|
||||
break;
|
||||
|
||||
// ============ FLICKR GALLERY ============
|
||||
|
||||
case 'flickr_albums':
|
||||
if (empty($config['flickr']['api_key'])) {
|
||||
echo json_encode(['error' => 'Flickr API not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$flickr = createFlickrAPI($config);
|
||||
$page = (int)($_GET['page'] ?? 1);
|
||||
$perPage = (int)($_GET['per_page'] ?? 50);
|
||||
$result = $flickr->getPhotosets($page, $perPage);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'albums' => $result['albums'],
|
||||
'page' => $result['page'],
|
||||
'pages' => $result['pages'],
|
||||
'total' => $result['total'],
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'flickr_photos':
|
||||
if (empty($config['flickr']['api_key'])) {
|
||||
echo json_encode(['error' => 'Flickr API not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$flickr = createFlickrAPI($config);
|
||||
$page = (int)($_GET['page'] ?? 1);
|
||||
$perPage = (int)($_GET['per_page'] ?? 50);
|
||||
$albumId = $_GET['album_id'] ?? '';
|
||||
$search = $_GET['search'] ?? '';
|
||||
|
||||
if ($search) {
|
||||
$result = $flickr->searchPhotos($search, $page, $perPage);
|
||||
} elseif ($albumId) {
|
||||
$result = $flickr->getPhotosetPhotos($albumId, $page, $perPage);
|
||||
} else {
|
||||
$result = $flickr->getPhotos($page, $perPage);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'photos' => $result['photos'],
|
||||
'pagination' => [
|
||||
'page' => $result['page'],
|
||||
'pages' => $result['pages'],
|
||||
'total' => $result['total'],
|
||||
],
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'flickr_photo_sizes':
|
||||
if (empty($config['flickr']['api_key'])) {
|
||||
echo json_encode(['error' => 'Flickr API not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$photoId = $_GET['photo_id'] ?? '';
|
||||
if (!$photoId) {
|
||||
echo json_encode(['error' => 'Photo ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$flickr = createFlickrAPI($config);
|
||||
$sizes = $flickr->getPhotoSizes($photoId);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'sizes' => $sizes,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'flickr_oauth_status':
|
||||
if (empty($config['flickr']['api_secret'])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'authorized' => false,
|
||||
'message' => 'API secret not configured',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$oauth = new FlickrOAuth(
|
||||
$config['flickr']['api_key'],
|
||||
$config['flickr']['api_secret']
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'authorized' => $oauth->isAuthorized(),
|
||||
'auth_url' => 'flickr_auth.php',
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'flickr_original_url':
|
||||
if (empty($config['flickr']['api_key'])) {
|
||||
echo json_encode(['error' => 'Flickr API not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$photoId = $_GET['photo_id'] ?? '';
|
||||
if (!$photoId) {
|
||||
echo json_encode(['error' => 'Photo ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$flickr = createFlickrAPI($config);
|
||||
$originalUrl = $flickr->getOriginalUrl($photoId);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'original_url' => $originalUrl,
|
||||
'has_oauth' => $flickr->hasOAuth(),
|
||||
]);
|
||||
break;
|
||||
|
||||
// ============ TELEGRAM ============
|
||||
|
||||
case 'telegram_status':
|
||||
if (empty($config['telegram']['bot_token'])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => false,
|
||||
'message' => 'Bot token not configured',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$telegram = new TelegramBot($config['telegram']['bot_token']);
|
||||
|
||||
try {
|
||||
$me = $telegram->getMe();
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => true,
|
||||
'bot_name' => $me['first_name'] ?? '',
|
||||
'bot_username' => $me['username'] ?? '',
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => false,
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'telegram_channels':
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'channels' => $config['telegram']['channels'] ?? [],
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'telegram_post':
|
||||
if (empty($config['telegram']['bot_token'])) {
|
||||
echo json_encode(['error' => 'Telegram bot not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$channelId = $_POST['channel_id'] ?? '';
|
||||
$text = $_POST['text'] ?? '';
|
||||
$photos = json_decode($_POST['photos'] ?? '[]', true);
|
||||
$parseMode = $_POST['parse_mode'] ?? 'HTML';
|
||||
|
||||
if (!$channelId) {
|
||||
echo json_encode(['error' => 'Channel ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$telegram = new TelegramBot($config['telegram']['bot_token']);
|
||||
|
||||
$result = $telegram->post($channelId, $photos, $text, $parseMode);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'result' => $result,
|
||||
]);
|
||||
break;
|
||||
|
||||
// ============ VK ============
|
||||
|
||||
case 'vk_status':
|
||||
if (empty($config['vk']['access_token'])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => false,
|
||||
'message' => 'VK access token not configured',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$vk = new VKAPI($config['vk']['access_token']);
|
||||
|
||||
try {
|
||||
$validation = $vk->validateToken();
|
||||
if ($validation['valid']) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => true,
|
||||
'user_name' => $validation['user_name'] ?? '',
|
||||
'user_id' => $validation['user_id'] ?? '',
|
||||
'type' => $validation['type'] ?? 'user',
|
||||
'screen_name' => $validation['screen_name'] ?? '',
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => false,
|
||||
'message' => $validation['error'] ?? 'Invalid token',
|
||||
]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'connected' => false,
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'vk_groups':
|
||||
if (empty($config['vk']['access_token'])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'groups' => [],
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$vk = new VKAPI($config['vk']['access_token']);
|
||||
|
||||
// First check if this is a community token
|
||||
try {
|
||||
$validation = $vk->validateToken();
|
||||
if ($validation['valid'] && ($validation['type'] ?? '') === 'community') {
|
||||
// Community token - return the community itself
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'groups' => [[
|
||||
'id' => $validation['user_id'],
|
||||
'name' => $validation['user_name'] ?? 'Сообщество',
|
||||
'screen_name' => $validation['screen_name'] ?? '',
|
||||
]],
|
||||
'type' => 'community',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Continue to try groups.get
|
||||
}
|
||||
|
||||
try {
|
||||
$groups = $vk->getGroups();
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'groups' => $groups,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'groups' => [],
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'vk_post':
|
||||
if (empty($config['vk']['access_token'])) {
|
||||
echo json_encode(['error' => 'VK not configured']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$groupId = $_POST['group_id'] ?? '';
|
||||
$text = $_POST['text'] ?? '';
|
||||
$photos = json_decode($_POST['photos'] ?? '[]', true);
|
||||
|
||||
if (!$groupId) {
|
||||
echo json_encode(['error' => 'Group ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$vk = new VKAPI($config['vk']['access_token']);
|
||||
|
||||
$result = $vk->post($groupId, $photos, $text);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'result' => $result,
|
||||
]);
|
||||
break;
|
||||
|
||||
// ============ FILE UPLOAD ============
|
||||
|
||||
case 'upload_file':
|
||||
if (empty($_FILES['file'])) {
|
||||
echo json_encode(['error' => 'No file uploaded']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['file'];
|
||||
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'video/mp4', 'video/quicktime', 'video/webm'];
|
||||
|
||||
if (!in_array($file['type'], $allowedTypes)) {
|
||||
echo json_encode(['error' => 'Неподдерживаемый тип файла: ' . $file['type']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($file['size'] > 50 * 1024 * 1024) {
|
||||
echo json_encode(['error' => 'Файл слишком большой (макс 50MB)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Create uploads directory
|
||||
$uploadsDir = __DIR__ . '/uploads';
|
||||
if (!is_dir($uploadsDir)) {
|
||||
mkdir($uploadsDir, 0755, true);
|
||||
}
|
||||
|
||||
// Generate unique filename
|
||||
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
$filename = uniqid('upload_') . '_' . time() . '.' . $ext;
|
||||
$filepath = $uploadsDir . '/' . $filename;
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $filepath)) {
|
||||
// Get the URL
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$path = dirname($_SERVER['REQUEST_URI']);
|
||||
$url = $protocol . '://' . $host . $path . '/uploads/' . $filename;
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'url' => $url,
|
||||
'filename' => $filename,
|
||||
'type' => $file['type'],
|
||||
'size' => $file['size']
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить файл']);
|
||||
}
|
||||
break;
|
||||
|
||||
// ============ MULTI-PLATFORM POSTING ============
|
||||
|
||||
case 'multi_post':
|
||||
$platforms = json_decode($_POST['platforms'] ?? '[]', true);
|
||||
$text = $_POST['text'] ?? '';
|
||||
$photos = json_decode($_POST['photos'] ?? '[]', true);
|
||||
$uploadedFiles = json_decode($_POST['uploaded_files'] ?? '[]', true);
|
||||
$parseMode = $_POST['parse_mode'] ?? 'HTML';
|
||||
|
||||
// Merge Flickr photos and uploaded files
|
||||
if (!empty($uploadedFiles)) {
|
||||
foreach ($uploadedFiles as $uploadedFile) {
|
||||
if (!empty($uploadedFile['url'])) {
|
||||
$photos[] = $uploadedFile['url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($platforms)) {
|
||||
echo json_encode(['error' => 'No platforms selected']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($platforms as $platform) {
|
||||
$type = $platform['type'] ?? '';
|
||||
$target = $platform['target'] ?? '';
|
||||
|
||||
switch ($type) {
|
||||
case 'telegram':
|
||||
if (empty($config['telegram']['bot_token'])) {
|
||||
$results['telegram'] = [
|
||||
'success' => false,
|
||||
'error' => 'Telegram not configured',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
$telegram = new TelegramBot($config['telegram']['bot_token']);
|
||||
$result = $telegram->post($target, $photos, $text, $parseMode);
|
||||
$results['telegram'] = [
|
||||
'success' => true,
|
||||
'result' => $result,
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
$results['telegram'] = [
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'vk':
|
||||
if (empty($config['vk']['access_token'])) {
|
||||
$results['vk'] = [
|
||||
'success' => false,
|
||||
'error' => 'VK not configured',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
$vk = new VKAPI($config['vk']['access_token']);
|
||||
// VK uses plain text, remove HTML/Markdown formatting
|
||||
$vkText = strip_tags($text);
|
||||
$result = $vk->post($target, $photos, $vkText);
|
||||
$vkResult = [
|
||||
'success' => true,
|
||||
'result' => $result,
|
||||
];
|
||||
// Include warning if photos were posted as links
|
||||
if (isset($result['warning'])) {
|
||||
$vkResult['warning'] = $result['warning'];
|
||||
}
|
||||
$results['vk'] = $vkResult;
|
||||
} catch (Exception $e) {
|
||||
$results['vk'] = [
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'instagram':
|
||||
// Instagram requires Facebook Business API
|
||||
$results['instagram'] = [
|
||||
'success' => false,
|
||||
'error' => 'Instagram posting requires Facebook Business API setup',
|
||||
];
|
||||
break;
|
||||
|
||||
default:
|
||||
$results[$type] = [
|
||||
'success' => false,
|
||||
'error' => 'Unknown platform',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'results' => $results,
|
||||
]);
|
||||
break;
|
||||
|
||||
// ============ TAG PRESETS ============
|
||||
|
||||
case 'get_presets':
|
||||
$presetsFile = __DIR__ . '/data/tag_presets.json';
|
||||
if (file_exists($presetsFile)) {
|
||||
$presets = json_decode(file_get_contents($presetsFile), true);
|
||||
echo json_encode(['success' => true, 'presets' => $presets ?: []]);
|
||||
} else {
|
||||
// Return default presets
|
||||
$defaultPresets = [
|
||||
['id' => 1, 'name' => 'BJD', 'tags' => ['bjd', 'doll', 'куклы']],
|
||||
['id' => 2, 'name' => 'Фото', 'tags' => ['фото', 'photo', 'photography']],
|
||||
['id' => 3, 'name' => 'Арт', 'tags' => ['art', 'artwork', 'творчество']],
|
||||
['id' => 4, 'name' => 'Handmade', 'tags' => ['handmade', 'ручнаяработа']],
|
||||
['id' => 5, 'name' => 'Faceup', 'tags' => ['faceup', 'мейк']],
|
||||
['id' => 6, 'name' => 'Outfit', 'tags' => ['outfit', 'одежда']],
|
||||
];
|
||||
echo json_encode(['success' => true, 'presets' => $defaultPresets]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'save_presets':
|
||||
$presetsFile = __DIR__ . '/data/tag_presets.json';
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$presets = $input['presets'] ?? [];
|
||||
|
||||
// Validate presets structure
|
||||
if (!is_array($presets)) {
|
||||
echo json_encode(['error' => 'Invalid presets format']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ensure data directory exists
|
||||
$dataDir = __DIR__ . '/data';
|
||||
if (!is_dir($dataDir)) {
|
||||
mkdir($dataDir, 0755, true);
|
||||
}
|
||||
|
||||
// Save presets
|
||||
if (file_put_contents($presetsFile, json_encode($presets, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true, 'message' => 'Presets saved']);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Failed to save presets']);
|
||||
}
|
||||
break;
|
||||
|
||||
// ============ SCHEDULED POSTS ============
|
||||
|
||||
case 'get_scheduled_posts':
|
||||
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
|
||||
if (file_exists($scheduledFile)) {
|
||||
$posts = json_decode(file_get_contents($scheduledFile), true) ?: [];
|
||||
// Sort by scheduled time
|
||||
usort($posts, function($a, $b) {
|
||||
return strtotime($a['scheduled_time']) - strtotime($b['scheduled_time']);
|
||||
});
|
||||
echo json_encode(['success' => true, 'posts' => $posts]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'posts' => []]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create_scheduled_post':
|
||||
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
|
||||
$dataDir = __DIR__ . '/data';
|
||||
|
||||
if (!is_dir($dataDir)) {
|
||||
mkdir($dataDir, 0755, true);
|
||||
}
|
||||
|
||||
$posts = file_exists($scheduledFile) ? json_decode(file_get_contents($scheduledFile), true) ?: [] : [];
|
||||
|
||||
$newPost = [
|
||||
'id' => uniqid('sched_'),
|
||||
'text' => $_POST['text'] ?? '',
|
||||
'tags' => json_decode($_POST['tags'] ?? '[]', true),
|
||||
'photos' => json_decode($_POST['photos'] ?? '[]', true),
|
||||
'uploaded_files' => json_decode($_POST['uploaded_files'] ?? '[]', true),
|
||||
'platforms' => json_decode($_POST['platforms'] ?? '[]', true),
|
||||
'scheduled_time' => $_POST['scheduled_time'] ?? '',
|
||||
'cross_promo' => ($_POST['cross_promo'] ?? '0') === '1',
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'status' => 'pending'
|
||||
];
|
||||
|
||||
if (empty($newPost['scheduled_time'])) {
|
||||
echo json_encode(['error' => 'Укажите дату и время публикации']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (strtotime($newPost['scheduled_time']) < time()) {
|
||||
echo json_encode(['error' => 'Нельзя запланировать на прошедшее время']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$posts[] = $newPost;
|
||||
|
||||
if (file_put_contents($scheduledFile, json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true, 'post' => $newPost]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update_scheduled_post':
|
||||
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
|
||||
$postId = $_POST['id'] ?? '';
|
||||
|
||||
if (!$postId) {
|
||||
echo json_encode(['error' => 'ID поста не указан']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$posts = file_exists($scheduledFile) ? json_decode(file_get_contents($scheduledFile), true) ?: [] : [];
|
||||
|
||||
$found = false;
|
||||
foreach ($posts as &$post) {
|
||||
if ($post['id'] === $postId && $post['status'] === 'pending') {
|
||||
$post['text'] = $_POST['text'] ?? $post['text'];
|
||||
$post['tags'] = isset($_POST['tags']) ? json_decode($_POST['tags'], true) : $post['tags'];
|
||||
$post['photos'] = isset($_POST['photos']) ? json_decode($_POST['photos'], true) : $post['photos'];
|
||||
$post['uploaded_files'] = isset($_POST['uploaded_files']) ? json_decode($_POST['uploaded_files'], true) : $post['uploaded_files'];
|
||||
$post['platforms'] = isset($_POST['platforms']) ? json_decode($_POST['platforms'], true) : $post['platforms'];
|
||||
$post['scheduled_time'] = $_POST['scheduled_time'] ?? $post['scheduled_time'];
|
||||
$post['cross_promo'] = isset($_POST['cross_promo']) ? ($_POST['cross_promo'] === '1') : ($post['cross_promo'] ?? false);
|
||||
$post['updated_at'] = date('Y-m-d H:i:s');
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
echo json_encode(['error' => 'Пост не найден или уже опубликован']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (file_put_contents($scheduledFile, json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true, 'message' => 'Пост обновлён']);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete_scheduled_post':
|
||||
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
|
||||
$postId = $_POST['id'] ?? '';
|
||||
|
||||
if (!$postId) {
|
||||
echo json_encode(['error' => 'ID поста не указан']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$posts = file_exists($scheduledFile) ? json_decode(file_get_contents($scheduledFile), true) ?: [] : [];
|
||||
$initialCount = count($posts);
|
||||
|
||||
$posts = array_filter($posts, function($post) use ($postId) {
|
||||
return $post['id'] !== $postId || $post['status'] !== 'pending';
|
||||
});
|
||||
|
||||
if (count($posts) === $initialCount) {
|
||||
echo json_encode(['error' => 'Пост не найден или уже опубликован']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$posts = array_values($posts); // Re-index
|
||||
|
||||
if (file_put_contents($scheduledFile, json_encode($posts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true, 'message' => 'Пост удалён']);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'get_published_posts':
|
||||
$scheduledFile = __DIR__ . '/data/scheduled_posts.json';
|
||||
if (file_exists($scheduledFile)) {
|
||||
$posts = json_decode(file_get_contents($scheduledFile), true) ?: [];
|
||||
// Filter only published posts
|
||||
$published = array_filter($posts, function($p) {
|
||||
return $p['status'] === 'published';
|
||||
});
|
||||
// Sort by published_at descending (newest first)
|
||||
usort($published, function($a, $b) {
|
||||
return strtotime($b['published_at'] ?? $b['scheduled_time']) - strtotime($a['published_at'] ?? $a['scheduled_time']);
|
||||
});
|
||||
// Return last 10
|
||||
$published = array_slice($published, 0, 10);
|
||||
echo json_encode(['success' => true, 'posts' => array_values($published)]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'posts' => []]);
|
||||
}
|
||||
break;
|
||||
|
||||
// ============ CROSS-PROMO SETTINGS ============
|
||||
|
||||
case 'save_cross_promo':
|
||||
$settingsFile = __DIR__ . '/data/cross_promo.json';
|
||||
$dataDir = __DIR__ . '/data';
|
||||
|
||||
if (!is_dir($dataDir)) {
|
||||
mkdir($dataDir, 0755, true);
|
||||
}
|
||||
|
||||
$settings = [
|
||||
'telegramLink' => trim($_POST['telegramLink'] ?? ''),
|
||||
'vkLink' => trim($_POST['vkLink'] ?? ''),
|
||||
'textForTg' => trim($_POST['textForTg'] ?? 'Мой канал ВКонтакте'),
|
||||
'textForVk' => trim($_POST['textForVk'] ?? 'Мой канал в Telegram')
|
||||
];
|
||||
|
||||
if (file_put_contents($settingsFile, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'get_cross_promo':
|
||||
$settingsFile = __DIR__ . '/data/cross_promo.json';
|
||||
if (file_exists($settingsFile)) {
|
||||
$settings = json_decode(file_get_contents($settingsFile), true) ?: [];
|
||||
echo json_encode(['success' => true, 'settings' => $settings]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'settings' => [
|
||||
'telegramLink' => '',
|
||||
'vkLink' => '',
|
||||
'textForTg' => 'Мой канал ВКонтакте',
|
||||
'textForVk' => 'Мой канал в Telegram'
|
||||
]]);
|
||||
}
|
||||
break;
|
||||
|
||||
// ============ DRAFTS ============
|
||||
|
||||
case 'save_draft':
|
||||
$draftFile = __DIR__ . '/data/draft.json';
|
||||
$dataDir = __DIR__ . '/data';
|
||||
|
||||
if (!is_dir($dataDir)) {
|
||||
mkdir($dataDir, 0755, true);
|
||||
}
|
||||
|
||||
$draft = [
|
||||
'text' => $_POST['text'] ?? '',
|
||||
'tags' => json_decode($_POST['tags'] ?? '[]', true),
|
||||
'photos' => json_decode($_POST['photos'] ?? '[]', true),
|
||||
'uploaded_files' => json_decode($_POST['uploaded_files'] ?? '[]', true),
|
||||
'updated_at' => date('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
if (file_put_contents($draftFile, json_encode($draft, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE))) {
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить черновик']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'get_draft':
|
||||
$draftFile = __DIR__ . '/data/draft.json';
|
||||
if (file_exists($draftFile)) {
|
||||
$draft = json_decode(file_get_contents($draftFile), true) ?: [];
|
||||
echo json_encode(['success' => true, 'draft' => $draft]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'draft' => null]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'clear_draft':
|
||||
$draftFile = __DIR__ . '/data/draft.json';
|
||||
if (file_exists($draftFile)) {
|
||||
unlink($draftFile);
|
||||
}
|
||||
echo json_encode(['success' => true]);
|
||||
break;
|
||||
|
||||
// ============ SETTINGS ============
|
||||
|
||||
case 'save_vk_token':
|
||||
$token = trim($_POST['token'] ?? '');
|
||||
|
||||
if (empty($token)) {
|
||||
echo json_encode(['error' => 'Токен не может быть пустым']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Update config.php with new VK token
|
||||
$configFile = __DIR__ . '/config.php';
|
||||
$configContent = file_get_contents($configFile);
|
||||
|
||||
// Check if vk section exists
|
||||
if (strpos($configContent, "'vk'") !== false) {
|
||||
// Update existing vk access_token
|
||||
$configContent = preg_replace(
|
||||
"/('vk'\s*=>\s*\[\s*'access_token'\s*=>\s*')[^']*(')/s",
|
||||
"$1" . addslashes($token) . "$2",
|
||||
$configContent
|
||||
);
|
||||
} else {
|
||||
// Add vk section before the closing ];
|
||||
$vkSection = "\n 'vk' => [\n 'access_token' => '" . addslashes($token) . "',\n ],\n";
|
||||
$configContent = preg_replace("/(\];)\s*$/", $vkSection . "$1", $configContent);
|
||||
}
|
||||
|
||||
if (file_put_contents($configFile, $configContent)) {
|
||||
// Validate the new token
|
||||
require_once __DIR__ . '/classes/VKAPI.php';
|
||||
$vk = new VKAPI($token);
|
||||
$validation = $vk->validateToken();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Токен сохранён',
|
||||
'validation' => $validation
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Не удалось сохранить config.php']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'change_password':
|
||||
$currentPassword = $_POST['current_password'] ?? '';
|
||||
$newPassword = $_POST['new_password'] ?? '';
|
||||
|
||||
if (strlen($newPassword) < 8) {
|
||||
echo json_encode(['error' => 'New password must be at least 8 characters']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$username = $auth->getCurrentUser();
|
||||
if ($auth->changePassword($username, $currentPassword, $newPassword)) {
|
||||
echo json_encode(['success' => true, 'message' => 'Password changed successfully']);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Current password is incorrect']);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
echo json_encode(['error' => 'Unknown action']);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
}
|
||||
Reference in New Issue
Block a user