mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 09:58:59 +01:00
Add PSR logger, remove CombinedAPI
This commit is contained in:
parent
b0bafaf431
commit
c9ebdd0fa8
@ -1,219 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CombinedAPI 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>
|
||||
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
||||
*
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\Loop;
|
||||
use function Amp\Promise\all;
|
||||
|
||||
class CombinedAPI
|
||||
{
|
||||
use \danog\Serializable;
|
||||
public $session;
|
||||
public $instance_paths = [];
|
||||
public $instances = [];
|
||||
public $timeout = 5;
|
||||
public $serialization_interval = 30;
|
||||
public $serialized = 0;
|
||||
protected $async;
|
||||
public function __magic_construct($session, $paths = [])
|
||||
{
|
||||
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
|
||||
\danog\MadelineProto\Magic::classExists();
|
||||
$realpaths = new SessionPaths($session);
|
||||
$this->session = $realpaths->getSessionPath();
|
||||
foreach ($paths as $path => $settings) {
|
||||
$this->addInstance($path, $settings);
|
||||
}
|
||||
if (\file_exists($realpaths->getSessionPath())) {
|
||||
if (!\file_exists($realpaths->getLockPath())) {
|
||||
\touch($realpaths->getLockPath());
|
||||
\clearstatcache();
|
||||
}
|
||||
$lock = \fopen($realpaths->getLockPath(), 'r');
|
||||
\danog\MadelineProto\Logger::log('Waiting for shared lock of serialization lockfile...');
|
||||
\flock($lock, LOCK_SH);
|
||||
\danog\MadelineProto\Logger::log('Shared lock acquired, deserializing...');
|
||||
try {
|
||||
$tounserialize = \file_get_contents($realpaths->getSessionPath());
|
||||
} finally {
|
||||
\flock($lock, LOCK_UN);
|
||||
\fclose($lock);
|
||||
}
|
||||
$deserialized = \unserialize($tounserialize);
|
||||
/*foreach ($deserialized['instance_paths'] as $path) {
|
||||
$this->addInstance($path, isset($paths[$path]) ? $paths[$path] : []);
|
||||
}*/
|
||||
$this->event_handler = $deserialized['event_handler'];
|
||||
$this->event_handler_instance = $deserialized['event_handler_instance'];
|
||||
if ($this->event_handler !== null) {
|
||||
$this->setEventHandler($this->event_handler);
|
||||
}
|
||||
}
|
||||
foreach ($paths as $path => $settings) {
|
||||
$this->addInstance($path, $settings);
|
||||
}
|
||||
}
|
||||
public function addInstance($path, $settings = [])
|
||||
{
|
||||
if (isset($this->instances[$path]) && isset($this->instance_paths[$path])) {
|
||||
if (isset($this->event_handler_instance)) {
|
||||
$this->event_handler_instance->referenceInstance($path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//\danog\MadelineProto\Logger::constructor(3);
|
||||
\danog\MadelineProto\Logger::log("INSTANTIATING {$path}...");
|
||||
$instance = new \danog\MadelineProto\API($path, $settings);
|
||||
$this->instance_paths[$path] = $path;
|
||||
$this->instances[$path] = $instance;
|
||||
if (isset($this->event_handler_instance)) {
|
||||
$this->event_handler_instance->referenceInstance($path);
|
||||
}
|
||||
}
|
||||
public function removeInstance($path)
|
||||
{
|
||||
if (isset($this->instance_paths[$path])) {
|
||||
unset($this->instance_paths[$path]);
|
||||
}
|
||||
if (isset($this->instances[$path])) {
|
||||
unset($this->instances[$path]);
|
||||
}
|
||||
if (isset($this->event_handler_instance)) {
|
||||
$this->event_handler_instance->removeInstance($path);
|
||||
}
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
$this->serialize();
|
||||
}
|
||||
public function serialize($filename = '')
|
||||
{
|
||||
/*foreach ($this->instances as $instance) {
|
||||
$instance->serialize();
|
||||
}*/
|
||||
if (\is_null($this->session)) {
|
||||
return;
|
||||
}
|
||||
if ($filename === '') {
|
||||
$filename = $this->session;
|
||||
}
|
||||
Logger::log(\danog\MadelineProto\Lang::$current_lang['serializing_madelineproto']);
|
||||
$realpaths = new SessionPaths($filename);
|
||||
if (!\file_exists($realpaths->getLockPath())) {
|
||||
\touch($realpaths->getLockPath());
|
||||
\clearstatcache();
|
||||
}
|
||||
$lock = \fopen($realpaths->getLockPath(), 'w');
|
||||
\danog\MadelineProto\Logger::log('Waiting for exclusive lock of serialization lockfile...');
|
||||
\flock($lock, LOCK_EX);
|
||||
\danog\MadelineProto\Logger::log('Lock acquired, serializing');
|
||||
try {
|
||||
$wrote = \file_put_contents($realpaths->getTempPath(), \serialize(['event_handler' => $this->event_handler, 'event_handler_instance' => $this->event_handler_instance, 'instance_paths' => $this->instance_paths]));
|
||||
\rename($realpaths->getTempPath(), $realpaths->getSessionPath());
|
||||
} finally {
|
||||
\flock($lock, LOCK_UN);
|
||||
\fclose($lock);
|
||||
}
|
||||
$this->serialized = \time();
|
||||
return $wrote;
|
||||
}
|
||||
public $event_handler;
|
||||
private $event_handler_instance;
|
||||
private $event_handler_methods = [];
|
||||
public function getEventHandler()
|
||||
{
|
||||
return $this->event_handler_instance;
|
||||
}
|
||||
public function setEventHandler($event_handler)
|
||||
{
|
||||
if (!\class_exists($event_handler) || !\is_subclass_of($event_handler, '\\danog\\MadelineProto\\CombinedEventHandler')) {
|
||||
throw new \danog\MadelineProto\Exception('Wrong event handler was defined');
|
||||
}
|
||||
$this->event_handler = $event_handler;
|
||||
if (!$this->event_handler_instance instanceof $this->event_handler) {
|
||||
$class_name = $this->event_handler;
|
||||
$this->event_handler_instance = new $class_name($this);
|
||||
} else {
|
||||
$this->event_handler_instance->__construct($this);
|
||||
}
|
||||
$this->event_handler_methods = [];
|
||||
foreach (\get_class_methods($this->event_handler) as $method) {
|
||||
if ($method === 'onLoop') {
|
||||
$this->loop_callback = [$this->event_handler_instance, 'onLoop'];
|
||||
} elseif ($method === 'onAny') {
|
||||
foreach (\end($this->instances)->API->getTL()->getConstructors()->by_id as $constructor) {
|
||||
if ($constructor['type'] === 'Update' && !isset($this->event_handler_methods[$constructor['predicate']])) {
|
||||
$this->event_handler_methods[$constructor['predicate']] = [$this->event_handler_instance, 'onAny'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$method_name = \lcfirst(\substr($method, 2));
|
||||
$this->event_handler_methods[$method_name] = [$this->event_handler_instance, $method];
|
||||
}
|
||||
}
|
||||
}
|
||||
public function eventUpdateHandler($update, $instance)
|
||||
{
|
||||
if (isset($this->event_handler_methods[$update['_']])) {
|
||||
return $this->event_handler_methods[$update['_']]($update, $instance);
|
||||
}
|
||||
}
|
||||
private $loop_callback;
|
||||
public function async($async)
|
||||
{
|
||||
$this->async = $async;
|
||||
foreach ($this->instances as $instance) {
|
||||
$instance->async($async);
|
||||
}
|
||||
}
|
||||
public function setLoopCallback($callback)
|
||||
{
|
||||
$this->loop_callback = $callback;
|
||||
}
|
||||
public function getUpdates($params = [])
|
||||
{
|
||||
}
|
||||
public function loop($max_forks = 0)
|
||||
{
|
||||
if (\is_callable($max_forks)) {
|
||||
return \danog\MadelineProto\Tools::wait($max_forks());
|
||||
}
|
||||
$loops = [];
|
||||
foreach ($this->instances as $path => $instance) {
|
||||
\danog\MadelineProto\Tools::wait($instance->initAsynchronously());
|
||||
if ($instance->API->authorized !== MTProto::LOGGED_IN) {
|
||||
continue;
|
||||
}
|
||||
$instance->setCallback(function ($update) use ($path) {
|
||||
return $this->eventUpdateHandler($update, $path);
|
||||
}, ['async' => false]);
|
||||
if ($this->loop_callback !== null) {
|
||||
$instance->setLoopCallback($this->loop_callback, ['async' => false]);
|
||||
}
|
||||
$loops[] = \danog\MadelineProto\Tools::call($instance->loop(0, ['async' => true]));
|
||||
}
|
||||
Loop::repeat($this->serialization_interval * 1000, function () {
|
||||
\danog\MadelineProto\Logger::log('Serializing combined event handler');
|
||||
$this->serialize();
|
||||
});
|
||||
\danog\MadelineProto\Logger::log('Started update loop', \danog\MadelineProto\Logger::NOTICE);
|
||||
\danog\MadelineProto\Tools::wait(all($loops));
|
||||
}
|
||||
}
|
@ -216,7 +216,6 @@ class DataCenter
|
||||
$this->settings = $settings;
|
||||
foreach ($this->sockets as $key => $socket) {
|
||||
if ($socket instanceof DataCenterConnection && !\strpos($key, '_bk')) {
|
||||
//$this->API->logger->logger(\sprintf(Lang::$current_lang['dc_con_stop'], $key), Logger::VERBOSE);
|
||||
if ($reconnectAll || isset($changed[$id])) {
|
||||
$this->API->logger->logger("Disconnecting all before reconnect!");
|
||||
$socket->needReconnect(true);
|
||||
|
@ -5133,8 +5133,6 @@ class InternalDoc extends APIFactory
|
||||
}
|
||||
/**
|
||||
* Get logger.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getLogger(): \danog\MadelineProto\Logger
|
||||
{
|
||||
@ -5209,6 +5207,13 @@ class InternalDoc extends APIFactory
|
||||
{
|
||||
return $this->__call(__FUNCTION__, [$data, $extra]);
|
||||
}
|
||||
/**
|
||||
* Get PSR logger.
|
||||
*/
|
||||
public function getPsrLogger(): \Psr\Log\LoggerInterface
|
||||
{
|
||||
return $this->API->getPsrLogger();
|
||||
}
|
||||
/**
|
||||
* Get full info about peer (including full list of channel members), returns a Chat object.
|
||||
*
|
||||
@ -6123,14 +6128,13 @@ class InternalDoc extends APIFactory
|
||||
/**
|
||||
* Parse, update and store settings.
|
||||
*
|
||||
* @param Settings|SettingsEmpty $settings Settings
|
||||
* @param bool $reinit Whether to reinit the instance
|
||||
* @param SettingsAbstract $settings Settings
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public function updateSettings(\danog\MadelineProto\SettingsAbstract $settings, bool $reinit = true, array $extra = [])
|
||||
public function updateSettings(\danog\MadelineProto\SettingsAbstract $settings, array $extra = [])
|
||||
{
|
||||
return $this->__call(__FUNCTION__, [$settings, $reinit, $extra]);
|
||||
return $this->__call(__FUNCTION__, [$settings, $extra]);
|
||||
}
|
||||
/**
|
||||
* Upload file.
|
||||
|
@ -22,7 +22,7 @@ use danog\MadelineProto\Ipc\Server;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Magic;
|
||||
use danog\MadelineProto\SessionPaths;
|
||||
use danog\MadelineProto\Settings;
|
||||
use danog\MadelineProto\Settings\Ipc;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
(static function (): void {
|
||||
@ -97,7 +97,7 @@ use danog\MadelineProto\Tools;
|
||||
Magic::classExists();
|
||||
Magic::$script_cwd = $_GET['cwd'] ?? Magic::getcwd();
|
||||
|
||||
$API = new API($ipcPath, (new Settings)->getSerialization()->setForceFull(true));
|
||||
$API = new API($ipcPath, (new Ipc)->setForceFull(true));
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
|
@ -28,6 +28,7 @@ use danog\MadelineProto\Ipc\Runner\WebRunner;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\InternalLoop;
|
||||
use danog\MadelineProto\SessionPaths;
|
||||
use danog\MadelineProto\Settings\Ipc;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
@ -56,6 +57,10 @@ class Server extends SignalLoop
|
||||
* Callback IPC server.
|
||||
*/
|
||||
private ServerCallback $callback;
|
||||
/**
|
||||
* IPC settings.
|
||||
*/
|
||||
private Ipc $settings;
|
||||
/**
|
||||
* Set IPC path.
|
||||
*
|
||||
@ -221,4 +226,18 @@ class Server extends SignalLoop
|
||||
{
|
||||
return "IPC server";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set IPC settings.
|
||||
*
|
||||
* @param Ipc $settings IPC settings
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSettings(Ipc $settings): self
|
||||
{
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -23,27 +23,13 @@ class Lang
|
||||
'it' =>
|
||||
[
|
||||
'phpseclib_fork' => 'Per favore installa questo fork di phpseclib: https://github.com/danog/phpseclib',
|
||||
'inst_dc' => 'Istanziamento dei DataCenter...',
|
||||
'load_rsa' => 'Caricamento delle chiavi RSA...',
|
||||
'TL_translation' => 'Translazione degli schemi TL...',
|
||||
'dh_prime_check_0' => 'Esecuzione dei check dh_prime (0/3)...',
|
||||
'nearest_dc' => 'Siamo in %s, il DC più vicino è %d.',
|
||||
'serialization_ofd' => 'La serializzazione non è aggiornata, reistanziamento dell\'oggetto in corso!',
|
||||
'getupdates_deserialization' => 'Ottenimento aggiornamenti dopo deserializzazione...',
|
||||
'shutdown_reader_pool' => 'Chiusura pool di lettura, %d thread rimasti',
|
||||
'threading_on' => 'IL THREADING È ABILITATO',
|
||||
'socket_reader' => 'Lettore socket su DC %s: ',
|
||||
'socket_status_1' => 'CREAZIONE',
|
||||
'socket_status_2' => 'INVIO',
|
||||
'socket_status_3' => 'ATTESA',
|
||||
'socket_status_4' => 'PRONTO',
|
||||
'socket_status_5' => 'AVVIATO',
|
||||
'api_not_set' => 'Devi specificare una chiave ed un ID API, ottienili su https://my.telegram.org',
|
||||
'session_corrupted' => 'La sessione si è corrotta!',
|
||||
'resetSession_seqno' => 'Resettando ID sessione e numero di sequenza sul DC %s...',
|
||||
'gen_perm_auth_key' => 'Generando chiave di autorizzazione permanente per il DC %s...',
|
||||
'gen_temp_auth_key' => 'Generando chiave di autorizzazione temporanea per il DC %s...',
|
||||
'copy_auth_dcs' => 'Copiando autorizzazione dal DC %s al DC %s...',
|
||||
'write_client_info' => 'Scrittura info sul client (eseguendo nel contempo il metodo %s)...',
|
||||
'config_updated' => 'La configurazione è stata aggiornata!',
|
||||
'length_not_4' => 'La lunghezza non è uguale a 4',
|
||||
@ -57,29 +43,12 @@ class Lang
|
||||
'encode_double_error' => 'Non sono riuscito a codificare il numero a virgola mobile fornito',
|
||||
'file_not_exist' => 'Il file specificato non esiste',
|
||||
'deserialization_error' => 'C\'è stato un errore durante la deserializzazione',
|
||||
'rsa_init' => 'Istanziamento di \\tgseclib\\Crypt\\RSA in corso...',
|
||||
'loading_key' => 'Caricamento della chiave in corso...',
|
||||
'computing_fingerprint' => 'Calcolo del fingerprint in corso...',
|
||||
'rsa_encrypting' => 'Criptando con chiave RSA...',
|
||||
'rpc_tg_error' => 'Telegram ha ritornato un errore RPC: %s (%s), causato da %s:%s%sTL trace:',
|
||||
'v_error' => '506572206661766f726520616767696f726e612071756573746120696e7374616c6c617a696f6e65206469204d6164656c696e6550726f746f20636f6e206769742070756c6c206520636f6d706f73657220757064617465',
|
||||
'v_tgerror' => '506572206661766f726520616767696f726e61207068702d6c69627467766f6970',
|
||||
'no_mode_specified' => 'Nessuna modalità di logging è stata specificata!',
|
||||
'constructor_function_uncalled' => 'Il metodo costruttore non è stato ancora chiamato! Per favore chiama il metodo costruttore prima di usare questo metodo.',
|
||||
'proxy_class_invalid' => 'È stata specificata una classe proxy errata!',
|
||||
'socket_con_error' => 'Connessione fallita.',
|
||||
'protocol_not_implemented' => 'Questo protocollo non è stato ancora implementato.',
|
||||
'protocol_invalid' => 'È stato fornito un protocollo non valido',
|
||||
'nothing_in_socket' => 'Non c\'è niente nel socket!',
|
||||
'wrong_length_read' => 'ATTENZIONE: Non sono stati letti abbastanza byte (dovevo leggere %s, ho letto %s)!',
|
||||
'no_data_in_socket' => 'Non ci sono dati nel socket!',
|
||||
'dc_con_start' => 'Connessione al DC %s in corso...',
|
||||
'dc_con_stop' => 'Disconnessione dal DC %s in corso...',
|
||||
'dc_con_test_start' => 'Connessione al DC %s (server %s, %s, %s)...',
|
||||
'script_not_exist' => 'Lo script fornito non esiste',
|
||||
'apifactory_start' => 'Sto avviando la fabbrica di API...',
|
||||
'madelineproto_ready' => 'MadelineProto è pronto!',
|
||||
'logout_error' => 'C\'è stato un errore durante il logout!',
|
||||
'logout_ok' => 'Il logout è stato eseguito correttamente!',
|
||||
'already_loggedIn' => 'Questa istanza di MadelineProto è già loggata, prima faccio il logout...',
|
||||
'login_ok' => 'Il login è stato eseguito correttamente!',
|
||||
@ -96,10 +65,8 @@ class Lang
|
||||
'signing_up' => 'Mi sto registrando su telegram come utente normale...',
|
||||
'signup_ok' => 'Mi sono registrato su Telegram!',
|
||||
'2fa_uncalled' => 'Non sto aspettando la password, chiama prima le funzioni phoneLogin e completePhoneLogin!',
|
||||
'getting_dialogs' => 'Sto ottenendo la lista delle chat...',
|
||||
'libtgvoip_required' => 'È necessario installare l\'estensione php-libtgvoip per accettare e gestire chiamate vocali, vistate https://docs.madelineproto.xyz per più info.',
|
||||
'peer_not_in_db' => 'Questo utente/gruppo/canale non è presente nel database interno MadelineProto',
|
||||
'calling_user' => 'Sto chiamando %s...',
|
||||
'generating_a' => 'Sto generando a...',
|
||||
'generating_g_a' => 'Sto generando g_a...',
|
||||
'call_error_1' => 'Impossibile trovare ed accettare la chiamata %s',
|
||||
@ -135,62 +102,108 @@ class Lang
|
||||
'sec_peer_not_in_db' => 'La chat segreta non è presente nel database interno MadelineProto',
|
||||
'stream_handle_invalid' => 'Il valore fornito non è uno stream',
|
||||
'length_too_big' => 'Il valore fornito è troppo lungo',
|
||||
'deserialize_not_str' => 'Il valore generato non è una stringa',
|
||||
'type_extract_error_id' => 'Non sono riuscito ad estrarre il tipo %s con ID %s',
|
||||
'vector_invalid' => 'ID vettore non valido: ',
|
||||
'constructor_not_found' => 'Costruttore non trovato per tipo: ',
|
||||
'rand_bytes_too_small' => 'random_bytes è troppo corto!',
|
||||
'botapi_conversion_error' => 'NOn sono risucito a convertire %s in un oggetto bot API',
|
||||
'non_text_conversion' => 'Non posso ancora convertire messaggi media',
|
||||
'last_byte_invalid' => 'L\'ultimo byte non è valido',
|
||||
'file_type_invalid' => 'È stato fornito un tipo file errato',
|
||||
'recreate_temp_auth_key' => 'Sono stato costretto a rigenerare la chiave di autorizzazione temporanea',
|
||||
'resetting_auth_key' => 'ATTENZIONE: Sto resettando la chiave temporanea...',
|
||||
'shutting_down_reader_pool' => 'Chisura pool di lettura',
|
||||
'shutting_down_handler_pool' => 'Chiusura pool di gestione per DC %s, %d thread rimasti',
|
||||
'secret_chat_skipping' => 'Non ho la chat segreta %s nel database, ignorando messaggio',
|
||||
'fingerprint_mismatch' => 'Fingerprint della chiave non valido',
|
||||
'msg_data_length_too_big' => 'message_data_length è troppo grande',
|
||||
'length_not_divisible_16' => 'La lunghezza dei dati decifrati non è divisibile per 16',
|
||||
'msg_key_mismatch' => 'msg_key non valido',
|
||||
'rand_bytes_too_short' => 'random_bytes è troppo corto!',
|
||||
'resending_unsupported' => 'IL riinvio di messaggi non è ancora supportato',
|
||||
'unrecognized_dec_msg' => 'È stato ricevuto un messaggio decifrato sconosciuto: ',
|
||||
'serializing_madelineproto' => 'Sto serializzando MadelineProto...',
|
||||
'req_pq' => 'Sto richiedendo pq...',
|
||||
'done' => 'Fatto!',
|
||||
'cdn_reupload' => 'Il file non è disponibile sul nostro CDN, richiedo la copia!',
|
||||
'stored_on_cdn' => 'Il file è scaricabile tramite CDN!',
|
||||
'apiAppInstructionsAuto0' => 'Inserisci il nome dell\'app, può essere qualsiasi cosa: ',
|
||||
'apiAppInstructionsAuto1' => 'Inserisci il nome ridotto dell\'app, caratteri alfanumerici: ',
|
||||
'apiAppInstructionsAuto2' => 'Inserisci il sito internet dell\'app, oppure t.me/username: ',
|
||||
'apiAppInstructionsAuto3' => 'Inserisci la piattaforma dell\'app: ',
|
||||
'apiAppInstructionsAuto4' => 'Descrivi la tua app: ',
|
||||
'apiAppInstructionsManual0' => 'titolo dell\'app, può essere qualsiasi cosa',
|
||||
'apiAppInstructionsManual1' => 'il nome ridotto dell\'app, caratteri alfanumerici: ',
|
||||
'apiAppInstructionsManual2' => '',
|
||||
'apiAppInstructionsManual3' => '',
|
||||
'apiAppInstructionsManual4' => '',
|
||||
'apiAutoPrompt0' => '',
|
||||
'apiAutoPrompt1' => '',
|
||||
'apiChooseManualAuto' => '',
|
||||
'apiChooseManualAutoTip' => '',
|
||||
'apiChoosePrompt' => '',
|
||||
'apiError' => '',
|
||||
'apiManualInstructions0' => '',
|
||||
'apiManualInstructions1' => '',
|
||||
'apiManualInstructions2' => '',
|
||||
'apiManualPrompt0' => '',
|
||||
'apiManualPrompt1' => '',
|
||||
'apiParamsError' => '',
|
||||
'loginBot' => '',
|
||||
'loginChoosePrompt' => '',
|
||||
'loginNoCode' => '',
|
||||
'loginNoName' => '',
|
||||
'loginNoPass' => '',
|
||||
'loginUser' => '',
|
||||
'loginUser2FA' => '',
|
||||
'loginUser2FAHint' => '',
|
||||
'loginUser2FAWeb' => '',
|
||||
'loginUserCode' => '',
|
||||
'signupFirstName' => '',
|
||||
'signupFirstNameWeb' => '',
|
||||
'signupLastName' => '',
|
||||
'signupLastNameWeb' => '',
|
||||
'signupWeb' => '',
|
||||
],
|
||||
'en' =>
|
||||
[
|
||||
'req_pq' => 'Requesting pq...',
|
||||
'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)',
|
||||
'apiChooseManualAutoTip' => 'Note that you can also provide the API parameters directly in the code using the settings: %s',
|
||||
'apiChoosePrompt' => 'Your choice (m/a): ',
|
||||
'apiManualInstructions0' => 'Login to my.telegram.org',
|
||||
'apiManualInstructions1' => 'Go to API development tools',
|
||||
'apiManualInstructions2' => 'Click on create application',
|
||||
'apiAppInstructionsManual0' => 'your app\'s name, can be anything',
|
||||
'apiAppInstructionsManual1' => 'your app\'s short name, alphanumeric',
|
||||
'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername',
|
||||
'apiAppInstructionsManual3' => 'anything',
|
||||
'apiAppInstructionsManual4' => 'Describe your app here',
|
||||
'apiManualPrompt0' => 'Enter your API ID: ',
|
||||
'apiManualPrompt1' => 'Enter your API hash: ',
|
||||
'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ',
|
||||
'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ',
|
||||
'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ',
|
||||
'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ',
|
||||
'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ',
|
||||
'apiAppInstructionsAuto3' => 'Enter the app platform: ',
|
||||
'apiAppInstructionsAuto4' => 'Describe your app: ',
|
||||
'apiParamsError' => 'You didn\'t provide all of the required parameters!',
|
||||
'apiError' => 'ERROR: %s. Try again.',
|
||||
'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ',
|
||||
'loginBot' => 'Enter your bot token: ',
|
||||
'loginUser' => 'Enter your phone number: ',
|
||||
'loginUserCode' => 'Enter the phone code: ',
|
||||
'loginUser2FA' => 'Enter your password (hint %s): ',
|
||||
'loginUser2FAWeb' => 'Enter your password: ',
|
||||
'loginUser2FAHint' => 'Hint: %s',
|
||||
'signupFirstName' => 'Enter your first name: ',
|
||||
'signupLastName' => 'Enter your last name (can be empty): ',
|
||||
'signupWeb' => 'Sign up please',
|
||||
'signupFirstNameWeb' => 'First name',
|
||||
'signupLastNameWeb' => 'Last name',
|
||||
'loginNoCode' => 'You didn\'t provide a phone code!',
|
||||
'loginNoPass' => 'You didn\'t provide the password!',
|
||||
'loginNoName' => 'You didn\'t provide the first name!',
|
||||
'done' => 'Done!',
|
||||
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
|
||||
'stored_on_cdn' => 'File is stored on CDN!',
|
||||
'serializing_madelineproto' => 'Serializing MadelineProto...',
|
||||
'phpseclib_fork' => 'Please install this fork of phpseclib: https://github.com/danog/phpseclib',
|
||||
'inst_dc' => 'Istantiating DataCenter...',
|
||||
'load_rsa' => 'Loading RSA keys...',
|
||||
'TL_translation' => 'Translating TL schemas...',
|
||||
'dh_prime_check_0' => 'Executing dh_prime checks (0/3)...',
|
||||
'nearest_dc' => 'We\'re in %s, nearest DC is %d.',
|
||||
'serialization_ofd' => 'Serialization is out of date, reconstructing object!',
|
||||
'getupdates_deserialization' => 'Getting updates after deserialization...',
|
||||
'shutdown_reader_pool' => 'Shutting down reader pool, %d jobs left',
|
||||
'threading_on' => 'THREADING IS ENABLED',
|
||||
'socket_reader' => 'Socket reader on DC %s: ',
|
||||
'socket_status_1' => 'CREATING',
|
||||
'socket_status_2' => 'SUBMITTING',
|
||||
'socket_status_3' => 'WAITING',
|
||||
'socket_status_4' => 'READY',
|
||||
'socket_status_5' => 'WORKING',
|
||||
'api_not_set' => 'You must provide an api key and an api id, get your own @ my.telegram.org',
|
||||
'session_corrupted' => 'The session is corrupted!',
|
||||
'resetSession_seqno' => 'Resetting session id and seq_no in DC %s...',
|
||||
'gen_perm_auth_key' => 'Generating permanent authorization key for DC %s...',
|
||||
'gen_temp_auth_key' => 'Generating temporary authorization key for DC %s...',
|
||||
'copy_auth_dcs' => 'Copying authorization from DC %s to DC %s...',
|
||||
'write_client_info' => 'Writing client info (also executing %s)...',
|
||||
'config_updated' => 'Updated config!',
|
||||
'length_not_4' => 'Length is not equal to 4',
|
||||
@ -204,29 +217,12 @@ class Lang
|
||||
'encode_double_error' => 'Could not properly encode double',
|
||||
'file_not_exist' => 'File does not exist',
|
||||
'deserialization_error' => 'An error occurred on deserialization',
|
||||
'rsa_init' => 'Istantiating \\tgseclib\\Crypt\\RSA...',
|
||||
'loading_key' => 'Loading key...',
|
||||
'computing_fingerprint' => 'Computing fingerprint...',
|
||||
'rsa_encrypting' => 'Encrypting with rsa key...',
|
||||
'rpc_tg_error' => 'Telegram returned an RPC error: %s (%s), caused by %s:%s%sTL trace:',
|
||||
'v_error' => '506c656173652075706461746520746f20746865206c61746573742076657273696f6e206f66204d6164656c696e6550726f746f2e',
|
||||
'v_tgerror' => '506c6561736520757064617465207068702d6c69627467766f6970',
|
||||
'no_mode_specified' => 'No mode was specified!',
|
||||
'constructor_function_uncalled' => 'The constructor function wasn\'t called! Please call the constructor function before using this method.',
|
||||
'proxy_class_invalid' => 'Invalid proxy class provided!',
|
||||
'socket_con_error' => 'Connection: couldn\'t connect to socket.',
|
||||
'protocol_not_implemented' => 'Connection: This protocol isn\'t implemented yet.',
|
||||
'protocol_invalid' => 'Connection: invalid protocol specified.',
|
||||
'nothing_in_socket' => 'Nothing in the socket!',
|
||||
'wrong_length_read' => 'WARNING: Wrong length was read (should\'ve read %s, read %s)!',
|
||||
'no_data_in_socket' => 'No data in the socket!',
|
||||
'dc_con_start' => 'Connecting to DC %s...',
|
||||
'dc_con_stop' => 'Disconnecting from DC %s...',
|
||||
'dc_con_test_start' => 'Connecting to DC %s (%s server, %s, %s)...',
|
||||
'script_not_exist' => 'Provided script does not exist',
|
||||
'apifactory_start' => 'Running APIFactory...',
|
||||
'madelineproto_ready' => 'MadelineProto is ready!',
|
||||
'logout_error' => 'An error occurred while logging out!',
|
||||
'logout_ok' => 'Logged out successfully!',
|
||||
'already_loggedIn' => 'This instance of MadelineProto is already logged in. Logging out first...',
|
||||
'login_ok' => 'Logged in successfully!',
|
||||
@ -243,10 +239,8 @@ class Lang
|
||||
'signing_up' => 'Signing up as a normal user...',
|
||||
'signup_ok' => 'Signed up in successfully!',
|
||||
'2fa_uncalled' => 'I\'m not waiting for the password! Please call the phoneLogin and the completePhoneLogin methods first!',
|
||||
'getting_dialogs' => 'Getting dialogs...',
|
||||
'libtgvoip_required' => 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.',
|
||||
'peer_not_in_db' => 'This peer is not present in the internal peer database',
|
||||
'calling_user' => 'Calling %s...',
|
||||
'generating_a' => 'Generating a...',
|
||||
'generating_g_a' => 'Generating g_a...',
|
||||
'call_error_1' => 'Could not find and accept call %s',
|
||||
@ -276,65 +270,76 @@ class Lang
|
||||
'long_not_64' => 'Given value is not 64 bytes long',
|
||||
'array_invalid' => 'You didn\'t provide a valid array',
|
||||
'predicate_not_set' => 'Predicate (value under _) was not set!',
|
||||
'type_extract_error' => 'Could not extract type "%s"',
|
||||
'type_extract_error' => 'Could not extract type "%s", you should update MadelineProto!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'params_missing' => 'Missing required parameter',
|
||||
'sec_peer_not_in_db' => 'This secret peer is not present in the internal peer database',
|
||||
'stream_handle_invalid' => 'An invalid stream handle was provided.',
|
||||
'length_too_big' => 'Length is too big',
|
||||
'deserialize_not_str' => 'Deserialize: Generated value isn\'t a string',
|
||||
'type_extract_error_id' => 'Could not extract type: %s with id %s',
|
||||
'vector_invalid' => 'Invalid vector constructor: ',
|
||||
'type_extract_error_id' => 'Could not extract type: %s with id %s, you should update MadelineProto!',
|
||||
'constructor_not_found' => 'Constructor not found for type: ',
|
||||
'rand_bytes_too_small' => 'Random_bytes is too small!',
|
||||
'botapi_conversion_error' => 'Can\'t convert %s to a bot API object',
|
||||
'non_text_conversion' => 'Can\'t convert non text messages yet!',
|
||||
'last_byte_invalid' => 'Invalid last byte',
|
||||
'file_type_invalid' => 'Invalid file type detected (%s)',
|
||||
'recreate_temp_auth_key' => 'I had to recreate the temporary authorization key',
|
||||
'resetting_auth_key' => 'WARNING: Resetting auth key...',
|
||||
'shutting_down_reader_pool' => 'Shutting down reader pool ',
|
||||
'shutting_down_handler_pool' => 'Shutting down handler pool for dc %s, %d jobs left',
|
||||
'secret_chat_skipping' => 'I do not have the secret chat %s in the database, skipping message...',
|
||||
'fingerprint_mismatch' => 'Key fingerprint mismatch',
|
||||
'msg_data_length_too_big' => 'Message_data_length is too big',
|
||||
'length_not_divisible_16' => 'Length of decrypted data is not divisible by 16',
|
||||
'msg_key_mismatch' => 'Msg_key mismatch',
|
||||
'rand_bytes_too_short' => 'Random_bytes is too short!',
|
||||
'resending_unsupported' => 'Resending of messages is not yet supported',
|
||||
'unrecognized_dec_msg' => 'Unrecognized decrypted message received: ',
|
||||
],
|
||||
];
|
||||
|
||||
// THIS WILL BE OVERWRITTEN BY $lang["en"]
|
||||
public static $current_lang = [
|
||||
'req_pq' => 'Requesting pq...',
|
||||
'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)',
|
||||
'apiChooseManualAutoTip' => 'Note that you can also provide the API parameters directly in the code using the settings: %s',
|
||||
'apiChoosePrompt' => 'Your choice (m/a): ',
|
||||
'apiManualInstructions0' => 'Login to my.telegram.org',
|
||||
'apiManualInstructions1' => 'Go to API development tools',
|
||||
'apiManualInstructions2' => 'Click on create application',
|
||||
'apiAppInstructionsManual0' => 'your app\'s name, can be anything',
|
||||
'apiAppInstructionsManual1' => 'your app\'s short name, alphanumeric',
|
||||
'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername',
|
||||
'apiAppInstructionsManual3' => 'anything',
|
||||
'apiAppInstructionsManual4' => 'Describe your app here',
|
||||
'apiManualPrompt0' => 'Enter your API ID: ',
|
||||
'apiManualPrompt1' => 'Enter your API hash: ',
|
||||
'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ',
|
||||
'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ',
|
||||
'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ',
|
||||
'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ',
|
||||
'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ',
|
||||
'apiAppInstructionsAuto3' => 'Enter the app platform: ',
|
||||
'apiAppInstructionsAuto4' => 'Describe your app: ',
|
||||
'apiParamsError' => 'You didn\'t provide all of the required parameters!',
|
||||
'apiError' => 'ERROR: %s. Try again.',
|
||||
'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ',
|
||||
'loginBot' => 'Enter your bot token: ',
|
||||
'loginUser' => 'Enter your phone number: ',
|
||||
'loginUserCode' => 'Enter the phone code: ',
|
||||
'loginUser2FA' => 'Enter your password (hint %s): ',
|
||||
'loginUser2FAWeb' => 'Enter your password: ',
|
||||
'loginUser2FAHint' => 'Hint: %s',
|
||||
'signupFirstName' => 'Enter your first name: ',
|
||||
'signupLastName' => 'Enter your last name (can be empty): ',
|
||||
'signupWeb' => 'Sign up please',
|
||||
'signupFirstNameWeb' => 'First name',
|
||||
'signupLastNameWeb' => 'Last name',
|
||||
'loginNoCode' => 'You didn\'t provide a phone code!',
|
||||
'loginNoPass' => 'You didn\'t provide the password!',
|
||||
'loginNoName' => 'You didn\'t provide the first name!',
|
||||
'done' => 'Done!',
|
||||
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
|
||||
'stored_on_cdn' => 'File is stored on CDN!',
|
||||
'serializing_madelineproto' => 'Serializing MadelineProto...',
|
||||
'phpseclib_fork' => 'Please install this fork of phpseclib: https://github.com/danog/phpseclib',
|
||||
'inst_dc' => 'Istantiating DataCenter...',
|
||||
'load_rsa' => 'Loading RSA keys...',
|
||||
'TL_translation' => 'Translating TL schemas...',
|
||||
'dh_prime_check_0' => 'Executing dh_prime checks (0/3)...',
|
||||
'nearest_dc' => 'We\'re in %s, nearest DC is %d.',
|
||||
'serialization_ofd' => 'Serialization is out of date, reconstructing object!',
|
||||
'getupdates_deserialization' => 'Getting updates after deserialization...',
|
||||
'shutdown_reader_pool' => 'Shutting down reader pool, %d jobs left',
|
||||
'threading_on' => 'THREADING IS ENABLED',
|
||||
'socket_reader' => 'Socket reader on DC %s: ',
|
||||
'socket_status_1' => 'CREATING',
|
||||
'socket_status_2' => 'SUBMITTING',
|
||||
'socket_status_3' => 'WAITING',
|
||||
'socket_status_4' => 'READY',
|
||||
'socket_status_5' => 'WORKING',
|
||||
'api_not_set' => 'You must provide an api key and an api id, get your own @ my.telegram.org',
|
||||
'session_corrupted' => 'The session is corrupted!',
|
||||
'resetSession_seqno' => 'Resetting session id and seq_no in DC %s...',
|
||||
'gen_perm_auth_key' => 'Generating permanent authorization key for DC %s...',
|
||||
'gen_temp_auth_key' => 'Generating temporary authorization key for DC %s...',
|
||||
'copy_auth_dcs' => 'Copying authorization from DC %s to DC %s...',
|
||||
'write_client_info' => 'Writing client info (also executing %s)...',
|
||||
'config_updated' => 'Updated config!',
|
||||
'length_not_4' => 'Length is not equal to 4',
|
||||
@ -348,29 +353,12 @@ class Lang
|
||||
'encode_double_error' => 'Could not properly encode double',
|
||||
'file_not_exist' => 'File does not exist',
|
||||
'deserialization_error' => 'An error occurred on deserialization',
|
||||
'rsa_init' => 'Istantiating \\tgseclib\\Crypt\\RSA...',
|
||||
'loading_key' => 'Loading key...',
|
||||
'computing_fingerprint' => 'Computing fingerprint...',
|
||||
'rsa_encrypting' => 'Encrypting with rsa key...',
|
||||
'rpc_tg_error' => 'Telegram returned an RPC error: %s (%s), caused by %s:%s%sTL trace:',
|
||||
'v_error' => '506c656173652075706461746520746f20746865206c61746573742076657273696f6e206f66204d6164656c696e6550726f746f2e',
|
||||
'v_tgerror' => '506c6561736520757064617465207068702d6c69627467766f6970',
|
||||
'no_mode_specified' => 'No mode was specified!',
|
||||
'constructor_function_uncalled' => 'The constructor function wasn\'t called! Please call the constructor function before using this method.',
|
||||
'proxy_class_invalid' => 'Invalid proxy class provided!',
|
||||
'socket_con_error' => 'Connection: couldn\'t connect to socket.',
|
||||
'protocol_not_implemented' => 'Connection: This protocol isn\'t implemented yet.',
|
||||
'protocol_invalid' => 'Connection: invalid protocol specified.',
|
||||
'nothing_in_socket' => 'Nothing in the socket!',
|
||||
'wrong_length_read' => 'WARNING: Wrong length was read (should\'ve read %s, read %s)!',
|
||||
'no_data_in_socket' => 'No data in the socket!',
|
||||
'dc_con_start' => 'Connecting to DC %s...',
|
||||
'dc_con_stop' => 'Disconnecting from DC %s...',
|
||||
'dc_con_test_start' => 'Connecting to DC %s (%s server, %s, %s)...',
|
||||
'script_not_exist' => 'Provided script does not exist',
|
||||
'apifactory_start' => 'Running APIFactory...',
|
||||
'madelineproto_ready' => 'MadelineProto is ready!',
|
||||
'logout_error' => 'An error occurred while logging out!',
|
||||
'logout_ok' => 'Logged out successfully!',
|
||||
'already_loggedIn' => 'This instance of MadelineProto is already logged in. Logging out first...',
|
||||
'login_ok' => 'Logged in successfully!',
|
||||
@ -387,10 +375,8 @@ class Lang
|
||||
'signing_up' => 'Signing up as a normal user...',
|
||||
'signup_ok' => 'Signed up in successfully!',
|
||||
'2fa_uncalled' => 'I\'m not waiting for the password! Please call the phoneLogin and the completePhoneLogin methods first!',
|
||||
'getting_dialogs' => 'Getting dialogs...',
|
||||
'libtgvoip_required' => 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.',
|
||||
'peer_not_in_db' => 'This peer is not present in the internal peer database',
|
||||
'calling_user' => 'Calling %s...',
|
||||
'generating_a' => 'Generating a...',
|
||||
'generating_g_a' => 'Generating g_a...',
|
||||
'call_error_1' => 'Could not find and accept call %s',
|
||||
@ -420,32 +406,22 @@ class Lang
|
||||
'long_not_64' => 'Given value is not 64 bytes long',
|
||||
'array_invalid' => 'You didn\'t provide a valid array',
|
||||
'predicate_not_set' => 'Predicate (value under _) was not set!',
|
||||
'type_extract_error' => 'Could not extract type "%s"',
|
||||
'type_extract_error' => 'Could not extract type "%s", you should update MadelineProto!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'params_missing' => 'Missing required parameter',
|
||||
'sec_peer_not_in_db' => 'This secret peer is not present in the internal peer database',
|
||||
'stream_handle_invalid' => 'An invalid stream handle was provided.',
|
||||
'length_too_big' => 'Length is too big',
|
||||
'deserialize_not_str' => 'Deserialize: Generated value isn\'t a string',
|
||||
'type_extract_error_id' => 'Could not extract type: %s with id %s',
|
||||
'vector_invalid' => 'Invalid vector constructor: ',
|
||||
'type_extract_error_id' => 'Could not extract type: %s with id %s, you should update MadelineProto!',
|
||||
'constructor_not_found' => 'Constructor not found for type: ',
|
||||
'rand_bytes_too_small' => 'Random_bytes is too small!',
|
||||
'botapi_conversion_error' => 'Can\'t convert %s to a bot API object',
|
||||
'non_text_conversion' => 'Can\'t convert non text messages yet!',
|
||||
'last_byte_invalid' => 'Invalid last byte',
|
||||
'file_type_invalid' => 'Invalid file type detected (%s)',
|
||||
'recreate_temp_auth_key' => 'I had to recreate the temporary authorization key',
|
||||
'resetting_auth_key' => 'WARNING: Resetting auth key...',
|
||||
'shutting_down_reader_pool' => 'Shutting down reader pool ',
|
||||
'shutting_down_handler_pool' => 'Shutting down handler pool for dc %s, %d jobs left',
|
||||
'secret_chat_skipping' => 'I do not have the secret chat %s in the database, skipping message...',
|
||||
'fingerprint_mismatch' => 'Key fingerprint mismatch',
|
||||
'msg_data_length_too_big' => 'Message_data_length is too big',
|
||||
'length_not_divisible_16' => 'Length of decrypted data is not divisible by 16',
|
||||
'msg_key_mismatch' => 'Msg_key mismatch',
|
||||
'rand_bytes_too_short' => 'Random_bytes is too short!',
|
||||
'resending_unsupported' => 'Resending of messages is not yet supported',
|
||||
'unrecognized_dec_msg' => 'Unrecognized decrypted message received: ',
|
||||
];
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use Amp\ByteStream\ResourceOutputStream;
|
||||
use Amp\Failure;
|
||||
use Amp\Loop;
|
||||
use danog\MadelineProto\Settings\Logger as SettingsLogger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function Amp\ByteStream\getStderr;
|
||||
use function Amp\ByteStream\getStdout;
|
||||
@ -94,6 +95,10 @@ class Logger
|
||||
* Log rotation loop ID.
|
||||
*/
|
||||
private string $rotateId = '';
|
||||
/**
|
||||
* PSR logger.
|
||||
*/
|
||||
private PsrLogger $psr;
|
||||
/**
|
||||
* Ultra verbose logging.
|
||||
*/
|
||||
@ -171,6 +176,7 @@ class Logger
|
||||
*/
|
||||
public function __construct(SettingsLogger $settings, string $prefix = '')
|
||||
{
|
||||
$this->psr = new PsrLogger($this);
|
||||
$this->prefix = $prefix === '' ? '' : ', '.$prefix;
|
||||
|
||||
$this->mode = $settings->getType();
|
||||
@ -237,7 +243,7 @@ class Logger
|
||||
if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
|
||||
try {
|
||||
\error_reporting(E_ALL);
|
||||
\ini_set('log_errors', 1);
|
||||
\ini_set('log_errors', "1");
|
||||
\ini_set('error_log', $this->mode === self::FILE_LOGGER
|
||||
? $this->optional
|
||||
: Magic::$script_cwd.'/MadelineProto.log');
|
||||
@ -327,4 +333,14 @@ class Logger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PSR logger.
|
||||
*
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getPsrLogger(): LoggerInterface
|
||||
{
|
||||
return $this->psr;
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ use danog\MadelineProto\Settings\Database\Memory;
|
||||
use danog\MadelineProto\Settings\TLSchema;
|
||||
use danog\MadelineProto\TL\TL;
|
||||
use danog\MadelineProto\TL\TLCallback;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function Amp\File\exists;
|
||||
use function Amp\File\size;
|
||||
@ -532,19 +533,16 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
// Initialize needed stuffs
|
||||
Magic::classExists();
|
||||
// Parse and store settings
|
||||
yield from $this->updateSettings($settings, false);
|
||||
$this->updateSettingsInternal($settings);
|
||||
// Actually instantiate needed classes like a boss
|
||||
$this->logger->logger(Lang::$current_lang['inst_dc'], Logger::ULTRA_VERBOSE);
|
||||
yield from $this->cleanupProperties();
|
||||
// Load rsa keys
|
||||
$this->logger->logger(Lang::$current_lang['load_rsa'], Logger::ULTRA_VERBOSE);
|
||||
$this->rsa_keys = [];
|
||||
foreach ($this->settings->getAuth()->getRsaKeys() as $key) {
|
||||
$key = (yield from (new RSA())->load($this->TL, $key));
|
||||
$this->rsa_keys[$key->fp] = $key;
|
||||
}
|
||||
// (re)-initialize TL
|
||||
$this->logger->logger(Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE);
|
||||
$callbacks = [$this, $this->referenceDatabase];
|
||||
if (!($this->authorization['user']['bot'] ?? false)) {
|
||||
$callbacks[] = $this->minDatabase;
|
||||
@ -570,6 +568,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$this->startUpdateSystem(true);
|
||||
$this->v = self::V;
|
||||
|
||||
$this->settings->applyChanges();
|
||||
GarbageCollector::start();
|
||||
}
|
||||
/**
|
||||
@ -734,13 +733,18 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
}
|
||||
/**
|
||||
* Get logger.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getLogger(): Logger
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
/**
|
||||
* Get PSR logger.
|
||||
*/
|
||||
public function getPsrLogger(): LoggerInterface
|
||||
{
|
||||
return $this->logger->getPsrLogger();
|
||||
}
|
||||
/**
|
||||
* Get async HTTP client.
|
||||
*
|
||||
@ -828,6 +832,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
}
|
||||
if (!$this->ipcServer) {
|
||||
$this->ipcServer = new Server($this);
|
||||
$this->ipcServer->setSettings($this->settings->getIpc());
|
||||
$this->ipcServer->setIpcPath($this->wrapper->session);
|
||||
}
|
||||
$this->callCheckerLoop->start();
|
||||
@ -933,7 +938,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
}
|
||||
if (!isset($this->TL)) {
|
||||
$this->TL = new TL($this);
|
||||
$this->logger->logger(Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE);
|
||||
$callbacks = [$this, $this->referenceDatabase];
|
||||
if (!($this->authorization['user']['bot'] ?? false)) {
|
||||
$callbacks[] = $this->minDatabase;
|
||||
@ -1075,7 +1079,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
// Reset MTProto session (not related to user session)
|
||||
$this->resetMTProtoSession();
|
||||
// Update settings from constructor
|
||||
yield from $this->updateSettings($settings, false);
|
||||
$this->updateSettingsInternal($settings);
|
||||
// Session update process for BC
|
||||
$forceDialogs = false;
|
||||
if (!isset($this->v)
|
||||
@ -1178,12 +1182,40 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
/**
|
||||
* Parse, update and store settings.
|
||||
*
|
||||
* @param Settings|SettingsEmpty $settings Settings
|
||||
* @param bool $reinit Whether to reinit the instance
|
||||
* @param SettingsAbstract $settings Settings
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public function updateSettings(SettingsAbstract $settings, bool $reinit = true): \Generator
|
||||
public function updateSettings(SettingsAbstract $settings): \Generator
|
||||
{
|
||||
$this->updateSettingsInternal($settings);
|
||||
|
||||
if ($this->settings->getDb()->hasChanged()) {
|
||||
yield from $this->initDb($this);
|
||||
$this->settings->getDb()->applyChanges();
|
||||
}
|
||||
if ($this->settings->getIpc()->hasChanged()) {
|
||||
$this->ipcServer->setSettings($this->settings->getIpc()->applyChanges());
|
||||
}
|
||||
if ($this->settings->getSerialization()->hasChanged()) {
|
||||
$this->serializeLoop->signal(true);
|
||||
$this->serializeLoop = new PeriodicLoopInternal($this, [$this, 'serialize'], 'serialize', $this->settings->getSerialization()->applyChanges()->getInterval() * 1000);
|
||||
}
|
||||
if ($this->settings->getAuth()->hasChanged()
|
||||
|| $this->settings->getConnection()->hasChanged()
|
||||
|| $this->settings->getSchema()->hasChanged()
|
||||
|| $this->settings->getSchema()->needsUpgrade()) {
|
||||
yield from $this->__construct_async($this->settings);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parse, update and store settings.
|
||||
*
|
||||
* @param SettingsAbstract $settings Settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateSettingsInternal(SettingsAbstract $settings): void
|
||||
{
|
||||
if ($settings instanceof SettingsEmpty) {
|
||||
if (!isset($this->settings)) {
|
||||
@ -1208,10 +1240,8 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
}
|
||||
|
||||
// Setup logger
|
||||
if ($this->settings->getLogger()->hasChanged() || !$this->logger) {
|
||||
$this->setupLogger();
|
||||
|
||||
if ($reinit) {
|
||||
yield from $this->__construct_async($this->settings);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -69,7 +69,7 @@ trait AuthKeyHandler
|
||||
$req_pq = $cdn ? 'req_pq' : 'req_pq_multi';
|
||||
for ($retry_id_total = 1; $retry_id_total <= $this->settings->getAuth()->getMaxAuthTries(); $retry_id_total++) {
|
||||
try {
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['req_pq'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->logger->logger("Requesting pq...", \danog\MadelineProto\Logger::VERBOSE);
|
||||
/**
|
||||
* ***********************************************************************
|
||||
* Make pq request, DH exchange initiation.
|
||||
|
48
src/danog/MadelineProto/PsrLogger.php
Normal file
48
src/danog/MadelineProto/PsrLogger.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Psr\Log\AbstractLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class PsrLogger extends AbstractLogger
|
||||
{
|
||||
private const LEVEL_MAP = [
|
||||
LogLevel::EMERGENCY => Logger::LEVEL_FATAL,
|
||||
LogLevel::ALERT => Logger::LEVEL_FATAL,
|
||||
LogLevel::CRITICAL => Logger::LEVEL_FATAL,
|
||||
LogLevel::ERROR => Logger::LEVEL_ERROR,
|
||||
LogLevel::WARNING => Logger::LEVEL_WARNING,
|
||||
LogLevel::NOTICE => Logger::LEVEL_NOTICE,
|
||||
LogLevel::INFO => Logger::LEVEL_VERBOSE,
|
||||
LogLevel::DEBUG => Logger::LEVEL_ULTRA_VERBOSE
|
||||
];
|
||||
/**
|
||||
* Logger.
|
||||
*/
|
||||
private Logger $logger;
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Logger $logger
|
||||
*/
|
||||
public function __construct(Logger $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param mixed[] $context
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Psr\Log\InvalidArgumentException
|
||||
*/
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
$this->logger->logger($message, self::LEVEL_MAP[$level]);
|
||||
}
|
||||
}
|
@ -55,12 +55,9 @@ class RSA
|
||||
*/
|
||||
public function load(TL $TL, string $rsa_key): \Generator
|
||||
{
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['rsa_init'], Logger::ULTRA_VERBOSE);
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['loading_key'], Logger::ULTRA_VERBOSE);
|
||||
$key = \tgseclib\Crypt\RSA::load($rsa_key);
|
||||
$this->n = Tools::getVar($key, 'modulus');
|
||||
$this->e = Tools::getVar($key, 'exponent');
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['computing_fingerprint'], Logger::ULTRA_VERBOSE);
|
||||
$this->fp = \substr(\sha1((yield from $TL->serializeObject(['type' => 'bytes'], $this->n->toBytes(), 'key')).(yield from $TL->serializeObject(['type' => 'bytes'], $this->e->toBytes(), 'key')), true), -8);
|
||||
return $this;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ trait MessageHandler
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
||||
}
|
||||
if ($message_key != \substr(\sha1(\substr($decrypted_data, 0, 4 + $message_data_length), true), -16)) {
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
||||
throw new \danog\MadelineProto\SecurityException('Msg_key mismatch');
|
||||
}
|
||||
if (\strlen($decrypted_data) - 4 - $message_data_length > 15) {
|
||||
throw new \danog\MadelineProto\SecurityException('difference between message_data_length and the length of the remaining decrypted buffer is too big');
|
||||
@ -155,7 +155,7 @@ trait MessageHandler
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
|
||||
}
|
||||
if ($message_key != \substr(\hash('sha256', \substr($this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 8 : 0), 32).$decrypted_data, true), 8, 16)) {
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_key_mismatch']);
|
||||
throw new \danog\MadelineProto\SecurityException('Msg_key mismatch');
|
||||
}
|
||||
if (\strlen($decrypted_data) - 4 - $message_data_length < 12) {
|
||||
throw new \danog\MadelineProto\SecurityException('padding is too small');
|
||||
|
@ -26,9 +26,6 @@ trait ResponseHandler
|
||||
{
|
||||
private function handleDecryptedUpdate($update): \Generator
|
||||
{
|
||||
/*if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) {
|
||||
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_short']);
|
||||
}*/
|
||||
// already checked in TL.php
|
||||
switch ($update['message']['decrypted_message']['_']) {
|
||||
case 'decryptedMessageService':
|
||||
@ -92,7 +89,7 @@ trait ResponseHandler
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['unrecognized_dec_msg'].\var_export($update, true));
|
||||
throw new \danog\MadelineProto\ResponseException('Unrecognized decrypted message received: '.\var_export($update, true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use danog\MadelineProto\Settings\Database\Postgres;
|
||||
use danog\MadelineProto\Settings\Database\Redis;
|
||||
use danog\MadelineProto\Settings\DatabaseAbstract;
|
||||
use danog\MadelineProto\Settings\Files;
|
||||
use danog\MadelineProto\Settings\Ipc;
|
||||
use danog\MadelineProto\Settings\Logger;
|
||||
use danog\MadelineProto\Settings\Peer;
|
||||
use danog\MadelineProto\Settings\Pwr;
|
||||
@ -37,6 +38,10 @@ class Settings extends SettingsAbstract
|
||||
* File management settings.
|
||||
*/
|
||||
protected Files $files;
|
||||
/**
|
||||
* IPC server settings.
|
||||
*/
|
||||
protected Ipc $ipc;
|
||||
/**
|
||||
* Logger settings.
|
||||
*/
|
||||
@ -106,6 +111,7 @@ class Settings extends SettingsAbstract
|
||||
$this->serialization = new Serialization;
|
||||
$this->schema = new TLSchema;
|
||||
$this->db = new DatabaseMemory;
|
||||
$this->ipc = new IPc;
|
||||
}
|
||||
/**
|
||||
* Merge legacy array settings.
|
||||
@ -177,6 +183,8 @@ class Settings extends SettingsAbstract
|
||||
$this->serialization->merge($settings);
|
||||
} elseif ($settings instanceof TLSchema) {
|
||||
$this->schema->merge($settings);
|
||||
} elseif ($settings instanceof Ipc) {
|
||||
$this->ipc->merge($settings);
|
||||
} elseif ($settings instanceof DatabaseAbstract) {
|
||||
if (!$this->db instanceof $settings) {
|
||||
$this->db = $settings;
|
||||
@ -197,6 +205,7 @@ class Settings extends SettingsAbstract
|
||||
$this->secretChats->merge($settings->secretChats);
|
||||
$this->serialization->merge($settings->serialization);
|
||||
$this->schema->merge($settings->schema);
|
||||
$this->ipc->merge($settings->ipc);
|
||||
|
||||
if (!$this->db instanceof $settings->db) {
|
||||
$this->db = $settings->db;
|
||||
@ -524,4 +533,36 @@ class Settings extends SettingsAbstract
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IPC server settings.
|
||||
*
|
||||
* @return Ipc
|
||||
*/
|
||||
public function getIpc(): Ipc
|
||||
{
|
||||
return $this->ipc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set IPC server settings.
|
||||
*
|
||||
* @param Ipc $ipc IPC server settings.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setIpc(Ipc $ipc): self
|
||||
{
|
||||
$this->ipc = $ipc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function applyChanges(): SettingsAbstract
|
||||
{
|
||||
foreach (\get_object_vars($this) as $setting) {
|
||||
$setting->applyChanges();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
43
src/danog/MadelineProto/Settings/Ipc.php
Normal file
43
src/danog/MadelineProto/Settings/Ipc.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Settings;
|
||||
|
||||
use danog\MadelineProto\SettingsAbstract;
|
||||
|
||||
class Ipc extends SettingsAbstract
|
||||
{
|
||||
/**
|
||||
* Whether to force full deserialization of instance, without using the IPC server/client.
|
||||
*
|
||||
* WARNING: this will cause slow startup if enabled.
|
||||
*/
|
||||
protected bool $forceFull = false;
|
||||
|
||||
public function mergeArray(array $settings): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getForceFull(): bool
|
||||
{
|
||||
return $this->forceFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @param bool $forceFull WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setForceFull(bool $forceFull): self
|
||||
{
|
||||
$this->forceFull = $forceFull;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -10,12 +10,6 @@ class Serialization extends SettingsAbstract
|
||||
* Serialization interval, in seconds.
|
||||
*/
|
||||
protected int $interval = 30;
|
||||
/**
|
||||
* Whether to force full deserialization of instance, without using the IPC server/client.
|
||||
*
|
||||
* WARNING: this will cause slow startup if enabled.
|
||||
*/
|
||||
protected bool $forceFull = false;
|
||||
|
||||
public function mergeArray(array $settings): void
|
||||
{
|
||||
@ -46,28 +40,4 @@ class Serialization extends SettingsAbstract
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getForceFull(): bool
|
||||
{
|
||||
return $this->forceFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @param bool $forceFull WARNING: this will cause slow startup if enabled.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setForceFull(bool $forceFull): self
|
||||
{
|
||||
$this->forceFull = $forceFull;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
61
src/danog/MadelineProto/Settings/Templates.php
Normal file
61
src/danog/MadelineProto/Settings/Templates.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace danog\MadelineProto\Settings;
|
||||
|
||||
/**
|
||||
* Web and CLI template settings for login.
|
||||
*/
|
||||
class Templates
|
||||
{
|
||||
/**
|
||||
* Web template used for querying app information.
|
||||
*/
|
||||
protected string $apiHtmlTemplate = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>Go</button></form></body></html>';
|
||||
/**
|
||||
* Prompt user to choose manual or automatic API ID generation.
|
||||
*/
|
||||
protected string $apiChooseManualAuto = 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)';
|
||||
/**
|
||||
* Settings tip for API ID generation.
|
||||
*/
|
||||
protected string $apiChooseManualAutoTip = 'Note that you can also provide the API parameters directly in the code using the settings: %s';
|
||||
/**
|
||||
* Final prompt to choose mode.
|
||||
*/
|
||||
protected string $apiChoosePrompt = 'Your choice (m/a): ';
|
||||
/**
|
||||
* Instructions for manual API ID generation.
|
||||
*
|
||||
* @var array{0: string, 1: string, 2: array{0: string, 1: string, 2: string, 3: string, 4: string}, 3: string}
|
||||
*/
|
||||
protected array $apiManualInstructions = [
|
||||
'Login to my.telegram.org',
|
||||
'Go to API development tools',
|
||||
[
|
||||
'App title: your app\'s name, can be anything',
|
||||
'Short name: your app\'s short name, can be anything',
|
||||
'URL: your app/website\'s URL, or t.me/yourusername',
|
||||
'Platform: anything',
|
||||
'Description: Describe your app here',
|
||||
],
|
||||
'Click on create application'
|
||||
];
|
||||
/**
|
||||
* Manual API ID/hash prompts.
|
||||
*/
|
||||
protected array $apiManualPrompts = [
|
||||
'Enter your API ID: ',
|
||||
'Enter your API hash: '
|
||||
];
|
||||
/**
|
||||
* Auto API ID/hash prompts.
|
||||
*/
|
||||
protected array $apiAutoPrompts = [
|
||||
'Enter a phone number that is already registered on Telegram: ',
|
||||
'Enter the verification code you received in Telegram: ',
|
||||
'Enter the app\'s name, can be anything: ',
|
||||
'Enter the app\'s short name, can be anything: ',
|
||||
'Enter the app/website\'s URL, or t.me/yourusername: ',
|
||||
'Describe your app: ',
|
||||
];
|
||||
}
|
@ -7,6 +7,12 @@ use ReflectionProperty;
|
||||
|
||||
abstract class SettingsAbstract
|
||||
{
|
||||
/**
|
||||
* Whether this setting was changed.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $changed = true;
|
||||
/**
|
||||
* Merge legacy settings array.
|
||||
*
|
||||
@ -29,13 +35,16 @@ abstract class SettingsAbstract
|
||||
$defaults = $class->getDefaultProperties();
|
||||
foreach ($class->getProperties(ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC) as $property) {
|
||||
$name = $property->getName();
|
||||
$uc = \ucfirst($name);
|
||||
if (isset($other->{$name})
|
||||
&& (
|
||||
!isset($defaults[$name])
|
||||
|| $other->{$name} !== $defaults[$name] // Isn't equal to the default value
|
||||
)
|
||||
&& $other->{$name} !== $this->{"get$uc"}
|
||||
) {
|
||||
$this->{'set'.\ucfirst($name)}($other->{$name});
|
||||
$this->{"set$uc"}($other->{$name});
|
||||
$this->changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,4 +63,24 @@ abstract class SettingsAbstract
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this setting was changed, also applies changes.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasChanged(): bool
|
||||
{
|
||||
return $this->changed;
|
||||
}
|
||||
/**
|
||||
* Apply changes.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function applyChanges(): self
|
||||
{
|
||||
$this->changed = false;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -878,7 +878,7 @@ class TL
|
||||
}
|
||||
}
|
||||
if (!\is_string($x)) {
|
||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['deserialize_not_str']);
|
||||
throw new Exception("Generated value isn't a string");
|
||||
}
|
||||
return $type['type'] === 'bytes' ? new Types\Bytes($x) : $x;
|
||||
case 'Vector t':
|
||||
@ -908,7 +908,7 @@ class TL
|
||||
case 'vector':
|
||||
break;
|
||||
default:
|
||||
throw new Exception(\danog\MadelineProto\Lang::$current_lang['vector_invalid'].$constructorData['predicate']);
|
||||
throw new Exception('Invalid vector constructor: '.$constructorData['predicate']);
|
||||
}
|
||||
// no break
|
||||
case 'vector':
|
||||
|
@ -98,7 +98,7 @@ trait AuthKeyHandler
|
||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
||||
}
|
||||
$user = $user['InputUser'];
|
||||
$this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['calling_user'], $user['user_id']), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->logger->logger(\sprintf("Calling %s...", $user['user_id']), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = (yield from $this->getDhConfig());
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_a'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
$a = \tgseclib\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
|
||||
|
@ -75,7 +75,7 @@ trait DialogHandler
|
||||
$res = ['dialogs' => [0], 'count' => 1];
|
||||
$datacenter = $this->datacenter->curdc;
|
||||
$dialogs = [];
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['getting_dialogs']);
|
||||
$this->logger->logger("Getting dialogs...");
|
||||
while ($this->dialog_params['count'] < $res['count']) {
|
||||
$res = yield from $this->methodCallAsyncRead('messages.getDialogs', $this->dialog_params, ['datacenter' => $datacenter, 'FloodWaitLimit' => 100]);
|
||||
$last_peer = 0;
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use danog\MadelineProto\Lang;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
$template = '<?php
|
||||
@ -39,64 +41,55 @@ function fromCamelCase($input)
|
||||
return \implode(' ', $ret);
|
||||
}
|
||||
|
||||
foreach (Lang::$lang as $code => &$currentLang) {
|
||||
if ($code === 'en') {
|
||||
continue;
|
||||
}
|
||||
$currentLang = \array_intersect_key($currentLang, Lang::$lang['en']);
|
||||
}
|
||||
|
||||
$lang_code = \readline('Enter the language you whish to localize: ');
|
||||
|
||||
if (!isset(\danog\MadelineProto\Lang::$lang[$lang_code])) {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code] = \danog\MadelineProto\Lang::$current_lang;
|
||||
if (!isset(Lang::$lang[$lang_code])) {
|
||||
Lang::$lang[$lang_code] = Lang::$current_lang;
|
||||
echo 'New language detected!'.PHP_EOL.PHP_EOL;
|
||||
} else {
|
||||
echo 'Completing localization of existing language'.PHP_EOL.PHP_EOL;
|
||||
}
|
||||
$count = \count(\danog\MadelineProto\Lang::$lang[$lang_code]);
|
||||
$count = \count(Lang::$lang[$lang_code]);
|
||||
$curcount = 0;
|
||||
\ksort(\danog\MadelineProto\Lang::$current_lang);
|
||||
foreach (\danog\MadelineProto\Lang::$current_lang as $key => $value) {
|
||||
if (!isset(\danog\MadelineProto\Lang::$lang[$lang_code][$key])) {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = $value;
|
||||
}
|
||||
\preg_match('/^[^_]+_(.*?)(?:_param_(.*)_type_(.*))?$/', $key, $matches);
|
||||
$method_name = isset($matches[1]) ? $matches[1] : '';
|
||||
$param_name = isset($matches[2]) ? $matches[2] : '';
|
||||
$param_type = isset($matches[3]) ? $matches[3] : '';
|
||||
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$method_name])) {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = \danog\MadelineProto\MTProto::DISALLOWED_METHODS[$method_name];
|
||||
\ksort(Lang::$current_lang);
|
||||
foreach (Lang::$current_lang as $key => $value) {
|
||||
if (!isset(Lang::$lang[$lang_code][$key])) {
|
||||
Lang::$lang[$lang_code][$key] = $value;
|
||||
}
|
||||
|
||||
if (\danog\MadelineProto\Lang::$lang[$lang_code][$key] === $value && (
|
||||
$lang_code !== 'en' || $value == '' ||
|
||||
\strpos($value, 'You cannot use this method directly') === 0 ||
|
||||
\strpos($value, 'Update ') === 0 ||
|
||||
\ctype_lower($value[0])
|
||||
if (Lang::$lang[$lang_code][$key] === $value && (
|
||||
$lang_code !== 'en' || $value == ''
|
||||
)) {
|
||||
$value = \danog\MadelineProto\Lang::$lang[$lang_code][$key];
|
||||
$value = Lang::$lang[$lang_code][$key];
|
||||
if (\in_array($key, ['v_error', 'v_tgerror'])) {
|
||||
$value = \hex2bin($value);
|
||||
}
|
||||
if ($value == '') {
|
||||
$value = $key;
|
||||
}
|
||||
\preg_match('/^[^_]+_(.*?)(?:_param_(.*)_type_(.*))?$/', $key, $matches);
|
||||
$method_name = isset($matches[1]) ? $matches[1] : '';
|
||||
$param_name = isset($matches[2]) ? $matches[2] : '';
|
||||
$param_type = isset($matches[3]) ? $matches[3] : '';
|
||||
if (isset(\danog\MadelineProto\MTProto::DISALLOWED_METHODS[$method_name])) {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = \danog\MadelineProto\MTProto::DISALLOWED_METHODS[$method_name];
|
||||
}
|
||||
Lang::$lang[$lang_code][$key] = \readline($value.' => ');
|
||||
/*
|
||||
if ($param_name === 'nonce' && $param_type === 'int128') {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
|
||||
Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
|
||||
} elseif ($param_name === 'server_nonce' && $param_type === 'int128') {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security, given by server';
|
||||
Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security, given by server';
|
||||
} elseif ($param_name === 'random_id' && $param_type === 'long') {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
|
||||
Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
|
||||
} else elseif (\strpos($value, 'Update ') === 0) {
|
||||
if (!$param_name && \strpos($key, 'object_') === 0) {
|
||||
$value = \str_replace('Update ', '', $value).' update';
|
||||
}
|
||||
//} elseif (ctype_lower($value[0])) {
|
||||
} else {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = \readline($value.' => ');
|
||||
if (\danog\MadelineProto\Lang::$lang[$lang_code][$key] === '') {
|
||||
Lang::$lang[$lang_code][$key] = \readline($value.' => ');
|
||||
if (Lang::$lang[$lang_code][$key] === '') {
|
||||
if ($param_name) {
|
||||
$l = \str_replace('_', ' ', $param_name);
|
||||
} else {
|
||||
@ -115,18 +108,18 @@ foreach (\danog\MadelineProto\Lang::$current_lang as $key => $value) {
|
||||
$l .= '?';
|
||||
}
|
||||
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = $l;
|
||||
echo 'Using default value '.\danog\MadelineProto\Lang::$lang[$lang_code][$key].PHP_EOL;
|
||||
Lang::$lang[$lang_code][$key] = $l;
|
||||
echo 'Using default value '.Lang::$lang[$lang_code][$key].PHP_EOL;
|
||||
}
|
||||
}*/
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = \ucfirst(\danog\MadelineProto\Lang::$lang[$lang_code][$key]);
|
||||
Lang::$lang[$lang_code][$key] = \ucfirst(Lang::$lang[$lang_code][$key]);
|
||||
if (\in_array($key, ['v_error', 'v_tgerror'])) {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = \bin2hex(\danog\MadelineProto\Lang::$lang[$lang_code][$key]);
|
||||
Lang::$lang[$lang_code][$key] = \bin2hex(Lang::$lang[$lang_code][$key]);
|
||||
}
|
||||
\file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(\danog\MadelineProto\Lang::$lang, true), \var_export(\danog\MadelineProto\Lang::$lang['en'], true)));
|
||||
\file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(Lang::$lang, true), \var_export(Lang::$lang['en'], true)));
|
||||
echo 'OK, '.($curcount * 100 / $count).'% done. edit src/danog/MadelineProto/Lang.php to fix mistakes.'.PHP_EOL;
|
||||
}
|
||||
$curcount++;
|
||||
}
|
||||
\file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(\danog\MadelineProto\Lang::$lang, true), \var_export(\danog\MadelineProto\Lang::$lang['en'], true)));
|
||||
\file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(Lang::$lang, true), \var_export(Lang::$lang['en'], true)));
|
||||
echo 'OK. edit src/danog/MadelineProto/Lang.php to fix mistakes.'.PHP_EOL;
|
||||
|
Loading…
Reference in New Issue
Block a user