mirror of
https://github.com/danog/telerpc.git
synced 2024-11-29 20:29:08 +01:00
Refactor
This commit is contained in:
parent
2d297398fc
commit
3a3bbb63ca
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM danog/madelineproto:latest
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
ADD src /app
|
||||||
|
ADD composer.json /app
|
||||||
|
ADD server.php /app
|
||||||
|
ADD db.php /app
|
||||||
|
ADD entrypoint.sh /
|
||||||
|
|
||||||
|
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
|
||||||
|
php composer-setup.php && \
|
||||||
|
php -r "unlink('composer-setup.php');" && \
|
||||||
|
mv composer.phar /usr/local/bin/composer && \
|
||||||
|
\
|
||||||
|
apk add procps git unzip github-cli openssh && \
|
||||||
|
composer update
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
@ -3,7 +3,10 @@
|
|||||||
"description": "RPC Error reporting API",
|
"description": "RPC Error reporting API",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"danog/madelineproto": "^8"
|
"danog/madelineproto": "^8",
|
||||||
|
"amphp/http-server": "3.x-dev",
|
||||||
|
"amphp/mysql": "3.x-dev",
|
||||||
|
"amphp/http-server-form-parser": "2.x-dev"
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
@ -17,6 +20,11 @@
|
|||||||
"email": "daniil.gentili.dg@gmail.com"
|
"email": "daniil.gentili.dg@gmail.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/Main.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff"
|
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return new PDO('mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=rpc;charset=utf8mb4', 'user', 'pass');
|
use Amp\Mysql\MysqlConfig;
|
||||||
|
|
||||||
|
return new MysqlConfig(
|
||||||
|
host: 'unix_socket=/var/run/mysqld/mysqld.sock',
|
||||||
|
user: 'user',
|
||||||
|
password: 'pass',
|
||||||
|
database: 'rpc',
|
||||||
|
);
|
||||||
|
5
entrypoint.sh
Executable file
5
entrypoint.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
composer update
|
||||||
|
|
||||||
|
php server.php server
|
@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
chdir(__DIR__);
|
|
||||||
|
|
||||||
require 'vendor/autoload.php';
|
|
||||||
|
|
||||||
include 'src/Main.php';
|
|
||||||
|
|
||||||
(new Main())->run();
|
|
7
server.php
Normal file
7
server.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
require __DIR__.'/vendor/autoload.php';
|
||||||
|
|
||||||
|
(new Main)->run($argv[1] === 'serve');
|
263
src/Main.php
263
src/Main.php
@ -1,8 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Amp\Http\HttpStatus;
|
||||||
|
use Amp\Http\Server\DefaultErrorHandler;
|
||||||
|
use Amp\Http\Server\FormParser\Form;
|
||||||
|
use Amp\Http\Server\Request;
|
||||||
|
use Amp\Http\Server\RequestHandler;
|
||||||
|
use Amp\Http\Server\Response;
|
||||||
|
use Amp\Http\Server\SocketHttpServer;
|
||||||
|
use Amp\Log\ConsoleFormatter;
|
||||||
|
use Amp\Log\StreamHandler;
|
||||||
|
use Amp\Mysql\MysqlConfig;
|
||||||
|
use Amp\Mysql\MysqlConnectionPool;
|
||||||
use danog\MadelineProto\RPCErrorException;
|
use danog\MadelineProto\RPCErrorException;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use Monolog\Processor\PsrLogMessageProcessor;
|
||||||
|
|
||||||
final class Main
|
use function Amp\ByteStream\getStdout;
|
||||||
|
|
||||||
|
final class Main implements RequestHandler
|
||||||
{
|
{
|
||||||
private const GLOBAL_CODES = [
|
private const GLOBAL_CODES = [
|
||||||
'FLOOD_WAIT_%d' => 420,
|
'FLOOD_WAIT_%d' => 420,
|
||||||
@ -67,28 +82,35 @@ final class Main
|
|||||||
'MSG_WAIT_FAILED' => -500,
|
'MSG_WAIT_FAILED' => -500,
|
||||||
];
|
];
|
||||||
|
|
||||||
private ?\PDO $pdo = null;
|
private MysqlConnectionPool $pool;
|
||||||
|
public function __construct()
|
||||||
private function connect(): \PDO
|
|
||||||
{
|
{
|
||||||
if ($this->pdo !== null) {
|
$this->pool = new MysqlConnectionPool(include __DIR__.'/../db.php');
|
||||||
return $this->pdo;
|
|
||||||
}
|
|
||||||
$this->pdo = include __DIR__.'/../db.php';
|
|
||||||
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
|
||||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
||||||
|
|
||||||
return $this->pdo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function error(string $message): string
|
private const HEADERS = [
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'access-control-allow-origin' => '*',
|
||||||
|
'access-control-allow-methods' => 'GET, POST, OPTIONS',
|
||||||
|
'access-control-expose-headers' => 'Content-Length,Content-Type,Date,Server,Connection'
|
||||||
|
];
|
||||||
|
|
||||||
|
private static function error(string $message, int $code = HttpStatus::BAD_REQUEST): Response
|
||||||
{
|
{
|
||||||
return \json_encode(['ok' => false, 'description' => $message]);
|
return new Response(
|
||||||
|
$code,
|
||||||
|
self::HEADERS,
|
||||||
|
json_encode(['ok' => false, 'description' => $message])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function ok(mixed $result): string
|
private static function ok(mixed $result): Response
|
||||||
{
|
{
|
||||||
return \json_encode(['ok' => true, 'result' => $result]);
|
return new Response(
|
||||||
|
HttpStatus::OK,
|
||||||
|
self::HEADERS,
|
||||||
|
json_encode(['ok' => false, 'result' => $result])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function sanitize(string $error): string
|
private static function sanitize(string $error): string
|
||||||
@ -104,69 +126,53 @@ final class Main
|
|||||||
|
|
||||||
private function v2(): array
|
private function v2(): array
|
||||||
{
|
{
|
||||||
$this->connect();
|
|
||||||
$desc = [];
|
$desc = [];
|
||||||
$q = $this->pdo->prepare('SELECT error, description FROM error_descriptions');
|
$q = $this->pool->prepare('SELECT error, description FROM error_descriptions');
|
||||||
$q->execute();
|
foreach ($q->execute() as ['error' => $error, 'description' => $description]) {
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($error, $description) use (&$desc) {
|
|
||||||
$desc[$error] = $description;
|
$desc[$error] = $description;
|
||||||
});
|
}
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT method, code, error FROM errors');
|
$q = $this->pool->prepare('SELECT method, code, error FROM errors WHERE code != 500');
|
||||||
$q->execute();
|
|
||||||
$r = [];
|
$r = [];
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($method, $code, $error) use (&$r, &$desc) {
|
foreach ($q->execute() as ['method' => $method, 'code' => $code, 'error' => $error]) {
|
||||||
$code = (int) $code;
|
$code = (int) $code;
|
||||||
if ($code === 500) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$r[$method][] = [
|
$r[$method][] = [
|
||||||
'error_code' => $code,
|
'error_code' => $code,
|
||||||
'error_message' => $error,
|
'error_message' => $error,
|
||||||
'error_description' => $desc[$error] ?? '',
|
'error_description' => $desc[$error] ?? '',
|
||||||
];
|
];
|
||||||
});
|
}
|
||||||
|
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function v3(): array
|
private function v3(): array
|
||||||
{
|
{
|
||||||
$this->connect();
|
$q = $this->pool->prepare('SELECT method, code, error FROM errors');
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT method, code, error FROM errors');
|
|
||||||
$q->execute();
|
|
||||||
$r = [];
|
$r = [];
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($method, $code, $error) use (&$r) {
|
foreach ($q->execute() as ['method' => $method, 'code' => $code, 'error' => $error]) {
|
||||||
$error = self::sanitize($error);
|
$error = self::sanitize($error);
|
||||||
$r[(int) $code][$method][$error] = $error;
|
$r[(int) $code][$method][$error] = $error;
|
||||||
});
|
}
|
||||||
|
|
||||||
$hr = [];
|
$hr = [];
|
||||||
$q = $this->pdo->prepare('SELECT error, description FROM error_descriptions');
|
$q = $this->pool->prepare('SELECT error, description FROM error_descriptions');
|
||||||
$q->execute();
|
foreach ($q->execute() as ['error' => $error, 'description' => $description]) {
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($error, $description) use (&$hr) {
|
|
||||||
$error = self::sanitize($error);
|
$error = self::sanitize($error);
|
||||||
$description = \str_replace(' X ', ' %d ', $description);
|
$description = \str_replace(' X ', ' %d ', $description);
|
||||||
$hr[$error] = $description;
|
$hr[$error] = $description;
|
||||||
});
|
}
|
||||||
|
|
||||||
return [$r, $hr];
|
return [$r, $hr];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function v4(bool $core = false): array
|
private function v4(bool $core = false): array
|
||||||
{
|
{
|
||||||
$this->connect();
|
$q = $this->pool->prepare('SELECT method, code, error FROM errors');
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT method, code, error FROM errors');
|
|
||||||
$q->execute();
|
|
||||||
$r = [];
|
$r = [];
|
||||||
$errors = [];
|
$errors = [];
|
||||||
$bot_only = [];
|
$bot_only = [];
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($method, $code, $error) use (&$r, &$bot_only, &$errors, $core) {
|
foreach ($q->execute() as ['method' => $method, 'code' => $code, 'error' => $error]) {
|
||||||
if ($core && ($error === 'UPDATE_APP_TO_LOGIN' || $error === 'UPDATE_APP_REQUIRED')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$code = (int) $code;
|
$code = (int) $code;
|
||||||
$error = self::sanitize($error);
|
$error = self::sanitize($error);
|
||||||
if (!\in_array($method, $r[$code][$error] ?? [])) {
|
if (!\in_array($method, $r[$code][$error] ?? [])) {
|
||||||
@ -176,21 +182,17 @@ final class Main
|
|||||||
if (\in_array($error, ['USER_BOT_REQUIRED', 'USER_BOT_INVALID']) && !\in_array($method, $bot_only) && !\in_array($method, ['bots.setBotInfo', 'bots.getBotInfo'])) {
|
if (\in_array($error, ['USER_BOT_REQUIRED', 'USER_BOT_INVALID']) && !\in_array($method, $bot_only) && !\in_array($method, ['bots.setBotInfo', 'bots.getBotInfo'])) {
|
||||||
$bot_only[] = $method;
|
$bot_only[] = $method;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
$hr = [];
|
$hr = [];
|
||||||
$q = $this->pdo->prepare('SELECT error, description FROM error_descriptions');
|
$q = $this->pool->prepare('SELECT error, description FROM error_descriptions');
|
||||||
$q->execute();
|
foreach ($q->execute() as ['error' => $error, 'description' => $description]) {
|
||||||
$q->fetchAll(PDO::FETCH_FUNC, function ($error, $description) use (&$hr, $core) {
|
|
||||||
if ($core && ($error === 'UPDATE_APP_TO_LOGIN' || $error === 'UPDATE_APP_REQUIRED')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$error = self::sanitize($error);
|
$error = self::sanitize($error);
|
||||||
$description = \str_replace(' X ', ' %d ', $description);
|
$description = \str_replace(' X ', ' %d ', $description);
|
||||||
if ($description !== '' && !\in_array($description[\strlen($description) - 1], ['?', '.', '!'])) {
|
if ($description !== '' && !\in_array($description[\strlen($description) - 1], ['?', '.', '!'])) {
|
||||||
$description .= '.';
|
$description .= '.';
|
||||||
}
|
}
|
||||||
$hr[$error] = $description;
|
$hr[$error] = $description;
|
||||||
});
|
}
|
||||||
|
|
||||||
$hr['FLOOD_WAIT_%d'] = 'Please wait %d seconds before repeating the action.';
|
$hr['FLOOD_WAIT_%d'] = 'Please wait %d seconds before repeating the action.';
|
||||||
|
|
||||||
@ -210,35 +212,35 @@ final class Main
|
|||||||
|
|
||||||
private function bot(): array
|
private function bot(): array
|
||||||
{
|
{
|
||||||
$this->connect();
|
$q = $this->pool->prepare('SELECT method FROM bot_method_invalid');
|
||||||
|
$r = [];
|
||||||
$q = $this->pdo->prepare('SELECT method FROM bot_method_invalid');
|
foreach ($q->execute() as $result) {
|
||||||
$q->execute();
|
$r []= $result['method'];
|
||||||
$r = $q->fetchAll(PDO::FETCH_COLUMN);
|
}
|
||||||
|
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cli(): void
|
private function cli(): void
|
||||||
{
|
{
|
||||||
$this->connect();
|
|
||||||
|
|
||||||
$bot_only = [];
|
$bot_only = [];
|
||||||
$q = $this->pdo->prepare('SELECT error, method FROM errors');
|
$q = $this->pool->prepare('SELECT error, method FROM errors');
|
||||||
$q->execute();
|
$r = [];
|
||||||
$r = $q->fetchAll(PDO::FETCH_COLUMN | PDO::FETCH_GROUP);
|
foreach ($q->execute() as $result) {
|
||||||
|
$r[$result['error']][]= $result['method'];
|
||||||
|
}
|
||||||
foreach ($r as $error => $methods) {
|
foreach ($r as $error => $methods) {
|
||||||
$fixed = self::sanitize($error);
|
$fixed = self::sanitize($error);
|
||||||
if ($fixed !== $error) {
|
if ($fixed !== $error) {
|
||||||
foreach ($methods as $method) {
|
foreach ($methods as $method) {
|
||||||
$q = $this->pdo->prepare('UPDATE errors SET error=? WHERE error=? AND method=?');
|
$q = $this->pool->prepare('UPDATE errors SET error=? WHERE error=? AND method=?');
|
||||||
$q->execute([$fixed, $error, $method]);
|
$q->execute([$fixed, $error, $method]);
|
||||||
|
|
||||||
$q = $this->pdo->prepare('UPDATE error_descriptions SET error=? WHERE error=?');
|
$q = $this->pool->prepare('UPDATE error_descriptions SET error=? WHERE error=?');
|
||||||
$q->execute([$fixed, $error]);
|
$q->execute([$fixed, $error]);
|
||||||
|
|
||||||
if (self::sanitize($method) === $fixed) {
|
if (self::sanitize($method) === $fixed) {
|
||||||
$q = $this->pdo->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
$q = $this->pool->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
||||||
$q->execute([$fixed, $fixed]);
|
$q->execute([$fixed, $fixed]);
|
||||||
echo 'Delete strange '.$error."\n";
|
echo 'Delete strange '.$error."\n";
|
||||||
}
|
}
|
||||||
@ -247,7 +249,7 @@ final class Main
|
|||||||
}
|
}
|
||||||
foreach ($methods as $method) {
|
foreach ($methods as $method) {
|
||||||
if (self::sanitize($method) === $fixed) {
|
if (self::sanitize($method) === $fixed) {
|
||||||
$q = $this->pdo->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
$q = $this->pool->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
||||||
$q->execute([$fixed, $method]);
|
$q->execute([$fixed, $method]);
|
||||||
echo 'Delete strange '.$error."\n";
|
echo 'Delete strange '.$error."\n";
|
||||||
}
|
}
|
||||||
@ -256,9 +258,11 @@ final class Main
|
|||||||
|
|
||||||
$allowed = [];
|
$allowed = [];
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT error, method FROM errors');
|
$q = $this->pool->prepare('SELECT error, method FROM errors');
|
||||||
$q->execute();
|
$r = [];
|
||||||
$r = $q->fetchAll(PDO::FETCH_COLUMN | PDO::FETCH_GROUP);
|
foreach ($q->execute() as $result) {
|
||||||
|
$r[$result['error']][]= $result['method'];
|
||||||
|
}
|
||||||
foreach (\array_merge($r, self::GLOBAL_CODES) as $error => $methods) {
|
foreach (\array_merge($r, self::GLOBAL_CODES) as $error => $methods) {
|
||||||
if (\is_int($methods)) {
|
if (\is_int($methods)) {
|
||||||
$allowed[$error] = true;
|
$allowed[$error] = true;
|
||||||
@ -267,7 +271,7 @@ final class Main
|
|||||||
$anyok = false;
|
$anyok = false;
|
||||||
foreach ($methods as $method) {
|
foreach ($methods as $method) {
|
||||||
if (RPCErrorException::isBad($error, 0, $method)) {
|
if (RPCErrorException::isBad($error, 0, $method)) {
|
||||||
$q = $this->pdo->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
$q = $this->pool->prepare('DELETE FROM errors WHERE error=? AND method=?');
|
||||||
$q->execute([$error, $method]);
|
$q->execute([$error, $method]);
|
||||||
echo "Delete $error for $method\n";
|
echo "Delete $error for $method\n";
|
||||||
continue;
|
continue;
|
||||||
@ -279,33 +283,31 @@ final class Main
|
|||||||
}
|
}
|
||||||
$allowed[$error] = true;
|
$allowed[$error] = true;
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT description FROM error_descriptions WHERE error=?');
|
$q = $this->pool->prepare('SELECT description FROM error_descriptions WHERE error=?');
|
||||||
$q->execute([$error]);
|
$res = $q->execute([$error])->fetchRow();
|
||||||
if (!$q->rowCount() || !($er = $q->fetchColumn())) {
|
if (!($res['description'] ?? null)) {
|
||||||
$methods = \implode(', ', $methods);
|
$methods = \implode(', ', $methods);
|
||||||
$description = \readline('Insert description for '.$error.' ('.$methods.'): ');
|
$description = \readline('Insert description for '.$error.' ('.$methods.'): ');
|
||||||
if (\strpos(\readline($error.' - '.$description.' OK? '), 'n') !== false) {
|
if (\strpos(\readline($error.' - '.$description.' OK? '), 'n') !== false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($description === 'drop' || $description === 'delete' || $description === 'd') {
|
if ($description === 'drop' || $description === 'delete' || $description === 'd') {
|
||||||
$q = $this->pdo->prepare('DELETE FROM errors WHERE error=?');
|
$q = $this->pool->prepare('DELETE FROM errors WHERE error=?');
|
||||||
$q->execute([$error]);
|
$q->execute([$error]);
|
||||||
echo 'Delete '.$error."\n";
|
echo 'Delete '.$error."\n";
|
||||||
} else {
|
} else {
|
||||||
$q = $this->pdo->prepare('REPLACE INTO error_descriptions VALUES (?, ?)');
|
$q = $this->pool->prepare('REPLACE INTO error_descriptions VALUES (?, ?)');
|
||||||
$q->execute([$error, $description]);
|
$q->execute([$error, $description]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT error FROM error_descriptions');
|
$q = $this->pool->prepare('SELECT error FROM error_descriptions');
|
||||||
$q->execute();
|
foreach ($q->execute() as ['error' => $error]) {
|
||||||
$r = $q->fetchAll(PDO::FETCH_COLUMN);
|
|
||||||
foreach ($r as $error) {
|
|
||||||
if (!isset($allowed[$error])) {
|
if (!isset($allowed[$error])) {
|
||||||
$q = $this->pdo->prepare('DELETE FROM errors WHERE error=?');
|
$q = $this->pool->prepare('DELETE FROM errors WHERE error=?');
|
||||||
$q->execute([$error]);
|
$q->execute([$error]);
|
||||||
$q = $this->pdo->prepare('DELETE FROM error_descriptions WHERE error=?');
|
$q = $this->pool->prepare('DELETE FROM error_descriptions WHERE error=?');
|
||||||
$q->execute([$error]);
|
$q->execute([$error]);
|
||||||
echo 'Delete '.$error."\n";
|
echo 'Delete '.$error."\n";
|
||||||
}
|
}
|
||||||
@ -326,54 +328,65 @@ final class Main
|
|||||||
\file_put_contents('data/core.json', \json_encode(['errors' => $r, 'descriptions' => $hr, 'user_only' => $bot, 'bot_only' => $bot_only]));
|
\file_put_contents('data/core.json', \json_encode(['errors' => $r, 'descriptions' => $hr, 'user_only' => $bot, 'bot_only' => $bot_only]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): void
|
public function handleRequest(Request $request): Response {
|
||||||
|
$form = Form::fromRequest($request);
|
||||||
|
$error = $request->getQueryParameter('error') ?? $form->getValue('error');
|
||||||
|
$code = $request->getQueryParameter('code') ?? $form->getValue('code');
|
||||||
|
$method = $request->getQueryParameter('method') ?? $form->getValue('method');
|
||||||
|
if ($error && $code && $method
|
||||||
|
&& \is_numeric($_REQUEST['code'])
|
||||||
|
&& !RPCErrorException::isBad(
|
||||||
|
$error,
|
||||||
|
(int) $code,
|
||||||
|
$method
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
$error = self::sanitize($error);
|
||||||
|
try {
|
||||||
|
if ($error === $code) {
|
||||||
|
$this->pool->prepare('REPLACE INTO code_errors VALUES (?);')->execute([$code]);
|
||||||
|
} elseif ($error === 'BOT_METHOD_INVALID') {
|
||||||
|
$this->pool->prepare('REPLACE INTO bot_method_invalid VALUES (?);')->execute([$method]);
|
||||||
|
} else {
|
||||||
|
$this->pool->prepare('REPLACE INTO errors VALUES (?, ?, ?);')->execute([$error, $method, $code]);
|
||||||
|
|
||||||
|
$q = $this->pool->prepare('SELECT description FROM error_descriptions WHERE error=?');
|
||||||
|
$result = $q->execute([$error]);
|
||||||
|
if ($row = $result->fetchRow()) {
|
||||||
|
return self::ok($row['description']);
|
||||||
|
}
|
||||||
|
return self::error('No description', 404);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return self::error($e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
return self::ok(true);
|
||||||
|
}
|
||||||
|
return self::error('API for reporting Telegram RPC errors. For localized errors see https://rpc.madelineproto.xyz, to report a new error use the `code`, `method` and `error` GET/POST parameters. Source code at https://github.com/danog/telerpc.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(bool $serve): void
|
||||||
{
|
{
|
||||||
if (PHP_SAPI === 'cli') {
|
if (!$serve) {
|
||||||
$this->cli();
|
$this->cli();
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
\ini_set('log_errors', 1);
|
$logHandler = new StreamHandler(getStdout());
|
||||||
\ini_set('error_log', '/tmp/rpc.log');
|
$logHandler->pushProcessor(new PsrLogMessageProcessor());
|
||||||
\header('Content-Type: application/json');
|
$logHandler->setFormatter(new ConsoleFormatter());
|
||||||
\header('access-control-allow-origin: *');
|
|
||||||
\header('access-control-allow-methods: GET, POST, OPTIONS');
|
|
||||||
\header('access-control-expose-headers: Content-Length,Content-Type,Date,Server,Connection');
|
|
||||||
if (isset($_REQUEST['error'], $_REQUEST['code'], $_REQUEST['method'])
|
|
||||||
&& $_REQUEST['error'] !== ''
|
|
||||||
&& $_REQUEST['method'] !== ''
|
|
||||||
&& \is_numeric($_REQUEST['code'])
|
|
||||||
&& !RPCErrorException::isBad(
|
|
||||||
$_REQUEST['error'],
|
|
||||||
(int) $_REQUEST['code'],
|
|
||||||
$_REQUEST['method']
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
$error = self::sanitize($_REQUEST['error']);
|
|
||||||
$method = $_REQUEST['method'];
|
|
||||||
$code = $_REQUEST['code'];
|
|
||||||
|
|
||||||
try {
|
$logger = new Logger('server');
|
||||||
$this->connect();
|
$logger->pushHandler($logHandler);
|
||||||
if ($error === $code) {
|
$errorHandler = new DefaultErrorHandler();
|
||||||
$this->pdo->prepare('REPLACE INTO code_errors VALUES (?);')->execute([$code]);
|
|
||||||
} elseif ($error === 'BOT_METHOD_INVALID') {
|
|
||||||
$this->pdo->prepare('REPLACE INTO bot_method_invalid VALUES (?);')->execute([$method]);
|
|
||||||
} else {
|
|
||||||
$this->pdo->prepare('REPLACE INTO errors VALUES (?, ?, ?);')->execute([$error, $method, $code]);
|
|
||||||
|
|
||||||
$q = $this->pdo->prepare('SELECT description FROM error_descriptions WHERE error=?');
|
$server = SocketHttpServer::createForDirectAccess($logger);
|
||||||
$q->execute([$error]);
|
$server->expose('127.0.0.1:1337');
|
||||||
if ($q->rowCount()) {
|
$server->start($this, $errorHandler);
|
||||||
exit(self::ok($q->fetchColumn()));
|
|
||||||
}
|
// Serve requests until SIGINT or SIGTERM is received by the process.
|
||||||
exit(self::error('No description'));
|
Amp\trapSignal([SIGINT, SIGTERM]);
|
||||||
}
|
|
||||||
} catch (\Throwable $e) {
|
$server->stop();
|
||||||
exit(self::error($e->getMessage()));
|
|
||||||
}
|
|
||||||
exit(self::ok(true));
|
|
||||||
}
|
|
||||||
exit(self::error('API for reporting Telegram RPC errors. For localized errors see https://rpc.madelineproto.xyz, to report a new error use the `code`, `method` and `error` GET/POST parameters. Source code at https://github.com/danog/telerpc.'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user