- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
380 lines
10 KiB
PHP
380 lines
10 KiB
PHP
<?php
|
|
/*******************************************************************************************************************
|
|
| Software Name : EasyStream
|
|
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
|
|
| Software Author : (c) Sami Ahmed
|
|
|*******************************************************************************************************************
|
|
|
|
|
|*******************************************************************************************************************
|
|
| This source file is subject to the EasyStream Proprietary License Agreement.
|
|
|
|
|
| By using this software, you acknowledge have read this Agreement and agree to be bound thereby.
|
|
|*******************************************************************************************************************
|
|
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|
|
|*******************************************************************************************************************/
|
|
|
|
define('_ISVALID', true);
|
|
|
|
// Include core configuration
|
|
include_once '../f_core/config.core.php';
|
|
|
|
// Set JSON response headers
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
|
|
|
|
// Handle preflight requests
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
http_response_code(200);
|
|
exit();
|
|
}
|
|
|
|
try {
|
|
// Initialize social system
|
|
$social = VSocial::getInstance();
|
|
|
|
// Get request method and path
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
|
$path = $_SERVER['PATH_INFO'] ?? $_SERVER['REQUEST_URI'] ?? '';
|
|
$path = parse_url($path, PHP_URL_PATH);
|
|
$pathParts = array_filter(explode('/', $path));
|
|
|
|
// Get current user
|
|
$userId = VSession::isLoggedIn() ? $_SESSION['user_id'] : null;
|
|
|
|
// Route the request
|
|
switch ($method) {
|
|
case 'POST':
|
|
handlePostRequest($social, $pathParts, $userId);
|
|
break;
|
|
|
|
case 'GET':
|
|
handleGetRequest($social, $pathParts, $userId);
|
|
break;
|
|
|
|
case 'DELETE':
|
|
handleDeleteRequest($social, $pathParts, $userId);
|
|
break;
|
|
|
|
default:
|
|
sendError('Method not allowed', 405);
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
VLogger::getInstance()->error('Social API error', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
|
|
sendError('Internal server error', 500);
|
|
}
|
|
|
|
/**
|
|
* Handle POST requests
|
|
*/
|
|
function handlePostRequest($social, $pathParts, $userId)
|
|
{
|
|
$action = end($pathParts);
|
|
$data = getJsonInput();
|
|
|
|
switch ($action) {
|
|
case 'vote':
|
|
handleVote($social, $data, $userId);
|
|
break;
|
|
|
|
case 'comment':
|
|
handleAddComment($social, $data, $userId);
|
|
break;
|
|
|
|
case 'share':
|
|
handleShare($social, $data, $userId);
|
|
break;
|
|
|
|
default:
|
|
sendError('Invalid action', 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle GET requests
|
|
*/
|
|
function handleGetRequest($social, $pathParts, $userId)
|
|
{
|
|
$action = end($pathParts);
|
|
|
|
switch ($action) {
|
|
case 'comments':
|
|
handleGetComments($social, $_GET, $userId);
|
|
break;
|
|
|
|
case 'replies':
|
|
handleGetReplies($social, $_GET, $userId);
|
|
break;
|
|
|
|
case 'sharing-urls':
|
|
handleGetSharingUrls($social, $_GET);
|
|
break;
|
|
|
|
case 'stats':
|
|
handleGetStats($social, $_GET);
|
|
break;
|
|
|
|
default:
|
|
sendError('Invalid action', 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle DELETE requests
|
|
*/
|
|
function handleDeleteRequest($social, $pathParts, $userId)
|
|
{
|
|
$action = $pathParts[count($pathParts) - 2] ?? '';
|
|
$id = end($pathParts);
|
|
|
|
switch ($action) {
|
|
case 'comment':
|
|
handleDeleteComment($social, $id, $userId);
|
|
break;
|
|
|
|
default:
|
|
sendError('Invalid action', 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle vote action (like/dislike)
|
|
*/
|
|
function handleVote($social, $data, $userId)
|
|
{
|
|
// Validate required fields
|
|
$requiredFields = ['content_type', 'content_id', 'action'];
|
|
foreach ($requiredFields as $field) {
|
|
if (!isset($data[$field]) || empty($data[$field])) {
|
|
sendError("Missing required field: {$field}", 400);
|
|
}
|
|
}
|
|
|
|
// Validate CSRF token
|
|
if (!VSecurity::validateCSRFToken('social_vote', $data['csrf_token'] ?? '')) {
|
|
sendError('Invalid CSRF token', 403);
|
|
}
|
|
|
|
$contentType = $data['content_type'];
|
|
$contentId = $data['content_id'];
|
|
$action = $data['action']; // 'like', 'dislike', or 'remove'
|
|
|
|
// Validate action
|
|
if (!in_array($action, ['like', 'dislike', 'remove'])) {
|
|
sendError('Invalid action. Must be like, dislike, or remove', 400);
|
|
}
|
|
|
|
$result = $social->handleVote($contentType, $contentId, $userId, $action);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle add comment
|
|
*/
|
|
function handleAddComment($social, $data, $userId)
|
|
{
|
|
// Validate required fields
|
|
$requiredFields = ['content_type', 'content_id', 'comment'];
|
|
foreach ($requiredFields as $field) {
|
|
if (!isset($data[$field])) {
|
|
sendError("Missing required field: {$field}", 400);
|
|
}
|
|
}
|
|
|
|
// Validate CSRF token
|
|
if (!VSecurity::validateCSRFToken('social_comment', $data['csrf_token'] ?? '')) {
|
|
sendError('Invalid CSRF token', 403);
|
|
}
|
|
|
|
$contentType = $data['content_type'];
|
|
$contentId = $data['content_id'];
|
|
$comment = $data['comment'];
|
|
$parentId = $data['parent_id'] ?? null;
|
|
|
|
$result = $social->addComment($contentType, $contentId, $userId, $comment, $parentId);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle share tracking
|
|
*/
|
|
function handleShare($social, $data, $userId)
|
|
{
|
|
// Validate required fields
|
|
$requiredFields = ['content_type', 'content_id', 'platform'];
|
|
foreach ($requiredFields as $field) {
|
|
if (!isset($data[$field]) || empty($data[$field])) {
|
|
sendError("Missing required field: {$field}", 400);
|
|
}
|
|
}
|
|
|
|
$contentType = $data['content_type'];
|
|
$contentId = $data['content_id'];
|
|
$platform = $data['platform'];
|
|
|
|
// Track the share
|
|
$social->trackShare($contentType, $contentId, $platform, $userId);
|
|
|
|
sendSuccess(['message' => 'Share tracked successfully']);
|
|
}
|
|
|
|
/**
|
|
* Handle get comments
|
|
*/
|
|
function handleGetComments($social, $params, $userId)
|
|
{
|
|
// Validate required parameters
|
|
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
|
sendError('Missing content_type or content_id parameter', 400);
|
|
}
|
|
|
|
$contentType = $params['content_type'];
|
|
$contentId = $params['content_id'];
|
|
$page = (int)($params['page'] ?? 1);
|
|
$limit = min(50, (int)($params['limit'] ?? 20)); // Max 50 comments per page
|
|
$sort = $params['sort'] ?? 'newest';
|
|
|
|
$result = $social->getComments($contentType, $contentId, $page, $limit, $sort);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle get comment replies
|
|
*/
|
|
function handleGetReplies($social, $params, $userId)
|
|
{
|
|
if (!isset($params['parent_id'])) {
|
|
sendError('Missing parent_id parameter', 400);
|
|
}
|
|
|
|
$parentId = $params['parent_id'];
|
|
$limit = min(50, (int)($params['limit'] ?? 10));
|
|
|
|
$replies = $social->getCommentReplies($parentId, $limit);
|
|
|
|
sendSuccess([
|
|
'replies' => $replies,
|
|
'count' => count($replies)
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Handle get sharing URLs
|
|
*/
|
|
function handleGetSharingUrls($social, $params)
|
|
{
|
|
// Validate required parameters
|
|
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
|
sendError('Missing content_type or content_id parameter', 400);
|
|
}
|
|
|
|
$contentType = $params['content_type'];
|
|
$contentId = $params['content_id'];
|
|
|
|
$result = $social->generateSharingUrls($contentType, $contentId);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle get social stats
|
|
*/
|
|
function handleGetStats($social, $params)
|
|
{
|
|
// Validate required parameters
|
|
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
|
sendError('Missing content_type or content_id parameter', 400);
|
|
}
|
|
|
|
$contentType = $params['content_type'];
|
|
$contentId = $params['content_id'];
|
|
|
|
$result = $social->getSocialStats($contentType, $contentId);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle delete comment
|
|
*/
|
|
function handleDeleteComment($social, $commentId, $userId)
|
|
{
|
|
if (!$commentId) {
|
|
sendError('Missing comment ID', 400);
|
|
}
|
|
|
|
$result = $social->deleteComment($commentId, $userId);
|
|
|
|
if ($result['success']) {
|
|
sendSuccess($result);
|
|
} else {
|
|
sendError($result['error'], 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility functions
|
|
*/
|
|
function getJsonInput()
|
|
{
|
|
$input = file_get_contents('php://input');
|
|
$data = json_decode($input, true);
|
|
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
sendError('Invalid JSON input', 400);
|
|
}
|
|
|
|
return $data ?? [];
|
|
}
|
|
|
|
function sendSuccess($data, $code = 200)
|
|
{
|
|
http_response_code($code);
|
|
echo json_encode([
|
|
'success' => true,
|
|
'data' => $data,
|
|
'timestamp' => time()
|
|
]);
|
|
exit();
|
|
}
|
|
|
|
function sendError($message, $code = 400)
|
|
{
|
|
http_response_code($code);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => $message,
|
|
'timestamp' => time()
|
|
]);
|
|
exit();
|
|
}
|
|
?>
|