Recursive session search

This commit is contained in:
Alexander Pankratov 2020-03-28 13:44:14 +03:00
parent ca740abbbd
commit e296836df5
6 changed files with 79 additions and 59 deletions

View File

@ -1,5 +1,6 @@
<?php <?php
use TelegramApiServer\Files;
use TelegramApiServer\Migrations\SessionsMigration; use TelegramApiServer\Migrations\SessionsMigration;
use TelegramApiServer\Migrations\SwooleToAmpMigration; use TelegramApiServer\Migrations\SwooleToAmpMigration;
@ -68,10 +69,10 @@ foreach ($options['session'] as $session) {
throw new InvalidArgumentException('Session name specified as directory'); throw new InvalidArgumentException('Session name specified as directory');
} }
$session = TelegramApiServer\Client::getSessionFile($session); $session = Files::getSessionFile($session);
if (preg_match('~[' . preg_quote('*?[]!', '~') . ']~', $session)) { if (preg_match('~[' . preg_quote('*?[]!', '~') . ']~', $session)) {
$sessions = glob($session); $sessions = Files::globRecursive($session);
} else { } else {
$sessions[] = $session; $sessions[] = $session;
} }

View File

@ -14,53 +14,9 @@ use function Amp\call;
class Client class Client
{ {
public static string $sessionExtension = '.madeline';
public static string $sessionFolder = 'sessions';
/** @var MadelineProto\API[] */ /** @var MadelineProto\API[] */
public array $instances = []; public array $instances = [];
/**
* @param string|null $session
*
* @return string|null
*/
public static function getSessionFile(?string $session): ?string
{
if (!$session) {
return null;
}
$session = trim(trim($session), '/');
$session = static::$sessionFolder . '/' . $session . static::$sessionExtension;
$session = str_replace('//', '/', $session);
return $session;
}
public static function getSessionName(?string $sessionFile): ?string
{
if (!$sessionFile) {
return null;
}
preg_match(
'~' . static::$sessionFolder . "/(?'sessionName'.*?)" . static::$sessionExtension . '$~',
$sessionFile,
$matches
);
return $matches['sessionName'] ?? null;
}
public static function checkOrCreateSessionFolder(string $session): void
{
$directory = dirname($session);
if ($directory && $directory !== '.' && !is_dir($directory)) {
$parentDirectoryPermissions = fileperms(ROOT_DIR);
if (!mkdir($directory, $parentDirectoryPermissions, true) && !is_dir($directory)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $directory));
}
}
}
private static function isSessionLoggedIn(MadelineProto\API $instance): bool private static function isSessionLoggedIn(MadelineProto\API $instance): bool
{ {
return ($instance->API->authorized ?? MTProto::NOT_LOGGED_IN) === MTProto::LOGGED_IN; return ($instance->API->authorized ?? MTProto::NOT_LOGGED_IN) === MTProto::LOGGED_IN;
@ -71,7 +27,7 @@ class Client
warning(PHP_EOL . 'Starting MadelineProto...' . PHP_EOL); warning(PHP_EOL . 'Starting MadelineProto...' . PHP_EOL);
foreach ($sessionFiles as $file) { foreach ($sessionFiles as $file) {
$sessionName = static::getSessionName($file); $sessionName = Files::getSessionName($file);
$instance = $this->addSession($sessionName); $instance = $this->addSession($sessionName);
$this->runSession($instance); $this->runSession($instance);
} }
@ -90,8 +46,8 @@ class Client
if (isset($this->instances[$session])) { if (isset($this->instances[$session])) {
throw new InvalidArgumentException('Session already exists'); throw new InvalidArgumentException('Session already exists');
} }
$file = static::getSessionFile($session); $file = Files::getSessionFile($session);
static::checkOrCreateSessionFolder($file); Files::checkOrCreateSessionFolder($file);
$settings = array_replace_recursive((array) Config::getInstance()->get('telegram'), $settings); $settings = array_replace_recursive((array) Config::getInstance()->get('telegram'), $settings);
$instance = new MadelineProto\API($file, $settings); $instance = new MadelineProto\API($file, $settings);
$instance->async(true); $instance->async(true);
@ -190,7 +146,7 @@ class Client
private function loop(MadelineProto\API $instance, callable $callback = null): void private function loop(MadelineProto\API $instance, callable $callback = null): void
{ {
$sessionName = static::getSessionName($instance->session); $sessionName = Files::getSessionName($instance->session);
try { try {
$callback ? $instance->loop($callback) : $instance->loop(); $callback ? $instance->loop($callback) : $instance->loop();
} catch (\Throwable $e) { } catch (\Throwable $e) {

View File

@ -3,7 +3,7 @@
namespace TelegramApiServer\EventObservers; namespace TelegramApiServer\EventObservers;
use danog\MadelineProto\APIWrapper; use danog\MadelineProto\APIWrapper;
use TelegramApiServer\Client; use TelegramApiServer\Files;
class EventHandler extends \danog\MadelineProto\EventHandler class EventHandler extends \danog\MadelineProto\EventHandler
{ {
@ -12,7 +12,7 @@ class EventHandler extends \danog\MadelineProto\EventHandler
public function __construct(APIWrapper $MadelineProto) public function __construct(APIWrapper $MadelineProto)
{ {
$this->sessionName = Client::getSessionName($MadelineProto->session); $this->sessionName = Files::getSessionName($MadelineProto->session);
if (empty(static::$instances[$this->sessionName])) { if (empty(static::$instances[$this->sessionName])) {
static::$instances[$this->sessionName] = true; static::$instances[$this->sessionName] = true;
parent::__construct($MadelineProto); parent::__construct($MadelineProto);

62
src/Files.php Normal file
View File

@ -0,0 +1,62 @@
<?php
namespace TelegramApiServer;
class Files
{
public static string $sessionExtension = '.madeline';
public static string $sessionFolder = 'sessions';
public static function checkOrCreateSessionFolder(string $session): void
{
$directory = dirname($session);
if ($directory && $directory !== '.' && !is_dir($directory)) {
$parentDirectoryPermissions = fileperms(ROOT_DIR);
if (!mkdir($directory, $parentDirectoryPermissions, true) && !is_dir($directory)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $directory));
}
}
}
public static function getSessionName(?string $sessionFile): ?string
{
if (!$sessionFile) {
return null;
}
preg_match(
'~' . Files::$sessionFolder . "/(?'sessionName'.*?)" . Files::$sessionExtension . '$~',
$sessionFile,
$matches
);
return $matches['sessionName'] ?? null;
}
/**
* @param string|null $session
*
* @return string|null
*/
public static function getSessionFile(?string $session): ?string
{
if (!$session) {
return null;
}
$session = trim(trim($session), '/');
$session = Files::$sessionFolder . '/' . $session . Files::$sessionExtension;
$session = str_replace('//', '/', $session);
return $session;
}
public static function globRecursive($pattern, $flags = 0): array
{
$files = glob($pattern, $flags) ?: [];
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = [...$files, ...static::globRecursive($dir.'/'.basename($pattern), $flags)];
}
return $files;
}
}

View File

@ -6,6 +6,7 @@ use Amp\Promise;
use danog\MadelineProto; use danog\MadelineProto;
use danog\MadelineProto\MTProto; use danog\MadelineProto\MTProto;
use TelegramApiServer\Client; use TelegramApiServer\Client;
use TelegramApiServer\Files;
use function Amp\call; use function Amp\call;
class SystemApiExtensions class SystemApiExtensions
@ -60,7 +61,7 @@ class SystemApiExtensions
$sessions[$session] = [ $sessions[$session] = [
'session' => $session, 'session' => $session,
'file' => Client::getSessionFile($session), 'file' => Files::getSessionFile($session),
'status' => $status, 'status' => $status,
]; ];
} }
@ -74,7 +75,7 @@ class SystemApiExtensions
public function removeSessionFile($session) public function removeSessionFile($session)
{ {
return call(static function() use($session) { return call(static function() use($session) {
$file = Client::getSessionFile($session); $file = Files::getSessionFile($session);
if (is_file($file)) { if (is_file($file)) {
yield \Amp\File\unlink($file); yield \Amp\File\unlink($file);
yield \Amp\File\unlink($file . '.lock'); yield \Amp\File\unlink($file . '.lock');

View File

@ -2,22 +2,22 @@
namespace TelegramApiServer\Migrations; namespace TelegramApiServer\Migrations;
use TelegramApiServer\Client; use TelegramApiServer\Files;
class SessionsMigration class SessionsMigration
{ {
public static function move($rootDir = ROOT_DIR) public static function move($rootDir = ROOT_DIR)
{ {
foreach (glob("$rootDir/*" . Client::$sessionExtension) as $oldFile) { foreach (glob("$rootDir/*" . Files::$sessionExtension) as $oldFile) {
preg_match( preg_match(
'~^' . "{$rootDir}(?'session'.*)" . preg_quote(Client::$sessionExtension, '\\') . '$~', '~^' . "{$rootDir}(?'session'.*)" . preg_quote(Files::$sessionExtension, '\\') . '$~',
$oldFile, $oldFile,
$matches $matches
); );
if ($session = $matches['session'] ?? null) { if ($session = $matches['session'] ?? null) {
$session = Client::getSessionFile($session); $session = Files::getSessionFile($session);
Client::checkOrCreateSessionFolder($session); Files::checkOrCreateSessionFolder($session);
rename($oldFile, "{$rootDir}/{$session}"); rename($oldFile, "{$rootDir}/{$session}");
rename("{$oldFile}.lock", "{$rootDir}/{$session}.lock"); rename("{$oldFile}.lock", "{$rootDir}/{$session}.lock");