mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-26 17:04:39 +01:00
Fixes
This commit is contained in:
parent
77ce9de35c
commit
151a809c6e
@ -8,6 +8,12 @@ $config = new class extends Amp\CodeStyle\Config {
|
||||
'array_indentation' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'assign_null_coalescing_to_coalesce_equal' => true,
|
||||
'@PHP82Migration' => true,
|
||||
'@PHP81Migration' => true,
|
||||
'@PHP80Migration' => true,
|
||||
'@PHP80Migration:risky' => true,
|
||||
'static_lambda' => true,
|
||||
'strict_param' => true,
|
||||
"native_function_invocation" => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced'],
|
||||
]);
|
||||
}
|
||||
|
2
docs
2
docs
@ -1 +1 @@
|
||||
Subproject commit 6033bfa2a31f6661681a06f4240d5bf18090df45
|
||||
Subproject commit 8d71029d3b3211f9298f58693d94d9572af3dae1
|
@ -69,7 +69,7 @@ class MyEventHandler extends SimpleEventHandler
|
||||
/**
|
||||
* @var int|string Username or ID of bot admin
|
||||
*/
|
||||
const ADMIN = "@me"; // !!! Change this to your username !!!
|
||||
public const ADMIN = "@me"; // !!! Change this to your username !!!
|
||||
|
||||
/**
|
||||
* @var array<int, bool>
|
||||
@ -112,7 +112,7 @@ class MyEventHandler extends SimpleEventHandler
|
||||
return [
|
||||
// Offers a /restart command to admins that can be used to restart the bot, applying changes.
|
||||
// Make sure to run in a bash while loop when running via CLI to allow self-restarts.
|
||||
RestartPlugin::class
|
||||
RestartPlugin::class,
|
||||
];
|
||||
}
|
||||
|
||||
@ -185,9 +185,9 @@ class MyEventHandler extends SimpleEventHandler
|
||||
|
||||
$stories = $this->stories->getUserStories(user_id: $message->commandArgs[0])['stories']['stories'];
|
||||
// Skip deleted stories
|
||||
$stories = array_filter($stories, fn (array $s): bool => $s['_'] === 'storyItem');
|
||||
$stories = array_filter($stories, static fn (array $s): bool => $s['_'] === 'storyItem');
|
||||
// Sort by date
|
||||
usort($stories, fn ($a, $b) => $a['date'] <=> $b['date']);
|
||||
usort($stories, static fn ($a, $b) => $a['date'] <=> $b['date']);
|
||||
|
||||
$result = "Total stories: ".count($stories)."\n\n";
|
||||
foreach ($stories as $story) {
|
||||
|
@ -41,7 +41,7 @@ class MyEventHandler extends EventHandler
|
||||
/**
|
||||
* @var int|string Username or ID of bot admin
|
||||
*/
|
||||
const ADMIN = "danogentili"; // Change this
|
||||
public const ADMIN = "danogentili"; // Change this
|
||||
/**
|
||||
* Get peer(s) where to report errors.
|
||||
*
|
||||
|
@ -43,7 +43,7 @@ if (file_exists('vendor/autoload.php')) {
|
||||
*/
|
||||
class MyEventHandler extends EventHandler
|
||||
{
|
||||
const START = "Send me a file URL and I will download it and send it to you!\n\n".
|
||||
public const START = "Send me a file URL and I will download it and send it to you!\n\n".
|
||||
"Usage: `https://example.com`\n".
|
||||
"Usage: `https://example.com file name.ext`\n\n".
|
||||
"I can also rename Telegram files, just send me any file and I will rename it!\n\n".
|
||||
@ -52,7 +52,7 @@ class MyEventHandler extends EventHandler
|
||||
/**
|
||||
* @var int|string Username or ID of bot admin
|
||||
*/
|
||||
const ADMIN = 'danogentili'; // Change this
|
||||
public const ADMIN = 'danogentili'; // Change this
|
||||
|
||||
/**
|
||||
* Get peer(s) where to report errors.
|
||||
@ -149,7 +149,7 @@ class MyEventHandler extends EventHandler
|
||||
|
||||
$msg->delete();
|
||||
} catch (Throwable $e) {
|
||||
if (strpos($e->getMessage(), 'Could not connect to URI') === false && !($e instanceof UriException) && strpos($e->getMessage(), 'URI') === false) {
|
||||
if (!str_contains($e->getMessage(), 'Could not connect to URI') && !($e instanceof UriException) && !str_contains($e->getMessage(), 'URI')) {
|
||||
$this->report((string) $e);
|
||||
$this->logger((string) $e, Logger::FATAL_ERROR);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class SecretHandler extends SimpleEventHandler
|
||||
/**
|
||||
* @var int|string Username or ID of bot admin
|
||||
*/
|
||||
const ADMIN = "danogentili"; // Change this
|
||||
public const ADMIN = "danogentili"; // Change this
|
||||
/**
|
||||
* Get peer(s) where to report errors.
|
||||
*
|
||||
|
@ -27,7 +27,7 @@ if (file_exists('vendor/autoload.php')) {
|
||||
class MyEventHandler extends SimpleEventHandler
|
||||
{
|
||||
// !!! Change this to your username !!!
|
||||
const ADMIN = "@me";
|
||||
public const ADMIN = "@me";
|
||||
|
||||
/**
|
||||
* Get peer(s) where to report errors.
|
||||
@ -47,7 +47,7 @@ class MyEventHandler extends SimpleEventHandler
|
||||
return [
|
||||
// Offers a /restart command to admins that can be used to restart the bot, applying changes.
|
||||
// Make sure to run in a bash while loop when running via CLI to allow self-restarts.
|
||||
RestartPlugin::class
|
||||
RestartPlugin::class,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -124,11 +124,11 @@ final class StoriesEventHandler extends SimpleEventHandler
|
||||
|
||||
$stories = $this->userInstance->stories->getUserStories(user_id: $message->commandArgs[0])['stories']['stories'];
|
||||
// Skip deleted stories
|
||||
$stories = array_filter($stories, fn (array $s): bool => $s['_'] === 'storyItem');
|
||||
$stories = array_filter($stories, static fn (array $s): bool => $s['_'] === 'storyItem');
|
||||
// Skip protected stories
|
||||
$stories = array_filter($stories, fn (array $s): bool => !$s['noforwards']);
|
||||
$stories = array_filter($stories, static fn (array $s): bool => !$s['noforwards']);
|
||||
// Sort by date
|
||||
usort($stories, fn ($a, $b) => $a['date'] <=> $b['date']);
|
||||
usort($stories, static fn ($a, $b) => $a['date'] <=> $b['date']);
|
||||
|
||||
$result = "Total stories: ".count($stories)."\n\n";
|
||||
foreach ($stories as $story) {
|
||||
|
@ -415,7 +415,7 @@ final class API extends AbstractAPI
|
||||
|
||||
$prev = EventLoop::getErrorHandler();
|
||||
EventLoop::setErrorHandler(
|
||||
$cb = function (Throwable $e) use ($instanceOne, &$errors, &$started, $eventHandler): void {
|
||||
$cb = static function (Throwable $e) use ($instanceOne, &$errors, &$started, $eventHandler): void {
|
||||
if ($e instanceof UnhandledFutureError) {
|
||||
$e = $e->getPrevious();
|
||||
}
|
||||
@ -442,7 +442,7 @@ final class API extends AbstractAPI
|
||||
$promises = [];
|
||||
foreach ($instances as $k => $instance) {
|
||||
$instance->start();
|
||||
$promises []= async(function () use ($k, $instance, $eventHandler, &$started): void {
|
||||
$promises []= async(static function () use ($k, $instance, $eventHandler, &$started): void {
|
||||
$instance->startAndLoopLogic($eventHandler[$k], $started[$k]);
|
||||
});
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ final class Blacklist {
|
||||
}
|
||||
$newParams[$param['name']] = $param;
|
||||
}
|
||||
uasort($newParams, fn (array $arr1, array $arr2) => isset($arr1['pow']) <=> isset($arr2['pow']));
|
||||
uasort($newParams, static fn (array $arr1, array $arr2) => isset($arr1['pow']) <=> isset($arr2['pow']));
|
||||
return $newParams;
|
||||
}
|
||||
private function prepareTLParams(array $data): array
|
||||
@ -418,14 +418,14 @@ final class Blacklist {
|
||||
foreach ($methods as $key => $method) {
|
||||
$name = $method->getName();
|
||||
if ($name == 'methodCallAsyncRead') {
|
||||
unset($methods[array_search('methodCall', $methods)]);
|
||||
} elseif (strpos($name, '__') === 0) {
|
||||
unset($methods[array_search('methodCall', $methods, true)]);
|
||||
} elseif (str_starts_with($name, '__')) {
|
||||
unset($methods[$key]);
|
||||
} elseif (stripos($name, 'async') !== false) {
|
||||
if (strpos($name, '_async') !== false) {
|
||||
unset($methods[array_search(str_ireplace('_async', '', $name), $methods)]);
|
||||
if (str_contains($name, '_async')) {
|
||||
unset($methods[array_search(str_ireplace('_async', '', $name), $methods, true)]);
|
||||
} else {
|
||||
unset($methods[array_search(str_ireplace('async', '', $name), $methods)]);
|
||||
unset($methods[array_search(str_ireplace('async', '', $name), $methods, true)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -439,21 +439,21 @@ final class Blacklist {
|
||||
|
||||
foreach ($methods as $method) {
|
||||
$name = $method->getName();
|
||||
if (strpos($method->getDocComment() ?: '', '@internal') !== false) {
|
||||
if (str_contains($method->getDocComment() ?: '', '@internal')) {
|
||||
continue;
|
||||
}
|
||||
$static = $method->isStatic();
|
||||
if (!$static) {
|
||||
$code = file_get_contents($method->getFileName());
|
||||
$code = implode("\n", \array_slice(explode("\n", $code), $method->getStartLine(), $method->getEndLine() - $method->getStartLine()));
|
||||
if (strpos($code, '$this') === false) {
|
||||
if (!str_contains($code, '$this')) {
|
||||
Logger::log("{$name} should be STATIC!", Logger::FATAL_ERROR);
|
||||
}
|
||||
}
|
||||
if ($name == 'methodCallAsyncRead') {
|
||||
$name = 'methodCall';
|
||||
} elseif (stripos($name, 'async') !== false) {
|
||||
if (strpos($name, '_async') !== false) {
|
||||
if (str_contains($name, '_async')) {
|
||||
$name = str_ireplace('_async', '', $name);
|
||||
} else {
|
||||
$name = str_ireplace('async', '', $name);
|
||||
@ -629,7 +629,7 @@ final class Blacklist {
|
||||
fwrite($handle, "/** @internal An internal interface used to avoid type errors when using simple filters. */\n");
|
||||
fwrite($handle, "interface SimpleFilters extends ");
|
||||
/** @psalm-suppress UndefinedClass */
|
||||
fwrite($handle, implode(", ", array_map(fn ($s) => "\\$s", ClassFinder::getClassesInNamespace(\danog\MadelineProto\EventHandler\SimpleFilter::class, ClassFinder::RECURSIVE_MODE|ClassFinder::ALLOW_INTERFACES))));
|
||||
fwrite($handle, implode(", ", array_map(static fn ($s) => "\\$s", ClassFinder::getClassesInNamespace(\danog\MadelineProto\EventHandler\SimpleFilter::class, ClassFinder::RECURSIVE_MODE|ClassFinder::ALLOW_INTERFACES))));
|
||||
fwrite($handle, "{}\n");
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ abstract class AsyncTools extends StrTools
|
||||
*/
|
||||
public static function rethrow(Throwable $e): void
|
||||
{
|
||||
EventLoop::queue(fn () => throw $e);
|
||||
EventLoop::queue(static fn () => throw $e);
|
||||
}
|
||||
/**
|
||||
* Fork a new green thread and execute the passed function in the background.
|
||||
@ -133,7 +133,7 @@ abstract class AsyncTools extends StrTools
|
||||
{
|
||||
$e = new TimeoutException($message);
|
||||
$deferred = new DeferredCancellation;
|
||||
EventLoop::delay($timeout, fn () => $deferred->cancel($e));
|
||||
EventLoop::delay($timeout, static fn () => $deferred->cancel($e));
|
||||
return $deferred->getCancellation();
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ final class ActionForward implements Action
|
||||
'unpin' => false,
|
||||
'pm_oneside' => false,
|
||||
'floodWaitLimit' => 2*86400,
|
||||
'cancellation' => $cancellation
|
||||
'cancellation' => $cancellation,
|
||||
],
|
||||
);
|
||||
} catch (RPCErrorException) {
|
||||
|
@ -304,7 +304,7 @@ final class Connection
|
||||
foreach ($this->new_outgoing as $message_id => $message) {
|
||||
if ($message->unencrypted) {
|
||||
if (!($message->getState() & MTProtoOutgoingMessage::STATE_REPLIED)) {
|
||||
$message->reply(fn () => new Exception('Restart because we were reconnected'));
|
||||
$message->reply(static fn () => new Exception('Restart because we were reconnected'));
|
||||
}
|
||||
unset($this->new_outgoing[$message_id], $this->outgoing_messages[$message_id]);
|
||||
}
|
||||
@ -527,7 +527,7 @@ final class Connection
|
||||
$arguments['reply_to'] = [
|
||||
'_' => 'inputReplyToMessage',
|
||||
'reply_to_msg_id' => $arguments['reply_to_msg_id'],
|
||||
'top_msg_id' => $arguments['top_msg_id'] ?? null
|
||||
'top_msg_id' => $arguments['top_msg_id'] ?? null,
|
||||
];
|
||||
unset($arguments['reply_to_msg_id'], $arguments['top_msg_id']);
|
||||
}
|
||||
|
@ -136,8 +136,8 @@ final class Conversion
|
||||
return strtoupper($result);
|
||||
}
|
||||
|
||||
const FILEOPTION_SAFE = 1;
|
||||
const FILEOPTION_USER = 2;
|
||||
private const FILEOPTION_SAFE = 1;
|
||||
private const FILEOPTION_USER = 2;
|
||||
public static $tdesktop_base_path;
|
||||
public static $tdesktop_user_base_path;
|
||||
public static $tdesktop_key;
|
||||
@ -227,85 +227,85 @@ final class Conversion
|
||||
return $res;
|
||||
}
|
||||
|
||||
const dbiKey = 0x00;
|
||||
const dbiUser = 0x01;
|
||||
const dbiDcOptionOldOld = 0x02;
|
||||
const dbiChatSizeMax = 0x03;
|
||||
const dbiMutePeer = 0x04;
|
||||
const dbiSendKey = 0x05;
|
||||
const dbiAutoStart = 0x06;
|
||||
const dbiStartMinimized = 0x07;
|
||||
const dbiSoundNotify = 0x08;
|
||||
const dbiWorkMode = 0x09;
|
||||
const dbiSeenTrayTooltip = 0x0a;
|
||||
const dbiDesktopNotify = 0x0b;
|
||||
const dbiAutoUpdate = 0x0c;
|
||||
const dbiLastUpdateCheck = 0x0d;
|
||||
const dbiWindowPosition = 0x0e;
|
||||
const dbiConnectionTypeOld = 0x0f;
|
||||
private const dbiKey = 0x00;
|
||||
private const dbiUser = 0x01;
|
||||
private const dbiDcOptionOldOld = 0x02;
|
||||
private const dbiChatSizeMax = 0x03;
|
||||
private const dbiMutePeer = 0x04;
|
||||
private const dbiSendKey = 0x05;
|
||||
private const dbiAutoStart = 0x06;
|
||||
private const dbiStartMinimized = 0x07;
|
||||
private const dbiSoundNotify = 0x08;
|
||||
private const dbiWorkMode = 0x09;
|
||||
private const dbiSeenTrayTooltip = 0x0a;
|
||||
private const dbiDesktopNotify = 0x0b;
|
||||
private const dbiAutoUpdate = 0x0c;
|
||||
private const dbiLastUpdateCheck = 0x0d;
|
||||
private const dbiWindowPosition = 0x0e;
|
||||
private const dbiConnectionTypeOld = 0x0f;
|
||||
// 0x10 reserved
|
||||
const dbiDefaultAttach = 0x11;
|
||||
const dbiCatsAndDogs = 0x12;
|
||||
const dbiReplaceEmojis = 0x13;
|
||||
const dbiAskDownloadPath = 0x14;
|
||||
const dbiDownloadPathOld = 0x15;
|
||||
const dbiScale = 0x16;
|
||||
const dbiEmojiTabOld = 0x17;
|
||||
const dbiRecentEmojiOldOld = 0x18;
|
||||
const dbiLoggedPhoneNumber = 0x19;
|
||||
const dbiMutedPeers = 0x1a;
|
||||
private const dbiDefaultAttach = 0x11;
|
||||
private const dbiCatsAndDogs = 0x12;
|
||||
private const dbiReplaceEmojis = 0x13;
|
||||
private const dbiAskDownloadPath = 0x14;
|
||||
private const dbiDownloadPathOld = 0x15;
|
||||
private const dbiScale = 0x16;
|
||||
private const dbiEmojiTabOld = 0x17;
|
||||
private const dbiRecentEmojiOldOld = 0x18;
|
||||
private const dbiLoggedPhoneNumber = 0x19;
|
||||
private const dbiMutedPeers = 0x1a;
|
||||
// 0x1b reserved
|
||||
const dbiNotifyView = 0x1c;
|
||||
const dbiSendToMenu = 0x1d;
|
||||
const dbiCompressPastedImage = 0x1e;
|
||||
const dbiLangOld = 0x1f;
|
||||
const dbiLangFileOld = 0x20;
|
||||
const dbiTileBackground = 0x21;
|
||||
const dbiAutoLock = 0x22;
|
||||
const dbiDialogLastPath = 0x23;
|
||||
const dbiRecentEmojiOld = 0x24;
|
||||
const dbiEmojiVariantsOld = 0x25;
|
||||
const dbiRecentStickers = 0x26;
|
||||
const dbiDcOptionOld = 0x27;
|
||||
const dbiTryIPv6 = 0x28;
|
||||
const dbiSongVolume = 0x29;
|
||||
const dbiWindowsNotificationsOld = 0x30;
|
||||
const dbiIncludeMuted = 0x31;
|
||||
const dbiMegagroupSizeMax = 0x32;
|
||||
const dbiDownloadPath = 0x33;
|
||||
const dbiAutoDownload = 0x34;
|
||||
const dbiSavedGifsLimit = 0x35;
|
||||
const dbiShowingSavedGifsOld = 0x36;
|
||||
const dbiAutoPlay = 0x37;
|
||||
const dbiAdaptiveForWide = 0x38;
|
||||
const dbiHiddenPinnedMessages = 0x39;
|
||||
const dbiRecentEmoji = 0x3a;
|
||||
const dbiEmojiVariants = 0x3b;
|
||||
const dbiDialogsMode = 0x40;
|
||||
const dbiModerateMode = 0x41;
|
||||
const dbiVideoVolume = 0x42;
|
||||
const dbiStickersRecentLimit = 0x43;
|
||||
const dbiNativeNotifications = 0x44;
|
||||
const dbiNotificationsCount = 0x45;
|
||||
const dbiNotificationsCorner = 0x46;
|
||||
const dbiThemeKey = 0x47;
|
||||
const dbiDialogsWidthRatioOld = 0x48;
|
||||
const dbiUseExternalVideoPlayer = 0x49;
|
||||
const dbiDcOptions = 0x4a;
|
||||
const dbiMtpAuthorization = 0x4b;
|
||||
const dbiLastSeenWarningSeenOld = 0x4c;
|
||||
const dbiAuthSessionSettings = 0x4d;
|
||||
const dbiLangPackKey = 0x4e;
|
||||
const dbiConnectionType = 0x4f;
|
||||
const dbiStickersFavedLimit = 0x50;
|
||||
const dbiSuggestStickersByEmoji = 0x51;
|
||||
private const dbiNotifyView = 0x1c;
|
||||
private const dbiSendToMenu = 0x1d;
|
||||
private const dbiCompressPastedImage = 0x1e;
|
||||
private const dbiLangOld = 0x1f;
|
||||
private const dbiLangFileOld = 0x20;
|
||||
private const dbiTileBackground = 0x21;
|
||||
private const dbiAutoLock = 0x22;
|
||||
private const dbiDialogLastPath = 0x23;
|
||||
private const dbiRecentEmojiOld = 0x24;
|
||||
private const dbiEmojiVariantsOld = 0x25;
|
||||
private const dbiRecentStickers = 0x26;
|
||||
private const dbiDcOptionOld = 0x27;
|
||||
private const dbiTryIPv6 = 0x28;
|
||||
private const dbiSongVolume = 0x29;
|
||||
private const dbiWindowsNotificationsOld = 0x30;
|
||||
private const dbiIncludeMuted = 0x31;
|
||||
private const dbiMegagroupSizeMax = 0x32;
|
||||
private const dbiDownloadPath = 0x33;
|
||||
private const dbiAutoDownload = 0x34;
|
||||
private const dbiSavedGifsLimit = 0x35;
|
||||
private const dbiShowingSavedGifsOld = 0x36;
|
||||
private const dbiAutoPlay = 0x37;
|
||||
private const dbiAdaptiveForWide = 0x38;
|
||||
private const dbiHiddenPinnedMessages = 0x39;
|
||||
private const dbiRecentEmoji = 0x3a;
|
||||
private const dbiEmojiVariants = 0x3b;
|
||||
private const dbiDialogsMode = 0x40;
|
||||
private const dbiModerateMode = 0x41;
|
||||
private const dbiVideoVolume = 0x42;
|
||||
private const dbiStickersRecentLimit = 0x43;
|
||||
private const dbiNativeNotifications = 0x44;
|
||||
private const dbiNotificationsCount = 0x45;
|
||||
private const dbiNotificationsCorner = 0x46;
|
||||
private const dbiThemeKey = 0x47;
|
||||
private const dbiDialogsWidthRatioOld = 0x48;
|
||||
private const dbiUseExternalVideoPlayer = 0x49;
|
||||
private const dbiDcOptions = 0x4a;
|
||||
private const dbiMtpAuthorization = 0x4b;
|
||||
private const dbiLastSeenWarningSeenOld = 0x4c;
|
||||
private const dbiAuthSessionSettings = 0x4d;
|
||||
private const dbiLangPackKey = 0x4e;
|
||||
private const dbiConnectionType = 0x4f;
|
||||
private const dbiStickersFavedLimit = 0x50;
|
||||
private const dbiSuggestStickersByEmoji = 0x51;
|
||||
|
||||
const dbiEncryptedWithSalt = 333;
|
||||
const dbiEncrypted = 444;
|
||||
private const dbiEncryptedWithSalt = 333;
|
||||
private const dbiEncrypted = 444;
|
||||
|
||||
// 500-600 reserved
|
||||
|
||||
const dbiVersion = 666;
|
||||
private const dbiVersion = 666;
|
||||
|
||||
private static function tdesktop(string $session, string $new_session, $settings = [])
|
||||
{
|
||||
|
@ -293,7 +293,7 @@ final class DataCenter
|
||||
foreach ([true, false] as $useDoH) {
|
||||
$ipv6Combos = [
|
||||
$this->getSettings()->getIpv6() ? 'ipv6' : 'ipv4',
|
||||
$this->getSettings()->getIpv6() ? 'ipv4' : 'ipv6'
|
||||
$this->getSettings()->getIpv6() ? 'ipv4' : 'ipv6',
|
||||
];
|
||||
foreach ($ipv6Combos as $ipv6) {
|
||||
if ($onlyIPv6 !== null && $onlyIPv6 !== $ipv6) {
|
||||
|
@ -41,9 +41,9 @@ use function count;
|
||||
*/
|
||||
final class DataCenterConnection implements JsonSerializable
|
||||
{
|
||||
const READ_WEIGHT = 1;
|
||||
const READ_WEIGHT_MEDIA = 5;
|
||||
const WRITE_WEIGHT = 10;
|
||||
public const READ_WEIGHT = 1;
|
||||
public const READ_WEIGHT_MEDIA = 5;
|
||||
public const WRITE_WEIGHT = 10;
|
||||
/**
|
||||
* Promise for connection.
|
||||
*
|
||||
@ -604,7 +604,7 @@ final class DataCenterConnection implements JsonSerializable
|
||||
return $this->connections[0];
|
||||
}
|
||||
$max = max($this->availableConnections);
|
||||
$key = array_search($max, $this->availableConnections);
|
||||
$key = array_search($max, $this->availableConnections, true);
|
||||
// Decrease to implement round robin
|
||||
$this->availableConnections[$key]--;
|
||||
return $this->connections[$key];
|
||||
|
@ -76,7 +76,7 @@ final class Mysql
|
||||
|
||||
self::$connections[$dbKey] = [
|
||||
new MysqlConnectionPool($config, $settings->getMaxConnections(), $settings->getIdleTimeout()),
|
||||
$pdo
|
||||
$pdo,
|
||||
];
|
||||
}
|
||||
} finally {
|
||||
|
@ -140,14 +140,14 @@ abstract class DriverArray implements DbArray, IteratorAggregate
|
||||
$this->serializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => \serialize(...),
|
||||
SerializerType::IGBINARY => \igbinary_serialize(...),
|
||||
SerializerType::JSON => fn ($value) => json_encode($value, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
|
||||
SerializerType::JSON => static fn ($value) => json_encode($value, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
|
||||
SerializerType::STRING => strval(...),
|
||||
};
|
||||
$this->deserializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => \unserialize(...),
|
||||
SerializerType::IGBINARY => \igbinary_unserialize(...),
|
||||
SerializerType::JSON => fn ($value) => json_decode($value, true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => fn ($v) => $v,
|
||||
SerializerType::JSON => static fn ($value) => json_decode($value, true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => static fn ($v) => $v,
|
||||
};
|
||||
}
|
||||
private static function migrateDataToDb(self $new, DbType|null $old): void
|
||||
|
@ -72,16 +72,16 @@ final class PostgresArray extends PostgresArrayBytea
|
||||
protected function setSerializer(SerializerType $serializer): void
|
||||
{
|
||||
$this->serializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => fn ($v) => bin2hex(serialize($v)),
|
||||
SerializerType::IGBINARY => fn ($v) => bin2hex(igbinary_serialize($v)),
|
||||
SerializerType::JSON => fn ($v) => bin2hex(json_encode($v, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)),
|
||||
SerializerType::STRING => fn ($v) => bin2hex(\strval($v)),
|
||||
SerializerType::SERIALIZE => static fn ($v) => bin2hex(serialize($v)),
|
||||
SerializerType::IGBINARY => static fn ($v) => bin2hex(igbinary_serialize($v)),
|
||||
SerializerType::JSON => static fn ($v) => bin2hex(json_encode($v, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)),
|
||||
SerializerType::STRING => static fn ($v) => bin2hex(\strval($v)),
|
||||
};
|
||||
$this->deserializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => fn ($v) => unserialize(hex2bin($v)),
|
||||
SerializerType::IGBINARY => fn ($v) => igbinary_unserialize(hex2bin($v)),
|
||||
SerializerType::JSON => fn ($value) => json_decode(hex2bin($value), true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => fn ($v) => hex2bin($v),
|
||||
SerializerType::SERIALIZE => static fn ($v) => unserialize(hex2bin($v)),
|
||||
SerializerType::IGBINARY => static fn ($v) => igbinary_unserialize(hex2bin($v)),
|
||||
SerializerType::JSON => static fn ($value) => json_decode(hex2bin($value), true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => static fn ($v) => hex2bin($v),
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
@ -90,16 +90,16 @@ class PostgresArrayBytea extends SqlArray
|
||||
protected function setSerializer(SerializerType $serializer): void
|
||||
{
|
||||
$this->serializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => fn ($v) => new ByteA(serialize($v)),
|
||||
SerializerType::IGBINARY => fn ($v) => new ByteA(igbinary_serialize($v)),
|
||||
SerializerType::JSON => fn ($v) => new ByteA(json_encode($v, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)),
|
||||
SerializerType::STRING => fn ($v) => new ByteA(\strval($v)),
|
||||
SerializerType::SERIALIZE => static fn ($v) => new ByteA(serialize($v)),
|
||||
SerializerType::IGBINARY => static fn ($v) => new ByteA(igbinary_serialize($v)),
|
||||
SerializerType::JSON => static fn ($v) => new ByteA(json_encode($v, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)),
|
||||
SerializerType::STRING => static fn ($v) => new ByteA(\strval($v)),
|
||||
};
|
||||
$this->deserializer = match ($serializer) {
|
||||
SerializerType::SERIALIZE => \unserialize(...),
|
||||
SerializerType::IGBINARY => \igbinary_unserialize(...),
|
||||
SerializerType::JSON => fn ($value) => json_decode($value, true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => fn ($v) => $v,
|
||||
SerializerType::JSON => static fn ($value) => json_decode($value, true, 256, JSON_THROW_ON_ERROR),
|
||||
SerializerType::STRING => static fn ($v) => $v,
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ final class DoHConnector implements SocketConnector
|
||||
} else {
|
||||
$records = $this->dataCenter->DoHClient->resolve($host, $socketContext->getDnsTypeRestriction());
|
||||
}
|
||||
usort($records, fn (DnsRecord $a, DnsRecord $b) => $a->getType() - $b->getType());
|
||||
usort($records, static fn (DnsRecord $a, DnsRecord $b) => $a->getType() - $b->getType());
|
||||
if ($this->ctx->getIpv6()) {
|
||||
$records = array_reverse($records);
|
||||
}
|
||||
@ -111,7 +111,7 @@ final class DoHConnector implements SocketConnector
|
||||
$streamContext = stream_context_create($socketContext->withoutTlsContext()->toStreamContextArray());
|
||||
/** @psalm-suppress NullArgument */
|
||||
if (!($socket = @stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) {
|
||||
throw new ConnectException(sprintf('Connection to %s failed: [Error #%d] %s%s', (string) $uri, $errno, $errstr, $failures ? '; previous attempts: '.implode($failures) : ''), $errno);
|
||||
throw new ConnectException(sprintf('Connection to %s failed: [Error #%d] %s%s', (string) $uri, $errno, $errstr, $failures ? '; previous attempts: '.implode('', $failures) : ''), $errno);
|
||||
}
|
||||
stream_set_blocking($socket, false);
|
||||
$deferred = new DeferredFuture();
|
||||
@ -125,7 +125,7 @@ final class DoHConnector implements SocketConnector
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw new ConnectException(sprintf('Connecting to %s failed: timeout exceeded (%d ms)%s', (string) $uri, $timeout, $failures ? '; previous attempts: '.implode($failures) : ''), 110);
|
||||
throw new ConnectException(sprintf('Connecting to %s failed: timeout exceeded (%d ms)%s', (string) $uri, $timeout, $failures ? '; previous attempts: '.implode('', $failures) : ''), 110);
|
||||
// See ETIMEDOUT in http://www.virtsync.com/c-error-codes-include-errno
|
||||
} finally {
|
||||
EventLoop::cancel($watcher);
|
||||
@ -134,7 +134,7 @@ final class DoHConnector implements SocketConnector
|
||||
// The following hack looks like the only way to detect connection refused errors with PHP's stream sockets.
|
||||
if (stream_socket_get_name($socket, true) === false) {
|
||||
fclose($socket);
|
||||
throw new ConnectException(sprintf('Connection to %s refused%s', (string) $uri, $failures ? '; previous attempts: '.implode($failures) : ''), 111);
|
||||
throw new ConnectException(sprintf('Connection to %s refused%s', (string) $uri, $failures ? '; previous attempts: '.implode('', $failures) : ''), 111);
|
||||
// See ECONNREFUSED in http://www.virtsync.com/c-error-codes-include-errno
|
||||
}
|
||||
} catch (ConnectException $e) {
|
||||
|
@ -133,7 +133,7 @@ final class DoHWrapper
|
||||
{
|
||||
$ctxs = [];
|
||||
$combos = [
|
||||
[[DefaultStream::class, []], [BufferedRawStream::class, []]]
|
||||
[[DefaultStream::class, []], [BufferedRawStream::class, []]],
|
||||
];
|
||||
if ($this->API->getSettings()->getConnection()->getRetry()) {
|
||||
$proxyCombos = [];
|
||||
|
@ -27,7 +27,7 @@ use danog\MadelineProto\TL\TL;
|
||||
// This code was written a few years ago: it is garbage, and has to be rewritten
|
||||
final class DocsBuilder
|
||||
{
|
||||
const DEFAULT_TEMPLATES = [
|
||||
public const DEFAULT_TEMPLATES = [
|
||||
'User' => ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'InputPeer', 'NotifyPeer', 'InputNotifyPeer'],
|
||||
'ReplyMarkup' => ['ReplyMarkup'],
|
||||
'InputFile' => ['InputFile', 'InputEncryptedFile'],
|
||||
|
@ -143,10 +143,10 @@ trait Constructors
|
||||
$ptype = 'Bool';
|
||||
}
|
||||
$human_ptype = $ptype;
|
||||
if (strpos($type, 'Input') === 0 && \in_array($ptype, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'InputPeer'], true) && !isset($this->settings['td'])) {
|
||||
if (str_starts_with($type, 'Input') && \in_array($ptype, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'InputPeer'], true) && !isset($this->settings['td'])) {
|
||||
$human_ptype = 'Username, chat ID, Update, Message or '.$ptype;
|
||||
}
|
||||
if (strpos($type, 'Input') === 0 && \in_array($ptype, ['InputMedia', 'InputDocument', 'InputPhoto'], true) && !isset($this->settings['td'])) {
|
||||
if (str_starts_with($type, 'Input') && \in_array($ptype, ['InputMedia', 'InputDocument', 'InputPhoto'], true) && !isset($this->settings['td'])) {
|
||||
$human_ptype = 'MessageMedia, Message, Update or '.$ptype;
|
||||
}
|
||||
if (\in_array($ptype, ['InputMessage'], true) && !isset($this->settings['td'])) {
|
||||
|
@ -180,12 +180,12 @@ abstract class EventHandler extends AbstractAPI
|
||||
$methods[$method_name] = [
|
||||
static function (array $update) use ($basic_handler, $closure): void {
|
||||
EventLoop::queue($basic_handler, $update, $closure);
|
||||
}
|
||||
},
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
array_map(fn (ReflectionAttribute $attribute) => $attribute->newInstance(), $methodRefl->getAttributes());
|
||||
array_map(static fn (ReflectionAttribute $attribute) => $attribute->newInstance(), $methodRefl->getAttributes());
|
||||
|
||||
if ($periodic = $methodRefl->getAttributes(Cron::class)) {
|
||||
if (!$this instanceof SimpleEventHandler) {
|
||||
@ -193,9 +193,7 @@ abstract class EventHandler extends AbstractAPI
|
||||
}
|
||||
$periodic = $periodic[0]->newInstance();
|
||||
$this->periodicLoops[$method] = new PeriodicLoop(
|
||||
static function (PeriodicLoop $loop) use ($closure): bool {
|
||||
return $closure($loop) ?? false;
|
||||
},
|
||||
static fn (PeriodicLoop $loop): bool => $closure($loop) ?? false,
|
||||
$method,
|
||||
$periodic->period
|
||||
);
|
||||
|
@ -167,7 +167,7 @@ abstract class AbstractMessage extends Update implements SimpleFilters
|
||||
DialogId::isSupergroupOrChannel($this->chatId) ? 'channels.getMessages' : 'messages.getMessages',
|
||||
[
|
||||
'channel' => $this->chatId,
|
||||
'id' => [['_' => 'inputMessageReplyTo', 'id' => $this->id]]
|
||||
'id' => [['_' => 'inputMessageReplyTo', 'id' => $this->id]],
|
||||
]
|
||||
)['messages'];
|
||||
/** @psalm-suppress InaccessibleProperty */
|
||||
@ -342,7 +342,7 @@ abstract class AbstractMessage extends Update implements SimpleFilters
|
||||
'peer' => $this->senderId,
|
||||
]
|
||||
)['stories']['stories'];
|
||||
$result = array_filter($result, fn (array $t): bool => $t['_'] !== 'storyItemDeleted');
|
||||
$result = array_filter($result, static fn (array $t): bool => $t['_'] !== 'storyItemDeleted');
|
||||
// Recall it because storyItemSkipped
|
||||
// TODO: Do this more efficiently
|
||||
$result = $client->methodCallAsyncRead(
|
||||
@ -375,7 +375,7 @@ abstract class AbstractMessage extends Update implements SimpleFilters
|
||||
[
|
||||
'peer' => $this->senderId,
|
||||
'top_msg_id' => $this->topicId,
|
||||
'action' => $action
|
||||
'action' => $action,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -393,7 +393,7 @@ abstract class AbstractMessage extends Update implements SimpleFilters
|
||||
[
|
||||
'peer' => $this->chatId,
|
||||
'channel' => $this->chatId,
|
||||
'max_id' => $readAll ? 0 : $this->id
|
||||
'max_id' => $readAll ? 0 : $this->id,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ final class EmojiTap extends Action
|
||||
'emoticon' => $this->emoticon,
|
||||
'interaction' => [
|
||||
'v' => 1,
|
||||
'a' => $this->animation
|
||||
]
|
||||
'a' => $this->animation,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ final class BotCommands extends Update
|
||||
$this->botId = $rawBotCommands['bot_id'];
|
||||
$this->chatId = $API->getIdInternal($rawBotCommands['peer']);
|
||||
$this->commands = array_map(
|
||||
fn (array $command): Command => new Command($command),
|
||||
static fn (array $command): Command => new Command($command),
|
||||
$rawBotCommands['commands']
|
||||
);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ final class FiltersAnd extends Filter
|
||||
}
|
||||
$final = array_filter(
|
||||
$final,
|
||||
fn (Filter $f): bool => !$f instanceof FilterAllowAll,
|
||||
static fn (Filter $f): bool => !$f instanceof FilterAllowAll,
|
||||
);
|
||||
$final = array_values($final);
|
||||
return match (\count($final)) {
|
||||
|
@ -54,7 +54,7 @@ final class Gif extends AbstractVideo
|
||||
'messages.saveGif',
|
||||
[
|
||||
'id' => $this->botApiFileId,
|
||||
'unsave' => false
|
||||
'unsave' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -69,7 +69,7 @@ final class Gif extends AbstractVideo
|
||||
'messages.saveGif',
|
||||
[
|
||||
'id' => $this->botApiFileId,
|
||||
'unsave' => true
|
||||
'unsave' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -50,11 +50,11 @@ abstract class MediaStory extends IpcCapable implements JsonSerializable // for
|
||||
$this->story = match ($rawMedia['story']['_'] ?? null) {
|
||||
'storyItem' => new Story($API, [
|
||||
'peer' => $this->senderId,
|
||||
'story' => $rawMedia['story']
|
||||
'story' => $rawMedia['story'],
|
||||
]),
|
||||
'storyItemDeleted' => new StoryDeleted($API, [
|
||||
'peer' => $this->senderId,
|
||||
'story' => $rawMedia['story']
|
||||
'story' => $rawMedia['story'],
|
||||
]),
|
||||
'storyItemSkipped' => null, // Will it happen?
|
||||
default => null
|
||||
|
@ -202,7 +202,7 @@ abstract class Message extends AbstractMessage
|
||||
'id' => $this->id,
|
||||
'pm_oneside' => $pmOneside,
|
||||
'silent' => $silent,
|
||||
'unpin' => false
|
||||
'unpin' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -222,7 +222,7 @@ abstract class Message extends AbstractMessage
|
||||
'id' => $this->id,
|
||||
'pm_oneside' => $pmOneside,
|
||||
'silent' => $silent,
|
||||
'unpin' => true
|
||||
'unpin' => true,
|
||||
]
|
||||
);
|
||||
return $this->getClient()->wrapUpdate($result);
|
||||
@ -252,7 +252,7 @@ abstract class Message extends AbstractMessage
|
||||
'reason' => ['_' => $reason->value],
|
||||
'message' => $message,
|
||||
'id' => [$this->id],
|
||||
'peer' => $this->chatId
|
||||
'peer' => $this->chatId,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -278,7 +278,7 @@ abstract class Message extends AbstractMessage
|
||||
'last_name' => $lastName,
|
||||
'phone_number' => $phoneNumber,
|
||||
'add_phone_privacy_exception' => $addPhonePrivacyException,
|
||||
'id' => $this->senderId
|
||||
'id' => $this->senderId,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -291,7 +291,7 @@ abstract class Message extends AbstractMessage
|
||||
$this->getClient()->methodCallAsyncRead(
|
||||
'contacts.deleteContacts',
|
||||
[
|
||||
'id' => [$this->senderId]
|
||||
'id' => [$this->senderId],
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -307,7 +307,7 @@ abstract class Message extends AbstractMessage
|
||||
'channels.inviteToChannel',
|
||||
[
|
||||
'channel' => $channel,
|
||||
'users' => [$this->senderId]
|
||||
'users' => [$this->senderId],
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -335,7 +335,7 @@ abstract class Message extends AbstractMessage
|
||||
? [['_' => 'reactionCustomEmoji', 'document_id' => $reaction]]
|
||||
: [['_' => 'reactionEmoji', 'emoticon' => $reaction]],
|
||||
'big' => $big,
|
||||
'add_to_recent' => $addToRecent
|
||||
'add_to_recent' => $addToRecent,
|
||||
]
|
||||
);
|
||||
$this->reactions[] = $reaction;
|
||||
@ -357,7 +357,7 @@ abstract class Message extends AbstractMessage
|
||||
}
|
||||
unset($this->reactions[$key]);
|
||||
$this->reactions = array_values($this->reactions);
|
||||
$r = array_map(fn (string|int $r): array => \is_int($r) ? ['_' => 'reactionCustomEmoji', 'document_id' => $r] : ['_' => 'reactionEmoji', 'emoticon' => $r], $this->reactions);
|
||||
$r = array_map(static fn (string|int $r): array => \is_int($r) ? ['_' => 'reactionCustomEmoji', 'document_id' => $r] : ['_' => 'reactionEmoji', 'emoticon' => $r], $this->reactions);
|
||||
$r[]= ['_' => 'reactionEmpty'];
|
||||
$this->getClient()->methodCallAsyncRead(
|
||||
'messages.sendReaction',
|
||||
@ -387,7 +387,7 @@ abstract class Message extends AbstractMessage
|
||||
[
|
||||
'peer' => $this->chatId,
|
||||
'id' => [$this->id],
|
||||
'to_lang' => $toLang
|
||||
'to_lang' => $toLang,
|
||||
]
|
||||
);
|
||||
return $result['result'][0]['text'];
|
||||
@ -419,7 +419,7 @@ abstract class Message extends AbstractMessage
|
||||
'reply_markup' => $replyMarkup,
|
||||
'parse_mode' => $parseMode,
|
||||
'schedule_date' => $scheduleDate,
|
||||
'no_webpage' => $noWebpage
|
||||
'no_webpage' => $noWebpage,
|
||||
]
|
||||
);
|
||||
return $this->getClient()->wrapMessage($this->getClient()->extractMessage($result));
|
||||
|
@ -110,7 +110,7 @@ final class ChannelMessage extends Message
|
||||
[
|
||||
'peer' => $this->chatId,
|
||||
'id' => [$this->id],
|
||||
'increment' => true
|
||||
'increment' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -165,14 +165,14 @@ final class GroupMessage extends Message
|
||||
'send_voices' => false,
|
||||
'send_docs' => false,
|
||||
'send_plain' => false,
|
||||
'until_date' => $untilDate
|
||||
'until_date' => $untilDate,
|
||||
];
|
||||
$this->getClient()->methodCallAsyncRead(
|
||||
'channels.editBanned',
|
||||
[
|
||||
'channel' => $this->chatId,
|
||||
'participant' => $this->senderId,
|
||||
'banned_rights' => $chatBannedRights
|
||||
'banned_rights' => $chatBannedRights,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -206,14 +206,14 @@ final class GroupMessage extends Message
|
||||
'send_voices' => true,
|
||||
'send_docs' => true,
|
||||
'send_plain' => true,
|
||||
'until_date' => $untilDate
|
||||
'until_date' => $untilDate,
|
||||
];
|
||||
$this->getClient()->methodCallAsyncRead(
|
||||
'channels.editBanned',
|
||||
[
|
||||
'channel' => $this->chatId,
|
||||
'participant' => $this->senderId,
|
||||
'banned_rights' => $chatBannedRights
|
||||
'banned_rights' => $chatBannedRights,
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -237,7 +237,7 @@ final class GroupMessage extends Message
|
||||
[
|
||||
'channel' => $this->chatId,
|
||||
'for_everyone' => $forEveryone,
|
||||
'max_id' => $maxId
|
||||
'max_id' => $maxId,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ class SecretMessage extends AbstractPrivateMessage
|
||||
'peer' => $this->chatId,
|
||||
'message' => [
|
||||
'_' => 'decryptedMessageService',
|
||||
'action' => ['_' => 'decryptedMessageActionScreenshotMessages', 'random_ids' => [$this->id]]
|
||||
]
|
||||
'action' => ['_' => 'decryptedMessageActionScreenshotMessages', 'random_ids' => [$this->id]],
|
||||
],
|
||||
]
|
||||
);
|
||||
return $this->getClient()->wrapMessage($this->getClient()->extractMessage($result));
|
||||
|
@ -170,7 +170,7 @@ final class Story extends AbstractStory
|
||||
'background' => $background,
|
||||
'clear_draft' => $clearDraft,
|
||||
'no_webpage' => $noWebpage,
|
||||
'update_stickersets_order' => $updateStickersetsOrder
|
||||
'update_stickersets_order' => $updateStickersetsOrder,
|
||||
]
|
||||
);
|
||||
if (isset($result['_'])) {
|
||||
|
@ -33,7 +33,7 @@ final class SecretUserTyping extends Typing
|
||||
$this->chatId = $rawMessage['chat_id'];
|
||||
parent::__construct($API, [
|
||||
'user_id' => $info['user_id'],
|
||||
'action' => $rawMessage['decrypted_message']['action']
|
||||
'action' => $rawMessage['decrypted_message']['action'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ final class Username extends Update
|
||||
$this->firstName = $rawUserName['first_name'];
|
||||
$this->lastName = $rawUserName['last_name'];
|
||||
$this->usernames = array_map(
|
||||
fn (array $username) => new UsernameInfo($username),
|
||||
static fn (array $username) => new UsernameInfo($username),
|
||||
$rawUserName['usernames']
|
||||
);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class Exception extends \Exception
|
||||
$this->line = $line;
|
||||
}
|
||||
parent::__construct($message, $code, $previous);
|
||||
if (strpos($message, 'socket_accept') === false
|
||||
if (!str_contains($message, 'socket_accept')
|
||||
&& !\in_array(basename($this->file), ['PKCS8.php', 'PSS.php'], true)
|
||||
) {
|
||||
Logger::log($message.' in '.basename($this->file).':'.$this->line, Logger::FATAL_ERROR);
|
||||
@ -85,13 +85,13 @@ class Exception extends \Exception
|
||||
// If error is suppressed with @, don't throw an exception
|
||||
if (error_reporting() === 0
|
||||
|| strpos($errstr, 'headers already sent')
|
||||
|| strpos($errstr, 'Creation of dynamic property') !== false
|
||||
|| strpos($errstr, 'Legacy nullable type detected') !== false
|
||||
|| str_contains($errstr, 'Creation of dynamic property')
|
||||
|| str_contains($errstr, 'Legacy nullable type detected')
|
||||
|| str_contains($errstr, '$tdMethods is deprecated')
|
||||
|| $errfileReplaced && (
|
||||
strpos($errfileReplaced, DIRECTORY_SEPARATOR.'amphp'.DIRECTORY_SEPARATOR) !== false
|
||||
|| strpos($errfileReplaced, DIRECTORY_SEPARATOR.'league'.DIRECTORY_SEPARATOR) !== false
|
||||
|| strpos($errfileReplaced, DIRECTORY_SEPARATOR.'phpseclib'.DIRECTORY_SEPARATOR) !== false
|
||||
str_contains($errfileReplaced, DIRECTORY_SEPARATOR.'amphp'.DIRECTORY_SEPARATOR)
|
||||
|| str_contains($errfileReplaced, DIRECTORY_SEPARATOR.'league'.DIRECTORY_SEPARATOR)
|
||||
|| str_contains($errfileReplaced, DIRECTORY_SEPARATOR.'phpseclib'.DIRECTORY_SEPARATOR)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
@ -105,7 +105,7 @@ class Exception extends \Exception
|
||||
*/
|
||||
public static function exceptionHandler(\Throwable $exception): void
|
||||
{
|
||||
$print = function (string $s): void {
|
||||
$print = static function (string $s): void {
|
||||
Logger::log($s, Logger::FATAL_ERROR);
|
||||
if (headers_sent()) {
|
||||
return;
|
||||
|
@ -81,7 +81,7 @@ final class GarbageCollector
|
||||
$client = HttpClientBuilder::buildDefault();
|
||||
|
||||
$id = null;
|
||||
$cb = function () use ($client, &$id): void {
|
||||
$cb = static function () use ($client, &$id): void {
|
||||
try {
|
||||
$request = new Request(MADELINE_RELEASE_URL);
|
||||
$latest = $client->request($request);
|
||||
@ -91,7 +91,7 @@ final class GarbageCollector
|
||||
$new = Magic::$latest_release;
|
||||
Logger::log("!!!!!!!!!!!!! An update of MadelineProto is required (old=$old, new=$new)! !!!!!!!!!!!!!", Logger::FATAL_ERROR);
|
||||
|
||||
$contents = $client->request(new Request("https://phar.madelineproto.xyz/phar.php?v=new".rand(0, PHP_INT_MAX)))
|
||||
$contents = $client->request(new Request("https://phar.madelineproto.xyz/phar.php?v=new".random_int(0, PHP_INT_MAX)))
|
||||
->getBody()
|
||||
->buffer();
|
||||
|
||||
|
@ -112,11 +112,11 @@ final class ProcessRunner extends RunnerAbstract
|
||||
}
|
||||
}
|
||||
$envVars = array_merge(
|
||||
array_filter($_SERVER, fn ($v, $k): bool => \is_string($v) && !\in_array($k, self::CGI_VARS, true), ARRAY_FILTER_USE_BOTH),
|
||||
array_filter($_SERVER, static fn ($v, $k): bool => \is_string($v) && !\in_array($k, self::CGI_VARS, true), ARRAY_FILTER_USE_BOTH),
|
||||
[
|
||||
'QUERY_STRING' => http_build_query($params),
|
||||
'absoluteRootDir' => $root,
|
||||
'serverName' => $_SERVER['SERVER_NAME'] ?? ''
|
||||
'serverName' => $_SERVER['SERVER_NAME'] ?? '',
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -68,7 +68,7 @@ final class WebRunner extends RunnerAbstract
|
||||
$params = [
|
||||
'argv' => ['madeline-ipc', $session, $startupId],
|
||||
'cwd' => Magic::getcwd(),
|
||||
'MadelineSelfRestart' => 1
|
||||
'MadelineSelfRestart' => 1,
|
||||
];
|
||||
if (\function_exists('memprof_enabled') && memprof_enabled()) {
|
||||
$params['MEMPROF_PROFILE'] = '1';
|
||||
@ -80,7 +80,7 @@ final class WebRunner extends RunnerAbstract
|
||||
}
|
||||
|
||||
private static ?string $absoluteRootDir = null;
|
||||
final public static function getAbsoluteRootDir(): string
|
||||
public static function getAbsoluteRootDir(): string
|
||||
{
|
||||
if (self::$absoluteRootDir) {
|
||||
return self::$absoluteRootDir;
|
||||
|
@ -59,7 +59,7 @@ use Webmozart\Assert\Assert;
|
||||
|
||||
if (\defined('SIGHUP')) {
|
||||
try {
|
||||
pcntl_signal(SIGHUP, fn () => null);
|
||||
pcntl_signal(SIGHUP, static fn () => null);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +52,11 @@ class Server extends Loop
|
||||
/**
|
||||
* Server version.
|
||||
*/
|
||||
const VERSION = 1;
|
||||
public const VERSION = 1;
|
||||
/**
|
||||
* Shutdown server.
|
||||
*/
|
||||
const SHUTDOWN = 0;
|
||||
public const SHUTDOWN = 0;
|
||||
/**
|
||||
* Boolean to shut down worker, if started.
|
||||
*/
|
||||
@ -246,7 +246,7 @@ class Server extends Loop
|
||||
$result = new ExitFailure($e);
|
||||
} finally {
|
||||
if (isset($wrapper)) {
|
||||
EventLoop::queue(function () use ($wrapper): void {
|
||||
EventLoop::queue(static function () use ($wrapper): void {
|
||||
try {
|
||||
$wrapper->disconnect();
|
||||
} catch (Throwable $e) {
|
||||
|
@ -54,19 +54,19 @@ final class Logger
|
||||
/**
|
||||
* @internal ANSI foreground color escapes
|
||||
*/
|
||||
const FOREGROUND = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97];
|
||||
public const FOREGROUND = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97];
|
||||
/**
|
||||
* @internal ANSI background color escapes
|
||||
*/
|
||||
const BACKGROUND = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107];
|
||||
public const BACKGROUND = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107];
|
||||
/**
|
||||
* @internal ANSI modifier escapes
|
||||
*/
|
||||
const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
|
||||
public const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
|
||||
/**
|
||||
* @internal ANSI reset modifier escapes
|
||||
*/
|
||||
const RESET = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28];
|
||||
public const RESET = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28];
|
||||
/**
|
||||
* Logging mode.
|
||||
*
|
||||
@ -134,104 +134,104 @@ final class Logger
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const ULTRA_VERBOSE = 5;
|
||||
public const ULTRA_VERBOSE = 5;
|
||||
/**
|
||||
* Verbose logging.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const VERBOSE = 4;
|
||||
public const VERBOSE = 4;
|
||||
/**
|
||||
* Notice logging.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const NOTICE = 3;
|
||||
public const NOTICE = 3;
|
||||
/**
|
||||
* Warning logging.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const WARNING = 2;
|
||||
public const WARNING = 2;
|
||||
/**
|
||||
* Error logging.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const ERROR = 1;
|
||||
public const ERROR = 1;
|
||||
/**
|
||||
* Log only fatal errors.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const FATAL_ERROR = 0;
|
||||
public const FATAL_ERROR = 0;
|
||||
|
||||
/**
|
||||
* Default logger (syslog).
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const DEFAULT_LOGGER = 1;
|
||||
public const DEFAULT_LOGGER = 1;
|
||||
/**
|
||||
* File logger.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const FILE_LOGGER = 2;
|
||||
public const FILE_LOGGER = 2;
|
||||
/**
|
||||
* Echo logger.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const ECHO_LOGGER = 3;
|
||||
public const ECHO_LOGGER = 3;
|
||||
/**
|
||||
* Callable logger.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const CALLABLE_LOGGER = 4;
|
||||
public const CALLABLE_LOGGER = 4;
|
||||
|
||||
/**
|
||||
* Ultra verbose level.
|
||||
*/
|
||||
const LEVEL_ULTRA_VERBOSE = self::ULTRA_VERBOSE;
|
||||
public const LEVEL_ULTRA_VERBOSE = self::ULTRA_VERBOSE;
|
||||
/**
|
||||
* Verbose level.
|
||||
*/
|
||||
const LEVEL_VERBOSE = self::VERBOSE;
|
||||
public const LEVEL_VERBOSE = self::VERBOSE;
|
||||
/**
|
||||
* Notice level.
|
||||
*/
|
||||
const LEVEL_NOTICE = self::NOTICE;
|
||||
public const LEVEL_NOTICE = self::NOTICE;
|
||||
/**
|
||||
* Warning level.
|
||||
*/
|
||||
const LEVEL_WARNING = self::WARNING;
|
||||
public const LEVEL_WARNING = self::WARNING;
|
||||
/**
|
||||
* Error level.
|
||||
*/
|
||||
const LEVEL_ERROR = self::ERROR;
|
||||
public const LEVEL_ERROR = self::ERROR;
|
||||
/**
|
||||
* Fatal error level.
|
||||
*/
|
||||
const LEVEL_FATAL = self::FATAL_ERROR;
|
||||
public const LEVEL_FATAL = self::FATAL_ERROR;
|
||||
|
||||
/**
|
||||
* Default logger (syslog).
|
||||
*/
|
||||
const LOGGER_DEFAULT = self::DEFAULT_LOGGER;
|
||||
public const LOGGER_DEFAULT = self::DEFAULT_LOGGER;
|
||||
/**
|
||||
* Echo logger.
|
||||
*/
|
||||
const LOGGER_ECHO = self::ECHO_LOGGER;
|
||||
public const LOGGER_ECHO = self::ECHO_LOGGER;
|
||||
/**
|
||||
* File logger.
|
||||
*/
|
||||
const LOGGER_FILE = self::FILE_LOGGER;
|
||||
public const LOGGER_FILE = self::FILE_LOGGER;
|
||||
/**
|
||||
* Callable logger.
|
||||
*/
|
||||
const LOGGER_CALLABLE = self::CALLABLE_LOGGER;
|
||||
public const LOGGER_CALLABLE = self::CALLABLE_LOGGER;
|
||||
|
||||
/**
|
||||
* Construct global static logger from MadelineProto settings.
|
||||
|
@ -40,9 +40,9 @@ use function strlen;
|
||||
*/
|
||||
final class WriteLoop extends Loop
|
||||
{
|
||||
const MAX_COUNT = 1020;
|
||||
public const MAX_COUNT = 1020;
|
||||
private const MAX_SIZE = 1 << 15;
|
||||
const MAX_IDS = 8192;
|
||||
public const MAX_IDS = 8192;
|
||||
|
||||
use Common;
|
||||
/**
|
||||
@ -226,9 +226,9 @@ final class WriteLoop extends Loop
|
||||
'lang_code' => $this->API->settings->getAppInfo()->getLangCode(),
|
||||
'lang_pack' => $this->API->settings->getAppInfo()->getLangPack(),
|
||||
'proxy' => $this->connection->getInputClientProxy(),
|
||||
'query' => $MTmessage['body']
|
||||
'query' => $MTmessage['body'],
|
||||
]
|
||||
)
|
||||
),
|
||||
]));
|
||||
} else {
|
||||
$this->API->logger("Skipping $message due to uninited connection in DC $this->datacenter");
|
||||
@ -257,7 +257,7 @@ final class WriteLoop extends Loop
|
||||
'invokeAfterMsg',
|
||||
[
|
||||
'msg_id' => $prevId,
|
||||
'query' => $MTmessage['body']
|
||||
'query' => $MTmessage['body'],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -45,6 +45,6 @@ final class PeriodicLoopInternal extends PeriodicLoop
|
||||
public function __construct(MTProto $API, callable $callable, string $name, ?int $interval)
|
||||
{
|
||||
$this->init($API);
|
||||
parent::__construct(fn () => $callable(), $name, $interval);
|
||||
parent::__construct(static fn () => $callable(), $name, $interval);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ final class FeedLoop extends Loop
|
||||
/**
|
||||
* Main loop ID.
|
||||
*/
|
||||
const GENERIC = 0;
|
||||
public const GENERIC = 0;
|
||||
/**
|
||||
* Incoming updates array.
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@ final class UpdateLoop extends Loop
|
||||
/**
|
||||
* Main loop ID.
|
||||
*/
|
||||
const GENERIC = 0;
|
||||
public const GENERIC = 0;
|
||||
|
||||
private const DEFAULT_TIMEOUT = 10.0;
|
||||
|
||||
|
@ -90,11 +90,11 @@ final class DjLoop extends VoIPLoop
|
||||
'instance' => $this->instance,
|
||||
'holdFiles' => array_filter(
|
||||
$this->holdFiles,
|
||||
fn ($v) => !$v instanceof ReadableStream
|
||||
static fn ($v) => !$v instanceof ReadableStream
|
||||
),
|
||||
'inputFiles' => array_filter(
|
||||
$this->inputFiles,
|
||||
fn ($v) => !$v instanceof ReadableStream
|
||||
static fn ($v) => !$v instanceof ReadableStream
|
||||
),
|
||||
'packetQueuePrimary' => $this->packetQueuePrimary,
|
||||
'packetQueueSecondary' => $this->packetQueueSecondary,
|
||||
@ -206,7 +206,7 @@ final class DjLoop extends VoIPLoop
|
||||
}
|
||||
$this->instance->log("Starting conversion fiber...");
|
||||
$pipe = new Pipe(4096);
|
||||
EventLoop::queue(function () use ($f, $pipe, $cancellation): void {
|
||||
EventLoop::queue(static function () use ($f, $pipe, $cancellation): void {
|
||||
try {
|
||||
Ogg::convert($f, $pipe->getSink(), $cancellation);
|
||||
} catch (CancelledException) {
|
||||
|
@ -122,37 +122,37 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
|
||||
* @internal
|
||||
* @var int
|
||||
*/
|
||||
const V = 176;
|
||||
public const V = 176;
|
||||
/**
|
||||
* Bad message error codes.
|
||||
*
|
||||
* @internal
|
||||
* @var array
|
||||
*/
|
||||
const BAD_MSG_ERROR_CODES = [16 => 'msg_id too low (most likely, client time is wrong; it would be worthwhile to synchronize it using msg_id notifications and re-send the original message with the correct msg_id or wrap it in a container with a new msg_id if the original message had waited too long on the client to be transmitted)', 17 => 'msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)', 18 => 'incorrect two lower order msg_id bits (the server expects client message msg_id to be divisible by 4)', 19 => 'container msg_id is the same as msg_id of a previously received message (this must never happen)', 20 => 'message too old, and it cannot be verified whether the server has received a message with this msg_id or not', 32 => 'msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)', 33 => 'msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)', 34 => 'an even msg_seqno expected (irrelevant message), but odd received', 35 => 'odd msg_seqno expected (relevant message), but even received', 48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)', 64 => 'invalid container'];
|
||||
public const BAD_MSG_ERROR_CODES = [16 => 'msg_id too low (most likely, client time is wrong; it would be worthwhile to synchronize it using msg_id notifications and re-send the original message with the correct msg_id or wrap it in a container with a new msg_id if the original message had waited too long on the client to be transmitted)', 17 => 'msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)', 18 => 'incorrect two lower order msg_id bits (the server expects client message msg_id to be divisible by 4)', 19 => 'container msg_id is the same as msg_id of a previously received message (this must never happen)', 20 => 'message too old, and it cannot be verified whether the server has received a message with this msg_id or not', 32 => 'msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)', 33 => 'msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)', 34 => 'an even msg_seqno expected (irrelevant message), but odd received', 35 => 'odd msg_seqno expected (relevant message), but even received', 48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)', 64 => 'invalid container'];
|
||||
/**
|
||||
* Localized message info flags.
|
||||
*
|
||||
* @internal
|
||||
* @var array
|
||||
*/
|
||||
const MSGS_INFO_FLAGS = [1 => 'nothing is known about the message (msg_id too low, the other party may have forgotten it)', 2 => 'message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)', 3 => 'message not received (msg_id too high; however, the other party has certainly not received it yet)', 4 => 'message received (note that this response is also at the same time a receipt acknowledgment)', 8 => ' and message already acknowledged', 16 => ' and message not requiring acknowledgment', 32 => ' and RPC query contained in message being processed or processing already complete', 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received'];
|
||||
public const MSGS_INFO_FLAGS = [1 => 'nothing is known about the message (msg_id too low, the other party may have forgotten it)', 2 => 'message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)', 3 => 'message not received (msg_id too high; however, the other party has certainly not received it yet)', 4 => 'message received (note that this response is also at the same time a receipt acknowledgment)', 8 => ' and message already acknowledged', 16 => ' and message not requiring acknowledgment', 32 => ' and RPC query contained in message being processed or processing already complete', 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received'];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], 'message' => ['message']], 'message' => ['_' => 'message', 'id' => ['id'], 'sender_user_id' => ['from_id'], 'chat_id' => ['peer_id', 'choose_chat_id_from_botapi'], 'send_state' => ['choose_incoming_or_sent'], 'can_be_edited' => ['choose_can_edit'], 'can_be_deleted' => ['choose_can_delete'], 'is_post' => ['post'], 'date' => ['date'], 'edit_date' => ['edit_date'], 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], 'ttl' => ['choose_ttl'], 'ttl_expires_in' => ['choose_ttl_expires_in'], 'via_bot_user_id' => ['via_bot_id'], 'views' => ['views'], 'content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']], 'messages.sendMessage' => ['chat_id' => ['peer'], 'reply_to_message_id' => ['reply_to_msg_id'], 'disable_notification' => ['silent'], 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']]];
|
||||
public const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], 'message' => ['message']], 'message' => ['_' => 'message', 'id' => ['id'], 'sender_user_id' => ['from_id'], 'chat_id' => ['peer_id', 'choose_chat_id_from_botapi'], 'send_state' => ['choose_incoming_or_sent'], 'can_be_edited' => ['choose_can_edit'], 'can_be_deleted' => ['choose_can_delete'], 'is_post' => ['post'], 'date' => ['date'], 'edit_date' => ['edit_date'], 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], 'ttl' => ['choose_ttl'], 'ttl_expires_in' => ['choose_ttl_expires_in'], 'via_bot_user_id' => ['via_bot_id'], 'views' => ['views'], 'content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']], 'messages.sendMessage' => ['chat_id' => ['peer'], 'reply_to_message_id' => ['reply_to_msg_id'], 'disable_notification' => ['silent'], 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']]];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const TD_REVERSE = ['sendMessage' => 'messages.sendMessage'];
|
||||
public const TD_REVERSE = ['sendMessage' => 'messages.sendMessage'];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const TD_IGNORE = ['updateMessageID'];
|
||||
public const TD_IGNORE = ['updateMessageID'];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const BOTAPI_PARAMS_CONVERSION = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message'];
|
||||
public const BOTAPI_PARAMS_CONVERSION = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message'];
|
||||
/**
|
||||
* Array of references to all instances of MTProto.
|
||||
*
|
||||
@ -1572,7 +1572,7 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
|
||||
public function setReportPeers(int|string|array $userOrId): void
|
||||
{
|
||||
$this->reportDest = $this->sanitizeReportPeers($userOrId);
|
||||
$this->admins = array_values(array_filter($this->reportDest, fn (int $v) => $v > 0));
|
||||
$this->admins = array_values(array_filter($this->reportDest, static fn (int $v) => $v > 0));
|
||||
}
|
||||
/**
|
||||
* Flush all postponed messages.
|
||||
@ -1762,7 +1762,7 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
|
||||
}],
|
||||
'config' => [function (array $config): void {
|
||||
$this->config = $config;
|
||||
}]
|
||||
}],
|
||||
];
|
||||
}
|
||||
/**
|
||||
@ -1813,9 +1813,7 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
|
||||
[
|
||||
'InputFileLocation' => $this->getDownloadInfo(...),
|
||||
'InputPeer' => $this->getInputPeer(...),
|
||||
'InputCheckPasswordSRP' => function (string $password): array {
|
||||
return (new PasswordCalculator($this->methodCallAsyncRead('account.getPassword', [])))->getCheckPassword($password);
|
||||
},
|
||||
'InputCheckPasswordSRP' => fn (string $password): array => (new PasswordCalculator($this->methodCallAsyncRead('account.getPassword', [])))->getCheckPassword($password),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ abstract class AuthKey implements JsonSerializable
|
||||
public function __construct(array $old = [])
|
||||
{
|
||||
if (isset($old['auth_key'])) {
|
||||
if (\strlen($old['auth_key']) !== 2048 / 8 && strpos($old['auth_key'], 'pony') === 0) {
|
||||
$old['auth_key'] = base64_decode(substr($old['auth_key'], 4));
|
||||
if (\strlen($old['auth_key']) !== 2048 / 8 && str_starts_with($old['auth_key'], 'pony')) {
|
||||
$old['auth_key'] = base64_decode(substr($old['auth_key'], 4), true);
|
||||
}
|
||||
$this->setAuthKey($old['auth_key']);
|
||||
}
|
||||
|
@ -30,15 +30,15 @@ final class MTProtoIncomingMessage extends MTProtoMessage
|
||||
/**
|
||||
* We have received this message.
|
||||
*/
|
||||
const STATE_RECEIVED = 4;
|
||||
public const STATE_RECEIVED = 4;
|
||||
/**
|
||||
* We have acknowledged this message.
|
||||
*/
|
||||
const STATE_ACKED = 8;
|
||||
public const STATE_ACKED = 8;
|
||||
/**
|
||||
* We have read the contents of this message.
|
||||
*/
|
||||
const STATE_READ = 128;
|
||||
public const STATE_READ = 128;
|
||||
|
||||
/**
|
||||
* Response field map.
|
||||
|
@ -40,19 +40,19 @@ class MTProtoOutgoingMessage extends MTProtoMessage
|
||||
/**
|
||||
* The message was created.
|
||||
*/
|
||||
const STATE_PENDING = 0;
|
||||
public const STATE_PENDING = 0;
|
||||
/**
|
||||
* The message was sent.
|
||||
*/
|
||||
const STATE_SENT = 1;
|
||||
public const STATE_SENT = 1;
|
||||
/**
|
||||
* The message was acked.
|
||||
*/
|
||||
const STATE_ACKED = 2;
|
||||
public const STATE_ACKED = 2;
|
||||
/**
|
||||
* We got a reply to the message.
|
||||
*/
|
||||
const STATE_REPLIED = self::STATE_ACKED | 4;
|
||||
public const STATE_REPLIED = self::STATE_ACKED | 4;
|
||||
|
||||
/**
|
||||
* State of message.
|
||||
@ -127,7 +127,7 @@ class MTProtoOutgoingMessage extends MTProtoMessage
|
||||
$this->userRelated = $constructor === 'users.getUsers' && $body === ['id' => [['_' => 'inputUserSelf']]] || $constructor === 'auth.exportAuthorization' || $constructor === 'updates.getDifference';
|
||||
|
||||
parent::__construct(!isset(MTProtoMessage::NOT_CONTENT_RELATED[$constructor]));
|
||||
$cancellation?->subscribe(fn (CancelledException $e) => $this->reply(fn () => throw $e));
|
||||
$cancellation?->subscribe(fn (CancelledException $e) => $this->reply(static fn () => throw $e));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +122,7 @@ trait AckHandler
|
||||
continue;
|
||||
}
|
||||
if ($message->getSent() + $dropTimeout < time()) {
|
||||
$this->handleReject($message, fn () => new Exception('Request timeout'));
|
||||
$this->handleReject($message, static fn () => new Exception('Request timeout'));
|
||||
continue;
|
||||
}
|
||||
if ($message->getState() & MTProtoOutgoingMessage::STATE_REPLIED) {
|
||||
|
@ -137,8 +137,8 @@ trait CallHandler
|
||||
if (!$postpone) {
|
||||
$this->flush();
|
||||
}
|
||||
return new WrappedFuture(async(fn () => array_map(
|
||||
fn (WrappedFuture $f) => $f->await(),
|
||||
return new WrappedFuture(async(static fn () => array_map(
|
||||
static fn (WrappedFuture $f) => $f->await(),
|
||||
await($promises)
|
||||
)));
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ trait ResponseHandler
|
||||
try {
|
||||
$exception = $this->handleRpcError($request, $response);
|
||||
} catch (Throwable $e) {
|
||||
$exception = fn () => $e;
|
||||
$exception = static fn () => $e;
|
||||
}
|
||||
if ($exception) {
|
||||
$this->handleReject($request, $exception);
|
||||
@ -229,7 +229,7 @@ trait ResponseHandler
|
||||
EventLoop::queue($this->methodRecall(...), $requestId);
|
||||
return;
|
||||
}
|
||||
$this->handleReject($request, fn () => new RPCErrorException('Received bad_msg_notification: ' . MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], $response['error_code'], $request->getConstructor()));
|
||||
$this->handleReject($request, static fn () => new RPCErrorException('Received bad_msg_notification: ' . MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], $response['error_code'], $request->getConstructor()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -284,7 +284,7 @@ trait ResponseHandler
|
||||
$this->shared->getTempAuthKey()->init(true);
|
||||
}
|
||||
if (\in_array($response['error_message'], ['PERSISTENT_TIMESTAMP_EMPTY', 'PERSISTENT_TIMESTAMP_INVALID'], true)) {
|
||||
return fn () => new PTSException($response['error_message']);
|
||||
return static fn () => new PTSException($response['error_message']);
|
||||
}
|
||||
if ($response['error_message'] === 'PERSISTENT_TIMESTAMP_OUTDATED') {
|
||||
$response['error_code'] = 500;
|
||||
@ -335,7 +335,7 @@ trait ResponseHandler
|
||||
EventLoop::delay(1.0, fn () => $this->methodRecall($msgId));
|
||||
return null;
|
||||
}
|
||||
return fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
return static fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
case 303:
|
||||
$datacenter = (int) preg_replace('/[^0-9]+/', '', $response['error_message']);
|
||||
if ($this->API->isTestMode()) {
|
||||
@ -379,7 +379,7 @@ trait ResponseHandler
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
return static fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
case 401:
|
||||
switch ($response['error_message']) {
|
||||
case 'USER_DEACTIVATED':
|
||||
@ -400,7 +400,7 @@ trait ResponseHandler
|
||||
EventLoop::queue(
|
||||
$this->handleReject(...),
|
||||
$request,
|
||||
fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor())
|
||||
static fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor())
|
||||
);
|
||||
return null;
|
||||
}
|
||||
@ -427,7 +427,7 @@ trait ResponseHandler
|
||||
EventLoop::queue($this->methodRecall(...), $request->getMsgId());
|
||||
return null;
|
||||
}
|
||||
return fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
return static fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
case 420:
|
||||
$seconds = preg_replace('/[^0-9]+/', '', $response['error_message']);
|
||||
$limit = $request->floodWaitLimit ?? $this->API->settings->getRPC()->getFloodTimeout();
|
||||
@ -440,15 +440,15 @@ trait ResponseHandler
|
||||
$request->setSeqNo(null);
|
||||
\assert($msgId !== null);
|
||||
$id = EventLoop::delay((float) $seconds, fn () => $this->methodRecall($msgId));
|
||||
$request->cancellation?->subscribe(fn () => EventLoop::cancel($id));
|
||||
$request->cancellation?->subscribe(static fn () => EventLoop::cancel($id));
|
||||
return null;
|
||||
}
|
||||
if (str_starts_with($response['error_message'], 'FLOOD_WAIT_')) {
|
||||
return fn () => new FloodWaitError($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
return static fn () => new FloodWaitError($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
}
|
||||
// no break
|
||||
default:
|
||||
return fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
return static fn () => new RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ trait Files
|
||||
'_' => 'messageMediaDocument',
|
||||
'document' => $media,
|
||||
'ttl_seconds' => $media['ttl_seconds'],
|
||||
'secret' => true
|
||||
'secret' => true,
|
||||
];
|
||||
}
|
||||
if ($media['_'] !== 'messageMediaDocument') {
|
||||
@ -234,8 +234,8 @@ trait Files
|
||||
$this->logger->logger('Upload status: '.$percent.'%', Logger::NOTICE);
|
||||
};
|
||||
} else {
|
||||
$cb = function (float $percent, float $speed, float $time) use ($cb): void {
|
||||
EventLoop::queue(function () use ($percent, $speed, $time, $cb): void {
|
||||
$cb = static function (float $percent, float $speed, float $time) use ($cb): void {
|
||||
EventLoop::queue(static function () use ($percent, $speed, $time, $cb): void {
|
||||
$cb($percent, $speed, $time);
|
||||
});
|
||||
};
|
||||
@ -272,7 +272,7 @@ trait Files
|
||||
$speed = 0;
|
||||
$time = 0;
|
||||
if ($size) {
|
||||
$cb = function () use ($cb, $part_total_num, &$speed, &$time): void {
|
||||
$cb = static function () use ($cb, $part_total_num, &$speed, &$time): void {
|
||||
static $cur = 0;
|
||||
$cur++;
|
||||
$cb($cur * 100 / $part_total_num, $speed, $time);
|
||||
@ -996,7 +996,7 @@ trait Files
|
||||
$this->logger->logger('Waiting for lock of file to download...');
|
||||
$unlock = Tools::flock("$file.lock", LOCK_EX);
|
||||
$this->logger->logger('Got lock of file to download');
|
||||
async($this->downloadToStream(...), $messageMedia, $stream, $cb, $size, -1, $cancellation)->finally(function () use ($stream, $unlock, $file): void {
|
||||
async($this->downloadToStream(...), $messageMedia, $stream, $cb, $size, -1, $cancellation)->finally(static function () use ($stream, $unlock, $file): void {
|
||||
$stream->close();
|
||||
$unlock();
|
||||
try {
|
||||
@ -1034,8 +1034,8 @@ trait Files
|
||||
$this->logger->logger('Download status: '.$percent.'%', Logger::NOTICE);
|
||||
};
|
||||
} else {
|
||||
$cb = function (float $percent, float $speed, float $time) use ($cb): void {
|
||||
EventLoop::queue(function () use ($percent, $speed, $time, $cb): void {
|
||||
$cb = static function (float $percent, float $speed, float $time) use ($cb): void {
|
||||
EventLoop::queue(static function () use ($percent, $speed, $time, $cb): void {
|
||||
$cb($percent, $speed, $time);
|
||||
});
|
||||
};
|
||||
|
@ -405,7 +405,7 @@ trait FilesAbstraction
|
||||
'_' => 'inputMediaUploadedPhoto',
|
||||
'spoiler' => $spoiler,
|
||||
'file' => $file,
|
||||
'ttl_seconds' => $ttl
|
||||
'ttl_seconds' => $ttl,
|
||||
],
|
||||
default => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -415,7 +415,7 @@ trait FilesAbstraction
|
||||
'file' => $file,
|
||||
'thumb' => $thumb,
|
||||
'mime_type' => $mimeType,
|
||||
'attributes' => $attributes
|
||||
'attributes' => $attributes,
|
||||
]
|
||||
};
|
||||
if ($reuseId) {
|
||||
|
@ -230,7 +230,7 @@ trait FilesLogic
|
||||
|
||||
$result = ResponseInfo::parseHeaders(
|
||||
$request->getMethod(),
|
||||
array_map(fn (array $headers) => $headers[0], $request->getHeaders()),
|
||||
array_map(static fn (array $headers) => $headers[0], $request->getHeaders()),
|
||||
$messageMedia,
|
||||
);
|
||||
|
||||
|
@ -38,9 +38,9 @@ final class MinDatabase implements TLCallback
|
||||
{
|
||||
use DbPropertiesTrait;
|
||||
|
||||
const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
|
||||
const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
|
||||
const ORIGINS = ['message', 'messageService'];
|
||||
public const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
|
||||
public const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
|
||||
public const ORIGINS = ['message', 'messageService'];
|
||||
private const V = 1;
|
||||
/**
|
||||
* References indexed by location.
|
||||
|
@ -85,16 +85,16 @@ final class PeerDatabase implements TLCallback
|
||||
protected static array $dbProperties = [
|
||||
'db' => [
|
||||
'innerMadelineProto' => true,
|
||||
'table' => 'MTProto_chats'
|
||||
'table' => 'MTProto_chats',
|
||||
],
|
||||
'fullDb' => [
|
||||
'innerMadelineProto' => true,
|
||||
'table' => 'MTProto_full_chats'
|
||||
'table' => 'MTProto_full_chats',
|
||||
],
|
||||
'usernames' => [
|
||||
'innerMadelineProto' => true,
|
||||
'innerMadelineProtoSerializer' => SerializerType::STRING,
|
||||
'table' => 'MTProto_usernames'
|
||||
'table' => 'MTProto_usernames',
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -167,7 +167,7 @@ trait PeerHandler
|
||||
*/
|
||||
public function getId(mixed $id): int
|
||||
{
|
||||
if (\is_integer($id)) {
|
||||
if (\is_int($id)) {
|
||||
return $id;
|
||||
}
|
||||
return $this->getInfo($id, \danog\MadelineProto\API::INFO_TYPE_ID);
|
||||
@ -306,7 +306,7 @@ trait PeerHandler
|
||||
}
|
||||
}
|
||||
if (\is_string($id)) {
|
||||
if (strpos($id, '#') !== false) {
|
||||
if (str_contains($id, '#')) {
|
||||
if (preg_match('/^channel#(\\d*)/', $id, $matches)) {
|
||||
return DialogId::fromSupergroupOrChannel((int) $matches[1]);
|
||||
}
|
||||
|
@ -46,34 +46,34 @@ final class ReferenceDatabase implements TLCallback
|
||||
return $this->API->getDbPrefix();
|
||||
}
|
||||
// Reference from a document
|
||||
const DOCUMENT_LOCATION = 0;
|
||||
public const DOCUMENT_LOCATION = 0;
|
||||
// Reference from a photo
|
||||
const PHOTO_LOCATION = 1;
|
||||
public const PHOTO_LOCATION = 1;
|
||||
// Reference from a photo location (can only be photo location)
|
||||
const PHOTO_LOCATION_LOCATION = 2;
|
||||
public const PHOTO_LOCATION_LOCATION = 2;
|
||||
// Peer + photo ID
|
||||
const USER_PHOTO_ORIGIN = 0;
|
||||
public const USER_PHOTO_ORIGIN = 0;
|
||||
// Peer (default photo ID)
|
||||
const PEER_PHOTO_ORIGIN = 1;
|
||||
public const PEER_PHOTO_ORIGIN = 1;
|
||||
// set ID
|
||||
const STICKER_SET_ID_ORIGIN = 2;
|
||||
public const STICKER_SET_ID_ORIGIN = 2;
|
||||
// Peer + msg ID
|
||||
const MESSAGE_ORIGIN = 3;
|
||||
const SAVED_GIFS_ORIGIN = 4;
|
||||
const STICKER_SET_RECENT_ORIGIN = 5;
|
||||
const STICKER_SET_FAVED_ORIGIN = 6;
|
||||
public const MESSAGE_ORIGIN = 3;
|
||||
public const SAVED_GIFS_ORIGIN = 4;
|
||||
public const STICKER_SET_RECENT_ORIGIN = 5;
|
||||
public const STICKER_SET_FAVED_ORIGIN = 6;
|
||||
// emoticon
|
||||
const STICKER_SET_EMOTICON_ORIGIN = 8;
|
||||
const WALLPAPER_ORIGIN = 9;
|
||||
const LOCATION_CONTEXT = [
|
||||
public const STICKER_SET_EMOTICON_ORIGIN = 8;
|
||||
public const WALLPAPER_ORIGIN = 9;
|
||||
public const LOCATION_CONTEXT = [
|
||||
//'inputFileLocation' => self::PHOTO_LOCATION_LOCATION, // DEPRECATED
|
||||
'inputDocumentFileLocation' => self::DOCUMENT_LOCATION,
|
||||
'inputPhotoFileLocation' => self::PHOTO_LOCATION,
|
||||
'inputPhoto' => self::PHOTO_LOCATION,
|
||||
'inputDocument' => self::DOCUMENT_LOCATION,
|
||||
];
|
||||
const METHOD_CONTEXT = ['photos.updateProfilePhoto' => self::USER_PHOTO_ORIGIN, 'photos.getUserPhotos' => self::USER_PHOTO_ORIGIN, 'photos.uploadProfilePhoto' => self::USER_PHOTO_ORIGIN, 'messages.getStickers' => self::STICKER_SET_EMOTICON_ORIGIN];
|
||||
const CONSTRUCTOR_CONTEXT = ['message' => self::MESSAGE_ORIGIN, 'messageService' => self::MESSAGE_ORIGIN, 'chatFull' => self::PEER_PHOTO_ORIGIN, 'channelFull' => self::PEER_PHOTO_ORIGIN, 'chat' => self::PEER_PHOTO_ORIGIN, 'channel' => self::PEER_PHOTO_ORIGIN, 'updateUserPhoto' => self::USER_PHOTO_ORIGIN, 'user' => self::USER_PHOTO_ORIGIN, 'userFull' => self::USER_PHOTO_ORIGIN, 'wallPaper' => self::WALLPAPER_ORIGIN, 'messages.savedGifs' => self::SAVED_GIFS_ORIGIN, 'messages.recentStickers' => self::STICKER_SET_RECENT_ORIGIN, 'messages.favedStickers' => self::STICKER_SET_FAVED_ORIGIN, 'messages.stickerSet' => self::STICKER_SET_ID_ORIGIN, 'document' => self::STICKER_SET_ID_ORIGIN];
|
||||
public const METHOD_CONTEXT = ['photos.updateProfilePhoto' => self::USER_PHOTO_ORIGIN, 'photos.getUserPhotos' => self::USER_PHOTO_ORIGIN, 'photos.uploadProfilePhoto' => self::USER_PHOTO_ORIGIN, 'messages.getStickers' => self::STICKER_SET_EMOTICON_ORIGIN];
|
||||
public const CONSTRUCTOR_CONTEXT = ['message' => self::MESSAGE_ORIGIN, 'messageService' => self::MESSAGE_ORIGIN, 'chatFull' => self::PEER_PHOTO_ORIGIN, 'channelFull' => self::PEER_PHOTO_ORIGIN, 'chat' => self::PEER_PHOTO_ORIGIN, 'channel' => self::PEER_PHOTO_ORIGIN, 'updateUserPhoto' => self::USER_PHOTO_ORIGIN, 'user' => self::USER_PHOTO_ORIGIN, 'userFull' => self::USER_PHOTO_ORIGIN, 'wallPaper' => self::WALLPAPER_ORIGIN, 'messages.savedGifs' => self::SAVED_GIFS_ORIGIN, 'messages.recentStickers' => self::STICKER_SET_RECENT_ORIGIN, 'messages.favedStickers' => self::STICKER_SET_FAVED_ORIGIN, 'messages.stickerSet' => self::STICKER_SET_ID_ORIGIN, 'document' => self::STICKER_SET_ID_ORIGIN];
|
||||
|
||||
private const V = 1;
|
||||
/**
|
||||
@ -97,7 +97,7 @@ final class ReferenceDatabase implements TLCallback
|
||||
* @see DbPropertiesFactory
|
||||
*/
|
||||
protected static array $dbProperties = [
|
||||
'db' => ['innerMadelineProto' => true]
|
||||
'db' => ['innerMadelineProto' => true],
|
||||
];
|
||||
|
||||
private LocalKeyedMutex $flushMutex;
|
||||
@ -428,7 +428,7 @@ final class ReferenceDatabase implements TLCallback
|
||||
$this->pendingDb[$location] = [
|
||||
$reference,
|
||||
$originType,
|
||||
$origin
|
||||
$origin,
|
||||
];
|
||||
|
||||
if ($this->refresh) {
|
||||
|
@ -789,7 +789,7 @@ trait UpdateHandler
|
||||
'clear_draft' => $clearDraft,
|
||||
'no_webpage' => $noWebpage,
|
||||
'update_stickersets_order' => $updateStickersetsOrder,
|
||||
'cancellation' => $cancellation
|
||||
'cancellation' => $cancellation,
|
||||
]
|
||||
);
|
||||
if (isset($result['_'])) {
|
||||
|
File diff suppressed because one or more lines are too long
@ -90,7 +90,8 @@ final class MyTelegramOrgWrapper
|
||||
$this->jar = new LocalCookieJar();
|
||||
}
|
||||
$this->datacenter = new DoHWrapper(
|
||||
new class($this->settings) implements SettingsGetter,
|
||||
new class($this->settings) implements
|
||||
SettingsGetter,
|
||||
LoggerGetter {
|
||||
public function __construct(
|
||||
private readonly Settings $settings
|
||||
|
26
src/Ogg.php
26
src/Ogg.php
@ -108,7 +108,7 @@ final class Ogg
|
||||
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
|
||||
0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
|
||||
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
|
||||
0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4
|
||||
0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4,
|
||||
];
|
||||
private const OPUS_SET_APPLICATION_REQUEST = 4000;
|
||||
private const OPUS_GET_APPLICATION_REQUEST = 4001;
|
||||
@ -185,14 +185,14 @@ final class Ogg
|
||||
private const OPUS_FRAMESIZE_120_MS = 5009 /**< Use 120 ms frames */;
|
||||
|
||||
private const CAPTURE_PATTERN = "OggS";
|
||||
const CONTINUATION = 1;
|
||||
const BOS = 2;
|
||||
const EOS = 4;
|
||||
public const CONTINUATION = 1;
|
||||
public const BOS = 2;
|
||||
public const EOS = 4;
|
||||
|
||||
const STATE_READ_HEADER = 0;
|
||||
const STATE_READ_COMMENT = 1;
|
||||
const STATE_STREAMING = 3;
|
||||
const STATE_END = 4;
|
||||
public const STATE_READ_HEADER = 0;
|
||||
public const STATE_READ_COMMENT = 1;
|
||||
public const STATE_STREAMING = 3;
|
||||
public const STATE_END = 4;
|
||||
|
||||
private int $currentDuration = 0;
|
||||
/**
|
||||
@ -243,7 +243,7 @@ final class Ogg
|
||||
$this->packFormat = implode(
|
||||
'/',
|
||||
array_map(
|
||||
fn (string $v, string $k): string => $v.$k,
|
||||
static fn (string $v, string $k): string => $v.$k,
|
||||
$pack_format,
|
||||
array_keys($pack_format),
|
||||
),
|
||||
@ -608,7 +608,7 @@ final class Ogg
|
||||
}
|
||||
}
|
||||
}
|
||||
$checkErr = function (int|CData $err) use ($opus): void {
|
||||
$checkErr = static function (int|CData $err) use ($opus): void {
|
||||
if ($err instanceof CData) {
|
||||
$err = $err->cdata;
|
||||
}
|
||||
@ -660,11 +660,11 @@ final class Ogg
|
||||
? openFile($oggOut->file, 'w')
|
||||
: $oggOut;
|
||||
|
||||
$writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
|
||||
$writePage = static function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
|
||||
Assert::true(\strlen($packet) < 65025);
|
||||
$segments = [
|
||||
...array_fill(0, (int) (\strlen($packet) / 255), 255),
|
||||
\strlen($packet) % 255
|
||||
\strlen($packet) % 255,
|
||||
];
|
||||
$data = 'OggS'.pack(
|
||||
'CCPVVVCC*',
|
||||
@ -713,7 +713,7 @@ final class Ogg
|
||||
);
|
||||
|
||||
$tags = 'OpusTags';
|
||||
$writeTag = function (string $tag) use (&$tags): void {
|
||||
$writeTag = static function (string $tag) use (&$tags): void {
|
||||
$tags .= pack('V', \strlen($tag)).$tag;
|
||||
};
|
||||
$writeTag("MadelineProto ".API::RELEASE.", ".$opus->opus_get_version_string());
|
||||
|
@ -77,7 +77,7 @@ class RPCErrorException extends \Exception
|
||||
&& !self::isBad($error, $code)
|
||||
&& !($error === 'Timeout' && !\in_array(strtolower($method), ['messages.getbotcallbackanswer', 'messages.getinlinebotresults'], true))
|
||||
) {
|
||||
EventLoop::queue(function () use ($method, $code, $error): void {
|
||||
EventLoop::queue(static function () use ($method, $code, $error): void {
|
||||
try {
|
||||
$res = json_decode(
|
||||
(
|
||||
|
@ -120,7 +120,7 @@ final class SecretChatController implements Stringable
|
||||
$this->inputChat = [
|
||||
'_' => 'inputEncryptedChat',
|
||||
'chat_id' => $id,
|
||||
'access_hash' => $accessHash
|
||||
'access_hash' => $accessHash,
|
||||
];
|
||||
if ($creator) {
|
||||
$this->in_seq_no_base = 0;
|
||||
@ -695,7 +695,7 @@ final class SecretChatController implements Stringable
|
||||
$this->gapQuery = ['peer' => $this->id, 'message' => ['_' => 'decryptedMessageService', 'action' => [
|
||||
'_' => 'decryptedMessageActionResend',
|
||||
'start_seq_no' => $C_plus_one * 2 + $this->in_seq_no_base,
|
||||
'end_seq_no' => $this->gapEnd * 2 + $this->in_seq_no_base
|
||||
'end_seq_no' => $this->gapEnd * 2 + $this->in_seq_no_base,
|
||||
]]];
|
||||
$this->API->methodCallAsyncRead('messages.sendEncryptedService', $this->gapQuery);
|
||||
return;
|
||||
|
@ -125,7 +125,7 @@ abstract class Serialization
|
||||
} else {
|
||||
Logger::log('It seems like the session is busy.');
|
||||
Logger::log('Telegram does not support starting multiple instances of the same session, make sure no other instance of the session is running.');
|
||||
$warningId = EventLoop::repeat(5, fn () => Logger::log('Still waiting for exclusive session lock...'));
|
||||
$warningId = EventLoop::repeat(5, static fn () => Logger::log('Still waiting for exclusive session lock...'));
|
||||
EventLoop::unreference($warningId);
|
||||
}
|
||||
});
|
||||
@ -144,7 +144,7 @@ abstract class Serialization
|
||||
$copy->cancel();
|
||||
}
|
||||
};
|
||||
EventLoop::queue(function () use ($session, $cancelFull, &$canContinue, &$lightState): void {
|
||||
EventLoop::queue(static function () use ($session, $cancelFull, &$canContinue, &$lightState): void {
|
||||
try {
|
||||
$lightState = $session->getLightState();
|
||||
if (!$lightState->canStartIpc()) {
|
||||
@ -181,7 +181,7 @@ abstract class Serialization
|
||||
// Unlock and fork
|
||||
$unlock();
|
||||
$monitor = Server::startMe($session);
|
||||
EventLoop::queue(function () use ($cancelIpc, $monitor): void {
|
||||
EventLoop::queue(static function () use ($cancelIpc, $monitor): void {
|
||||
try {
|
||||
$cancelIpc->complete($monitor->await());
|
||||
} catch (\Throwable $e) {
|
||||
|
@ -377,7 +377,7 @@ final class Connection extends SettingsAbstract
|
||||
if (!isset($this->proxy[$proxy])) {
|
||||
return $this;
|
||||
}
|
||||
if (false === $index = array_search($extra, $this->proxy[$proxy])) {
|
||||
if (false === $index = array_search($extra, $this->proxy[$proxy], true)) {
|
||||
return $this;
|
||||
}
|
||||
unset($this->proxy[$proxy][$index]);
|
||||
|
@ -84,7 +84,7 @@ final class Shutdown
|
||||
public static function init(): void
|
||||
{
|
||||
if (!self::$registered) {
|
||||
register_shutdown_function(fn () => self::shutdown());
|
||||
register_shutdown_function(static fn () => self::shutdown());
|
||||
self::$registered = true;
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ final class Snitch
|
||||
/**
|
||||
* Maximum starts without a phar file.
|
||||
*/
|
||||
const MAX_NO_PHAR_STARTS = 3;
|
||||
public const MAX_NO_PHAR_STARTS = 3;
|
||||
|
||||
/**
|
||||
* Whether madeline.phar was downloaded from scratch.
|
||||
|
@ -409,7 +409,7 @@ trait BotAPI
|
||||
'file_id' => (string) $fileId,
|
||||
'file_unique_id' => $fileId->getUniqueBotAPI(),
|
||||
'file_size' => $data['size'],
|
||||
'mime_type' => 'application/octet-stream'
|
||||
'mime_type' => 'application/octet-stream',
|
||||
];
|
||||
return ['encrypted' => $res];
|
||||
default:
|
||||
|
@ -147,7 +147,7 @@ final class MarkdownEntities extends Entities
|
||||
'_' => 'messageEntityPre',
|
||||
'language' => $language,
|
||||
'offset' => $start,
|
||||
'length' => $pieceLen
|
||||
'length' => $pieceLen,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -367,29 +367,29 @@ final class TL implements TLInterface
|
||||
public function updateCallbacks(array $callbacks): void
|
||||
{
|
||||
$this->beforeMethodResponseDeserialization = array_merge_recursive(...array_map(
|
||||
fn (TLCallback $t) => $t->getMethodBeforeResponseDeserializationCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getMethodBeforeResponseDeserializationCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
$this->afterMethodResponseDeserialization = array_merge_recursive(...array_map(
|
||||
fn (TLCallback $t) => $t->getMethodAfterResponseDeserializationCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getMethodAfterResponseDeserializationCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
|
||||
$this->beforeConstructorSerialization = array_merge(...array_map(
|
||||
fn (TLCallback $t) => $t->getConstructorBeforeSerializationCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getConstructorBeforeSerializationCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
$this->beforeConstructorDeserialization = array_merge_recursive(...array_map(
|
||||
fn (TLCallback $t) => $t->getConstructorBeforeDeserializationCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getConstructorBeforeDeserializationCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
$this->afterConstructorDeserialization = array_merge_recursive(...array_map(
|
||||
fn (TLCallback $t) => $t->getConstructorAfterDeserializationCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getConstructorAfterDeserializationCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
|
||||
$this->typeMismatch = array_merge(...array_map(
|
||||
fn (TLCallback $t) => $t->getTypeMismatchCallbacks(),
|
||||
static fn (TLCallback $t) => $t->getTypeMismatchCallbacks(),
|
||||
$callbacks
|
||||
));
|
||||
}
|
||||
@ -451,7 +451,7 @@ final class TL implements TLInterface
|
||||
return Tools::packSignedLong((int) $object);
|
||||
case 'int128':
|
||||
if (\strlen($object) !== 16) {
|
||||
$object = base64_decode($object);
|
||||
$object = base64_decode($object, true);
|
||||
if (\strlen($object) !== 16) {
|
||||
throw new Exception(Lang::$current_lang['long_not_16']);
|
||||
}
|
||||
@ -459,7 +459,7 @@ final class TL implements TLInterface
|
||||
return (string) $object;
|
||||
case 'int256':
|
||||
if (\strlen($object) !== 32) {
|
||||
$object = base64_decode($object);
|
||||
$object = base64_decode($object, true);
|
||||
if (\strlen($object) !== 32) {
|
||||
throw new Exception(Lang::$current_lang['long_not_32']);
|
||||
}
|
||||
@ -467,7 +467,7 @@ final class TL implements TLInterface
|
||||
return (string) $object;
|
||||
case 'int512':
|
||||
if (\strlen($object) !== 64) {
|
||||
$object = base64_decode($object);
|
||||
$object = base64_decode($object, true);
|
||||
if (\strlen($object) !== 64) {
|
||||
throw new Exception(Lang::$current_lang['long_not_64']);
|
||||
}
|
||||
@ -497,7 +497,7 @@ final class TL implements TLInterface
|
||||
return $concat;
|
||||
case 'bytes':
|
||||
if (\is_array($object) && isset($object['_']) && $object['_'] === 'bytes') {
|
||||
$object = base64_decode($object['bytes']);
|
||||
$object = base64_decode($object['bytes'], true);
|
||||
}
|
||||
if ($object instanceof Bytes || \is_int($object) || \is_float($object)) {
|
||||
$object = (string) $object;
|
||||
@ -520,7 +520,7 @@ final class TL implements TLInterface
|
||||
return $concat;
|
||||
case 'waveform':
|
||||
if (\is_array($object) && isset($object['_']) && $object['_'] === 'bytes') {
|
||||
$object = base64_decode($object['bytes']);
|
||||
$object = base64_decode($object['bytes'], true);
|
||||
}
|
||||
if (\is_array($object)) {
|
||||
$object = self::compressWaveform($object);
|
||||
@ -742,7 +742,7 @@ final class TL implements TLInterface
|
||||
$value = ['_' => 'dataJSON', 'data' => json_encode($value)];
|
||||
}
|
||||
if (isset($current_argument['subtype']) && \in_array($current_argument['subtype'], ['DataJSON', '%DataJSON'], true)) {
|
||||
array_walk($value, function (&$arg): void {
|
||||
array_walk($value, static function (&$arg): void {
|
||||
$arg = ['_' => 'dataJSON', 'data' => json_encode($arg)];
|
||||
});
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ final class TLConstructors
|
||||
'params' => $json_dict['params'],
|
||||
'flags' => [],
|
||||
'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '').$json_dict['type'],
|
||||
'encrypted' => $scheme_type !== 'mtproto'
|
||||
'encrypted' => $scheme_type !== 'mtproto',
|
||||
];
|
||||
if ($scheme_type === 'secret') {
|
||||
$this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
|
||||
|
@ -40,7 +40,7 @@ final class TLMethods
|
||||
'type' => $json_dict['type'],
|
||||
'params' => $json_dict['params'],
|
||||
'flags' => [],
|
||||
'encrypted' => $scheme_type !== 'mtproto'
|
||||
'encrypted' => $scheme_type !== 'mtproto',
|
||||
];
|
||||
if (preg_match('/^(v|V)ector\\<(.*)\\>$/', $json_dict['type'], $matches)) {
|
||||
$this->by_id[$json_dict['id']]['type'] = $matches[1] === 'v' ? 'vector' : 'Vector t';
|
||||
|
@ -30,7 +30,7 @@ trait TLParams
|
||||
foreach ($this->by_id[$key]['params'] as $kkey => $param) {
|
||||
if (preg_match('/([^.]+)\\.(\\d+)\\?(.+)/', $param['type'], $matches)) {
|
||||
$param['flag'] = $matches[1];
|
||||
$param['pow'] = pow(2, (int) $matches[2]);
|
||||
$param['pow'] = 2** (int) $matches[2];
|
||||
$param['type'] = $matches[3];
|
||||
}
|
||||
if (preg_match('/^(v|V)ector\\<(.*)\\>$/', $param['type'], $matches)) {
|
||||
|
@ -84,7 +84,7 @@ abstract class Tools extends AsyncTools
|
||||
$f = [];
|
||||
for ($x = 0; $x < $fiberCount; $x++) {
|
||||
try {
|
||||
$f []= $cur = new Fiber(function (): void {
|
||||
$f []= $cur = new Fiber(static function (): void {
|
||||
Fiber::suspend();
|
||||
});
|
||||
$cur->start();
|
||||
@ -338,7 +338,7 @@ abstract class Tools extends AsyncTools
|
||||
*/
|
||||
public static function base64urlDecode(string $data): string
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT), true);
|
||||
}
|
||||
/**
|
||||
* Base64URL encode.
|
||||
@ -616,7 +616,7 @@ abstract class Tools extends AsyncTools
|
||||
{
|
||||
if ($stream instanceof LocalFile) {
|
||||
$stream = openFile($stream->file, 'r');
|
||||
return fn (int $len): ?string => $stream->read(cancellation: $cancellation, length: $len);
|
||||
return static fn (int $len): ?string => $stream->read(cancellation: $cancellation, length: $len);
|
||||
}
|
||||
if ($stream instanceof RemoteUrl) {
|
||||
self::$client ??= HttpClientBuilder::buildDefault();
|
||||
@ -628,7 +628,7 @@ abstract class Tools extends AsyncTools
|
||||
)->getBody();
|
||||
}
|
||||
$buffer = '';
|
||||
return function (int $len) use (&$buffer, $stream, $cancellation): ?string {
|
||||
return static function (int $len) use (&$buffer, $stream, $cancellation): ?string {
|
||||
if ($buffer === null) {
|
||||
return null;
|
||||
}
|
||||
@ -683,7 +683,7 @@ abstract class Tools extends AsyncTools
|
||||
private const NO_YIELD_FUNCTIONS = [
|
||||
'onstart',
|
||||
'onupdatenewmessage',
|
||||
'onupdatenewchannelmessage'
|
||||
'onupdatenewchannelmessage',
|
||||
];
|
||||
/**
|
||||
* Perform static analysis on a certain event handler class, to make sure it satisfies some performance requirements.
|
||||
@ -712,7 +712,7 @@ abstract class Tools extends AsyncTools
|
||||
|
||||
if ($plugin) {
|
||||
$class = $finder->findInstanceOf($code, ClassLike::class);
|
||||
$class = array_filter($class, fn (ClassLike $c): bool => $c->name !== null);
|
||||
$class = array_filter($class, static fn (ClassLike $c): bool => $c->name !== null);
|
||||
if (\count($class) !== 1 || !$class[0] instanceof Class_) {
|
||||
$issues []= new EventHandlerIssue(
|
||||
message: Lang::$current_lang['plugins_must_have_exactly_one_class'],
|
||||
|
@ -82,7 +82,7 @@ trait AuthKeyHandler
|
||||
$res = $this->methodCallAsyncRead('phone.requestCall', [
|
||||
'user_id' => $user,
|
||||
'g_a_hash' => hash('sha256', $g_a->toBytes(), true),
|
||||
'protocol' => VoIPController::CALL_PROTOCOL
|
||||
'protocol' => VoIPController::CALL_PROTOCOL,
|
||||
])['phone_call'];
|
||||
$res['a'] = $a;
|
||||
$res['g_a'] = str_pad($g_a->toBytes(), 256, \chr(0), STR_PAD_LEFT);
|
||||
@ -152,7 +152,7 @@ trait AuthKeyHandler
|
||||
*/
|
||||
public function getAllCalls(): array
|
||||
{
|
||||
return array_map(fn (VoIPController $v): VoIP => $v->public, $this->callsByPeer);
|
||||
return array_map(static fn (VoIPController $v): VoIP => $v->public, $this->callsByPeer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,7 +457,7 @@ final class Endpoint
|
||||
'protocol' => VoIPController::PROTOCOL_VERSION,
|
||||
'min_protocol' => VoIPController::MIN_PROTOCOL_VERSION,
|
||||
'audio_streams' => [VoIPController::CODEC_OPUS],
|
||||
'video_streams' => []
|
||||
'video_streams' => [],
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
@ -60,61 +60,61 @@ final class VoIPController
|
||||
"11.0.0"
|
||||
]*/
|
||||
];
|
||||
const NET_TYPE_UNKNOWN = 0;
|
||||
const NET_TYPE_GPRS = 1;
|
||||
const NET_TYPE_EDGE = 2;
|
||||
const NET_TYPE_3G = 3;
|
||||
const NET_TYPE_HSPA = 4;
|
||||
const NET_TYPE_LTE = 5;
|
||||
const NET_TYPE_WIFI = 6;
|
||||
const NET_TYPE_ETHERNET = 7;
|
||||
const NET_TYPE_OTHER_HIGH_SPEED = 8;
|
||||
const NET_TYPE_OTHER_LOW_SPEED = 9;
|
||||
const NET_TYPE_DIALUP = 10;
|
||||
const NET_TYPE_OTHER_MOBILE = 11;
|
||||
public const NET_TYPE_UNKNOWN = 0;
|
||||
public const NET_TYPE_GPRS = 1;
|
||||
public const NET_TYPE_EDGE = 2;
|
||||
public const NET_TYPE_3G = 3;
|
||||
public const NET_TYPE_HSPA = 4;
|
||||
public const NET_TYPE_LTE = 5;
|
||||
public const NET_TYPE_WIFI = 6;
|
||||
public const NET_TYPE_ETHERNET = 7;
|
||||
public const NET_TYPE_OTHER_HIGH_SPEED = 8;
|
||||
public const NET_TYPE_OTHER_LOW_SPEED = 9;
|
||||
public const NET_TYPE_DIALUP = 10;
|
||||
public const NET_TYPE_OTHER_MOBILE = 11;
|
||||
|
||||
const DATA_SAVING_NEVER = 0;
|
||||
const DATA_SAVING_MOBILE = 1;
|
||||
const DATA_SAVING_ALWAYS = 2;
|
||||
public const DATA_SAVING_NEVER = 0;
|
||||
public const DATA_SAVING_MOBILE = 1;
|
||||
public const DATA_SAVING_ALWAYS = 2;
|
||||
|
||||
const PROXY_NONE = 0;
|
||||
const PROXY_SOCKS5 = 1;
|
||||
public const PROXY_NONE = 0;
|
||||
public const PROXY_SOCKS5 = 1;
|
||||
|
||||
const AUDIO_STATE_NONE = -1;
|
||||
const AUDIO_STATE_CREATED = 0;
|
||||
const AUDIO_STATE_CONFIGURED = 1;
|
||||
const AUDIO_STATE_RUNNING = 2;
|
||||
public const AUDIO_STATE_NONE = -1;
|
||||
public const AUDIO_STATE_CREATED = 0;
|
||||
public const AUDIO_STATE_CONFIGURED = 1;
|
||||
public const AUDIO_STATE_RUNNING = 2;
|
||||
|
||||
const PKT_INIT = 1;
|
||||
const PKT_INIT_ACK = 2;
|
||||
const PKT_STREAM_STATE = 3;
|
||||
const PKT_STREAM_DATA = 4;
|
||||
const PKT_UPDATE_STREAMS = 5;
|
||||
const PKT_PING = 6;
|
||||
const PKT_PONG = 7;
|
||||
const PKT_STREAM_DATA_X2 = 8;
|
||||
const PKT_STREAM_DATA_X3 = 9;
|
||||
const PKT_LAN_ENDPOINT = 10;
|
||||
const PKT_NETWORK_CHANGED = 11;
|
||||
const PKT_SWITCH_PREF_RELAY = 12;
|
||||
const PKT_SWITCH_TO_P2P = 13;
|
||||
const PKT_NOP = 14;
|
||||
public const PKT_INIT = 1;
|
||||
public const PKT_INIT_ACK = 2;
|
||||
public const PKT_STREAM_STATE = 3;
|
||||
public const PKT_STREAM_DATA = 4;
|
||||
public const PKT_UPDATE_STREAMS = 5;
|
||||
public const PKT_PING = 6;
|
||||
public const PKT_PONG = 7;
|
||||
public const PKT_STREAM_DATA_X2 = 8;
|
||||
public const PKT_STREAM_DATA_X3 = 9;
|
||||
public const PKT_LAN_ENDPOINT = 10;
|
||||
public const PKT_NETWORK_CHANGED = 11;
|
||||
public const PKT_SWITCH_PREF_RELAY = 12;
|
||||
public const PKT_SWITCH_TO_P2P = 13;
|
||||
public const PKT_NOP = 14;
|
||||
|
||||
const TLID_DECRYPTED_AUDIO_BLOCK = "\xc1\xdb\xf9\x48";
|
||||
const TLID_SIMPLE_AUDIO_BLOCK = "\x0d\x0e\x76\xcc";
|
||||
public const TLID_DECRYPTED_AUDIO_BLOCK = "\xc1\xdb\xf9\x48";
|
||||
public const TLID_SIMPLE_AUDIO_BLOCK = "\x0d\x0e\x76\xcc";
|
||||
|
||||
const TLID_REFLECTOR_SELF_INFO = "\xC7\x72\x15\xc0";
|
||||
const TLID_REFLECTOR_PEER_INFO = "\x1C\x37\xD9\x27";
|
||||
public const TLID_REFLECTOR_SELF_INFO = "\xC7\x72\x15\xc0";
|
||||
public const TLID_REFLECTOR_PEER_INFO = "\x1C\x37\xD9\x27";
|
||||
|
||||
const PROTO_ID = 'GrVP';
|
||||
public const PROTO_ID = 'GrVP';
|
||||
|
||||
const PROTOCOL_VERSION = 9;
|
||||
const MIN_PROTOCOL_VERSION = 9;
|
||||
public const PROTOCOL_VERSION = 9;
|
||||
public const MIN_PROTOCOL_VERSION = 9;
|
||||
|
||||
const STREAM_TYPE_AUDIO = 1;
|
||||
const STREAM_TYPE_VIDEO = 2;
|
||||
public const STREAM_TYPE_AUDIO = 1;
|
||||
public const STREAM_TYPE_VIDEO = 2;
|
||||
|
||||
const CODEC_OPUS = 'SUPO';
|
||||
public const CODEC_OPUS = 'SUPO';
|
||||
|
||||
private MessageHandler $messageHandler;
|
||||
private VoIPState $voipState = VoIPState::CREATED;
|
||||
@ -229,7 +229,7 @@ final class VoIPController
|
||||
'key_fingerprint' => substr(sha1($key, true), -8),
|
||||
'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'],
|
||||
'g_a' => $this->call['g_a'],
|
||||
'protocol' => self::CALL_PROTOCOL
|
||||
'protocol' => self::CALL_PROTOCOL,
|
||||
]))['phone_call'];
|
||||
} catch (RPCErrorException $e) {
|
||||
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
|
||||
@ -287,10 +287,10 @@ final class VoIPController
|
||||
'peer' => [
|
||||
'id' => $this->call['id'],
|
||||
'access_hash' => $this->call['access_hash'],
|
||||
'_' => 'inputPhoneCall'
|
||||
'_' => 'inputPhoneCall',
|
||||
],
|
||||
'g_b' => $g_b->toBytes(),
|
||||
'protocol' => self::CALL_PROTOCOL
|
||||
'protocol' => self::CALL_PROTOCOL,
|
||||
]);
|
||||
} catch (RPCErrorException $e) {
|
||||
if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
|
||||
@ -469,7 +469,7 @@ final class VoIPController
|
||||
}
|
||||
$formats[]= [
|
||||
'name' => $name,
|
||||
'parameters' => $parameters
|
||||
'parameters' => $parameters,
|
||||
];
|
||||
}
|
||||
return [
|
||||
@ -596,8 +596,8 @@ final class VoIPController
|
||||
'protocol' => self::PROTOCOL_VERSION,
|
||||
'min_protocol' => self::MIN_PROTOCOL_VERSION,
|
||||
'all_streams' => [
|
||||
['id' => 0, 'type' => self::STREAM_TYPE_AUDIO, 'codec' => self::CODEC_OPUS, 'frame_duration' => 60, 'enabled' => 1]
|
||||
]
|
||||
['id' => 0, 'type' => self::STREAM_TYPE_AUDIO, 'codec' => self::CODEC_OPUS, 'frame_duration' => 60, 'enabled' => 1],
|
||||
],
|
||||
]));
|
||||
$socket->sendInit();
|
||||
break;
|
||||
@ -634,7 +634,7 @@ final class VoIPController
|
||||
$this->bestEndpoint->writeReliably([
|
||||
'_' => self::PKT_STREAM_STATE,
|
||||
'id' => 0,
|
||||
'enabled' => false
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->startWriteLoop();
|
||||
@ -696,7 +696,7 @@ final class VoIPController
|
||||
if (!$this->bestEndpoint->writeReliably([
|
||||
'_' => self::PKT_STREAM_STATE,
|
||||
'id' => 0,
|
||||
'enabled' => true
|
||||
'enabled' => true,
|
||||
])) {
|
||||
$this->log("Exiting write loop in $this because we could not write stream state!");
|
||||
return;
|
||||
@ -709,7 +709,7 @@ final class VoIPController
|
||||
'_' => self::PKT_STREAM_DATA,
|
||||
'stream_id' => 0,
|
||||
'data' => $packet,
|
||||
'timestamp' => $this->opusTimestamp
|
||||
'timestamp' => $this->opusTimestamp,
|
||||
]);
|
||||
$this->opusTimestamp += 60;
|
||||
} else {
|
||||
@ -718,7 +718,7 @@ final class VoIPController
|
||||
if (!$this->bestEndpoint->writeReliably([
|
||||
'_' => self::PKT_STREAM_STATE,
|
||||
'id' => 0,
|
||||
'enabled' => false
|
||||
'enabled' => false,
|
||||
])) {
|
||||
$this->log("Exiting write loop in $this because we could not write stream state!");
|
||||
return;
|
||||
@ -727,7 +727,7 @@ final class VoIPController
|
||||
$delay = 0.2;
|
||||
}
|
||||
$packet = $this->messageHandler->encryptPacket([
|
||||
'_' => self::PKT_NOP
|
||||
'_' => self::PKT_NOP,
|
||||
]);
|
||||
}
|
||||
//$this->log("Writing {$this->opusTimestamp} in $this!");
|
||||
|
@ -70,7 +70,7 @@ trait DialogHandler
|
||||
[
|
||||
...$this->botDialogsUpdatesState,
|
||||
'pts_total_limit' => 2147483647,
|
||||
'floodWaitLimit' => 86400
|
||||
'floodWaitLimit' => 86400,
|
||||
],
|
||||
);
|
||||
switch ($result['_']) {
|
||||
|
@ -125,7 +125,7 @@ trait Loop
|
||||
{
|
||||
if (!$this->hasEventHandler()) {
|
||||
if (Magic::$isIpcWorker) {
|
||||
EventLoop::queue(fn () => throw new SignalException('Restarting IPC daemon!'));
|
||||
EventLoop::queue(static fn () => throw new SignalException('Restarting IPC daemon!'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ trait Start
|
||||
if ($qr) {
|
||||
$result = [
|
||||
'logged_in' => false,
|
||||
'svg' => $qr->getQRSvg(400, 2)
|
||||
'svg' => $qr->getQRSvg(400, 2),
|
||||
];
|
||||
} else {
|
||||
$result = [
|
||||
|
@ -68,7 +68,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
|
||||
private function assertNoRelevantEntities(array $entities): void
|
||||
{
|
||||
$entities = array_filter($entities, fn (array $e) => !\in_array(
|
||||
$entities = array_filter($entities, static fn (array $e) => !\in_array(
|
||||
$e['type'],
|
||||
['url', 'email', 'phone_number', 'mention', 'bot_command'],
|
||||
true
|
||||
@ -244,7 +244,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'type' => 'spoiler',
|
||||
],
|
||||
],
|
||||
'<b>test</b><br><i>test</i> <code>test</code> <pre language="html">test</pre> <a href="https://example.com/">test</a> <s>strikethrough</s> <u>underline</u> blockquote <a href="https://google.com">https://google.com</a> <a href="mailto:daniil@daniil.it">daniil@daniil.it</a> <a href="phone:+39398172758722">+39398172758722</a> <a href="https://t.me/daniilgentili">@daniilgentili</a> <tg-spoiler>spoiler</tg-spoiler> <b>not_bold</b>'
|
||||
'<b>test</b><br><i>test</i> <code>test</code> <pre language="html">test</pre> <a href="https://example.com/">test</a> <s>strikethrough</s> <u>underline</u> blockquote <a href="https://google.com">https://google.com</a> <a href="mailto:daniil@daniil.it">daniil@daniil.it</a> <a href="phone:+39398172758722">+39398172758722</a> <a href="https://t.me/daniilgentili">@daniilgentili</a> <tg-spoiler>spoiler</tg-spoiler> <b>not_bold</b>',
|
||||
],
|
||||
[
|
||||
'markdown',
|
||||
@ -290,8 +290,8 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 2,
|
||||
'length' => 17,
|
||||
'type' => 'pre',
|
||||
'language' => 'php'
|
||||
]
|
||||
'language' => 'php',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
@ -305,7 +305,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'type' => 'bold',
|
||||
],
|
||||
],
|
||||
'<b>'"</b>'
|
||||
'<b>'"</b>',
|
||||
],
|
||||
[
|
||||
'html',
|
||||
@ -353,8 +353,8 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 5,
|
||||
'type' => 'pre',
|
||||
'language' => ''
|
||||
]
|
||||
'language' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
@ -366,7 +366,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -379,9 +379,9 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://transfer.sh/(/test/test.PNG,/test/test.MP4).zip'
|
||||
]
|
||||
]
|
||||
'url' => 'https://transfer.sh/(/test/test.PNG,/test/test.MP4).zip',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'markdown',
|
||||
@ -392,7 +392,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -405,7 +405,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/?v=\\test'
|
||||
'url' => 'https://google.com/?v=\\test',
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -418,7 +418,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -431,7 +431,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -450,7 +450,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
'<a href="https://google.com/">link</a> test',
|
||||
@ -464,7 +464,7 @@ class EntitiesTest extends MadelineTestCase
|
||||
'offset' => 0,
|
||||
'length' => 4,
|
||||
'type' => 'text_url',
|
||||
'url' => 'https://google.com/'
|
||||
'url' => 'https://google.com/',
|
||||
],
|
||||
],
|
||||
'<a href="https://google.com/">link</a> ',
|
||||
|
@ -61,7 +61,7 @@ if ($loader) {
|
||||
'PhabelVendor\\Monolog\\Test\\TestCase',
|
||||
'PhabelVendor\\Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface',
|
||||
'PhabelVendor\\Symfony\\Component\\String\\Slugger\\AsciiSlugger',
|
||||
])) {
|
||||
], true)) {
|
||||
continue;
|
||||
}
|
||||
if (str_starts_with($class, 'PhabelVendor\\Symfony\\Component\\Console') || str_starts_with($class, 'Phabel\\Symfony\\Component\\Console') || str_ends_with($class, 'Test') || class_exists($class) || interface_exists($class)) {
|
||||
@ -296,18 +296,18 @@ function eq(string $file, string $contents, string $type, string $subtype): void
|
||||
function sendMedia(API $MadelineProto, array $media, string $message, string $mention, mixed $peer, string $type): void
|
||||
{
|
||||
$medias = [
|
||||
'base' => $media
|
||||
'base' => $media,
|
||||
];
|
||||
if (isset($media['file']) && is_string($media['file'])) {
|
||||
$MadelineProto->sendDocument(
|
||||
peer: $peer,
|
||||
file: new ReadableBuffer(read($media['file'])),
|
||||
callback: fn ($v) => $MadelineProto->logger($v),
|
||||
callback: static fn ($v) => $MadelineProto->logger($v),
|
||||
fileName: basename($media['file'])
|
||||
);
|
||||
$medias['callback'] = array_merge(
|
||||
$media,
|
||||
['file' => new FileCallback($media['file'], fn ($v) => $MadelineProto->logger(...))]
|
||||
['file' => new FileCallback($media['file'], static fn ($v) => $MadelineProto->logger(...))]
|
||||
);
|
||||
$medias['stream'] = array_merge(
|
||||
$media,
|
||||
@ -315,12 +315,12 @@ function sendMedia(API $MadelineProto, array $media, string $message, string $me
|
||||
);
|
||||
$medias['callback stream'] = array_merge(
|
||||
$media,
|
||||
['file' => new FileCallback(new ReadableBuffer(read($media['file'])), fn ($v) => $MadelineProto->logger(...))]
|
||||
['file' => new FileCallback(new ReadableBuffer(read($media['file'])), static fn ($v) => $MadelineProto->logger(...))]
|
||||
);
|
||||
} elseif (isset($media['url'])) {
|
||||
$medias['callback'] = array_merge(
|
||||
$media,
|
||||
['url' => new FileCallback($media['url'], fn ($v) => $MadelineProto->logger(...))]
|
||||
['url' => new FileCallback($media['url'], static fn ($v) => $MadelineProto->logger(...))]
|
||||
);
|
||||
}
|
||||
foreach ($medias as $subtype => $m) {
|
||||
|
@ -73,7 +73,7 @@ $doc = new \danog\MadelineProto\AnnotationsBuilder(
|
||||
$docs[0],
|
||||
[
|
||||
'API' => API::class,
|
||||
'MTProto' => MTProto::class
|
||||
'MTProto' => MTProto::class,
|
||||
],
|
||||
'danog\\MadelineProto'
|
||||
);
|
||||
@ -127,7 +127,7 @@ foreach ($files as $file) {
|
||||
if ($base === 'UPDATES_INTERNAL') {
|
||||
continue;
|
||||
}
|
||||
$key = array_search($base, $order);
|
||||
$key = array_search($base, $order, true);
|
||||
if ($key !== false) {
|
||||
$orderedfiles[$key] = $file;
|
||||
}
|
||||
@ -170,7 +170,7 @@ function printTypes(array $types, string $type): string
|
||||
|
||||
foreach ($orderedfiles as $key => $filename) {
|
||||
$lines = file_get_contents($filename);
|
||||
$lines = preg_replace_callback('/\<\!--\s+cut_here\s+(\S+)\s+-->.*\<\!--\s+cut_here_end\s+\1\s+--\>/sim', function ($matches) {
|
||||
$lines = preg_replace_callback('/\<\!--\s+cut_here\s+(\S+)\s+-->.*\<\!--\s+cut_here_end\s+\1\s+--\>/sim', static function ($matches) {
|
||||
[, $match] = $matches;
|
||||
if ($match === "concretefilters") {
|
||||
$result = ClassFinder::getClassesInNamespace(
|
||||
@ -180,7 +180,7 @@ foreach ($orderedfiles as $key => $filename) {
|
||||
$result []= ServiceMessage::class;
|
||||
$result = array_filter(
|
||||
$result,
|
||||
fn ($class) => is_subclass_of($class, Update::class)
|
||||
static fn ($class) => is_subclass_of($class, Update::class)
|
||||
);
|
||||
sort($result);
|
||||
$data = printTypes($result, $match);
|
||||
@ -195,7 +195,7 @@ foreach ($orderedfiles as $key => $filename) {
|
||||
\danog\MadelineProto\EventHandler\Filter::class,
|
||||
ClassFinder::RECURSIVE_MODE | ClassFinder::ALLOW_ALL
|
||||
);
|
||||
$result = array_filter($result, fn (string $class) => (new ReflectionClass($class))->getAttributes());
|
||||
$result = array_filter($result, static fn (string $class) => (new ReflectionClass($class))->getAttributes());
|
||||
$data = printTypes($result, $match);
|
||||
} elseif ($match === "plugins") {
|
||||
$result = ClassFinder::getClassesInNamespace(
|
||||
|
@ -14,8 +14,8 @@ if (!\defined('MADELINE_ALLOW_COMPOSER') && class_exists(\Composer\Autoload\Clas
|
||||
|
||||
class Installer
|
||||
{
|
||||
const RELEASE_TEMPLATE = 'https://phar.madelineproto.xyz/release%s?v=new';
|
||||
const PHAR_TEMPLATE = 'https://github.com/danog/MadelineProto/releases/latest/download/madeline%s.phar?v=%s';
|
||||
public const RELEASE_TEMPLATE = 'https://phar.madelineproto.xyz/release%s?v=new';
|
||||
public const PHAR_TEMPLATE = 'https://github.com/danog/MadelineProto/releases/latest/download/madeline%s.phar?v=%s';
|
||||
|
||||
/**
|
||||
* Phar lock instance.
|
||||
@ -100,7 +100,7 @@ class Installer
|
||||
}
|
||||
foreach ($composer['packages'] as $dep) {
|
||||
$name = $dep['name'];
|
||||
if (strpos($name, 'phabel/transpiler') === 0) {
|
||||
if (str_starts_with($name, 'phabel/transpiler')) {
|
||||
$name = explode('/', $name, 3)[2];
|
||||
}
|
||||
$version = $dep['version_normalized'];
|
||||
@ -126,7 +126,7 @@ class Installer
|
||||
}
|
||||
$postData['downloads'][] = [
|
||||
'name' => $name,
|
||||
'version' => $version
|
||||
'version' => $version,
|
||||
];
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ class Installer
|
||||
$phpVersion,
|
||||
'streams',
|
||||
getenv('CI') ? '; CI' : ''
|
||||
)
|
||||
),
|
||||
],
|
||||
'content' => json_encode($postData),
|
||||
'timeout' => 6,
|
||||
@ -221,7 +221,7 @@ class Installer
|
||||
if (!file_exists($madeline_phar)) {
|
||||
for ($x = 0; $x < 10; $x++) {
|
||||
$pharTest = file_get_contents(sprintf(self::PHAR_TEMPLATE, $this->version, $remote_release.$x));
|
||||
if ($pharTest && strpos($pharTest, $remote_release) !== false) {
|
||||
if ($pharTest && str_contains($pharTest, $remote_release)) {
|
||||
$phar = $pharTest;
|
||||
unset($pharTest);
|
||||
break;
|
||||
|
@ -95,8 +95,8 @@ $ignore = [ // Disallow list
|
||||
\ArrayIterator::class,
|
||||
];
|
||||
|
||||
$filter = function (string $class) use ($ignore): bool {
|
||||
if (in_array($class, $ignore)) {
|
||||
$filter = static function (string $class) use ($ignore): bool {
|
||||
if (in_array($class, $ignore, true)) {
|
||||
return false;
|
||||
}
|
||||
if (str_starts_with($class, 'danog\\MadelineProto\\Ipc')
|
||||
|
@ -15,7 +15,7 @@ foreach ($classes as $class) {
|
||||
}
|
||||
$methods = array_unique($methods);
|
||||
|
||||
usort($methods, fn ($a, $b) => strlen($b->getName())-strlen($a->getName()));
|
||||
usort($methods, static fn ($a, $b) => strlen($b->getName())-strlen($a->getName()));
|
||||
|
||||
$find = [];
|
||||
$replace = [];
|
||||
@ -23,7 +23,7 @@ $findDocs = [];
|
||||
$replaceDocs = [];
|
||||
foreach ($methods as $methodObj) {
|
||||
$method = $methodObj->getName();
|
||||
if (strpos($method, '__') === 0 || $method === 'async') {
|
||||
if (str_starts_with($method, '__') || $method === 'async') {
|
||||
continue;
|
||||
}
|
||||
$method = Tools::fromCamelCase($method);
|
||||
@ -31,7 +31,7 @@ foreach ($methods as $methodObj) {
|
||||
$new = Tools::fromSnakeCase($method);
|
||||
$new = str_ireplace(['mtproto', 'api'], ['MTProto', 'API'], $new);
|
||||
$new = preg_replace('/TL$/i', 'TL', $new);
|
||||
if (!in_array($method, ['discardCallAsync', 'acceptCallAsync', 'requestCallAsync'])) {
|
||||
if (!in_array($method, ['discardCallAsync', 'acceptCallAsync', 'requestCallAsync'], true)) {
|
||||
$new = preg_replace('/async$/i', '', $new);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user