272 lines
8.2 KiB
PHP
272 lines
8.2 KiB
PHP
<?php
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use danog\MadelineProto\API;
|
|
use Predis\Client;
|
|
|
|
$redis = new Client(['host' => getenv('REDIS_HOST') ?: 'redis']);
|
|
|
|
// Router
|
|
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
|
|
|
// API: Queue
|
|
if ($method === 'POST' && $uri === '/api/queue') {
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
if (!$data || !isset($data['username'], $data['message'])) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Missing username or message']);
|
|
exit;
|
|
}
|
|
|
|
// Normalize Username (Add @ if missing and not numeric/phone)
|
|
$username = trim($data['username']);
|
|
if (!empty($username) && !is_numeric($username) && $username[0] !== '+' && $username[0] !== '@') {
|
|
$username = '@' . $username;
|
|
}
|
|
$data['username'] = $username;
|
|
|
|
$jobId = uniqid('job_');
|
|
$data['id'] = $jobId;
|
|
$data['status'] = 'queued';
|
|
$data['created_at'] = date('Y-m-d H:i:s');
|
|
|
|
// Store status
|
|
$redis->hmset("job:$jobId", $data);
|
|
// Push to processing queue
|
|
$redis->rpush('call_queue', json_encode($data));
|
|
// Push to history list (for display)
|
|
$redis->lpush('job_history', $jobId);
|
|
|
|
echo json_encode(['job_id' => $jobId, 'status' => 'queued', 'normalized_username' => $username]);
|
|
exit;
|
|
}
|
|
|
|
// API: Jobs History (Paginated)
|
|
if ($method === 'GET' && $uri === '/api/jobs') {
|
|
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
|
$limit = isset($_GET['limit']) ? max(1, min(100, (int)$_GET['limit'])) : 20;
|
|
|
|
$start = ($page - 1) * $limit;
|
|
$end = $start + $limit - 1;
|
|
|
|
$total = $redis->llen('job_history');
|
|
$ids = $redis->lrange('job_history', $start, $end);
|
|
|
|
$jobs = [];
|
|
foreach ($ids as $id) {
|
|
$job = $redis->hgetall("job:$id");
|
|
if ($job) {
|
|
$jobs[] = $job;
|
|
}
|
|
}
|
|
|
|
echo json_encode([
|
|
'jobs' => $jobs,
|
|
'total' => $total,
|
|
'page' => $page,
|
|
'limit' => $limit,
|
|
'total_pages' => ceil($total / $limit)
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// API: Preview Audio
|
|
if ($method === 'POST' && $uri === '/api/preview') {
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
if (!$data || !isset($data['message'])) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Missing message']);
|
|
exit;
|
|
}
|
|
|
|
try {
|
|
require_once __DIR__ . '/TTS.php';
|
|
$path = TTS::generate($data['message'], 'es');
|
|
$filename = basename($path);
|
|
echo json_encode(['url' => "/data/$filename"]);
|
|
} catch (\Throwable $e) {
|
|
http_response_code(500);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
// API: Status
|
|
if ($method === 'GET' && $uri === '/api/status') {
|
|
$jobId = $_GET['id'] ?? null;
|
|
if (!$jobId) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Missing id']);
|
|
exit;
|
|
}
|
|
|
|
$status = $redis->hgetall("job:$jobId");
|
|
echo json_encode($status ?: ['status' => 'not_found']);
|
|
exit;
|
|
}
|
|
|
|
// API: Telegram Status
|
|
if ($method === 'GET' && $uri === '/api/me') {
|
|
$status = $redis->get('telegram:status') ?: 'unknown';
|
|
$me = json_decode($redis->get('telegram:me') ?: '{}', true);
|
|
|
|
echo json_encode(['status' => $status, 'me' => $me]);
|
|
exit;
|
|
}
|
|
|
|
// API: Legacy Send Message (Compatibility)
|
|
if ($method === 'GET' && $uri === '/sendmessage') {
|
|
$user = $_GET['user'] ?? null;
|
|
$message = $_GET['message'] ?? null;
|
|
$audioParam = $_GET['audio'] ?? null;
|
|
|
|
if (!$user || !$message) {
|
|
echo "Error: Missing user or message";
|
|
exit;
|
|
}
|
|
|
|
// Normalize Username (Add @ if missing and not numeric/phone)
|
|
$user = trim($user);
|
|
if (!empty($user) && !is_numeric($user) && $user[0] !== '+' && $user[0] !== '@') {
|
|
$user = '@' . $user;
|
|
}
|
|
|
|
$audio = 0;
|
|
if ($audioParam && strtolower($audioParam) === 'yes') {
|
|
$audio = 1;
|
|
}
|
|
|
|
$jobId = uniqid('job_');
|
|
$data = [
|
|
'id' => $jobId,
|
|
'username' => $user, // Map 'user' to 'username' as used internally
|
|
'message' => $message,
|
|
'audio_enabled' => ($audio === 1),
|
|
'status' => 'queued',
|
|
'created_at' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
// Store status
|
|
$redis->hmset("job:$jobId", $data);
|
|
// Push to processing queue
|
|
$redis->rpush('call_queue', json_encode($data));
|
|
// Push to history list
|
|
$redis->lpush('job_history', $jobId);
|
|
|
|
// Return legacy format
|
|
echo "Inserted {$user} - {$message} - {$audio}";
|
|
exit;
|
|
}
|
|
|
|
// API: Logout
|
|
if ($method === 'POST' && $uri === '/api/logout') {
|
|
touch('/app/data/logout.signal');
|
|
echo json_encode(['status' => 'logout_requested']);
|
|
exit;
|
|
}
|
|
|
|
// API: Save Config
|
|
if ($method === 'POST' && $uri === '/api/config') {
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
if (!isset($data['api_id'], $data['api_hash'], $data['phone'])) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Missing api_id, api_hash, or phone']);
|
|
exit;
|
|
}
|
|
|
|
file_put_contents('/app/data/config.json', json_encode([
|
|
'api_id' => trim($data['api_id']),
|
|
'api_hash' => trim($data['api_hash']),
|
|
'phone' => trim($data['phone']),
|
|
'call_timeout' => isset($data['call_timeout']) ? (int)$data['call_timeout'] : 15
|
|
]));
|
|
|
|
// Force worker restart to pick up new config
|
|
touch('/app/data/logout.signal');
|
|
|
|
echo json_encode(['status' => 'config_saved']);
|
|
exit;
|
|
}
|
|
|
|
// API: Reset Config
|
|
if ($method === 'POST' && $uri === '/api/reset') {
|
|
if (file_exists('/app/data/config.json')) {
|
|
unlink('/app/data/config.json');
|
|
}
|
|
|
|
// Force worker restart (which will then see missing config)
|
|
touch('/app/data/logout.signal');
|
|
|
|
echo json_encode(['status' => 'reset_complete']);
|
|
exit;
|
|
}
|
|
|
|
// Frontend: Dashboard
|
|
if ($method === 'GET' && ($uri === '/' || $uri === '/index.php')) {
|
|
include 'dashboard_view.php';
|
|
exit;
|
|
}
|
|
|
|
// Frontend: Login UI
|
|
if ($method === 'GET' && $uri === '/login') {
|
|
include 'login_view.php';
|
|
exit;
|
|
}
|
|
|
|
// Frontend: Login Logic
|
|
if ($method === 'POST' && $uri === '/login') {
|
|
// This is complex because MP interactive login is stateful.
|
|
// We will use a dedicated session API wrapper or just basic calls if possible.
|
|
// For simplicity, we try to Instantiate MP and check state.
|
|
|
|
// Load Config
|
|
if (!file_exists('/app/data/config.json')) {
|
|
echo json_encode(['status' => 'error', 'message' => 'Config missing']);
|
|
exit;
|
|
}
|
|
$config = json_decode(file_get_contents('/app/data/config.json'), true);
|
|
|
|
$settings = new \danog\MadelineProto\Settings();
|
|
$settings->setAppInfo((new \danog\MadelineProto\Settings\AppInfo())
|
|
->setApiId((int)$config['api_id'])
|
|
->setApiHash($config['api_hash'])
|
|
);
|
|
|
|
$MadelineProto = new API('/app/data/session.madeline', $settings);
|
|
|
|
$phone = $_POST['phone'] ?? $config['phone'] ?? null;
|
|
$code = $_POST['code'] ?? null;
|
|
$password = $_POST['password'] ?? null;
|
|
|
|
try {
|
|
if ($phone && !$code && !$password) {
|
|
// Create lock file to pause worker
|
|
touch('/app/data/login.lock');
|
|
|
|
$MadelineProto->phoneLogin($phone);
|
|
echo json_encode(['status' => 'code_requested']);
|
|
} elseif ($code) {
|
|
$authorization = $MadelineProto->completePhoneLogin($code);
|
|
// If we are here, login was successful (otherwise exception)
|
|
unlink('/app/data/login.lock');
|
|
echo json_encode(['status' => 'success']);
|
|
|
|
} elseif ($password) {
|
|
$authorization = $MadelineProto->complete2faLogin($password);
|
|
unlink('/app/data/login.lock');
|
|
echo json_encode(['status' => 'success']);
|
|
|
|
} else {
|
|
echo json_encode(['status' => 'error', 'message' => 'Invalid Request']);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
// Remove lock on error so worker can resume or user can retry
|
|
if (file_exists('/app/data/login.lock')) {
|
|
unlink('/app/data/login.lock');
|
|
}
|
|
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
|
}
|
|
exit;
|
|
}
|