1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-26 17:04:39 +01:00
This commit is contained in:
Daniil Gentili 2023-11-11 16:55:29 +01:00
parent 77ce9de35c
commit 151a809c6e
93 changed files with 457 additions and 454 deletions

View File

@ -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

@ -1 +1 @@
Subproject commit 6033bfa2a31f6661681a06f4240d5bf18090df45
Subproject commit 8d71029d3b3211f9298f58693d94d9572af3dae1

View File

@ -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) {

View File

@ -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.
*

View File

@ -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);
}

View File

@ -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.
*

View File

@ -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,
];
}

View File

@ -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) {

View File

@ -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]);
});
}

View File

@ -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");
}

View File

@ -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();
}

View File

@ -63,7 +63,7 @@ final class ActionForward implements Action
'unpin' => false,
'pm_oneside' => false,
'floodWaitLimit' => 2*86400,
'cancellation' => $cancellation
'cancellation' => $cancellation,
],
);
} catch (RPCErrorException) {

View File

@ -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']);
}

View File

@ -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 = [])
{

View File

@ -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) {

View File

@ -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];

View File

@ -76,7 +76,7 @@ final class Mysql
self::$connections[$dbKey] = [
new MysqlConnectionPool($config, $settings->getMaxConnections(), $settings->getIdleTimeout()),
$pdo
$pdo,
];
}
} finally {

View File

@ -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

View File

@ -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),
};
}
/**

View File

@ -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,
};
}
/**

View File

@ -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) {

View File

@ -133,7 +133,7 @@ final class DoHWrapper
{
$ctxs = [];
$combos = [
[[DefaultStream::class, []], [BufferedRawStream::class, []]]
[[DefaultStream::class, []], [BufferedRawStream::class, []]],
];
if ($this->API->getSettings()->getConnection()->getRetry()) {
$proxyCombos = [];

View File

@ -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'],

View File

@ -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'])) {

View File

@ -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
);

View File

@ -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,
]
);
}

View File

@ -45,8 +45,8 @@ final class EmojiTap extends Action
'emoticon' => $this->emoticon,
'interaction' => [
'v' => 1,
'a' => $this->animation
]
'a' => $this->animation,
],
];
}
}

View File

@ -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']
);
}

View File

@ -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)) {

View File

@ -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,
]
);
}

View File

@ -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

View File

@ -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));

View File

@ -110,7 +110,7 @@ final class ChannelMessage extends Message
[
'peer' => $this->chatId,
'id' => [$this->id],
'increment' => true
'increment' => true,
]
);
}

View File

@ -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,
]
);
}

View File

@ -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));

View File

@ -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['_'])) {

View File

@ -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'],
]);
}
}

View File

@ -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']
);
}

View File

@ -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;

View File

@ -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();

View File

@ -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'] ?? '',
],
);

View File

@ -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;

View File

@ -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) {
}
}

View File

@ -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) {

View File

@ -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.

View File

@ -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'],
]
);
}

View File

@ -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);
}
}

View File

@ -43,7 +43,7 @@ final class FeedLoop extends Loop
/**
* Main loop ID.
*/
const GENERIC = 0;
public const GENERIC = 0;
/**
* Incoming updates array.
*/

View File

@ -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;

View File

@ -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) {

View File

@ -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),
],
);
}

View File

@ -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']);
}

View File

@ -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.

View File

@ -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));
}
/**

View File

@ -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) {

View File

@ -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)
)));
}

View File

@ -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());
}
}
}

View File

@ -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);
});
};

View File

@ -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) {

View File

@ -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,
);

View File

@ -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.

View File

@ -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',
],
];

View File

@ -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]);
}

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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(
(

View File

@ -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;

View File

@ -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) {

View File

@ -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]);

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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:

View File

@ -147,7 +147,7 @@ final class MarkdownEntities extends Entities
'_' => 'messageEntityPre',
'language' => $language,
'offset' => $start,
'length' => $pieceLen
'length' => $pieceLen,
];
}

View File

@ -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)];
});
}

View File

@ -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'];

View File

@ -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';

View File

@ -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)) {

View File

@ -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'],

View File

@ -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);
}
/**

View File

@ -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' => [],
]));
}
}

View File

@ -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!");

View File

@ -70,7 +70,7 @@ trait DialogHandler
[
...$this->botDialogsUpdatesState,
'pts_total_limit' => 2147483647,
'floodWaitLimit' => 86400
'floodWaitLimit' => 86400,
],
);
switch ($result['_']) {

View File

@ -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;
}

View File

@ -226,7 +226,7 @@ trait Start
if ($qr) {
$result = [
'logged_in' => false,
'svg' => $qr->getQRSvg(400, 2)
'svg' => $qr->getQRSvg(400, 2),
];
} else {
$result = [

View File

@ -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> &lt;b&gt;not_bold&lt;/b&gt;'
'<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> &lt;b&gt;not_bold&lt;/b&gt;',
],
[
'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>&#039;&quot;</b>'
'<b>&#039;&quot;</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> ',

View File

@ -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) {

View File

@ -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(

View File

@ -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;

View File

@ -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')

View File

@ -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);
}