This commit is contained in:
Daniil Gentili 2019-10-31 12:45:19 +01:00
parent f0e616aade
commit 75e84f87f9
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
3 changed files with 303 additions and 96 deletions

View File

@ -16,9 +16,6 @@
*
* @link https://docs.madelineproto.xyz MadelineProto documentation
*/
/*
* Logger class
*/
namespace danog\MadelineProto;
@ -27,6 +24,9 @@ use Amp\Failure;
use function Amp\ByteStream\getStderr;
use function Amp\ByteStream\getStdout;
/**
* Logger class
*/
class Logger
{
use Tools;
@ -36,14 +36,54 @@ class Logger
const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
const RESET = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28];
/**
* Logging mode
*
* @var integer
*/
public $mode = 0;
/**
* Optional logger parameter
*
* @var mixed
*/
public $optional = null;
/**
* Logger prefix
*
* @var string
*/
public $prefix = '';
public $level = 3;
/**
* Logging level
*
* @var integer
*/
public $level = self::NOTICE;
/**
* Logging colors
*
* @var array
*/
public $colors = [];
/**
* Newline
*
* @var string
*/
public $newline = "\n";
/**
* Default logger instance
*
* @var self
*/
public static $default;
/**
* Whether the AGPL notice was printed
*
* @var boolean
*/
public static $printed = false;
const ULTRA_VERBOSE = 5;
@ -53,31 +93,17 @@ class Logger
const ERROR = 1;
const FATAL_ERROR = 0;
const NO_LOGGER = 0;
const DEFAULT_LOGGER = 1;
const FILE_LOGGER = 2;
const ECHO_LOGGER = 3;
const CALLABLE_LOGGER = 4;
/**
* Construct global logger.
*
* @param [type] $mode
* @param [type] $optional
* @param string $prefix
* @param [type] $level
* @param [type] $max_size
* @return void
*/
public static function constructor($mode, $optional = null, $prefix = '', $level = self::NOTICE, $max_size = 100 * 1024 * 1024)
{
self::$default = new self($mode, $optional, $prefix, $level, $max_size);
}
/**
* Construct global static logger from MadelineProto settings.
*
* @param array $settings
* @param array $settings Settings array
*
* @return void
*/
public static function constructorFromSettings(array $settings)
@ -90,8 +116,9 @@ class Logger
/**
* Get logger from MadelineProto settings.
*
* @param array $settings
* @param string $prefix Optional prefix
* @param array $settings Settings array
* @param string $prefix Optional prefix for log messages
*
* @return self
*/
public static function getLoggerFromSettings(array $settings, string $prefix = ''): self
@ -127,7 +154,35 @@ class Logger
return $logger;
}
public function __construct($mode, $optional = null, $prefix = '', $level = self::NOTICE, $max_size = 100 * 1024 * 1024)
/**
* Construct global logger.
*
* @param int $mode One of the logger constants
* @param mixed $optional Optional parameter for logger
* @param string $prefix Prefix for log messages
* @param int $level Default logging level
* @param int $max_size Maximum size for logfile
*
* @return void
*/
public static function constructor(int $mode, $optional = null, string $prefix = '', int $level = self::NOTICE, int $max_size = 100 * 1024 * 1024)
{
self::$default = new self($mode, $optional, $prefix, $level, $max_size);
}
/**
* Construct global logger.
*
* @param int $mode One of the logger constants
* @param mixed $optional Optional parameter for logger
* @param string $prefix Prefix for log messages
* @param int $level Default logging level
* @param int $max_size Maximum size for logfile
*
* @return void
*/
public function __construct(int $mode, $optional = null, string $prefix = '', int $level = self::NOTICE, int $max_size = 100 * 1024 * 1024)
{
if ($mode === null) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['no_mode_specified']);
@ -176,7 +231,15 @@ class Logger
}
}
public static function log($param, $level = self::NOTICE)
/**
* Log a message
*
* @param mixed $param Message
* @param int $level Logging level
*
* @return void
*/
public static function log($param, int $level = self::NOTICE)
{
if (!\is_null(self::$default)) {
self::$default->logger($param, $level, \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'));
@ -185,7 +248,16 @@ class Logger
}
}
public function logger($param, $level = self::NOTICE, $file = null)
/**
* Log a message
*
* @param mixed $param Message to log
* @param int $level Logging level
* @param string $file File that originated the message
*
* @return void
*/
public function logger($param, int $level = self::NOTICE, string $file = '')
{
if ($level > $this->level || $this->mode === 0) {
return false;
@ -213,7 +285,7 @@ class Logger
} elseif (!\is_string($param)) {
$param = \json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
if ($file === null) {
if (empty($file)) {
$file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
}
$param = \str_pad($file.$prefix.': ', 16 + \strlen($prefix))."\t".$param;
@ -234,9 +306,4 @@ class Logger
break;
}
}
public function __destruct()
{
//\danog\MadelineProto\Tools::wait($this->stdout->write(''));
}
}

View File

@ -19,6 +19,8 @@
namespace danog\MadelineProto;
use Amp\Artax\Client;
use Amp\Dns\Resolver;
use Amp\Loop;
use danog\MadelineProto\Async\AsyncConstruct;
use danog\MadelineProto\Loop\Generic\PeriodicLoop;
@ -410,6 +412,13 @@ class MTProto extends AsyncConstruct implements TLCallback
*/
public $datacenter;
/**
* Logger instance
*
* @var Logger
*/
public $logger;
/**
* Constructor function.
*
@ -512,7 +521,7 @@ class MTProto extends AsyncConstruct implements TLCallback
*
* @return void
*/
private function cleanup()
public function cleanup()
{
$this->referenceDatabase = new ReferenceDatabase($this);
$callbacks = [$this, $this->referenceDatabase];
@ -523,7 +532,16 @@ class MTProto extends AsyncConstruct implements TLCallback
return $this;
}
public function logger($param, $level = Logger::NOTICE, $file = null)
/**
* Logger
*
* @param string $param Parameter
* @param int $level Logging level
* @param string $file File where the message originated
*
* @return void
*/
public function logger($param, int $level = Logger::NOTICE, string $file = '')
{
if ($file === null) {
$file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
@ -533,37 +551,37 @@ class MTProto extends AsyncConstruct implements TLCallback
}
/**
* Whether this is altervista
* Get async HTTP client
*
* @return boolean
* @return \Amp\Artax\Client
*/
public function isAltervista(): bool
{
return Magic::$altervista;
}
public function isInitingAuthorization()
{
return $this->initing_authorization;
}
public function getHTTPClient()
public function getHTTPClient(): Client
{
return $this->datacenter->getHTTPClient();
}
public function getDNSClient()
/**
* Get async DNS client
*
* @return \Amp\Dns\Resolver
*/
public function getDNSClient(): Resolver
{
return $this->datacenter->getDNSClient();
}
public function fileGetContents($url): \Generator
/**
* Get contents of remote file asynchronously
*
* @param string $url URL
*
* @return \Generator<string>
*/
public function fileGetContents(string $url): \Generator
{
return $this->datacenter->fileGetContents($url);
}
public function testing(callable $a, ?string $b = null, $c = null, $d = 2, $e = self::METHOD_BEFORE_CALLBACK): ?string
{
}
/**
* Get all datacenter connections.
*
@ -588,6 +606,11 @@ class MTProto extends AsyncConstruct implements TLCallback
return true;
}
/**
* Prompt serialization of instance
*
* @return void
*/
public function serialize()
{
if ($this->wrapper instanceof API && isset($this->wrapper->session) && !\is_null($this->wrapper->session) && !$this->asyncInitPromise) {
@ -595,7 +618,12 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->wrapper->serialize($this->wrapper->session);
}
}
public function startLoops()
/**
* Start all internal loops
*
* @return void
*/
private function startLoops()
{
if (!$this->callCheckerLoop) {
$this->callCheckerLoop = new PeriodicLoop($this, [$this, 'checkCalls'], 'call check', 10);
@ -619,7 +647,12 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->configLoop->start();
$this->checkTosLoop->start();
}
public function stopLoops()
/**
* Stop all internal loops
*
* @return void
*/
private function stopLoops()
{
if ($this->callCheckerLoop) {
$this->callCheckerLoop->signal(true);
@ -642,6 +675,10 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->checkTosLoop = null;
}
}
/**
* Wakeup function
*/
public function __wakeup()
{
$backtrace = \debug_backtrace(0, 3);
@ -649,7 +686,14 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->setInitPromise($this->__wakeup_async($backtrace));
}
public function __wakeup_async($backtrace)
/**
* Async wakeup function
*
* @param array $backtrace Stack trace
*
* @return \Generator
*/
public function __wakeup_async(array $backtrace): \Generator
{
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
$this->setupLogger();
@ -834,6 +878,9 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->updaters[false]->start();
}
/**
* Destructor
*/
public function __destruct()
{
$this->stopLoops();
@ -859,7 +906,15 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->logger("Successfully destroyed MadelineProto");
}
public static function getSettings($settings, $previousSettings = []): array
/**
* Get correct settings array for the latest version
*
* @param array $settings Current settings array
* @param array $previousSettings Previous settings array
*
* @return array
*/
public static function getSettings(array $settings, array $previousSettings = []): array
{
Magic::classExists();
if (isset($previousSettings['connection_settings']['default_dc'])) {
@ -1186,7 +1241,14 @@ class MTProto extends AsyncConstruct implements TLCallback
}
return $settings;
}
public function parseSettings($settings)
/**
* Parse and store settings
*
* @param array $settings Settings
*
* @return void
*/
public function parseSettings(array $settings)
{
$settings = self::getSettings($settings, $this->settings);
if ($settings['app_info'] === null) {
@ -1200,6 +1262,11 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->setupLogger();
}
/**
* Setup logger
*
* @return void
*/
public function setupLogger()
{
$this->logger = Logger::getLoggerFromSettings($this->settings, isset($this->authorization['user']) ? isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'] : '');
@ -1240,7 +1307,19 @@ class MTProto extends AsyncConstruct implements TLCallback
return $this->datacenter->isHttp($datacenter);
}
// Connects to all datacenters and if necessary creates authorization keys, binds them and writes client info
public function isInitingAuthorization()
{
return $this->initing_authorization;
}
/**
* Connects to all datacenters and if necessary creates authorization keys, binds them and writes client info
*
* @param boolean $reconnectAll Whether to reconnect to all DCs
*
* @return \Generator
*/
public function connectToAllDcs(bool $reconnectAll = true): \Generator
{
$this->channels_state->get(false);
@ -1275,6 +1354,11 @@ class MTProto extends AsyncConstruct implements TLCallback
yield $this->getPhoneConfig();
}
/**
* Clean up MadelineProto session after logout
*
* @return void
*/
public function resetSession()
{
if (isset($this->seqUpdater)) {
@ -1316,6 +1400,11 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->dialog_params = ['_' => 'MadelineProto.dialogParams', 'limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0];
$this->full_chats = [];
}
/**
* Reset the update state and fetch all updates from the beginning
*
* @return void
*/
public function resetUpdateState()
{
if (isset($this->seqUpdater)) {
@ -1343,6 +1432,13 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->startUpdateSystem();
}
/**
* Start the update system
*
* @param boolean $anyway Force start update system?
*
* @return void
*/
public function startUpdateSystem($anyway = false)
{
if ($this->asyncInitPromise && !$anyway) {
@ -1382,6 +1478,13 @@ class MTProto extends AsyncConstruct implements TLCallback
}
}
/**
* Store shared phone config
*
* @param mixed $watcherId Watcher ID
*
* @return void
*/
public function getPhoneConfig($watcherId = null)
{
if ($this->authorized === self::LOGGED_IN && \class_exists(VoIPServerConfigInternal::class) && !$this->authorization['user']['bot'] && $this->datacenter->getDataCenterConnection($this->settings['connection_settings']['default_dc'])->hasTempAuthKey()) {
@ -1392,13 +1495,15 @@ class MTProto extends AsyncConstruct implements TLCallback
}
}
public function getCdnConfig($datacenter)
/**
* Store RSA keys for CDN datacenters
*
* @param string $datacenter DC ID
*
* @return \Generator
*/
public function getCdnConfig(string $datacenter): \Generator
{
/*
* ***********************************************************************
* Fetch RSA keys for CDN datacenters
*/
try {
foreach ((yield $this->methodCallAsyncRead('help.getCdnConfig', [], ['datacenter' => $datacenter]))['public_keys'] as $curkey) {
$tempkey = new \danog\MadelineProto\RSA($curkey['public_key']);
@ -1409,12 +1514,25 @@ class MTProto extends AsyncConstruct implements TLCallback
}
}
public function getCachedConfig()
/**
* Get cached server-side config
*
* @return array
*/
public function getCachedConfig(): array
{
return $this->config;
}
public function getConfig($config = [], $options = [])
/**
* Get cached (or eventually re-fetch) server-side config
*
* @param array $config Current config
* @param array $options Options for method call
*
* @return \Generator
*/
public function getConfig(array $config = [], array $options = []): \Generator
{
if ($this->config['expires'] > \time()) {
return $this->config;
@ -1425,7 +1543,12 @@ class MTProto extends AsyncConstruct implements TLCallback
return $this->config;
}
public function parseConfig()
/**
* Parse cached config
*
* @return \Generator
*/
private function parseConfig(): \Generator
{
if (isset($this->config['dc_options'])) {
$options = $this->config['dc_options'];
@ -1436,7 +1559,14 @@ class MTProto extends AsyncConstruct implements TLCallback
$this->logger->logger($this->config, Logger::NOTICE);
}
public function parseDcOptions($dc_options)
/**
* Parse DC options from config
*
* @param array $dc_options DC options
*
* @return \Generator
*/
private function parseDcOptions(array $dc_options): \Generator
{
foreach ($dc_options as $dc) {
$test = $this->config['test_mode'] ? 'test' : 'main';

View File

@ -223,10 +223,10 @@ trait Tools
}
/**
* Convert value to unsigned base256 int
* Convert value to unsigned base256 int.
*
* @param int $value Value
*
*
* @return string
*/
public static function packUnsignedInt(int $value): string
@ -242,10 +242,10 @@ trait Tools
}
/**
* Convert double to binary version
* Convert double to binary version.
*
* @param double $value Value to convert
*
*
* @return string
*/
public static function packDouble(double $value): string
@ -259,10 +259,10 @@ trait Tools
}
/**
* Unpack binary double
* Unpack binary double.
*
* @param string $value Value to unpack
*
*
* @return double
*/
public static function unpackDouble(string $value): double
@ -275,11 +275,11 @@ trait Tools
}
/**
* Synchronously wait for a promise|generator
* Synchronously wait for a promise|generator.
*
* @param \Generator|Promise $promise The promise to wait for
* @param boolean $ignoreSignal Whether to ignore shutdown signals
*
*
* @return mixed
*/
public static function wait($promise, $ignoreSignal = false)
@ -320,7 +320,7 @@ trait Tools
* Returned promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to the array of promises.
*
* @param array<\Generator|Promise> $promises Promises
*
*
* @return Promise
*/
public static function all(array $promises): Promise
@ -334,9 +334,9 @@ trait Tools
/**
* Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
*
*
* @param array<Promise|\Generator> $promises Promises
*
*
* @return Promise
*/
public static function any(array $promises): Promise
@ -353,7 +353,7 @@ trait Tools
* The returned promise will only fail if the given number of required promises fail.
*
* @param array<Promise|\Generator> $promises Promises
*
*
* @return Promise
*/
public static function some(array $promises): Promise
@ -369,7 +369,7 @@ trait Tools
* Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
*
* @param array<Promise|\Generator> $promises Promises
*
*
* @return Promise
*/
public static function first(array $promises): Promise
@ -382,11 +382,11 @@ trait Tools
}
/**
* Create an artificial timeout for any \Generator or Promise
* Create an artificial timeout for any \Generator or Promise.
*
* @param \Generator|Promise $promise
* @param integer $timeout
*
*
* @return Promise
*/
public static function timeout($promise, int $timeout): Promise
@ -395,10 +395,10 @@ trait Tools
}
/**
* Convert generator, promise or any other value to a promise
* Convert generator, promise or any other value to a promise.
*
* @param \Generator|Promise|mixed $promise
*
*
* @return Promise
*/
public static function call($promise): Promise
@ -413,12 +413,12 @@ trait Tools
}
/**
* Call promise in background
* Call promise in background.
*
* @param \Generator|Promise $promise Promise to resolve
* @param ?\Generator|Promise $actual Promise to resolve instead of $promise
* @param string $file File
*
*
* @return void
*/
public static function callFork($promise, $actual = null, $file = '')
@ -454,10 +454,10 @@ trait Tools
}
/**
* Call promise in background, deferring execution
* Call promise in background, deferring execution.
*
* @param \Generator|Promise $promise Promise to resolve
*
*
* @return void
*/
public static function callForkDefer($promise)
@ -466,11 +466,11 @@ trait Tools
}
/**
* Rethrow error catched in strand
* Rethrow error catched in strand.
*
* @param \Throwable $e Exception
* @param string $file File where the strand started
*
*
* @return void
*/
public static function rethrow(\Throwable $e, $file = '')
@ -499,11 +499,11 @@ trait Tools
}
/**
* Call promise $b after promise $a
* Call promise $b after promise $a.
*
* @param \Generator|Promise $a Promise A
* @param \Generator|Promise $b Promise B
*
*
* @return Promise
*/
public static function after($a, $b): Promise
@ -513,9 +513,9 @@ trait Tools
$a->onResolve(static function ($e, $res) use ($b, $deferred) {
if ($e) {
if (isset($this)) {
$this->rethrow($e, $file);
$this->rethrow($e);
} else {
self::rethrow($e, $file);
self::rethrow($e);
}
return;
}
@ -523,9 +523,9 @@ trait Tools
$b->onResolve(function ($e, $res) use ($deferred) {
if ($e) {
if (isset($this)) {
$this->rethrow($e, $file);
$this->rethrow($e);
} else {
self::rethrow($e, $file);
self::rethrow($e);
}
return;
}
@ -809,4 +809,14 @@ trait Tools
{
return \str_replace('_', '\\_', $hwat);
}
/**
* Whether this is altervista.
*
* @return boolean
*/
public function isAltervista(): bool
{
return Magic::$altervista;
}
}