2022-12-30 21:54:44 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2018-02-24 17:54:13 +01:00
|
|
|
|
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
|
|
|
/**
|
|
|
|
* API module.
|
|
|
|
*
|
|
|
|
* This file is part of MadelineProto.
|
|
|
|
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* See the GNU Affero General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License along with MadelineProto.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* @author Daniil Gentili <daniil@daniil.it>
|
2023-01-04 12:43:01 +01:00
|
|
|
* @copyright 2016-2023 Daniil Gentili <daniil@daniil.it>
|
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
|
|
|
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
2019-10-31 15:07:35 +01:00
|
|
|
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
Merge alpha into master (async, huge bugfixes and more) (#546)
* Implement async and lots of bugfixes
* Implement more async
* Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr
* Apply fixes from StyleCI
* Bugfixes
* Apply fixes from StyleCI
* Bugfixes, implement combined promises
* Apply fixes from StyleCI
* Support passing method arguments as callable
* Starting to write async upload logic
* Apply fixes from StyleCI
* Start implementing async file upload
* Apply fixes from StyleCI
* bugfix
* Apply fixes from StyleCI
* Start rewriting connection module
* Add PHP file docblocks for all classes
* Start working on new async stream API
* Finish writing stream API
* More stream API fixes
* Apply fixes from StyleCI
* Rewrite DataCenter and Connection modules
* Clean up stream API documentation
* Fixes
* Apply fixes from StyleCI
* Add referenced parameter to get length of buffer to read in getReadBuffer API
* Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar
* Start fixing reads
* Fix all protocol stream wrappers
* Apply fixes from StyleCI
* Implement disconnection, and remove end function
* Working async RPC
* Implement async file upload
* Bugfix
* Method recall bugfixes
* Bugfixes
* Trait bugfixes
* Fix FIFO buffer
* Bugfixes and speedtests
* Async logging
* Implement websocket streams
* Implement loop API, signal API, clean closing and start changing layer
* Small magna, websocket and HTTP fixes
* Clean up loop API
* Improved stack traces, 2FA and async
* Login fixes
* Added instructions for manual verification
* Small fixes
* More app info improvements
* More app info improvements
* TL and 2FA fixes
* Update to layer 89
* More bugfixes
* Implement broken media reporting
* Remove debug comments
* PHP 7.2 backwards compatibility
* Bugfixes
* Async key generation
* Some simplifications
* Transport fixes
* Cleanup
* async API
* Performance fixes
* Fixes to async API
* Bugfixes
* Implement one-time async loop
* Authorization and logging fixes
* Update to layer 91
* 7to5 fix
* Null coalesce conversion
* Implement socks5 proxy
* Implement HTTP proxy
* Fixes to HTTP proxy
* MTProxy and socks5 fixes
* Disable PHP 5 conversion
* Proxies have higher priority
* Avoid error handling in vendor
* Override composer dependencies
* Fix travis build
* Final composer fixes
* Proxy logic fixes
* Fix get_updates update handling
* Do not use parallel file driver if not supported
* Refactor loader and implement HTTP fixes
* Suppress errors in loader
* HTTP and authorization fixes
* HTTP fixes
* Improved peer management
* Use HTTP protocol on altervista
* Small bugfixes
* Minor fixes
* Docufix
* Docufix
* Legacy fixes
* Fix message queue
* Avoid updating if using MTProxy
* Improve logs and examples
* Trim final newlines while converting parse mode
* Reimplement noResponse flag
* Async combined event handler and APIFactory fixes
* Actually return config
* Case-insensitive methods
* Bugfix
* Apply fixes from StyleCI (#545)
* MTProxy fixes
* PHP 5 warning
* Improved PHP 5 warning
* Use <br> along with newlines in web logs
* Update docs
2018-12-26 20:51:14 +01:00
|
|
|
*/
|
2018-02-25 17:50:03 +01:00
|
|
|
|
2016-08-07 23:23:10 +02:00
|
|
|
namespace danog\MadelineProto;
|
2016-08-08 18:10:28 +02:00
|
|
|
|
2023-01-11 18:47:27 +01:00
|
|
|
use Amp\CancelledException;
|
2022-12-30 20:24:13 +01:00
|
|
|
use Amp\DeferredFuture;
|
2023-01-15 16:12:12 +01:00
|
|
|
use Amp\Future;
|
2023-01-21 21:21:35 +01:00
|
|
|
use Amp\Future\UnhandledFutureError;
|
2020-09-22 23:10:56 +02:00
|
|
|
use Amp\Ipc\Sync\ChannelledSocket;
|
2023-01-15 16:12:12 +01:00
|
|
|
use Amp\SignalException;
|
2023-01-11 18:47:27 +01:00
|
|
|
use Amp\TimeoutCancellation;
|
|
|
|
use Amp\TimeoutException;
|
2022-12-30 19:21:36 +01:00
|
|
|
use danog\MadelineProto\ApiWrappers\Start;
|
2020-09-22 23:10:56 +02:00
|
|
|
use danog\MadelineProto\Ipc\Client;
|
2023-01-22 10:48:22 +01:00
|
|
|
use danog\MadelineProto\Ipc\Server;
|
2020-09-26 21:57:06 +02:00
|
|
|
use danog\MadelineProto\Settings\Ipc as SettingsIpc;
|
2020-09-22 11:48:12 +02:00
|
|
|
use danog\MadelineProto\Settings\Logger as SettingsLogger;
|
2023-01-21 21:21:35 +01:00
|
|
|
use Revolt\EventLoop;
|
2023-01-15 16:12:12 +01:00
|
|
|
use Revolt\EventLoop\UncaughtThrowable;
|
2022-12-30 19:21:36 +01:00
|
|
|
use Throwable;
|
2023-01-26 19:52:35 +01:00
|
|
|
use Webmozart\Assert\Assert;
|
2020-02-26 14:14:26 +01:00
|
|
|
|
2023-01-03 21:51:49 +01:00
|
|
|
use function Amp\async;
|
2023-01-11 18:47:27 +01:00
|
|
|
use function Amp\Future\await;
|
2023-02-12 14:09:36 +01:00
|
|
|
use function Amp\Future\awaitFirst;
|
2023-01-03 21:51:49 +01:00
|
|
|
|
2019-12-28 17:34:04 +01:00
|
|
|
/**
|
|
|
|
* Main API wrapper for MadelineProto.
|
|
|
|
*/
|
2023-01-27 14:20:47 +01:00
|
|
|
final class API extends AbstractAPI
|
2016-08-07 23:23:30 +02:00
|
|
|
{
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* Release version.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const RELEASE = MTProto::RELEASE;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* We're not logged in.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const NOT_LOGGED_IN = MTProto::NOT_LOGGED_IN;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* We're waiting for the login code.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const WAITING_CODE = MTProto::WAITING_CODE;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* We're waiting for parameters to sign up.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const WAITING_SIGNUP = MTProto::WAITING_SIGNUP;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* We're waiting for the 2FA password.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const WAITING_PASSWORD = MTProto::WAITING_PASSWORD;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* We're logged in.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const LOGGED_IN = MTProto::LOGGED_IN;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* Secret chat was not found.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const SECRET_EMPTY = MTProto::SECRET_EMPTY;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* Secret chat was requested.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const SECRET_REQUESTED = MTProto::SECRET_REQUESTED;
|
2020-10-15 19:07:37 +02:00
|
|
|
/**
|
|
|
|
* Secret chat was found.
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-06-27 19:47:41 +02:00
|
|
|
public const SECRET_READY = MTProto::SECRET_READY;
|
|
|
|
/**
|
|
|
|
* This peer is a user.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const PEER_TYPE_USER = MTProto::PEER_TYPE_USER;
|
|
|
|
/**
|
|
|
|
* This peer is a bot.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const PEER_TYPE_BOT = MTProto::PEER_TYPE_BOT;
|
|
|
|
/**
|
|
|
|
* This peer is a normal group.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const PEER_TYPE_GROUP = MTProto::PEER_TYPE_GROUP;
|
|
|
|
/**
|
|
|
|
* This peer is a supergroup.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const PEER_TYPE_SUPERGROUP = MTProto::PEER_TYPE_SUPERGROUP;
|
|
|
|
/**
|
|
|
|
* This peer is a channel.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public const PEER_TYPE_CHANNEL = MTProto::PEER_TYPE_CHANNEL;
|
2022-12-30 19:21:36 +01:00
|
|
|
use Start;
|
2020-02-25 18:02:32 +01:00
|
|
|
/**
|
2020-09-22 17:30:07 +02:00
|
|
|
* Session paths.
|
2020-02-25 18:02:32 +01:00
|
|
|
*
|
|
|
|
* @internal
|
|
|
|
*/
|
2023-01-25 19:12:49 +01:00
|
|
|
private SessionPaths $session;
|
2020-02-25 18:02:32 +01:00
|
|
|
|
2020-09-24 20:49:34 +02:00
|
|
|
/**
|
|
|
|
* Unlock callback.
|
|
|
|
*
|
|
|
|
* @var ?callable
|
|
|
|
*/
|
|
|
|
private $unlock = null;
|
2020-02-25 18:02:32 +01:00
|
|
|
|
2023-06-13 21:30:02 +02:00
|
|
|
/**
|
|
|
|
* Obtain the API ID UI template.
|
|
|
|
*/
|
2023-01-25 19:12:49 +01:00
|
|
|
public function getWebAPITemplate(): string
|
|
|
|
{
|
|
|
|
return $this->wrapper->getWebApiTemplate();
|
|
|
|
}
|
2023-06-13 21:30:02 +02:00
|
|
|
/**
|
|
|
|
* Set the API ID UI template.
|
|
|
|
*/
|
2023-01-25 19:12:49 +01:00
|
|
|
public function setWebApiTemplate(string $template): void
|
|
|
|
{
|
|
|
|
$this->wrapper->setWebApiTemplate($template);
|
|
|
|
}
|
|
|
|
|
2019-12-28 17:34:04 +01:00
|
|
|
/**
|
2023-06-27 19:47:41 +02:00
|
|
|
* Constructor function.
|
2019-12-28 17:34:04 +01:00
|
|
|
*
|
2023-01-15 16:12:12 +01:00
|
|
|
* @param string $session Session name
|
|
|
|
* @param array|SettingsAbstract $settings Settings
|
2019-12-28 17:34:04 +01:00
|
|
|
*/
|
2023-01-15 13:07:48 +01:00
|
|
|
public function __construct(string $session, array|SettingsAbstract $settings = [])
|
2016-08-07 23:23:30 +02:00
|
|
|
{
|
2023-01-24 12:45:55 +01:00
|
|
|
Magic::start(light: true);
|
2020-09-22 11:48:12 +02:00
|
|
|
$settings = Settings::parseFromLegacy($settings);
|
2020-09-22 17:30:07 +02:00
|
|
|
$this->session = new SessionPaths($session);
|
2023-01-26 14:33:30 +01:00
|
|
|
$this->wrapper = new APIWrapper($this->session);
|
|
|
|
$this->exportNamespaces();
|
2023-01-03 22:07:58 +01:00
|
|
|
|
2020-09-24 11:45:20 +02:00
|
|
|
Logger::constructorFromSettings($settings instanceof Settings
|
|
|
|
? $settings->getLogger()
|
2020-09-26 21:57:06 +02:00
|
|
|
: ($settings instanceof SettingsLogger ? $settings : new SettingsLogger));
|
2020-09-24 11:45:20 +02:00
|
|
|
|
2022-12-30 22:31:20 +01:00
|
|
|
if ($this->connectToMadelineProto($settings)) {
|
2020-09-24 11:45:20 +02:00
|
|
|
return; // OK
|
|
|
|
}
|
2021-05-12 20:43:55 +02:00
|
|
|
|
2020-09-24 11:45:20 +02:00
|
|
|
if (!$settings instanceof Settings) {
|
2020-09-26 21:57:06 +02:00
|
|
|
$newSettings = new Settings;
|
|
|
|
$newSettings->merge($settings);
|
|
|
|
$settings = $newSettings;
|
2020-09-24 11:45:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$appInfo = $settings->getAppInfo();
|
|
|
|
if (!$appInfo->hasApiInfo()) {
|
2023-05-27 18:35:31 +02:00
|
|
|
if (!$appInfo->getShowPrompt()) {
|
|
|
|
throw new Exception("No API ID or API hash was provided, please specify them in the settings!");
|
|
|
|
}
|
2022-12-30 22:31:20 +01:00
|
|
|
$app = $this->APIStart($settings);
|
2020-09-24 11:45:20 +02:00
|
|
|
if (!$app) {
|
|
|
|
die();
|
|
|
|
}
|
|
|
|
$appInfo->setApiId($app['api_id']);
|
|
|
|
$appInfo->setApiHash($app['api_hash']);
|
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->setAPI(new MTProto($settings, $this->wrapper));
|
|
|
|
$this->wrapper->logger(Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
|
2020-09-24 11:45:20 +02:00
|
|
|
}
|
2020-09-24 23:25:54 +02:00
|
|
|
|
2020-09-24 20:49:34 +02:00
|
|
|
/**
|
|
|
|
* Reconnect to full instance.
|
|
|
|
*/
|
2023-01-27 14:20:47 +01:00
|
|
|
protected function reconnectFull(): bool
|
2020-09-24 20:49:34 +02:00
|
|
|
{
|
2023-01-25 19:12:49 +01:00
|
|
|
if ($this->wrapper->getAPI() instanceof Client) {
|
|
|
|
$this->wrapper->logger('Restarting to full instance...');
|
2021-04-07 19:28:42 +02:00
|
|
|
try {
|
2022-12-30 22:31:20 +01:00
|
|
|
if (!isset($_GET['MadelineSelfRestart']) && (($this->hasEventHandler()) || !($this->isIpcWorker()))) {
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger('Restarting to full instance: the bot is already running!');
|
2023-01-04 15:13:55 +01:00
|
|
|
Tools::closeConnection($this->getWebMessage('The bot is already running!'));
|
2021-04-07 20:20:46 +02:00
|
|
|
return false;
|
2021-04-07 19:28:42 +02:00
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger('Restarting to full instance: stopping IPC server...');
|
|
|
|
$this->wrapper->getAPI()->stopIpcServer();
|
2023-01-15 16:12:12 +01:00
|
|
|
} catch (SecurityException|SignalException $e) {
|
2021-12-03 18:15:56 +01:00
|
|
|
throw $e;
|
2022-12-30 19:21:36 +01:00
|
|
|
} catch (Throwable $e) {
|
2023-01-15 16:12:12 +01:00
|
|
|
if ($e instanceof UncaughtThrowable) {
|
|
|
|
$e = $e->getPrevious();
|
|
|
|
if ($e instanceof SecurityException || $e instanceof SignalException) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger("Restarting to full instance: error $e");
|
2021-04-07 17:28:34 +02:00
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger('Restarting to full instance: reconnecting...');
|
2022-12-30 20:24:13 +01:00
|
|
|
$cancel = new DeferredFuture;
|
2023-01-03 22:07:58 +01:00
|
|
|
$cb = function () use ($cancel, &$cb): void {
|
2022-12-30 22:31:20 +01:00
|
|
|
[$result] = Serialization::tryConnect($this->session->getIpcPath(), $cancel->getFuture());
|
2021-04-18 16:02:59 +02:00
|
|
|
if ($result instanceof ChannelledSocket) {
|
|
|
|
try {
|
2023-01-25 19:12:49 +01:00
|
|
|
if (!$this->wrapper->getAPI() instanceof Client) {
|
|
|
|
$this->wrapper->logger('Restarting to full instance (again): the bot is already running!');
|
2022-12-30 22:31:20 +01:00
|
|
|
$result->disconnect();
|
2021-05-03 23:51:11 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger('Restarting to full instance (again): sending shutdown signal!');
|
2023-01-22 10:48:22 +01:00
|
|
|
$result->send(Server::SHUTDOWN);
|
|
|
|
$result->disconnect();
|
2023-01-15 16:12:12 +01:00
|
|
|
} catch (SecurityException|SignalException $e) {
|
2021-12-03 18:15:56 +01:00
|
|
|
throw $e;
|
2022-12-30 19:21:36 +01:00
|
|
|
} catch (Throwable $e) {
|
2023-01-15 16:12:12 +01:00
|
|
|
if ($e instanceof UncaughtThrowable) {
|
|
|
|
$e = $e->getPrevious();
|
|
|
|
if ($e instanceof SecurityException || $e instanceof SignalException) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->logger("Restarting to full instance: error in stop loop $e");
|
2021-04-18 16:02:59 +02:00
|
|
|
}
|
2023-01-21 21:21:35 +01:00
|
|
|
EventLoop::queue($cb);
|
2021-04-18 16:02:59 +02:00
|
|
|
}
|
|
|
|
};
|
2023-01-21 21:21:35 +01:00
|
|
|
EventLoop::queue($cb);
|
2022-12-30 22:31:20 +01:00
|
|
|
$this->connectToMadelineProto(new SettingsEmpty, true);
|
2023-01-22 17:52:44 +01:00
|
|
|
$cancel->complete(new Exception('Connected!'));
|
2020-09-24 20:49:34 +02:00
|
|
|
}
|
2021-04-07 20:20:46 +02:00
|
|
|
return true;
|
2020-09-24 20:49:34 +02:00
|
|
|
}
|
2020-09-24 11:45:20 +02:00
|
|
|
/**
|
|
|
|
* Connect to MadelineProto.
|
|
|
|
*
|
2020-10-07 19:31:52 +02:00
|
|
|
* @param SettingsAbstract $settings Settings
|
2020-09-24 11:45:20 +02:00
|
|
|
* @param bool $forceFull Whether to force full initialization
|
|
|
|
*/
|
2023-01-11 18:47:27 +01:00
|
|
|
protected function connectToMadelineProto(SettingsAbstract $settings, bool $forceFull = false, bool $tryReconnect = true): bool
|
2020-09-24 11:45:20 +02:00
|
|
|
{
|
2020-09-26 21:57:06 +02:00
|
|
|
if ($settings instanceof SettingsIpc) {
|
2021-04-23 14:21:47 +02:00
|
|
|
$forceFull = $forceFull || $settings->getSlow();
|
2020-09-24 11:45:20 +02:00
|
|
|
} elseif ($settings instanceof Settings) {
|
2021-04-23 14:21:47 +02:00
|
|
|
$forceFull = $forceFull || $settings->getIpc()->getSlow();
|
2020-09-24 11:45:20 +02:00
|
|
|
}
|
2021-09-25 14:02:12 +02:00
|
|
|
$forceFull = $forceFull || isset($_GET['MadelineSelfRestart']) || Magic::$altervista;
|
2020-09-22 17:30:07 +02:00
|
|
|
|
2023-01-11 18:47:27 +01:00
|
|
|
try {
|
|
|
|
[$unserialized, $this->unlock] = async(
|
|
|
|
Serialization::unserialize(...),
|
|
|
|
$this->session,
|
|
|
|
$settings,
|
|
|
|
$forceFull
|
|
|
|
)->await(new TimeoutCancellation(30.0));
|
|
|
|
} catch (CancelledException $e) {
|
|
|
|
if (!$e->getPrevious() instanceof TimeoutException) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
|
|
|
|
[$unserialized, $this->unlock] = [0, null];
|
|
|
|
}
|
2020-10-04 14:55:05 +02:00
|
|
|
|
2020-09-24 11:45:20 +02:00
|
|
|
if ($unserialized === 0) {
|
|
|
|
// Timeout
|
2023-01-04 15:13:55 +01:00
|
|
|
Logger::log('!!! Could not connect to MadelineProto, please check and report the logs for more details. !!!', Logger::FATAL_ERROR);
|
|
|
|
if (!$tryReconnect || (\defined('MADELINEPROTO_TEST') && \constant('MADELINEPROTO_TEST') === 'testing')) {
|
2021-07-01 15:43:00 +02:00
|
|
|
throw new Exception('Could not connect to MadelineProto, please check the MadelineProto.log file to debug!');
|
|
|
|
}
|
2023-01-04 15:13:55 +01:00
|
|
|
Logger::log('!!! Reconnecting using slower method. !!!', Logger::FATAL_ERROR);
|
2021-06-10 15:54:15 +02:00
|
|
|
// IPC server error, try fetching full session
|
2022-12-30 22:31:20 +01:00
|
|
|
return $this->connectToMadelineProto($settings, true, false);
|
2022-12-30 19:21:36 +01:00
|
|
|
} elseif ($unserialized instanceof Throwable) {
|
2020-09-24 11:45:20 +02:00
|
|
|
// IPC server error, try fetching full session
|
2022-12-30 22:31:20 +01:00
|
|
|
return $this->connectToMadelineProto($settings, true);
|
2020-09-24 11:45:20 +02:00
|
|
|
} elseif ($unserialized instanceof ChannelledSocket) {
|
|
|
|
// Success, IPC client
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->setAPI(new Client($unserialized, $this->session, Logger::$default));
|
2020-09-24 11:45:20 +02:00
|
|
|
return true;
|
2020-09-22 23:10:56 +02:00
|
|
|
} elseif ($unserialized) {
|
2020-09-24 11:45:20 +02:00
|
|
|
// Success, full session
|
2023-01-26 14:33:30 +01:00
|
|
|
$this->wrapper->getAPI()?->unreference();
|
|
|
|
$this->wrapper = $unserialized;
|
|
|
|
$this->wrapper->setSession($this->session);
|
|
|
|
$this->exportNamespaces();
|
2023-01-25 19:12:49 +01:00
|
|
|
if ($this->wrapper->getAPI()) {
|
2020-02-25 18:02:32 +01:00
|
|
|
unset($unserialized);
|
2020-02-26 11:47:30 +01:00
|
|
|
|
2020-09-26 21:57:06 +02:00
|
|
|
if ($settings instanceof SettingsIpc) {
|
2020-09-24 11:45:20 +02:00
|
|
|
$settings = new SettingsEmpty;
|
|
|
|
}
|
2023-01-25 19:12:49 +01:00
|
|
|
$this->wrapper->getAPI()->wakeup($settings, $this->wrapper);
|
|
|
|
$this->wrapper->logger(Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
|
2020-09-24 11:45:20 +02:00
|
|
|
return true;
|
2017-11-08 13:04:40 +01:00
|
|
|
}
|
2017-11-03 13:02:01 +01:00
|
|
|
}
|
2020-09-24 11:45:20 +02:00
|
|
|
return false;
|
Added documentation, simplified code, organized exceptions, added some more examples in testing.php, decided to unset flags in deserialized responses, moved message id arrays to Connection classes, added wrappers for logging in to telegram as a bot or as a user and for logging out, fixed deserializing of gzip packed objects, added more logging, fixed bugs, added methods to get and parse configuration, saved some fairies, fixed exporting/importing of authorization, added some wakeup methods to prevent problems during serialization, added support for ipv6 and automagical detection too. I think we can safely say this is now a beta.
2016-11-25 00:15:22 +01:00
|
|
|
}
|
2020-03-07 21:45:50 +01:00
|
|
|
/**
|
|
|
|
* Wakeup function.
|
|
|
|
*/
|
|
|
|
public function __wakeup(): void
|
|
|
|
{
|
2023-05-26 21:42:02 +02:00
|
|
|
$this->__construct($this->session->getSessionDirectoryPath());
|
2020-03-07 21:45:50 +01:00
|
|
|
}
|
2023-04-03 12:07:27 +02:00
|
|
|
public function __sleep(): array
|
|
|
|
{
|
2023-05-26 21:42:02 +02:00
|
|
|
return ['session'];
|
2023-04-03 12:07:27 +02:00
|
|
|
}
|
2023-01-15 16:12:12 +01:00
|
|
|
/**
|
|
|
|
* @var array<Future<null>>
|
|
|
|
*/
|
|
|
|
private static array $destructors = [];
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
public static function finalize(): void
|
|
|
|
{
|
2023-01-25 15:53:28 +01:00
|
|
|
if (self::$destructors) {
|
|
|
|
await(self::$destructors);
|
|
|
|
}
|
2023-01-15 16:12:12 +01:00
|
|
|
}
|
2019-12-28 17:34:04 +01:00
|
|
|
/**
|
|
|
|
* Destruct function.
|
|
|
|
*
|
|
|
|
* @internal
|
|
|
|
*/
|
2017-04-21 13:14:21 +02:00
|
|
|
public function __destruct()
|
|
|
|
{
|
2023-01-25 19:12:49 +01:00
|
|
|
$id = \count(self::$destructors);
|
|
|
|
self::$destructors[$id] = async(function () use ($id): void {
|
|
|
|
$this->wrapper->logger('Shutting down MadelineProto ('.static::class.')');
|
2023-01-26 19:57:50 +01:00
|
|
|
$this->wrapper->getAPI()?->unreference();
|
2023-01-25 19:12:49 +01:00
|
|
|
if (isset($this->wrapper)) {
|
|
|
|
$this->wrapper->logger('Prompting final serialization...');
|
|
|
|
$this->wrapper->serialize();
|
|
|
|
$this->wrapper->logger('Done final serialization!');
|
|
|
|
}
|
|
|
|
if ($this->unlock) {
|
|
|
|
($this->unlock)();
|
|
|
|
}
|
|
|
|
unset(self::$destructors[$id]);
|
|
|
|
});
|
2016-08-07 23:23:10 +02:00
|
|
|
}
|
2020-02-25 18:02:32 +01:00
|
|
|
|
2020-02-26 14:14:26 +01:00
|
|
|
/**
|
2020-02-26 15:15:37 +01:00
|
|
|
* Start multiple instances of MadelineProto and the event handlers (enables async).
|
2020-02-26 14:14:26 +01:00
|
|
|
*
|
2023-01-04 15:13:55 +01:00
|
|
|
* @param array<API> $instances Instances of madeline
|
2023-01-21 21:21:35 +01:00
|
|
|
* @param array<class-string<EventHandler>>|class-string<EventHandler> $eventHandler Event handler(s)
|
2020-02-26 14:14:26 +01:00
|
|
|
*/
|
2023-01-04 15:13:55 +01:00
|
|
|
public static function startAndLoopMulti(array $instances, array|string $eventHandler): void
|
2020-02-26 14:14:26 +01:00
|
|
|
{
|
2020-02-26 15:15:37 +01:00
|
|
|
if (\is_string($eventHandler)) {
|
2023-01-26 19:52:35 +01:00
|
|
|
Assert::classExists($eventHandler);
|
2020-02-26 15:15:37 +01:00
|
|
|
$eventHandler = \array_fill_keys(\array_keys($instances), $eventHandler);
|
2023-01-26 19:52:35 +01:00
|
|
|
} else {
|
|
|
|
Assert::notEmpty($eventHandler);
|
|
|
|
Assert::allClassExists($eventHandler);
|
2020-02-26 15:15:37 +01:00
|
|
|
}
|
|
|
|
|
2021-05-09 22:33:59 +02:00
|
|
|
$errors = [];
|
2021-05-11 15:56:31 +02:00
|
|
|
$started = \array_fill_keys(\array_keys($instances), false);
|
2020-02-26 15:59:34 +01:00
|
|
|
$instanceOne = \array_values($instances)[0];
|
2023-01-21 21:21:35 +01:00
|
|
|
|
2023-01-26 14:33:30 +01:00
|
|
|
$prev = EventLoop::getErrorHandler();
|
2023-01-21 21:21:35 +01:00
|
|
|
EventLoop::setErrorHandler(
|
2023-01-26 19:52:35 +01:00
|
|
|
$cb = function (\Throwable $e) use ($instanceOne, &$errors, &$started, $eventHandler): void {
|
2023-01-21 21:21:35 +01:00
|
|
|
if ($e instanceof UnhandledFutureError) {
|
2023-01-15 16:12:12 +01:00
|
|
|
$e = $e->getPrevious();
|
2023-01-21 21:21:35 +01:00
|
|
|
}
|
|
|
|
if ($e instanceof SecurityException || $e instanceof SignalException) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
if (\str_starts_with($e->getMessage(), 'Could not connect to DC ')) {
|
|
|
|
throw $e;
|
2023-01-15 16:12:12 +01:00
|
|
|
}
|
2021-05-09 22:33:59 +02:00
|
|
|
$t = \time();
|
|
|
|
$errors = [$t => $errors[$t] ?? 0];
|
|
|
|
$errors[$t]++;
|
2023-01-25 16:32:48 +01:00
|
|
|
if ($errors[$t] > 10 && \array_sum($started) !== \count($eventHandler)) {
|
2023-01-25 19:12:49 +01:00
|
|
|
$instanceOne->wrapper->logger('More than 10 errors in a second and not inited, exiting!', Logger::FATAL_ERROR);
|
2021-05-09 22:33:59 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
echo $e;
|
2023-01-25 19:12:49 +01:00
|
|
|
$instanceOne->wrapper->logger((string) $e, Logger::FATAL_ERROR);
|
2020-02-26 15:15:37 +01:00
|
|
|
$instanceOne->report("Surfaced: $e");
|
|
|
|
}
|
2023-01-21 21:21:35 +01:00
|
|
|
);
|
|
|
|
|
2023-01-26 19:52:35 +01:00
|
|
|
try {
|
|
|
|
$promises = [];
|
|
|
|
foreach ($instances as $k => $instance) {
|
|
|
|
$instance->start();
|
|
|
|
$promises []= async(function () use ($k, $instance, $eventHandler, &$started): void {
|
|
|
|
$instance->startAndLoopLogic($eventHandler[$k], $started[$k]);
|
|
|
|
});
|
|
|
|
}
|
2023-02-12 14:09:36 +01:00
|
|
|
awaitFirst($promises);
|
2023-01-26 19:52:35 +01:00
|
|
|
} finally {
|
|
|
|
if (EventLoop::getErrorHandler() === $cb) {
|
|
|
|
EventLoop::setErrorHandler($prev);
|
|
|
|
}
|
2021-04-07 20:20:46 +02:00
|
|
|
}
|
2020-06-20 13:03:15 +02:00
|
|
|
}
|
2018-02-25 17:50:03 +01:00
|
|
|
}
|