- New /social page with left/right layout (form + post list) - Social topbar link - Tables: social_posts, social_targets (project-agnostic posts, per-target project refs) - CRUD: create, edit, duplicate, delete, retry - Image upload (JPEG/PNG/GIF/WebP, 10MB max) stored in data/social-uploads/ - Per-platform image toggle (Discord multipart, Mastodon /api/v2/media, LinkedIn Assets API) - bin/dispatch-social.php cron dispatcher (every minute via /etc/cron.d) - Settings: eligible projects section to enable bot projects as social account sources - Platforms: Discord (webhook), Mastodon, LinkedIn personal profile Cron setup: * * * * * www-data /usr/bin/php /opt/hackmancms/bin/dispatch-social.php >> /var/log/hackman_social.log 2>&1 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.5 KiB
PHP
58 lines
1.5 KiB
PHP
<?php
|
|
define('ROOT', dirname(__DIR__));
|
|
require ROOT . '/lib/bootstrap.php';
|
|
|
|
$uri = rtrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/') ?: '/';
|
|
|
|
// Public routes — no auth required
|
|
if ($uri === '/login') {
|
|
if (Auth::check()) { header('Location: /'); exit; }
|
|
include ROOT . '/views/login.php';
|
|
exit;
|
|
}
|
|
if ($uri === '/api/auth') {
|
|
include ROOT . '/web/api/auth.php';
|
|
exit;
|
|
}
|
|
|
|
// LinkedIn OAuth callback — session required but no full auth check
|
|
// (LinkedIn redirects back here; user's browser session is active)
|
|
if ($uri === '/linkedin/callback') {
|
|
include ROOT . '/web/linkedin_callback.php';
|
|
exit;
|
|
}
|
|
|
|
// All other routes require login
|
|
Auth::requireLogin();
|
|
ProjectTypes::load();
|
|
|
|
if ($uri === '/' || $uri === '/dashboard') {
|
|
include ROOT . '/views/dashboard.php';
|
|
|
|
} elseif ($uri === '/settings') {
|
|
include ROOT . '/views/settings.php';
|
|
|
|
} elseif ($uri === '/audit') {
|
|
include ROOT . '/views/audit.php';
|
|
|
|
} elseif ($uri === '/social') {
|
|
include ROOT . '/views/social.php';
|
|
|
|
} elseif (preg_match('#^/project/(\d+)$#', $uri, $m)) {
|
|
$project_id = (int)$m[1];
|
|
include ROOT . '/views/project/view.php';
|
|
|
|
} elseif (preg_match('#^/api/([a-z_]+)#', $uri, $m)) {
|
|
$api_file = ROOT . '/web/api/' . $m[1] . '.php';
|
|
if (file_exists($api_file)) {
|
|
include $api_file;
|
|
} else {
|
|
http_response_code(404);
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['error' => 'API endpoint not found']);
|
|
}
|
|
|
|
} else {
|
|
http_response_code(404);
|
|
include ROOT . '/views/error.php';
|
|
}
|