Style fixes
This commit is contained in:
parent
832df205c4
commit
a1daca04da
45
asyncify.php
45
asyncify.php
@ -1,28 +1,41 @@
|
||||
<?php
|
||||
|
||||
$not_subbing = [];
|
||||
|
||||
foreach (explode("\n", shell_exec("find src -type f -name '*.php'")) as $file) {
|
||||
if (!$file) continue;
|
||||
if (in_array(basename($file, '.php'), ['APIFactory', 'API', 'Connection', 'Coroutine', 'ReferenceDatabase', 'ProxySocketPool'])) continue;
|
||||
if (strpos($file, 'Loop/')) continue;
|
||||
if (strpos($file, 'Stream/')) continue;
|
||||
if (strpos($file, 'Server/')) continue;
|
||||
if (strpos($file, 'Async/')) continue;
|
||||
if (!$file) {
|
||||
continue;
|
||||
}
|
||||
if (in_array(basename($file, '.php'), ['APIFactory', 'API', 'Connection', 'Coroutine', 'ReferenceDatabase', 'ProxySocketPool'])) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($file, 'Loop/')) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($file, 'Stream/')) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($file, 'Server/')) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($file, 'Async/')) {
|
||||
continue;
|
||||
}
|
||||
$to_sub = [];
|
||||
$last_match = null;
|
||||
foreach (explode("\n", $filec = file_get_contents($file)) as $number => $line) {
|
||||
if (preg_match("/public function (\w*)[(]/", $line, $matches)) {
|
||||
$last_match = stripos($matches[1], 'async') === false ? $matches[1] : null;
|
||||
}
|
||||
if (preg_match("/function [(]/", $line) && stripos($line, 'public function') === false) {
|
||||
if (preg_match('/function [(]/', $line) && stripos($line, 'public function') === false) {
|
||||
$last_match = 0;
|
||||
}
|
||||
if (strpos($line, "yield") !== false) {
|
||||
if (strpos($line, 'yield') !== false) {
|
||||
if ($last_match) {
|
||||
echo ("subbing $last_match for $line at $number in $file".PHP_EOL);
|
||||
$to_sub []= $last_match;
|
||||
} else if ($last_match === 0) {
|
||||
echo ("============\nNOT SUBBING $last_match for $line at $number in $file\n============".PHP_EOL);
|
||||
echo "subbing $last_match for $line at $number in $file".PHP_EOL;
|
||||
$to_sub[] = $last_match;
|
||||
} elseif ($last_match === 0) {
|
||||
echo "============\nNOT SUBBING $last_match for $line at $number in $file\n============".PHP_EOL;
|
||||
$not_subbing[$file] = $file;
|
||||
}
|
||||
}
|
||||
@ -30,9 +43,11 @@ foreach (explode("\n", shell_exec("find src -type f -name '*.php'")) as $file) {
|
||||
$input = [];
|
||||
$output = [];
|
||||
foreach ($to_sub as $func) {
|
||||
$input []= "public function $func(";
|
||||
$output []= "public function $func"."_async(";
|
||||
$input[] = "public function $func(";
|
||||
$output[] = "public function $func".'_async(';
|
||||
}
|
||||
if ($input) {
|
||||
file_put_contents($file, str_replace($input, $output, $filec));
|
||||
}
|
||||
if ($input) file_put_contents($file, str_replace($input, $output, $filec));
|
||||
}
|
||||
var_dump(array_values($not_subbing));
|
||||
|
15
bot.php
15
bot.php
@ -17,7 +17,7 @@ set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelinePro
|
||||
*/
|
||||
if (!file_exists(__DIR__.'/vendor/autoload.php')) {
|
||||
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
|
||||
define('MADELINE_BRANCH','');
|
||||
define('MADELINE_BRANCH', '');
|
||||
if (!file_exists('madeline.php')) {
|
||||
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
|
||||
}
|
||||
@ -33,8 +33,12 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
if (isset($update['message']['out']) && $update['message']['out']) {
|
||||
return;
|
||||
}
|
||||
if ($update['_'] === 'updateReadChannelOutbox') return;
|
||||
if (isset($update['message']['_']) && $update['message']['_'] === 'messageEmpty') return;
|
||||
if ($update['_'] === 'updateReadChannelOutbox') {
|
||||
return;
|
||||
}
|
||||
if (isset($update['message']['_']) && $update['message']['_'] === 'messageEmpty') {
|
||||
return;
|
||||
}
|
||||
|
||||
$res = json_encode($update, JSON_PRETTY_PRINT);
|
||||
if ($res == '') {
|
||||
@ -50,14 +54,15 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
\danog\MadelineProto\Logger::log((string) $e, \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
if (stripos($e->getMessage(), 'invalid constructor given') === false) \danog\MadelineProto\Logger::log((string) $e, \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||
if (stripos($e->getMessage(), 'invalid constructor given') === false) {
|
||||
\danog\MadelineProto\Logger::log((string) $e, \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||
}
|
||||
//$this->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings = ['logger' => ['logger_level' => 5]];
|
||||
|
||||
|
||||
$MadelineProto = new \danog\MadelineProto\API('bot.madeline', $settings);
|
||||
$MadelineProto->async(true);
|
||||
$MadelineProto->loop(function () use ($MadelineProto) {
|
||||
|
@ -107,7 +107,7 @@ $order = [
|
||||
'PROXY',
|
||||
'USING_METHODS',
|
||||
'CONTRIB',
|
||||
'TEMPLATES'
|
||||
'TEMPLATES',
|
||||
];
|
||||
$index = '';
|
||||
$files = glob('docs/docs/docs/*md');
|
||||
@ -158,7 +158,7 @@ foreach ($orderedfiles as $key => $filename) {
|
||||
$url = $matches[3][$key][0] === '#' ? $file.$matches[3][$key] : $matches[3][$key];
|
||||
$index .= "$spaces* [$name]($url)\n";
|
||||
if ($name === 'FULL API Documentation with descriptions') {
|
||||
$spaces .= " ";
|
||||
$spaces .= ' ';
|
||||
preg_match_all('|\* (.*)|', file_get_contents('docs/docs/API_docs/methods/index.md'), $smatches);
|
||||
foreach ($smatches[1] as $key => $match) {
|
||||
$match = str_replace('href="', 'href="https://docs.madelineproto.xyz/API_docs/methods/', $match);
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\TL\TL;
|
||||
|
||||
@ -24,28 +25,31 @@ if ($argc !== 3) {
|
||||
die("Usage: {$argv[0]} layernumberold layernumbernew\n");
|
||||
}
|
||||
/**
|
||||
* Get TL info of layer
|
||||
* Get TL info of layer.
|
||||
*
|
||||
* @param int $layer Layer number
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function getTL($layer)
|
||||
{
|
||||
$layer = __DIR__."/src/danog/MadelineProto/TL_telegram_v$layer.tl";
|
||||
$layer = new class($layer)
|
||||
{
|
||||
$layer = new class($layer) {
|
||||
use TL;
|
||||
|
||||
public function __construct($layer)
|
||||
{
|
||||
$this->logger = Logger::$default;
|
||||
$this->construct_TL(['telegram' => $layer]);
|
||||
}
|
||||
};
|
||||
|
||||
return ['methods' => $layer->methods, 'constructors' => $layer->constructors];
|
||||
}
|
||||
function getUrl($constructor, $type)
|
||||
{
|
||||
$changed = str_replace('.', '_', $constructor);
|
||||
|
||||
return "[$constructor](https://docs.madelineproto.xyz/API_docs/$type/$changed.html)";
|
||||
}
|
||||
$old = getTL($argv[1]);
|
||||
@ -105,7 +109,6 @@ foreach (['methods', 'constructors'] as $type) {
|
||||
$res .= "Removed $name\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo($res);
|
||||
echo $res;
|
||||
|
46
magna.php
46
magna.php
@ -11,10 +11,10 @@ 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/>.
|
||||
*/
|
||||
set_include_path(get_include_path() . ':' . realpath(dirname(__FILE__) . '/MadelineProto/'));
|
||||
set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelineProto/'));
|
||||
|
||||
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
|
||||
echo 'You did not run composer update, using madeline.php' . PHP_EOL;
|
||||
if (!file_exists(__DIR__.'/vendor/autoload.php')) {
|
||||
echo 'You did not run composer update, using madeline.php'.PHP_EOL;
|
||||
if (!file_exists('madeline.php')) {
|
||||
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
|
||||
}
|
||||
@ -27,7 +27,7 @@ if (!file_exists('songs.php')) {
|
||||
copy('https://github.com/danog/MadelineProto/raw/master/songs.php', 'songs.php');
|
||||
}
|
||||
|
||||
echo 'Deserializing MadelineProto from session.madeline...' . PHP_EOL;
|
||||
echo 'Deserializing MadelineProto from session.madeline...'.PHP_EOL;
|
||||
|
||||
/*if (!isset($MadelineProto->inputEncryptedFilePhoto) && false) {
|
||||
$MadelineProto->inputEncryptedFilePhoto = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic
|
||||
@ -46,7 +46,7 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
$call->configuration['enable_NS'] = false;
|
||||
$call->configuration['enable_AGC'] = false;
|
||||
$call->configuration['enable_AEC'] = false;
|
||||
$call->configuration['log_file_path'] = '/tmp/logs' . $call->getCallID()['id'] . '.log'; // Default is /dev/null
|
||||
$call->configuration['log_file_path'] = '/tmp/logs'.$call->getCallID()['id'].'.log'; // Default is /dev/null
|
||||
//$call->configuration["stats_dump_file_path"] = "/tmp/stats".$call->getCallID()['id'].".txt"; // Default is /dev/null
|
||||
$call->parseConfig();
|
||||
$call->playOnHold($songs);
|
||||
@ -84,7 +84,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
$this->configureCall($call);
|
||||
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$this->calls[$call->getOtherID()] = $call;
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()])['id']];
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
|
||||
}
|
||||
}
|
||||
if (strpos($message, '/program') === 0) {
|
||||
@ -174,7 +174,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
$this->calls[$update['phone_call']->getOtherID()] = $update['phone_call'];
|
||||
|
||||
try {
|
||||
$this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL])['id']];
|
||||
$this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL])['id']];
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
}
|
||||
}
|
||||
@ -196,7 +196,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
$this->configureCall($call);
|
||||
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$this->calls[$call->getOtherID()] = $call;
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()])['id']];
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
try {
|
||||
@ -232,7 +232,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
}
|
||||
break;
|
||||
}
|
||||
\danog\MadelineProto\Logger::log(count($this->calls) . ' calls running!');
|
||||
\danog\MadelineProto\Logger::log(count($this->calls).' calls running!');
|
||||
foreach ($this->calls as $key => $call) {
|
||||
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
try {
|
||||
@ -250,12 +250,12 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
]);*/
|
||||
$this->messages->sendMedia([
|
||||
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
|
||||
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => '/tmp/logs' . $call->getCallID()['id'] . '.log',
|
||||
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => '/tmp/logs'.$call->getCallID()['id'].'.log',
|
||||
'attributes' => [
|
||||
['_' => 'documentAttributeFilename', 'file_name' => 'logs' . $call->getCallID()['id'] . '.log'],
|
||||
['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
@ -267,14 +267,14 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
echo $e;
|
||||
}
|
||||
@unlink('/tmp/logs' . $call->getCallID()['id'] . '.log');
|
||||
@unlink('/tmp/stats' . $call->getCallID()['id'] . '.txt');
|
||||
@unlink('/tmp/logs'.$call->getCallID()['id'].'.log');
|
||||
@unlink('/tmp/stats'.$call->getCallID()['id'].'.txt');
|
||||
unset($this->calls[$key]);
|
||||
} elseif (isset($this->times[$call->getOtherID()]) && $this->times[$call->getOtherID()][0] < time()) {
|
||||
$this->times[$call->getOtherID()][0] += 30 + count($this->calls);
|
||||
|
||||
try {
|
||||
$this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()]);
|
||||
$this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
echo $e;
|
||||
}
|
||||
@ -283,17 +283,19 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) die('Install the libtgvoip extension: https://voip.madelineproto.xyz'.PHP_EOL);
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) {
|
||||
die('Install the libtgvoip extension: https://voip.madelineproto.xyz'.PHP_EOL);
|
||||
}
|
||||
|
||||
\danog\MadelineProto\VoIPServerConfig::update(
|
||||
[
|
||||
'audio_init_bitrate' => 100 * 1000,
|
||||
'audio_max_bitrate' => 100 * 1000,
|
||||
'audio_min_bitrate' => 10 * 1000,
|
||||
'audio_init_bitrate' => 100 * 1000,
|
||||
'audio_max_bitrate' => 100 * 1000,
|
||||
'audio_min_bitrate' => 10 * 1000,
|
||||
'audio_congestion_window' => 4 * 1024,
|
||||
]
|
||||
);
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd() . '/MadelineProto.log']]);
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd().'/MadelineProto.log']]);
|
||||
$MadelineProto->start();
|
||||
|
||||
if (!isset($MadelineProto->programmed_call)) {
|
||||
|
7
phar.php
7
phar.php
@ -5,7 +5,9 @@ if (PHP_MAJOR_VERSION === 5) {
|
||||
throw new \Exception('MadelineProto requires at least PHP 5.6 to run');
|
||||
}
|
||||
$newline = PHP_EOL;
|
||||
if (php_sapi_name() !== 'cli') $newline = '<br>'.$newline;
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$newline = '<br>'.$newline;
|
||||
}
|
||||
echo "**********************************************************************$newline";
|
||||
echo "**********************************************************************$newline$newline";
|
||||
echo "YOU ARE USING AN OLD AND BUGGED VERSION OF PHP, PLEASE UPDATE TO PHP 7$newline";
|
||||
@ -39,7 +41,6 @@ function ___install_madeline()
|
||||
$release_template = 'https://phar.madelineproto.xyz/release%s?v=new';
|
||||
$phar_template = 'https://phar.madelineproto.xyz/madeline%s.phar?v=new';
|
||||
|
||||
|
||||
// Version definition
|
||||
$release_branch = defined('MADELINE_BRANCH') ? '-'.MADELINE_BRANCH : '-old';
|
||||
if ($release_branch === '-') {
|
||||
@ -50,7 +51,7 @@ function ___install_madeline()
|
||||
if (PHP_MAJOR_VERSION <= 5) {
|
||||
$release_branch = '5'.$release_branch;
|
||||
$release_default_branch = '5';
|
||||
} else if (PHP_MINOR_VERSION >= 3) {
|
||||
} elseif (PHP_MINOR_VERSION >= 3) {
|
||||
$release_branch = '';
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,15 @@
|
||||
*
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
|
||||
class YieldReturnValue
|
||||
{
|
||||
private $value;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getReturn()
|
||||
{
|
||||
return $this->value;
|
||||
|
@ -37,13 +37,14 @@ class API extends APIFactory
|
||||
{
|
||||
Magic::class_exists();
|
||||
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
|
||||
$deferred = new Deferred;
|
||||
$deferred = new Deferred();
|
||||
$this->asyncAPIPromise = $deferred->promise();
|
||||
$this->asyncAPIPromise->onResolve(function () {
|
||||
$this->asyncAPIPromise = null;
|
||||
});
|
||||
$this->setInitPromise($this->__construct_async($params, $settings, $deferred));
|
||||
}
|
||||
|
||||
public function __construct_async($params, $settings, $deferred)
|
||||
{
|
||||
if (is_string($params)) {
|
||||
@ -184,10 +185,12 @@ class API extends APIFactory
|
||||
|
||||
return implode('_', $ret);
|
||||
}
|
||||
|
||||
public function my_get_self()
|
||||
{
|
||||
return $this->API->authorization['user'];
|
||||
}
|
||||
|
||||
public function APIFactory()
|
||||
{
|
||||
if ($this->API) {
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Async\AsyncConstruct;
|
||||
|
||||
class APIFactory extends AsyncConstruct
|
||||
@ -156,10 +155,10 @@ class APIFactory extends AsyncConstruct
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
yield $this->initAsync();
|
||||
$this->API->logger->logger("Finished init asynchronously");
|
||||
$this->API->logger->logger('Finished init asynchronously');
|
||||
}
|
||||
if (Magic::is_fork() && !Magic::$processed_fork) {
|
||||
throw new Exception("Forking not supported, use async logic, instead: https://docs.madelineproto.xyz/docs/ASYNC.html");
|
||||
throw new Exception('Forking not supported, use async logic, instead: https://docs.madelineproto.xyz/docs/ASYNC.html');
|
||||
}
|
||||
if (isset($this->session) && !is_null($this->session) && time() - $this->serialized > $this->API->settings['serialization']['serialization_interval']) {
|
||||
Logger::log("Didn't serialize in a while, doing that now...");
|
||||
@ -172,7 +171,7 @@ class APIFactory extends AsyncConstruct
|
||||
}
|
||||
if ($this->API->asyncInitPromise) {
|
||||
yield $this->API->initAsync();
|
||||
$this->API->logger->logger("Finished init asynchronously");
|
||||
$this->API->logger->logger('Finished init asynchronously');
|
||||
}
|
||||
|
||||
$lower_name = strtolower($name);
|
||||
@ -215,6 +214,7 @@ class APIFactory extends AsyncConstruct
|
||||
if ($this->API->asyncInitPromise) {
|
||||
$this->API->init();
|
||||
}
|
||||
|
||||
return $this->API->__construct(array_replace_recursive($this->API->settings, $value));
|
||||
}
|
||||
|
||||
@ -226,6 +226,7 @@ class APIFactory extends AsyncConstruct
|
||||
if ($this->asyncAPIPromise) {
|
||||
$this->wait($this->asyncAPIPromise);
|
||||
}
|
||||
|
||||
return isset($this->API->storage[$name]);
|
||||
}
|
||||
|
||||
@ -236,5 +237,4 @@ class APIFactory extends AsyncConstruct
|
||||
}
|
||||
unset($this->API->storage[$name]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ class Absolute
|
||||
if (($file[0] !== '/') && ($file[1] !== ':') && !in_array(substr($file, 0, 4), ['phar', 'http'])) {
|
||||
$file = Magic::getcwd().'/'.$file;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
@ -31,18 +31,21 @@ class AsyncConstruct
|
||||
{
|
||||
use Tools;
|
||||
public $asyncInitPromise;
|
||||
|
||||
public function init()
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
$this->wait($this->asyncInitPromise);
|
||||
}
|
||||
}
|
||||
|
||||
public function initAsync()
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
yield $this->asyncInitPromise;
|
||||
}
|
||||
}
|
||||
|
||||
public function setInitPromise($promise)
|
||||
{
|
||||
$this->asyncInitPromise = $this->call($promise);
|
||||
|
@ -54,6 +54,7 @@ class AsyncParameters extends Parameters
|
||||
public function getParameters()
|
||||
{
|
||||
$callable = $this->callable;
|
||||
|
||||
return yield $callable();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ class CombinedAPI
|
||||
$realpaths = Serialization::realpaths($session);
|
||||
$this->session = $realpaths['file'];
|
||||
|
||||
|
||||
foreach ($paths as $path => $settings) {
|
||||
$this->addInstance($path, $settings);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\ByteStream\ClosedException;
|
||||
use Amp\Deferred;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Loop\Connection\CheckLoop;
|
||||
@ -28,7 +29,6 @@ use danog\MadelineProto\MTProtoTools\Crypt;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\MTProtoTools\MsgIdHandler;
|
||||
use danog\MadelineProto\Stream\MTProtoTools\SeqNoHandler;
|
||||
use Amp\ByteStream\ClosedException;
|
||||
|
||||
/**
|
||||
* Connection class.
|
||||
@ -147,7 +147,6 @@ class Connection
|
||||
$this->checker->resume();
|
||||
}
|
||||
$this->waiter->start();
|
||||
|
||||
}
|
||||
|
||||
public function sendMessage($message, $flush = true)
|
||||
@ -235,6 +234,7 @@ class Connection
|
||||
if ($pfs && !isset($this->temp_auth_key['bound']) && $this->outgoing_messages[$message_id]['_'] !== 'auth.bindTempAuthKey') {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +90,14 @@ final class Coroutine implements Promise
|
||||
//public function __destruct() { var_dump($this->s); }
|
||||
};*/
|
||||
$this->generator = $generator;
|
||||
|
||||
try {
|
||||
$yielded = $this->generator->current();
|
||||
while (!$yielded instanceof Promise) {
|
||||
if ($yielded instanceof \YieldReturnValue) {
|
||||
$this->resolve($yielded->getReturn());
|
||||
$this->generator->next();
|
||||
|
||||
return;
|
||||
}
|
||||
if (!$this->generator->valid()) {
|
||||
@ -145,6 +147,7 @@ final class Coroutine implements Promise
|
||||
$this->resolve($yielded->getReturn());
|
||||
$this->onResolve = null;
|
||||
$this->generator->next();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,10 @@
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
use Amp\CancellationToken;
|
||||
use Amp\Artax\Cookie\ArrayCookieJar;
|
||||
use Amp\Artax\DefaultClient;
|
||||
use Amp\Artax\HttpSocketPool;
|
||||
use Amp\CancellationToken;
|
||||
use Amp\Socket\ClientConnectContext;
|
||||
use danog\MadelineProto\Stream\Common\BufferedRawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
@ -38,7 +39,6 @@ use danog\MadelineProto\Stream\Transport\DefaultStream;
|
||||
use danog\MadelineProto\Stream\Transport\WssStream;
|
||||
use danog\MadelineProto\Stream\Transport\WsStream;
|
||||
use danog\MadelineProto\TL\Conversion\Exception;
|
||||
use Amp\Artax\Cookie\ArrayCookieJar;
|
||||
|
||||
/**
|
||||
* Manages datacenters.
|
||||
@ -74,8 +74,9 @@ class DataCenter
|
||||
unset($this->sockets[$key]);
|
||||
}
|
||||
}
|
||||
$this->HTTPClient = new DefaultClient(new ArrayCookieJar, new HttpSocketPool(new ProxySocketPool($this)));
|
||||
$this->HTTPClient = new DefaultClient(new ArrayCookieJar(), new HttpSocketPool(new ProxySocketPool($this)));
|
||||
}
|
||||
|
||||
public function rawConnectAsync(string $uri, CancellationToken $token = null, ClientConnectContext $ctx = null): \Generator
|
||||
{
|
||||
$ctxs = $this->generateContexts(0, $uri, $ctx);
|
||||
@ -83,7 +84,7 @@ class DataCenter
|
||||
throw new Exception("No contexts for raw connection to URI $uri");
|
||||
}
|
||||
foreach ($ctxs as $ctx) {
|
||||
/** @var $ctx \danog\MadelineProto\Stream\ConnectionContext */
|
||||
/* @var $ctx \danog\MadelineProto\Stream\ConnectionContext */
|
||||
try {
|
||||
$ctx->setCancellationToken($token);
|
||||
$result = yield $ctx->getStream();
|
||||
@ -364,15 +365,15 @@ class DataCenter
|
||||
unset($this->sockets[$dc_number]);
|
||||
|
||||
$this->API->logger->logger("No info for DC $dc_number", \danog\MadelineProto\Logger::ERROR);
|
||||
|
||||
} else if (defined('MADELINEPROTO_TEST') && MADELINEPROTO_TEST === 'pony') {
|
||||
} elseif (defined('MADELINEPROTO_TEST') && MADELINEPROTO_TEST === 'pony') {
|
||||
return [$ctxs[0]];
|
||||
}
|
||||
|
||||
return $ctxs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Artax async HTTP client
|
||||
* Get Artax async HTTP client.
|
||||
*
|
||||
* @return \Amp\Artax\DefaultClient
|
||||
*/
|
||||
@ -380,10 +381,12 @@ class DataCenter
|
||||
{
|
||||
return $this->HTTPClient;
|
||||
}
|
||||
|
||||
public function fileGetContents($url): \Generator
|
||||
{
|
||||
return yield (yield $this->getHTTPClient()->request($url))->getBody();
|
||||
}
|
||||
|
||||
public function get_dcs($all = true)
|
||||
{
|
||||
$test = $this->settings['all']['test_mode'] ? 'test' : 'main';
|
||||
|
@ -38,6 +38,7 @@ class FileCallback implements FileCallbackInterface
|
||||
public function __invoke($percent)
|
||||
{
|
||||
$callback = $this->callback;
|
||||
|
||||
return $callback($percent);
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ namespace danog\MadelineProto;
|
||||
|
||||
use Amp\ByteStream\ResourceOutputStream;
|
||||
use Amp\Failure;
|
||||
use function \Amp\ByteStream\getStdout;
|
||||
use function \Amp\ByteStream\getStderr;
|
||||
use function Amp\ByteStream\getStderr;
|
||||
use function Amp\ByteStream\getStdout;
|
||||
|
||||
class Logger
|
||||
{
|
||||
@ -100,7 +100,9 @@ class Logger
|
||||
|
||||
if ($this->mode === 3) {
|
||||
$this->stdout = getStdout();
|
||||
if (php_sapi_name() !== 'cli') $this->newline = '<br>'.$this->newline;
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$this->newline = '<br>'.$this->newline;
|
||||
}
|
||||
} elseif ($this->mode === 2) {
|
||||
$this->stdout = new ResourceOutputStream(fopen($this->optional, 'a+'));
|
||||
} elseif ($this->mode === 1) {
|
||||
@ -147,7 +149,7 @@ class Logger
|
||||
}
|
||||
if ($param instanceof \Throwable) {
|
||||
$param = (string) $param;
|
||||
} else if (!is_string($param)) {
|
||||
} elseif (!is_string($param)) {
|
||||
$param = json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
if ($file === null) {
|
||||
@ -171,6 +173,7 @@ class Logger
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
//$this->wait($this->stdout->write(''));
|
||||
|
@ -19,7 +19,6 @@
|
||||
namespace danog\MadelineProto\Loop\Connection;
|
||||
|
||||
use Amp\Deferred;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
|
||||
/**
|
||||
@ -66,6 +65,7 @@ class CheckLoop extends ResumableSignalLoop
|
||||
if ($e) {
|
||||
$API->logger("Got exception in check loop for DC $datacenter");
|
||||
$API->logger((string) $e);
|
||||
|
||||
return;
|
||||
}
|
||||
$reply = [];
|
||||
|
@ -18,8 +18,6 @@
|
||||
|
||||
namespace danog\MadelineProto\Loop\Connection;
|
||||
|
||||
use Amp\Success;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
|
||||
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
|
||||
@ -40,6 +38,7 @@ class HttpWaitLoop extends ResumableSignalLoop
|
||||
$this->datacenter = $datacenter;
|
||||
$this->connection = $API->datacenter->sockets[$datacenter];
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$API = $this->API;
|
||||
@ -68,7 +67,6 @@ class HttpWaitLoop extends ResumableSignalLoop
|
||||
yield $connection->sendMessage(['_' => 'http_wait', 'body' => ['max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'content_related' => true, 'unencrypted' => false, 'method' => false]);
|
||||
}
|
||||
$API->logger->logger("DC $datacenter: request {$connection->http_req_count}, response {$connection->http_res_count}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ class ReadLoop extends SignalLoop
|
||||
$this->datacenter = $datacenter;
|
||||
$this->connection = $API->datacenter->sockets[$datacenter];
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$API = $this->API;
|
||||
@ -92,6 +93,7 @@ class ReadLoop extends SignalLoop
|
||||
$API->logger->logger("Got NOOP from DC {$datacenter}", \danog\MadelineProto\Logger::WARNING);
|
||||
} else {
|
||||
yield $connection->reconnect();
|
||||
|
||||
throw new \danog\MadelineProto\RPCErrorException($error, $error);
|
||||
}
|
||||
|
||||
@ -114,7 +116,8 @@ class ReadLoop extends SignalLoop
|
||||
$datacenter = $this->datacenter;
|
||||
$connection = $this->connection;
|
||||
if (isset($this->connection->old)) {
|
||||
$API->logger->logger("Not reading because connection is old");
|
||||
$API->logger->logger('Not reading because connection is old');
|
||||
|
||||
throw new NothingInTheSocketException();
|
||||
}
|
||||
|
||||
@ -203,6 +206,7 @@ class ReadLoop extends SignalLoop
|
||||
$connection->incoming_messages[$message_id] = ['seq_no' => $seq_no];
|
||||
} else {
|
||||
$API->logger->logger('Got unknown auth_key id', \danog\MadelineProto\Logger::ERROR);
|
||||
|
||||
return -404;
|
||||
}
|
||||
$deserialized = $API->deserialize($message_data, ['type' => '', 'datacenter' => $datacenter]);
|
||||
|
@ -197,15 +197,15 @@ class WriteLoop extends ResumableSignalLoop
|
||||
'query' => yield $API->serialize_method_async(
|
||||
'initConnection',
|
||||
[
|
||||
'api_id' => $API->settings['app_info']['api_id'],
|
||||
'api_hash' => $API->settings['app_info']['api_hash'],
|
||||
'device_model' => strpos($datacenter, 'cdn') === false ? $API->settings['app_info']['device_model'] : 'n/a',
|
||||
'system_version' => strpos($datacenter, 'cdn') === false ? $API->settings['app_info']['system_version'] : 'n/a',
|
||||
'app_version' => $API->settings['app_info']['app_version'],
|
||||
'api_id' => $API->settings['app_info']['api_id'],
|
||||
'api_hash' => $API->settings['app_info']['api_hash'],
|
||||
'device_model' => strpos($datacenter, 'cdn') === false ? $API->settings['app_info']['device_model'] : 'n/a',
|
||||
'system_version' => strpos($datacenter, 'cdn') === false ? $API->settings['app_info']['system_version'] : 'n/a',
|
||||
'app_version' => $API->settings['app_info']['app_version'],
|
||||
'system_lang_code' => $API->settings['app_info']['lang_code'],
|
||||
'lang_code' => $API->settings['app_info']['lang_code'],
|
||||
'lang_pack' => $API->settings['app_info']['lang_pack'],
|
||||
'query' => $MTmessage['body'],
|
||||
'lang_code' => $API->settings['app_info']['lang_code'],
|
||||
'lang_pack' => $API->settings['app_info']['lang_pack'],
|
||||
'query' => $MTmessage['body'],
|
||||
]
|
||||
),
|
||||
]
|
||||
@ -331,6 +331,7 @@ class WriteLoop extends ResumableSignalLoop
|
||||
} while (!empty($connection->pending_outgoing) && !$skipped);
|
||||
|
||||
$connection->pending_outgoing_key = 0;
|
||||
|
||||
return $skipped;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Generic loop
|
||||
* Generic loop.
|
||||
*
|
||||
* 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.
|
||||
@ -35,7 +35,7 @@ class GenericLoop extends ResumableSignalLoop
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor.
|
||||
*
|
||||
* The callback will be bound to the GenericLoop instance: this means that you will be able to use `$this` as if the callback were actually the `loop` function (you can access the API property, use the pause/waitSignal methods & so on).
|
||||
* The return value of the callable can be:
|
||||
@ -43,10 +43,10 @@ class GenericLoop extends ResumableSignalLoop
|
||||
* GenericLoop::STOP - The loop will stop
|
||||
* GenericLoop::PAUSE - The loop will pause forever (or until the `resume` method is called on the loop object from outside the loop)
|
||||
* GenericLoop::CONTINUE - Return this if you want to rerun the loop without waiting
|
||||
*
|
||||
* @param \danog\MadelineProto\API $API Instance of MadelineProto
|
||||
* @param callback $callback Callback to run
|
||||
* @param string $name Fetcher name
|
||||
*
|
||||
* @param \danog\MadelineProto\API $API Instance of MadelineProto
|
||||
* @param callable $callback Callback to run
|
||||
* @param string $name Fetcher name
|
||||
*/
|
||||
public function __construct($API, $callback, $name)
|
||||
{
|
||||
@ -54,6 +54,7 @@ class GenericLoop extends ResumableSignalLoop
|
||||
$this->callback = $callback->bindTo($this);
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$callback = $this->callback;
|
||||
@ -62,7 +63,7 @@ class GenericLoop extends ResumableSignalLoop
|
||||
$timeout = yield $callback();
|
||||
if ($timeout === self::PAUSE) {
|
||||
$this->API->logger->logger("Pausing $this", \danog\MadelineProto\Logger::VERBOSE);
|
||||
} else if ($timeout > 0) {
|
||||
} elseif ($timeout > 0) {
|
||||
$this->API->logger->logger("Pausing $this for $timeout", \danog\MadelineProto\Logger::VERBOSE);
|
||||
}
|
||||
if ($timeout === self::STOP || yield $this->waitSignal($this->pause($timeout))) {
|
||||
|
@ -36,6 +36,7 @@ abstract class Loop implements LoopInterface
|
||||
private $count = 0;
|
||||
|
||||
public $API;
|
||||
|
||||
public function __construct($API)
|
||||
{
|
||||
$this->API = $API;
|
||||
@ -48,6 +49,7 @@ abstract class Loop implements LoopInterface
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->callFork($this->loopImpl());
|
||||
}
|
||||
|
||||
@ -56,6 +58,7 @@ abstract class Loop implements LoopInterface
|
||||
//yield ['my_trace' => debug_backtrace(0, 1)[0], (string) $this];
|
||||
$this->startedLoop();
|
||||
$this->API->logger->logger("Entered $this", Logger::ULTRA_VERBOSE);
|
||||
|
||||
try {
|
||||
yield $this->loop();
|
||||
} finally {
|
||||
@ -81,5 +84,4 @@ abstract class Loop implements LoopInterface
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,8 +54,10 @@ abstract class ResumableSignalLoop extends SignalLoop implements ResumableLoopIn
|
||||
$this->resume = new Deferred();
|
||||
|
||||
$pause = $this->pause;
|
||||
$this->pause = new Deferred;
|
||||
if ($pause) Loop::defer([$pause, 'resolve']);
|
||||
$this->pause = new Deferred();
|
||||
if ($pause) {
|
||||
Loop::defer([$pause, 'resolve']);
|
||||
}
|
||||
|
||||
return $this->resume->promise();
|
||||
}
|
||||
@ -82,6 +84,7 @@ abstract class ResumableSignalLoop extends SignalLoop implements ResumableLoopIn
|
||||
public function resumeDefer()
|
||||
{
|
||||
Loop::defer([$this, 'resume']);
|
||||
|
||||
return $this->pause ? $this->pause->promise() : null;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ namespace danog\MadelineProto\Loop\Impl;
|
||||
|
||||
use Amp\Deferred;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Loop\SignalLoopInterface;
|
||||
use danog\MadelineProto\Coroutine;
|
||||
use danog\MadelineProto\Loop\SignalLoopInterface;
|
||||
|
||||
/**
|
||||
* Signal loop helper trait.
|
||||
|
@ -40,7 +40,7 @@ interface LoopInterface
|
||||
public function loop();
|
||||
|
||||
/**
|
||||
* Get name of the loop
|
||||
* Get name of the loop.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -19,8 +19,6 @@
|
||||
namespace danog\MadelineProto\Loop\Update;
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Success;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
|
||||
/**
|
||||
@ -41,6 +39,7 @@ class FeedLoop extends ResumableSignalLoop
|
||||
$this->API = $API;
|
||||
$this->channelId = $channelId;
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$API = $this->API;
|
||||
@ -83,9 +82,9 @@ class FeedLoop extends ResumableSignalLoop
|
||||
$this->parsedUpdates = [];
|
||||
$this->API->signalUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function parse($updates)
|
||||
{
|
||||
reset($updates);
|
||||
@ -110,12 +109,12 @@ class FeedLoop extends ResumableSignalLoop
|
||||
};
|
||||
$result = $this->state->checkPts($update);
|
||||
if ($result < 0) {
|
||||
$logger("PTS duplicate");
|
||||
$logger('PTS duplicate');
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($result > 0) {
|
||||
$logger("PTS hole");
|
||||
$logger('PTS hole');
|
||||
$this->updater->setLimit($this->state->pts() + $result);
|
||||
yield $this->updater->resume();
|
||||
$updates = array_merge($this->incomingUpdates, $updates);
|
||||
@ -124,20 +123,20 @@ class FeedLoop extends ResumableSignalLoop
|
||||
}
|
||||
if (isset($update['message']['id'], $update['message']['to_id']) && !in_array($update['_'], ['updateEditMessage', 'updateEditChannelMessage'])) {
|
||||
if (!$this->API->check_msg_id($update['message'])) {
|
||||
$logger("MSGID duplicate");
|
||||
$logger('MSGID duplicate');
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$logger("PTS OK");
|
||||
$logger('PTS OK');
|
||||
|
||||
$this->state->pts($update['pts']);
|
||||
|
||||
}
|
||||
|
||||
$this->save($update);
|
||||
}
|
||||
}
|
||||
|
||||
public function feed($updates)
|
||||
{
|
||||
$result = [];
|
||||
@ -148,8 +147,10 @@ class FeedLoop extends ResumableSignalLoop
|
||||
}
|
||||
$result[$res] = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function feedSingle($update)
|
||||
{
|
||||
$channelId = false;
|
||||
@ -173,7 +174,7 @@ class FeedLoop extends ResumableSignalLoop
|
||||
if ($channelId && !$this->API->getChannelStates()->has($channelId)) {
|
||||
$this->API->loadChannelState($channelId, $update);
|
||||
if (!isset($this->API->feeders[$channelId])) {
|
||||
$this->API->feeders[$channelId] = new FeedLoop($this->API, $channelId);
|
||||
$this->API->feeders[$channelId] = new self($this->API, $channelId);
|
||||
}
|
||||
if (!isset($this->API->updaters[$channelId])) {
|
||||
$this->API->updaters[$channelId] = new UpdateLoop($this->API, $channelId);
|
||||
@ -204,7 +205,7 @@ class FeedLoop extends ResumableSignalLoop
|
||||
}
|
||||
|
||||
if ($to) {
|
||||
$log .= "to_id ".json_encode($update['message']['to_id']).", ";
|
||||
$log .= 'to_id '.json_encode($update['message']['to_id']).', ';
|
||||
}
|
||||
|
||||
if ($via_bot) {
|
||||
@ -212,7 +213,7 @@ class FeedLoop extends ResumableSignalLoop
|
||||
}
|
||||
|
||||
if ($entities) {
|
||||
$log .= "entities ".json_encode($update['message']['entities']).", ";
|
||||
$log .= 'entities '.json_encode($update['message']['entities']).', ';
|
||||
}
|
||||
|
||||
$this->API->logger->logger("Not enough data: for message update $log, getting difference...", \danog\MadelineProto\Logger::VERBOSE);
|
||||
@ -233,12 +234,15 @@ class FeedLoop extends ResumableSignalLoop
|
||||
|
||||
$this->API->logger->logger('Was fed an update of type '.$update['_']." in $this...", \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->incomingUpdates[] = $update;
|
||||
|
||||
return $this->channelId;
|
||||
}
|
||||
|
||||
public function save($update)
|
||||
{
|
||||
$this->parsedUpdates[] = $update;
|
||||
}
|
||||
|
||||
public function saveMessages($messages)
|
||||
{
|
||||
foreach ($messages as $message) {
|
||||
@ -270,6 +274,6 @@ class FeedLoop extends ResumableSignalLoop
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return !$this->channelId ? "update feed loop generic" : "update feed loop channel {$this->channelId}";
|
||||
return !$this->channelId ? 'update feed loop generic' : "update feed loop channel {$this->channelId}";
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,6 @@
|
||||
|
||||
namespace danog\MadelineProto\Loop\Update;
|
||||
|
||||
use Amp\Success;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
|
||||
/**
|
||||
@ -38,6 +36,7 @@ class SeqLoop extends ResumableSignalLoop
|
||||
{
|
||||
$this->API = $API;
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$API = $this->API;
|
||||
@ -80,6 +79,7 @@ class SeqLoop extends ResumableSignalLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function parse($updates)
|
||||
{
|
||||
reset($updates);
|
||||
@ -88,8 +88,7 @@ class SeqLoop extends ResumableSignalLoop
|
||||
$key = key($updates);
|
||||
$update = $updates[$key];
|
||||
unset($updates[$key]);
|
||||
|
||||
|
||||
|
||||
$options = $update['options'];
|
||||
$seq_start = $options['seq_start'];
|
||||
$seq_end = $options['seq_end'];
|
||||
@ -117,20 +116,24 @@ class SeqLoop extends ResumableSignalLoop
|
||||
yield $this->save($update);
|
||||
}
|
||||
}
|
||||
|
||||
public function feed($updates)
|
||||
{
|
||||
$this->API->logger->logger('Was fed updates of type '.$updates['_'].'...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
|
||||
$this->incomingUpdates[] = $updates;
|
||||
}
|
||||
|
||||
public function save($updates)
|
||||
{
|
||||
$this->pendingWakeups += yield $this->feeder->feed($updates['updates']);
|
||||
}
|
||||
|
||||
public function addPendingWakeups($wakeups)
|
||||
{
|
||||
$this->pendingWakeups += $wakeups;
|
||||
}
|
||||
|
||||
public function has_all_auth()
|
||||
{
|
||||
if ($this->API->isInitingAuthorization()) {
|
||||
@ -148,6 +151,6 @@ class SeqLoop extends ResumableSignalLoop
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "update seq loop";
|
||||
return 'update seq loop';
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,8 @@
|
||||
|
||||
namespace danog\MadelineProto\Loop\Update;
|
||||
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
use Amp\Loop;
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
|
||||
/**
|
||||
@ -41,6 +40,7 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
$this->API = $API;
|
||||
$this->channelId = $channelId;
|
||||
}
|
||||
|
||||
public function loop()
|
||||
{
|
||||
$API = $this->API;
|
||||
@ -49,17 +49,18 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
while (!$this->API->settings['updates']['handle_updates'] || !$this->has_all_auth()) {
|
||||
if (yield $this->waitSignal($this->pause())) {
|
||||
$API->logger->logger("Exiting $this due to signal");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->state = $state = $this->channelId === false ? (yield $API->load_update_state_async()) : $API->loadChannelState($this->channelId);
|
||||
|
||||
|
||||
$timeout = $API->settings['updates']['getdifference_interval'];
|
||||
while (true) {
|
||||
while (!$this->API->settings['updates']['handle_updates'] || !$this->has_all_auth()) {
|
||||
if (yield $this->waitSignal($this->pause())) {
|
||||
$API->logger->logger("Exiting $this due to signal");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -71,21 +72,24 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
$this->API->logger->logger('Resumed and fetching '.$this->channelId.' difference...', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
if ($state->pts() <= 1) {
|
||||
$limit = 10;
|
||||
} else if ($API->authorization['user']['bot']) {
|
||||
} elseif ($API->authorization['user']['bot']) {
|
||||
$limit = 100000;
|
||||
} else {
|
||||
$limit = 100;
|
||||
}
|
||||
$request_pts = $state->pts();
|
||||
|
||||
try {
|
||||
$difference = yield $this->API->method_call_async_read('updates.getChannelDifference', ['channel' => 'channel#'.$this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true], ['datacenter' => $this->API->datacenter->curdc]);
|
||||
} catch (RPCErrorException $e) {
|
||||
if (in_array($e->rpc, ['CHANNEL_PRIVATE', 'CHAT_FORBIDDEN'])) {
|
||||
$feeder->signal(true);
|
||||
$API->logger->logger("Channel private, exiting $this");
|
||||
|
||||
return true;
|
||||
}
|
||||
throw $e;
|
||||
|
||||
throw $e;
|
||||
}
|
||||
if (isset($difference['timeout'])) {
|
||||
$timeout = $difference['timeout'];
|
||||
@ -99,7 +103,7 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
break 2;
|
||||
case 'updates.channelDifference':
|
||||
if ($request_pts >= $difference['pts'] && $request_pts > 1) {
|
||||
$this->API->logger->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().", using ".($state->pts() + 1), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->API->logger->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$difference['pts'] = $request_pts + 1;
|
||||
}
|
||||
$state->update($difference);
|
||||
@ -175,14 +179,17 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
|
||||
if (yield $this->waitSignal($this->pause($timeout))) {
|
||||
$API->logger->logger("Exiting $this due to signal");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setLimit($toPts)
|
||||
{
|
||||
$this->toPts = $toPts;
|
||||
}
|
||||
|
||||
public function has_all_auth()
|
||||
{
|
||||
if ($this->API->isInitingAuthorization()) {
|
||||
@ -200,6 +207,6 @@ class UpdateLoop extends ResumableSignalLoop
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return !$this->channelId ? "getUpdate loop generic" : "getUpdate loop channel {$this->channelId}";
|
||||
return !$this->channelId ? 'getUpdate loop generic' : "getUpdate loop channel {$this->channelId}";
|
||||
}
|
||||
}
|
||||
|
@ -228,10 +228,12 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
{
|
||||
return ['supportUser', 'referenceDatabase', 'channel_participants', 'event_handler', 'event_handler_instance', 'loop_callback', 'web_template', 'encrypted_layer', 'settings', 'config', 'authorization', 'authorized', 'rsa_keys', 'dh_config', 'chats', 'last_stored', 'qres', 'got_state', 'channels_state', 'updates', 'updates_key', 'full_chats', 'msg_ids', 'dialog_params', 'datacenter', 'v', 'constructors', 'td_constructors', 'methods', 'td_methods', 'td_descriptions', 'tl_callbacks', 'temp_requested_secret_chats', 'temp_rekeyed_secret_chats', 'secret_chats', 'hook_url', 'storage', 'authorized_dc', 'tos'];
|
||||
}
|
||||
|
||||
public function logger(...$params)
|
||||
{
|
||||
return $this->logger->logger(...$params);
|
||||
}
|
||||
|
||||
public function isAltervista()
|
||||
{
|
||||
return Magic::$altervista;
|
||||
@ -246,12 +248,14 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
{
|
||||
return $this->datacenter->getHTTPClient();
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$backtrace = debug_backtrace(0, 3);
|
||||
$this->asyncInitPromise = true;
|
||||
$this->setInitPromise($this->__wakeup_async($backtrace));
|
||||
}
|
||||
|
||||
public function __wakeup_async($backtrace)
|
||||
{
|
||||
set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
|
||||
@ -356,7 +360,6 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
if (isset($full['full'], $full['last_update'])) {
|
||||
$this->full_chats[$id] = ['full' => $full['full'], 'last_update' => $full['last_update']];
|
||||
}
|
||||
|
||||
}
|
||||
foreach ($this->secret_chats as $key => &$chat) {
|
||||
if (!is_array($chat)) {
|
||||
@ -592,9 +595,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
2 => [
|
||||
// The rest will be fetched using help.getConfig
|
||||
'ip_address' => '149.154.167.40',
|
||||
'port' => 443,
|
||||
'port' => 443,
|
||||
'media_only' => false,
|
||||
'tcpo_only' => false,
|
||||
'tcpo_only' => false,
|
||||
],
|
||||
],
|
||||
'ipv6' => [
|
||||
@ -602,9 +605,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
2 => [
|
||||
// The rest will be fetched using help.getConfig
|
||||
'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000e',
|
||||
'port' => 443,
|
||||
'port' => 443,
|
||||
'media_only' => false,
|
||||
'tcpo_only' => false,
|
||||
'tcpo_only' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -615,9 +618,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
2 => [
|
||||
// The rest will be fetched using help.getConfig
|
||||
'ip_address' => '149.154.167.51',
|
||||
'port' => 443,
|
||||
'port' => 443,
|
||||
'media_only' => false,
|
||||
'tcpo_only' => false,
|
||||
'tcpo_only' => false,
|
||||
],
|
||||
],
|
||||
'ipv6' => [
|
||||
@ -625,9 +628,9 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
2 => [
|
||||
// The rest will be fetched using help.getConfig
|
||||
'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000a',
|
||||
'port' => 443,
|
||||
'port' => 443,
|
||||
'media_only' => false,
|
||||
'tcpo_only' => false,
|
||||
'tcpo_only' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -648,17 +651,17 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
'proxy_extra' => Magic::$altervista ? ['address' => 'localhost', 'port' => 80] : [],
|
||||
// Extra parameters to pass to the proxy class using setExtra
|
||||
'obfuscated' => false,
|
||||
'transport' => 'tcp',
|
||||
'pfs' => extension_loaded('gmp'),
|
||||
'transport' => 'tcp',
|
||||
'pfs' => extension_loaded('gmp'),
|
||||
],
|
||||
'default_dc' => 2,
|
||||
], 'app_info' => [
|
||||
// obtained in https://my.telegram.org
|
||||
//'api_id' => you should put an API id in the settings array you provide
|
||||
//'api_hash' => you should put an API hash in the settings array you provide
|
||||
'device_model' => $device_model,
|
||||
'device_model' => $device_model,
|
||||
'system_version' => $system_version,
|
||||
'app_version' => $app_version,
|
||||
'app_version' => $app_version,
|
||||
// 🌚
|
||||
// 'app_version' => self::V,
|
||||
'lang_code' => $lang_code,
|
||||
@ -692,10 +695,10 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
*/
|
||||
// write to
|
||||
'logger_param' => Magic::$script_cwd.'/MadelineProto.log',
|
||||
'logger' => php_sapi_name() === 'cli' ? 3 : 2,
|
||||
'logger' => php_sapi_name() === 'cli' ? 3 : 2,
|
||||
// overwrite previous setting and echo logs
|
||||
'logger_level' => Logger::VERBOSE,
|
||||
'max_size' => 100 * 1024 * 1024,
|
||||
'max_size' => 100 * 1024 * 1024,
|
||||
// Logging level, available logging levels are: ULTRA_VERBOSE, VERBOSE, NOTICE, WARNING, ERROR, FATAL_ERROR. Can be provided as last parameter to the logging function.
|
||||
'rollbar_token' => '',
|
||||
], 'max_tries' => [
|
||||
@ -706,8 +709,8 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
'response' => 5,
|
||||
], 'flood_timeout' => ['wait_if_lt' => 20], 'msg_array_limit' => [
|
||||
// How big should be the arrays containing the incoming and outgoing messages?
|
||||
'incoming' => 100,
|
||||
'outgoing' => 100,
|
||||
'incoming' => 100,
|
||||
'outgoing' => 100,
|
||||
'call_queue' => 200,
|
||||
], 'peer' => [
|
||||
'full_info_cache_time' => 3600,
|
||||
@ -731,10 +734,10 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
'handler_workers' => 10,
|
||||
], 'upload' => [
|
||||
'allow_automatic_upload' => true,
|
||||
'part_size' => 512 * 1024,
|
||||
'part_size' => 512 * 1024,
|
||||
], 'download' => [
|
||||
'report_broken_media' => true,
|
||||
'part_size' => 1024 * 1024,
|
||||
'part_size' => 1024 * 1024,
|
||||
], 'pwr' => [
|
||||
'pwr' => false,
|
||||
// Need info ?
|
||||
@ -794,7 +797,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
if (isset($this->settings['logger']['logger_param']) && basename($this->settings['logger']['logger_param']) === 'MadelineProto.log') {
|
||||
$this->settings['logger']['logger_param'] = Magic::$script_cwd."/MadelineProto.log";
|
||||
$this->settings['logger']['logger_param'] = Magic::$script_cwd.'/MadelineProto.log';
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,11 +809,11 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
try {
|
||||
error_reporting(E_ALL);
|
||||
ini_set("log_errors", 1);
|
||||
ini_set("error_log", Magic::$script_cwd."/MadelineProto.log");
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', Magic::$script_cwd.'/MadelineProto.log');
|
||||
error_log('Enabled PHP logging');
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger("Could not enable PHP logging");
|
||||
$this->logger->logger('Could not enable PHP logging');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -886,6 +889,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
|
||||
yield $this->get_phone_config_async();
|
||||
}
|
||||
|
||||
public function resetUpdateSystem()
|
||||
{
|
||||
foreach ($this->channels_state->get() as $state) {
|
||||
@ -894,6 +898,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
}
|
||||
$this->startUpdateSystem();
|
||||
}
|
||||
|
||||
public function startUpdateSystem()
|
||||
{
|
||||
if ($this->asyncInitPromise) {
|
||||
@ -922,13 +927,14 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$this->seqUpdater->resume();
|
||||
}
|
||||
}
|
||||
|
||||
public function get_phone_config_async($watcherId = null)
|
||||
{
|
||||
if ($this->authorized === self::LOGGED_IN && class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal') && !$this->authorization['user']['bot'] && $this->datacenter->sockets[$this->settings['connection_settings']['default_dc']]->temp_auth_key !== null) {
|
||||
$this->logger->logger("Fetching phone config...");
|
||||
$this->logger->logger('Fetching phone config...');
|
||||
VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->settings['connection_settings']['default_dc']]));
|
||||
} else {
|
||||
$this->logger->logger("Not fetching phone config");
|
||||
$this->logger->logger('Not fetching phone config');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,14 +519,14 @@ trait AuthKeyHandler
|
||||
$code = yield $this->datacenter->fileGetContents('http://www.wolframalpha.com/api/v1/code');
|
||||
$query = 'Do prime factorization of '.$what;
|
||||
$params = [
|
||||
'async' => true,
|
||||
'banners' => 'raw',
|
||||
'async' => true,
|
||||
'banners' => 'raw',
|
||||
'debuggingdata' => false,
|
||||
'format' => 'moutput',
|
||||
'format' => 'moutput',
|
||||
'formattimeout' => 8,
|
||||
'input' => $query,
|
||||
'output' => 'JSON',
|
||||
'proxycode' => json_decode($code, true)['code'],
|
||||
'input' => $query,
|
||||
'output' => 'JSON',
|
||||
'proxycode' => json_decode($code, true)['code'],
|
||||
];
|
||||
$url = 'https://www.wolframalpha.com/input/json.jsp?'.http_build_query($params);
|
||||
|
||||
@ -612,6 +612,7 @@ trait AuthKeyHandler
|
||||
public function init_authorization_socket_async($id, $socket)
|
||||
{
|
||||
$this->init_auth_dcs[$id] = true;
|
||||
|
||||
try {
|
||||
if ($socket->session_id === null) {
|
||||
$socket->session_id = $this->random(8);
|
||||
|
@ -54,7 +54,7 @@ trait CallHandler
|
||||
$this->ack_outgoing_message_id($message_id, $old_datacenter);
|
||||
$this->got_response_for_outgoing_message_id($message_id, $old_datacenter);
|
||||
} else {
|
||||
$this->logger->logger("Could not resend ".isset($this->datacenter->sockets[$old_datacenter]->outgoing_messages[$message_id]['_']) ? $this->datacenter->sockets[$old_datacenter]->outgoing_messages[$message_id]['_'] : $message_id);
|
||||
$this->logger->logger('Could not resend '.isset($this->datacenter->sockets[$old_datacenter]->outgoing_messages[$message_id]['_']) ? $this->datacenter->sockets[$old_datacenter]->outgoing_messages[$message_id]['_'] : $message_id);
|
||||
}
|
||||
}
|
||||
if (!$postpone) {
|
||||
@ -92,6 +92,7 @@ trait CallHandler
|
||||
{
|
||||
return $this->call($this->method_call_async_write_generator($method, $args, $aargs));
|
||||
}
|
||||
|
||||
public function method_call_async_write_generator($method, $args = [], $aargs = ['msg_id' => null, 'heavy' => false]): \Generator
|
||||
{
|
||||
if (is_array($args) && isset($args['id']['_']) && isset($args['id']['dc_id']) && $args['id']['_'] === 'inputBotInlineMessageID') {
|
||||
|
@ -20,11 +20,12 @@
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
/**
|
||||
* Stores multiple states
|
||||
* Stores multiple states.
|
||||
*/
|
||||
class CombinedUpdatesState
|
||||
{
|
||||
private $states = [];
|
||||
|
||||
public function __construct($init = [])
|
||||
{
|
||||
$this->states[false] = new UpdatesState();
|
||||
@ -38,11 +39,13 @@ class CombinedUpdatesState
|
||||
$this->states[$channel] = $state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update multiple parameters
|
||||
* Update multiple parameters.
|
||||
*
|
||||
* @param array|null $init
|
||||
* @param integer $channel
|
||||
* @param int $channel
|
||||
*
|
||||
* @return UpdatesState
|
||||
*/
|
||||
public function get($channel = null, $init = [])
|
||||
@ -53,12 +56,15 @@ class CombinedUpdatesState
|
||||
if (!isset($this->states[$channel])) {
|
||||
return $this->states[$channel] = new UpdatesState($init, $channel);
|
||||
}
|
||||
|
||||
return $this->states[$channel]->update($init);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove update state
|
||||
* Remove update state.
|
||||
*
|
||||
* @param int $channel
|
||||
*
|
||||
* @param integer $channel
|
||||
* @return void
|
||||
*/
|
||||
public function remove($channel)
|
||||
@ -67,22 +73,26 @@ class CombinedUpdatesState
|
||||
unset($this->states[$channel]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if update state is present
|
||||
* Check if update state is present.
|
||||
*
|
||||
* @param int $channel
|
||||
*
|
||||
* @param integer $channel
|
||||
* @return void
|
||||
*/
|
||||
public function has($channel)
|
||||
{
|
||||
return isset($this->states[$channel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we currently busy?
|
||||
*
|
||||
* @param integer $channel
|
||||
* @param boolean|null $set
|
||||
* @return boolean
|
||||
* @param int $channel
|
||||
* @param bool|null $set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncLoading($channel, $set = null)
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ trait Files
|
||||
static function () use ($file_id, $part_num, $part_total_num, $part_size, $f, $ctx, $ige, $seekable) {
|
||||
if ($seekable) {
|
||||
fseek($f, $part_num * $part_size);
|
||||
} else if (ftell($f) !== $part_num * $part_size) {
|
||||
} elseif (ftell($f) !== $part_num * $part_size) {
|
||||
throw new \danog\MadelineProto\Exception('Wrong position!');
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Artax\Request;
|
||||
|
||||
/**
|
||||
@ -30,7 +29,7 @@ trait PeerHandler
|
||||
public $caching_simple = [];
|
||||
public $caching_simple_username = [];
|
||||
public $caching_possible_username = [];
|
||||
|
||||
|
||||
public function to_supergroup($id)
|
||||
{
|
||||
return -($id + pow(10, (int) floor(log($id, 10) + 3)));
|
||||
@ -65,9 +64,11 @@ trait PeerHandler
|
||||
}*/
|
||||
if (!isset($this->caching_simple[$user['id']]) && !(isset($user['username']) && isset($this->caching_simple_username[$user['username']]))) {
|
||||
$this->logger->logger("No access hash with user {$user['id']}, trying to fetch by ID...");
|
||||
if (isset($user['username']) && !isset($this->caching_simple_username[$user['username']])) $this->caching_possible_username[$user['id']] = $user['username'];
|
||||
if (isset($user['username']) && !isset($this->caching_simple_username[$user['username']])) {
|
||||
$this->caching_possible_username[$user['id']] = $user['username'];
|
||||
}
|
||||
$this->cache_pwr_chat($user['id'], false, true);
|
||||
} else if (isset($user['username']) && !isset($this->chats[$user['id']]) && !isset($this->caching_simple_username[$user['username']])) {
|
||||
} elseif (isset($user['username']) && !isset($this->chats[$user['id']]) && !isset($this->caching_simple_username[$user['username']])) {
|
||||
$this->logger->logger("No access hash with user {$user['id']}, trying to fetch by username...");
|
||||
$this->cache_pwr_chat($user['username'], false, true);
|
||||
} else {
|
||||
@ -111,15 +112,18 @@ trait PeerHandler
|
||||
if (!isset($chat['access_hash'])) {
|
||||
if (!isset($this->caching_simple[$bot_api_id]) && !(isset($chat['username']) && isset($this->caching_simple_username[$chat['username']]))) {
|
||||
$this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, trying to fetch by ID...");
|
||||
if (isset($chat['username']) && !isset($this->caching_simple_username[$chat['username']])) $this->caching_possible_username[$bot_api_id] = $chat['username'];
|
||||
if (isset($chat['username']) && !isset($this->caching_simple_username[$chat['username']])) {
|
||||
$this->caching_possible_username[$bot_api_id] = $chat['username'];
|
||||
}
|
||||
|
||||
$this->cache_pwr_chat($bot_api_id, false, true);
|
||||
} else if (isset($chat['username']) && !isset($this->chats[$bot_api_id]) && !isset($this->caching_simple_username[$chat['username']])) {
|
||||
} elseif (isset($chat['username']) && !isset($this->chats[$bot_api_id]) && !isset($this->caching_simple_username[$chat['username']])) {
|
||||
$this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, trying to fetch by username...");
|
||||
$this->cache_pwr_chat($chat['username'], false, true);
|
||||
} else {
|
||||
$this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, tried and failed to fetch data...");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (!isset($this->chats[$bot_api_id]) || $this->chats[$bot_api_id] !== $chat) {
|
||||
@ -141,13 +145,13 @@ trait PeerHandler
|
||||
public function cache_pwr_chat($id, $full_fetch, $send)
|
||||
{
|
||||
$this->callFork((function () use ($id, $full_fetch, $send) {
|
||||
try {
|
||||
yield $this->get_pwr_chat_async($id, $full_fetch, $send);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger("While caching: ".$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger("While caching: ".$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
try {
|
||||
yield $this->get_pwr_chat_async($id, $full_fetch, $send);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$this->logger->logger('While caching: '.$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('While caching: '.$e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
})());
|
||||
}
|
||||
|
||||
@ -248,6 +252,7 @@ trait PeerHandler
|
||||
if (!isset($id['from_id']) || $id['to_id']['_'] !== 'peerUser' || $id['to_id']['user_id'] !== $this->authorization['user']['id']) {
|
||||
return $this->get_id($id['to_id']);
|
||||
}
|
||||
|
||||
return $id['from_id'];
|
||||
|
||||
case 'updateChannelReadMessagesContents':
|
||||
@ -321,10 +326,13 @@ trait PeerHandler
|
||||
if (is_string($id)) {
|
||||
$id = \danog\MadelineProto\Magic::$bigint ? (float) $id : (int) $id;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function get_info_async($id, $recursive = true)
|
||||
{
|
||||
if (is_array($id)) {
|
||||
@ -345,7 +353,9 @@ trait PeerHandler
|
||||
}
|
||||
}
|
||||
$try_id = $this->get_id($id);
|
||||
if ($try_id !== false) $id = $try_id;
|
||||
if ($try_id !== false) {
|
||||
$id = $try_id;
|
||||
}
|
||||
|
||||
$tried_simple = false;
|
||||
|
||||
@ -367,7 +377,9 @@ trait PeerHandler
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
|
||||
} finally {
|
||||
if (isset($this->caching_simple[$id])) unset($this->caching_simple[$id]);
|
||||
if (isset($this->caching_simple[$id])) {
|
||||
unset($this->caching_simple[$id]);
|
||||
}
|
||||
$tried_simple = true;
|
||||
}
|
||||
}
|
||||
@ -384,6 +396,7 @@ trait PeerHandler
|
||||
}
|
||||
if (!isset($this->settings['pwr']['requests']) || $this->settings['pwr']['requests'] === true && $recursive) {
|
||||
$dbres = [];
|
||||
|
||||
try {
|
||||
$dbres = json_decode(yield $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id='.$id), true);
|
||||
} catch (\Throwable $e) {
|
||||
@ -400,8 +413,10 @@ trait PeerHandler
|
||||
|
||||
$user = $this->caching_possible_username[$id];
|
||||
unset($this->caching_possible_username[$id]);
|
||||
|
||||
return yield $this->get_info_async($user);
|
||||
}
|
||||
|
||||
throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
|
||||
}
|
||||
if (preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $id, $matches)) {
|
||||
@ -697,6 +712,7 @@ trait PeerHandler
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
if ($e->rpc === 'CHAT_ADMIN_REQUIRED') {
|
||||
$this->logger->logger($e->rpc);
|
||||
|
||||
return $has_more;
|
||||
} else {
|
||||
throw $e;
|
||||
@ -759,7 +775,9 @@ trait PeerHandler
|
||||
$offset += count($gres['participants']);
|
||||
} while (count($gres['participants']));
|
||||
|
||||
if ($offset === $limit) return true;
|
||||
if ($offset === $limit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $has_more;
|
||||
}
|
||||
@ -816,7 +834,7 @@ trait PeerHandler
|
||||
$request = (new Request('https://id.pwrtelegram.xyz/db'.$this->settings['pwr']['db_token'].'/addnewmadeline?d=pls&from='.$id, 'POST'))->withHeader('content-type', 'application/json')->withBody($payload);
|
||||
|
||||
$result = yield (yield $this->datacenter->getHTTPClient()->request($request))->getBody();
|
||||
|
||||
|
||||
$this->logger->logger("============ $result =============", \danog\MadelineProto\Logger::VERBOSE);
|
||||
$this->qres = [];
|
||||
$this->last_stored = time() + 10;
|
||||
@ -838,7 +856,9 @@ trait PeerHandler
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
if (isset($this->caching_simple_username[$username])) unset($this->caching_simple_username[$username]);
|
||||
if (isset($this->caching_simple_username[$username])) {
|
||||
unset($this->caching_simple_username[$username]);
|
||||
}
|
||||
}
|
||||
if ($res['_'] === 'contacts.resolvedPeer') {
|
||||
return $res;
|
||||
|
@ -19,9 +19,6 @@
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Deferred;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\TL\TLCallback;
|
||||
use danog\MadelineProto\Tools;
|
||||
@ -85,7 +82,6 @@ class ReferenceDatabase implements TLCallback
|
||||
'user' => self::USER_PHOTO_ORIGIN,
|
||||
'userFull' => self::USER_PHOTO_ORIGIN,
|
||||
|
||||
|
||||
'wallPaper' => self::WALLPAPER_ORIGIN,
|
||||
|
||||
'messages.savedGifs' => self::SAVED_GIFS_ORIGIN,
|
||||
@ -214,6 +210,7 @@ class ReferenceDatabase implements TLCallback
|
||||
}
|
||||
if (!isset($location['file_reference'])) {
|
||||
$this->API->logger->logger("Object {$location['_']} does not have reference", \danog\MadelineProto\Logger::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
$key = count($this->cacheContexts) - 1;
|
||||
@ -528,6 +525,7 @@ class ReferenceDatabase implements TLCallback
|
||||
public function populateReference(array $object)
|
||||
{
|
||||
$object['file_reference'] = yield $this->getReference(self::LOCATION_CONTEXT[$object['_']], $object);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ trait ResponseHandler
|
||||
{
|
||||
public function send_msgs_state_info_async($req_msg_id, $msg_ids, $datacenter)
|
||||
{
|
||||
$this->logger->logger("Sending state info for ".count($msg_ids)." message IDs");
|
||||
$this->logger->logger('Sending state info for '.count($msg_ids).' message IDs');
|
||||
$info = '';
|
||||
foreach ($msg_ids as $msg_id) {
|
||||
$cur_info = 0;
|
||||
@ -148,7 +148,7 @@ trait ResponseHandler
|
||||
// Acknowledge that I received the server's response
|
||||
if (isset($this->datacenter->sockets[$datacenter]->incoming_messages[$this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id']])) {
|
||||
$this->ack_incoming_message_id($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']['orig_message']['msg_id'], $datacenter);
|
||||
// Acknowledge that I received the server's response
|
||||
// Acknowledge that I received the server's response
|
||||
} else {
|
||||
$message = $this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content'];
|
||||
$this->datacenter->sockets[$datacenter]->check_message_id($message['orig_message']['msg_id'], ['outgoing' => false, 'container' => true]);
|
||||
@ -361,6 +361,7 @@ trait ResponseHandler
|
||||
if ($response['error_message'] === 'MSG_WAIT_FAILED') {
|
||||
$this->datacenter->sockets[$datacenter]->call_queue[$request['queue']] = [];
|
||||
$this->method_recall('', ['message_id' => $request_id, 'datacenter' => $datacenter, 'postpone' => true]);
|
||||
|
||||
return;
|
||||
}
|
||||
$this->got_response_for_outgoing_message_id($request_id, $datacenter);
|
||||
@ -628,6 +629,7 @@ trait ResponseHandler
|
||||
$to_id = isset($updates['chat_id']) ? -$updates['chat_id'] : ($updates['out'] ? $updates['user_id'] : $this->authorization['user']['id']);
|
||||
if (!yield $this->peer_isset_async($from_id) || !yield $this->peer_isset_async($to_id) || isset($updates['via_bot_id']) && !yield $this->peer_isset_async($updates['via_bot_id']) || isset($updates['entities']) && !yield $this->entities_peer_isset_async($updates['entities']) || isset($updates['fwd_from']) && !yield $this->fwd_peer_isset_async($updates['fwd_from'])) {
|
||||
yield $this->updaters[false]->resume();
|
||||
|
||||
return;
|
||||
}
|
||||
$message = $updates;
|
||||
|
@ -21,7 +21,6 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Artax\Request;
|
||||
use Amp\Deferred;
|
||||
use Amp\Delayed;
|
||||
use Amp\Loop;
|
||||
|
||||
/**
|
||||
@ -98,22 +97,24 @@ trait UpdateHandler
|
||||
|
||||
return $updates;
|
||||
}
|
||||
|
||||
public $update_resolved = false;
|
||||
public $update_deferred;
|
||||
|
||||
public function waitUpdate()
|
||||
{
|
||||
if (!$this->update_deferred) {
|
||||
$this->update_deferred = new Deferred;
|
||||
$this->update_deferred = new Deferred();
|
||||
}
|
||||
yield $this->update_deferred->promise();
|
||||
$this->update_resolved = false;
|
||||
$this->update_deferred = new Deferred;
|
||||
$this->update_deferred = new Deferred();
|
||||
}
|
||||
|
||||
public function signalUpdate()
|
||||
{
|
||||
if (!$this->update_deferred) {
|
||||
$this->update_deferred = new Deferred;
|
||||
$this->update_deferred = new Deferred();
|
||||
}
|
||||
Loop::defer(function () {
|
||||
if (!$this->update_resolved) {
|
||||
@ -125,7 +126,10 @@ trait UpdateHandler
|
||||
|
||||
public function check_msg_id($message)
|
||||
{
|
||||
if (!isset($message['to_id'])) return true;
|
||||
if (!isset($message['to_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$peer_id = $this->get_id($message['to_id']);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
@ -152,10 +156,12 @@ trait UpdateHandler
|
||||
|
||||
return $this->channels_state->get(false);
|
||||
}
|
||||
|
||||
public function loadChannelState($channelId = null, $init = [])
|
||||
{
|
||||
return $this->channels_state->get($channelId, $init);
|
||||
}
|
||||
|
||||
public function getChannelStates()
|
||||
{
|
||||
return $this->channels_state;
|
||||
|
@ -20,37 +20,37 @@
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
/**
|
||||
* Stores the state of updates
|
||||
* Stores the state of updates.
|
||||
*/
|
||||
class UpdatesState
|
||||
{
|
||||
/**
|
||||
* PTS
|
||||
* PTS.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $pts = 1;
|
||||
/**
|
||||
* QTS
|
||||
* QTS.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $qts = -1;
|
||||
/**
|
||||
* Seq
|
||||
* Seq.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $seq = 0;
|
||||
/**
|
||||
* Date
|
||||
* Date.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $date = 1;
|
||||
|
||||
/**
|
||||
* Channel ID
|
||||
* Channel ID.
|
||||
*
|
||||
* @var int|bool
|
||||
*/
|
||||
@ -59,23 +59,24 @@ class UpdatesState
|
||||
/**
|
||||
* Is busy?
|
||||
*
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*/
|
||||
private $syncLoading = false;
|
||||
|
||||
/**
|
||||
* Init function
|
||||
* Init function.
|
||||
*
|
||||
* @param array $init Initial parameters
|
||||
* @param boolean $channelId Channel ID
|
||||
* @param array $init Initial parameters
|
||||
* @param bool $channelId Channel ID
|
||||
*/
|
||||
public function __construct($init = [], $channelId = false)
|
||||
{
|
||||
$this->channelId = $channelId;
|
||||
$this->update($init);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep function
|
||||
* Sleep function.
|
||||
*
|
||||
* @return array Parameters to serialize
|
||||
*/
|
||||
@ -83,17 +84,19 @@ class UpdatesState
|
||||
{
|
||||
return $this->channelId ? ['pts', 'channelId'] : ['pts', 'qts', 'seq', 'date', 'channelId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this state relative to a channel?
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function isChannel()
|
||||
{
|
||||
return (bool) $this->channelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel ID
|
||||
* Get the channel ID.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
@ -101,24 +104,28 @@ class UpdatesState
|
||||
{
|
||||
return $this->channelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we currently busy?
|
||||
*
|
||||
* @param boolean|null $set
|
||||
* @return boolean
|
||||
* @param bool|null $set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncLoading($set = null)
|
||||
{
|
||||
if ($set !== null) {
|
||||
$this->syncLoading = $set;
|
||||
}
|
||||
|
||||
return $this->syncLoading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update multiple parameters
|
||||
* Update multiple parameters.
|
||||
*
|
||||
* @param array $init
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function update($init)
|
||||
@ -128,75 +135,91 @@ class UpdatesState
|
||||
$this->{$param}($init[$param]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set PTS
|
||||
* Get/set PTS.
|
||||
*
|
||||
* @param integer $set
|
||||
* @return integer
|
||||
* @param int $set
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function pts($set = 0)
|
||||
{
|
||||
if ($set !== 0 && $set > $this->pts) {
|
||||
$this->pts = $set;
|
||||
}
|
||||
|
||||
return $this->pts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set QTS
|
||||
* Get/set QTS.
|
||||
*
|
||||
* @param integer $set
|
||||
* @return integer
|
||||
* @param int $set
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function qts($set = 0)
|
||||
{
|
||||
if ($set !== 0 && $set > $this->qts) {
|
||||
$this->qts = $set;
|
||||
}
|
||||
|
||||
return $this->qts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set seq
|
||||
* Get/set seq.
|
||||
*
|
||||
* @param integer $set
|
||||
* @return integer
|
||||
* @param int $set
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function seq($set = 0)
|
||||
{
|
||||
if ($set !== 0 && $set > $this->seq) {
|
||||
$this->seq = $set;
|
||||
}
|
||||
|
||||
return $this->seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set date
|
||||
* Get/set date.
|
||||
*
|
||||
* @param integer $set
|
||||
* @return integer
|
||||
* @param int $set
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function date($set = 0)
|
||||
{
|
||||
if ($set !== 0 && $set > $this->date) {
|
||||
$this->date = $set;
|
||||
}
|
||||
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validity of PTS contained in update
|
||||
* Check validity of PTS contained in update.
|
||||
*
|
||||
* @param array $update
|
||||
*
|
||||
* @return int -1 if it's too old, 0 if it's ok, 1 if it's too new
|
||||
*/
|
||||
public function checkPts($update)
|
||||
{
|
||||
return $update['pts'] - ($this->pts + $update['pts_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validity of seq contained in update
|
||||
* Check validity of seq contained in update.
|
||||
*
|
||||
* @param int $seq
|
||||
*
|
||||
* @return int -1 if it's too old, 0 if it's ok, 1 if it's too new
|
||||
*/
|
||||
public function checkSeq($seq)
|
||||
|
@ -124,10 +124,12 @@ class Magic
|
||||
}
|
||||
$backtrace = debug_backtrace(0);
|
||||
self::$script_cwd = self::$cwd = dirname(end($backtrace)['file']);
|
||||
|
||||
try {
|
||||
self::$cwd = getcwd();
|
||||
self::$can_getcwd = true;
|
||||
} catch (\danog\MadelineProto\Exception $e) {}
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
}
|
||||
self::$inited = true;
|
||||
}
|
||||
}
|
||||
@ -151,6 +153,7 @@ class Magic
|
||||
return self::$can_getmypid = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getcwd()
|
||||
{
|
||||
return self::$can_getcwd ? getcwd() : self::$cwd;
|
||||
|
@ -40,6 +40,7 @@ class MyTelegramOrgWrapper
|
||||
{
|
||||
return ['logged', 'hash', 'token', 'number', 'creation_hash', 'settings'];
|
||||
}
|
||||
|
||||
public function __construct($settings)
|
||||
{
|
||||
if (!isset($settings['all'])) {
|
||||
@ -58,21 +59,21 @@ class MyTelegramOrgWrapper
|
||||
'proxy_extra' => Magic::$altervista ? ['address' => 'localhost', 'port' => 80] : [],
|
||||
// Extra parameters to pass to the proxy class using setExtra
|
||||
'obfuscated' => false,
|
||||
'transport' => 'tcp',
|
||||
'pfs' => extension_loaded('gmp'),
|
||||
'transport' => 'tcp',
|
||||
'pfs' => extension_loaded('gmp'),
|
||||
],
|
||||
];
|
||||
}
|
||||
$this->settings = $settings;
|
||||
$this->__wakeup();
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->datacenter = new DataCenter(
|
||||
new class($this->settings)
|
||||
{
|
||||
new class($this->settings) {
|
||||
public function __construct($settings)
|
||||
{
|
||||
{
|
||||
$this->logger = new Logger(
|
||||
isset($settings['logger']['logger']) ? $settings['logger']['logger'] : php_sapi_name() === 'cli' ? 3 : 2,
|
||||
isset($settings['logger']['logger_param']) ? $settings['logger']['logger_param'] : Magic::$script_cwd.'/MadelineProto.log',
|
||||
@ -84,6 +85,7 @@ class MyTelegramOrgWrapper
|
||||
$this->settings['connection_settings']
|
||||
);
|
||||
}
|
||||
|
||||
public function login_async($number)
|
||||
{
|
||||
$this->number = $number;
|
||||
@ -271,14 +273,17 @@ class MyTelegramOrgWrapper
|
||||
|
||||
return $final_headers;
|
||||
}
|
||||
|
||||
public function async($async)
|
||||
{
|
||||
$this->async = $async;
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$name .= '_async';
|
||||
$async = is_array(end($arguments)) && isset(end($arguments)['async']) ? end($arguments)['async'] : $this->async;
|
||||
|
||||
return $async ? $this->{$name}(...$arguments) : $this->wait($this->{$name}(...$arguments));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// Based on AMPHP's default socket pool
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
@ -8,22 +9,22 @@ use Amp\CancelledException;
|
||||
use Amp\Failure;
|
||||
use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
use Amp\Struct;
|
||||
use Amp\Success;
|
||||
use Amp\Socket\SocketPool;
|
||||
use function Amp\call;
|
||||
use Amp\Socket\ClientConnectContext;
|
||||
use Amp\Socket\ClientSocket;
|
||||
use Amp\Socket\SocketPool;
|
||||
use Amp\Struct;
|
||||
use Amp\Success;
|
||||
use League\Uri;
|
||||
use function Amp\call;
|
||||
|
||||
class ProxySocketPool implements SocketPool
|
||||
{
|
||||
use Tools;
|
||||
const ALLOWED_SCHEMES = [
|
||||
'tcp' => null,
|
||||
'udp' => null,
|
||||
'tcp' => null,
|
||||
'udp' => null,
|
||||
'unix' => null,
|
||||
'udg' => null,
|
||||
'udg' => null,
|
||||
];
|
||||
private $sockets = [];
|
||||
private $socketIdUriMap = [];
|
||||
@ -31,35 +32,38 @@ class ProxySocketPool implements SocketPool
|
||||
private $idleTimeout;
|
||||
private $socketContext;
|
||||
private $dataCenter;
|
||||
|
||||
public function __construct(DataCenter $dataCenter, int $idleTimeout = 10000, ClientConnectContext $socketContext = null)
|
||||
{
|
||||
$this->idleTimeout = $idleTimeout;
|
||||
$this->socketContext = $socketContext ?? new ClientConnectContext;
|
||||
$this->socketContext = $socketContext ?? new ClientConnectContext();
|
||||
$this->dataCenter = $dataCenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws SocketException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function normalizeUri(string $uri): string
|
||||
{
|
||||
if (\stripos($uri, 'unix://') === 0) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
try {
|
||||
$parts = Uri\parse($uri);
|
||||
} catch (\Exception $exception) {
|
||||
throw new SocketException("Could not parse URI", 0, $exception);
|
||||
throw new SocketException('Could not parse URI', 0, $exception);
|
||||
}
|
||||
if ($parts['scheme'] === null) {
|
||||
throw new SocketException("Invalid URI for socket pool; no scheme given");
|
||||
throw new SocketException('Invalid URI for socket pool; no scheme given');
|
||||
}
|
||||
$port = $parts['port'] ?? 0;
|
||||
if ($parts['host'] === null || $port === 0) {
|
||||
throw new SocketException("Invalid URI for socket pool; missing host or port");
|
||||
throw new SocketException('Invalid URI for socket pool; missing host or port');
|
||||
}
|
||||
$scheme = \strtolower($parts['scheme']);
|
||||
$host = \strtolower($parts['host']);
|
||||
@ -71,17 +75,19 @@ class ProxySocketPool implements SocketPool
|
||||
));
|
||||
}
|
||||
if ($parts['query'] !== null || $parts['fragment'] !== null) {
|
||||
throw new SocketException("Invalid URI for socket pool; query or fragment components not allowed");
|
||||
throw new SocketException('Invalid URI for socket pool; query or fragment components not allowed');
|
||||
}
|
||||
if ($parts['path'] !== '') {
|
||||
throw new SocketException("Invalid URI for socket pool; path component must be empty");
|
||||
throw new SocketException('Invalid URI for socket pool; path component must be empty');
|
||||
}
|
||||
if ($parts['user'] !== null) {
|
||||
throw new SocketException("Invalid URI for socket pool; user component not allowed");
|
||||
throw new SocketException('Invalid URI for socket pool; user component not allowed');
|
||||
}
|
||||
|
||||
return $scheme.'://'.$host.':'.$port;
|
||||
}
|
||||
/** @inheritdoc */
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function checkout(string $uri, CancellationToken $token = null): Promise
|
||||
{
|
||||
// A request might already be cancelled before we reach the checkout, so do not even attempt to checkout in that
|
||||
@ -109,14 +115,18 @@ class ProxySocketPool implements SocketPool
|
||||
if ($socket->idleWatcher !== null) {
|
||||
Loop::disable($socket->idleWatcher);
|
||||
}
|
||||
|
||||
return new Success(new ClientSocket($socket->resource));
|
||||
}
|
||||
|
||||
return $this->checkoutNewSocket($uri, $token);
|
||||
}
|
||||
|
||||
private function checkoutNewSocket(string $uri, CancellationToken $token = null): Promise
|
||||
{
|
||||
return call(function () use ($uri, $token) {
|
||||
$this->pendingCount[$uri] = ($this->pendingCount[$uri] ?? 0) + 1;
|
||||
|
||||
try {
|
||||
/** @var ClientSocket $rawSocket */
|
||||
$rawSocket = yield $this->call($this->dataCenter->rawConnectAsync($uri, $token, $this->socketContext));
|
||||
@ -126,9 +136,7 @@ class ProxySocketPool implements SocketPool
|
||||
}
|
||||
}
|
||||
$socketId = (int) $rawSocket->getResource();
|
||||
$socket = new class
|
||||
|
||||
{
|
||||
$socket = new class() {
|
||||
use Struct;
|
||||
public $id;
|
||||
public $uri;
|
||||
@ -142,14 +150,17 @@ class ProxySocketPool implements SocketPool
|
||||
$socket->isAvailable = false;
|
||||
$this->sockets[$uri][$socketId] = $socket;
|
||||
$this->socketIdUriMap[$socketId] = $uri;
|
||||
|
||||
return $rawSocket;
|
||||
});
|
||||
}
|
||||
/** @inheritdoc */
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function clear(ClientSocket $socket): void
|
||||
{
|
||||
$this->clearFromId((int) $socket->getResource());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $socketId
|
||||
*/
|
||||
@ -173,7 +184,8 @@ class ProxySocketPool implements SocketPool
|
||||
unset($this->sockets[$uri]);
|
||||
}
|
||||
}
|
||||
/** @inheritdoc */
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function checkin(ClientSocket $socket): void
|
||||
{
|
||||
$socketId = (int) $socket->getResource();
|
||||
@ -186,6 +198,7 @@ class ProxySocketPool implements SocketPool
|
||||
$resource = $socket->getResource();
|
||||
if (!\is_resource($resource) || \feof($resource)) {
|
||||
$this->clearFromId((int) $resource);
|
||||
|
||||
return;
|
||||
}
|
||||
$socket = $this->sockets[$uri][$socketId];
|
||||
|
@ -43,6 +43,7 @@ class RPCErrorException extends \Exception
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ class Serialization
|
||||
public static function serialize_all($exception)
|
||||
{
|
||||
echo $exception.PHP_EOL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static function realpaths($file)
|
||||
|
@ -18,9 +18,7 @@
|
||||
|
||||
namespace danog\MadelineProto\Stream\Async;
|
||||
|
||||
use Amp\Failure;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
/**
|
||||
* Buffered stream helper trait.
|
||||
|
@ -20,7 +20,6 @@ namespace danog\MadelineProto\Stream\Async;
|
||||
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use function Amp\call;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
@ -33,6 +32,7 @@ use danog\MadelineProto\Tools;
|
||||
trait Stream
|
||||
{
|
||||
use Tools;
|
||||
|
||||
public function connect(ConnectionContext $ctx, string $header = ''): Promise
|
||||
{
|
||||
return $this->call($this->connectAsync($ctx, $header));
|
||||
|
@ -23,9 +23,7 @@ use Amp\Success;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\Stream\Async\RawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use function Amp\call;
|
||||
use function Amp\Socket\connect;
|
||||
use danog\MadelineProto\NothingInTheSocketException;
|
||||
|
||||
/**
|
||||
* Buffered raw stream.
|
||||
@ -42,6 +40,7 @@ class BufferedRawStream implements \danog\MadelineProto\Stream\BufferedStreamInt
|
||||
protected $memory_stream;
|
||||
private $append = '';
|
||||
private $append_after = 0;
|
||||
|
||||
/**
|
||||
* Asynchronously connect to a TCP/TLS server.
|
||||
*
|
||||
@ -177,6 +176,7 @@ class BufferedRawStream implements \danog\MadelineProto\Stream\BufferedStreamInt
|
||||
$chunk = yield $this->read();
|
||||
if ($chunk === null) {
|
||||
$this->disconnect();
|
||||
|
||||
throw new \danog\MadelineProto\NothingInTheSocketException();
|
||||
}
|
||||
fwrite($this->memory_stream, $chunk);
|
||||
@ -213,8 +213,8 @@ class BufferedRawStream implements \danog\MadelineProto\Stream\BufferedStreamInt
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -310,9 +310,10 @@ class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterf
|
||||
|
||||
return $this->write_buffer->bufferWrite($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -19,7 +19,6 @@
|
||||
namespace danog\MadelineProto\Stream;
|
||||
|
||||
use Amp\CancellationToken;
|
||||
use Amp\Promise;
|
||||
use Amp\Socket\ClientConnectContext;
|
||||
use Amp\Uri\Uri;
|
||||
|
||||
@ -320,7 +319,6 @@ class ConnectionContext
|
||||
return $this->nextStreams[$this->key][0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a stream from the stream chain.
|
||||
*
|
||||
|
@ -98,9 +98,10 @@ class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -106,9 +106,10 @@ class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -24,7 +24,6 @@ use danog\MadelineProto\Stream\Async\BufferedStream;
|
||||
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\MTProtoBufferInterface;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* HTTP stream wrapper.
|
||||
@ -180,9 +179,10 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
|
||||
{
|
||||
return new Success($this->code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -39,9 +39,10 @@ class HttpsStream extends HttpStream implements MTProtoBufferInterface
|
||||
{
|
||||
return parent::connectAsync($ctx->getCtx()->secure(true), $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -23,7 +23,6 @@ use danog\MadelineProto\Stream\Async\BufferedStream;
|
||||
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\MTProtoBufferInterface;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* TCP Intermediate stream wrapper.
|
||||
@ -89,9 +88,10 @@ class IntermediatePaddedStream implements BufferedStreamInterface, MTProtoBuffer
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -87,9 +87,10 @@ class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterf
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -24,7 +24,6 @@ use danog\MadelineProto\Stream\Async\Buffer;
|
||||
use danog\MadelineProto\Stream\Async\BufferedStream;
|
||||
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Tools;
|
||||
|
||||
/**
|
||||
* Obfuscated2 stream wrapper.
|
||||
@ -195,9 +194,10 @@ class ObfuscatedStream implements BufferedProxyStreamInterface
|
||||
}
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -19,11 +19,11 @@
|
||||
namespace danog\MadelineProto\Stream\Proxy;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Socket\ClientTlsContext;
|
||||
use danog\MadelineProto\Stream\Async\RawStream;
|
||||
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\RawProxyStreamInterface;
|
||||
use Amp\Socket\ClientTlsContext;
|
||||
|
||||
/**
|
||||
* HTTP proxy stream wrapper.
|
||||
@ -56,7 +56,7 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
|
||||
if (strlen(inet_pton($address)) === 16) {
|
||||
$address = '['.$address.']';
|
||||
}
|
||||
|
||||
|
||||
yield $this->stream->write("CONNECT $address:$port HTTP/1.1\r\nHost: $address:$port\r\nAccept: */*\r\n".$this->getProxyAuthHeader()."Connection: keep-Alive\r\n\r\n");
|
||||
|
||||
$buffer = yield $this->stream->getReadBuffer($l);
|
||||
@ -124,7 +124,7 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
|
||||
\danog\MadelineProto\Logger::log('Connected to '.$address.':'.$port.' via http');
|
||||
|
||||
if ($secure && method_exists($this->getSocket(), 'enableCrypto')) {
|
||||
yield $this->getSocket()->enableCrypto((new ClientTlsContext)->withPeerName($uri->getHost()));
|
||||
yield $this->getSocket()->enableCrypto((new ClientTlsContext())->withPeerName($uri->getHost()));
|
||||
}
|
||||
|
||||
if (strlen($header)) {
|
||||
@ -196,9 +196,10 @@ class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
|
||||
{
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -19,11 +19,11 @@
|
||||
namespace danog\MadelineProto\Stream\Proxy;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Socket\ClientTlsContext;
|
||||
use danog\MadelineProto\Stream\Async\RawStream;
|
||||
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\RawProxyStreamInterface;
|
||||
use Amp\Socket\ClientTlsContext;
|
||||
|
||||
/**
|
||||
* Socks5 stream wrapper.
|
||||
@ -54,7 +54,7 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
|
||||
$methods .= chr(2);
|
||||
}
|
||||
$this->stream = yield $ctx->getStream(chr(5).chr(strlen($methods)).$methods);
|
||||
|
||||
|
||||
$l = 2;
|
||||
|
||||
$buffer = yield $this->stream->getReadBuffer($l);
|
||||
@ -139,7 +139,7 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
|
||||
\danog\MadelineProto\Logger::log(['Connected to '.$ip.':'.$port.' via socks5']);
|
||||
|
||||
if ($secure && method_exists($this->getSocket(), 'enableCrypto')) {
|
||||
yield $this->getSocket()->enableCrypto((new ClientTlsContext)->withPeerName($uri->getHost()));
|
||||
yield $this->getSocket()->enableCrypto((new ClientTlsContext())->withPeerName($uri->getHost()));
|
||||
}
|
||||
if (strlen($header)) {
|
||||
yield (yield $this->stream->getWriteBuffer(strlen($header)))->bufferWrite($header);
|
||||
@ -201,8 +201,9 @@ class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterfac
|
||||
{
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
|
@ -45,8 +45,8 @@ interface StreamInterface
|
||||
public function disconnect();
|
||||
|
||||
/**
|
||||
* Get underlying AMPHP socket resource
|
||||
*
|
||||
* Get underlying AMPHP socket resource.
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): Socket;
|
||||
|
@ -40,6 +40,7 @@ class DefaultStream extends Socket implements RawStreamInterface
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function enableCrypto(ClientTlsContext $tlsContext = null): \Amp\Promise
|
||||
{
|
||||
return $this->enableCrypto($tlsContext);
|
||||
@ -105,9 +106,10 @@ class DefaultStream extends Socket implements RawStreamInterface
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
public function getSocket(): \Amp\Socket\Socket
|
||||
|
@ -31,7 +31,6 @@ use Amp\Websocket\Rfc7692CompressionFactory;
|
||||
use danog\MadelineProto\Stream\Async\RawStream;
|
||||
use danog\MadelineProto\Stream\ConnectionContext;
|
||||
use danog\MadelineProto\Stream\RawStreamInterface;
|
||||
use danog\MadelineProto\Tools;
|
||||
use function Amp\Websocket\generateKey;
|
||||
use function Amp\Websocket\validateAcceptForKey;
|
||||
|
||||
@ -60,7 +59,7 @@ class WsStream implements RawStreamInterface
|
||||
$stream = yield $ctx->getStream();
|
||||
$resource = $stream->getStream()->getResource();
|
||||
|
||||
$this->compressionFactory = new Rfc7692CompressionFactory;
|
||||
$this->compressionFactory = new Rfc7692CompressionFactory();
|
||||
|
||||
$handshake = new Handshake(str_replace('tcp://', $ctx->isSecure() ? 'ws://' : 'wss://', $ctx->getStringUri()));
|
||||
|
||||
@ -154,8 +153,10 @@ class WsStream implements RawStreamInterface
|
||||
if (($query = $uri->getQuery()) !== '') {
|
||||
$path .= '?'.$query;
|
||||
}
|
||||
|
||||
return \sprintf("GET %s HTTP/1.1\r\n%s\r\n", $path, Rfc7230::formatHeaders($headers));
|
||||
}
|
||||
|
||||
private function handleResponse(string $headerBuffer, string $key): array
|
||||
{
|
||||
if (\substr($headerBuffer, -4) !== "\r\n\r\n") {
|
||||
@ -190,8 +191,10 @@ class WsStream implements RawStreamInterface
|
||||
if (!validateAcceptForKey($secWebsocketAccept, $key)) {
|
||||
throw new ConnectionException('Invalid "Sec-WebSocket-Accept" header');
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
final protected function createCompressionContext(array $headers): ?Websocket\CompressionContext
|
||||
{
|
||||
$extensions = $headers['sec-websocket-extensions'][0] ?? '';
|
||||
@ -201,10 +204,12 @@ class WsStream implements RawStreamInterface
|
||||
return $compressionContext;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Amp\Socket\Socket
|
||||
*/
|
||||
|
@ -550,7 +550,6 @@ trait BotAPI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$multiple_args_base = array_merge($args, ['entities' => [], 'parse_mode' => 'text', 'message' => '']);
|
||||
$multiple_args = [$multiple_args_base];
|
||||
$i = 0;
|
||||
@ -630,12 +629,13 @@ trait BotAPI
|
||||
}
|
||||
}
|
||||
if ($c >= 8110) {
|
||||
$this->logger->logger("Entity size limit possibly exceeded, you may get an error indicating that the entities are too long. Reduce the number of entities and/or size of the URLs used.", Logger::FATAL_ERROR);
|
||||
$this->logger->logger('Entity size limit possibly exceeded, you may get an error indicating that the entities are too long. Reduce the number of entities and/or size of the URLs used.', Logger::FATAL_ERROR);
|
||||
}
|
||||
}
|
||||
if ($total) {
|
||||
$this->logger->logger("Too many entities, $total entities will be truncated", Logger::FATAL_ERROR);
|
||||
}
|
||||
|
||||
return $multiple_args;
|
||||
}
|
||||
|
||||
@ -678,6 +678,7 @@ trait BotAPI
|
||||
$temp .= substr($text, $match[1] + strlen($match[0]));
|
||||
$text = $temp;
|
||||
}
|
||||
|
||||
return $text;
|
||||
} else {
|
||||
return htmlentities($text);
|
||||
|
@ -29,6 +29,7 @@ class Exception extends \Exception
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ class Exception extends \Exception
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,9 @@ trait PrettyException
|
||||
public function prettify_tl($init = '')
|
||||
{
|
||||
$eol = PHP_EOL;
|
||||
if (php_sapi_name() !== 'cli') $eol = '<br>'.PHP_EOL;
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$eol = '<br>'.PHP_EOL;
|
||||
}
|
||||
$tl = false;
|
||||
foreach (array_reverse($this->getTrace()) as $k => $frame) {
|
||||
if (isset($frame['function']) && in_array($frame['function'], ['serialize_params', 'serialize_object'])) {
|
||||
|
@ -63,6 +63,7 @@ class Button implements \JsonSerializable, \ArrayAccess
|
||||
$res = $this->info['API']->$method('messages.getBotCallbackAnswer', ['peer' => $this->info['peer'], 'msg_id' => $this->info['id'], 'game' => true], ['datacenter' => $this->info['API']->datacenter->curdc]);
|
||||
break;
|
||||
}
|
||||
|
||||
return $async ? $res : $this->wait($res);
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ trait Tools
|
||||
});
|
||||
});
|
||||
} catch (\Throwable $throwable) {
|
||||
throw new \Error("Loop exceptionally stopped without resolving the promise", 0, $throwable);
|
||||
throw new \Error('Loop exceptionally stopped without resolving the promise', 0, $throwable);
|
||||
}
|
||||
} while (!$resolved);
|
||||
|
||||
@ -205,38 +205,48 @@ trait Tools
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function all($promises)
|
||||
{
|
||||
foreach ($promises as &$promise) {
|
||||
$promise = $this->call($promise);
|
||||
}
|
||||
|
||||
return all($promises);
|
||||
}
|
||||
|
||||
public function any($promises)
|
||||
{
|
||||
foreach ($promises as &$promise) {
|
||||
$promise = $this->call($promise);
|
||||
}
|
||||
|
||||
return any($promises);
|
||||
}
|
||||
|
||||
public function some($promises)
|
||||
{
|
||||
foreach ($promises as &$promise) {
|
||||
$promise = $this->call($promise);
|
||||
}
|
||||
|
||||
return some($promises);
|
||||
}
|
||||
|
||||
public function first($promises)
|
||||
{
|
||||
foreach ($promises as &$promise) {
|
||||
$promise = $this->call($promise);
|
||||
}
|
||||
|
||||
return first($promises);
|
||||
}
|
||||
|
||||
public function timeout($promise, $timeout)
|
||||
{
|
||||
return timeout($this->call($promise), $timeout);
|
||||
}
|
||||
|
||||
public function call($promise)
|
||||
{
|
||||
if ($promise instanceof \Generator) {
|
||||
@ -247,6 +257,7 @@ trait Tools
|
||||
|
||||
return $promise;
|
||||
}
|
||||
|
||||
public function callFork($promise, $actual = null, $file = '')
|
||||
{
|
||||
if ($actual) {
|
||||
@ -271,12 +282,15 @@ trait Tools
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $promise;
|
||||
}
|
||||
|
||||
public function callForkDefer($promise)
|
||||
{
|
||||
Loop::defer([$this, 'callFork'], $promise);
|
||||
}
|
||||
|
||||
public function rethrow($e, $file = '')
|
||||
{
|
||||
$logger = isset($this->logger) ? $this->logger : Logger::$default;
|
||||
@ -287,6 +301,7 @@ trait Tools
|
||||
$logger->logger((string) $e);
|
||||
Promise\rethrow(new Failure($e));
|
||||
}
|
||||
|
||||
public function after($a, $b)
|
||||
{
|
||||
$a = $this->call($a());
|
||||
@ -311,6 +326,7 @@ trait Tools
|
||||
{
|
||||
return new \Amp\Delayed($time * 1000);
|
||||
}
|
||||
|
||||
public function is_array_or_alike($var)
|
||||
{
|
||||
return is_array($var) ||
|
||||
|
@ -28,18 +28,22 @@ namespace danog\MadelineProto\VoIP;
|
||||
trait AuthKeyHandler
|
||||
{
|
||||
private $calls = [];
|
||||
|
||||
public function request_call($user)
|
||||
{
|
||||
return $this->wait($this->request_call_async($user));
|
||||
}
|
||||
|
||||
public function accept_call($user)
|
||||
{
|
||||
return $this->wait($this->accept_call_async($user));
|
||||
}
|
||||
|
||||
public function discard_call($call, $reason, $rating = [], $need_debug = true)
|
||||
{
|
||||
return $this->wait($this->discard_call_async($call, $reason, $rating, $need_debug));
|
||||
}
|
||||
|
||||
public function request_call_async($user)
|
||||
{
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
|
@ -20,27 +20,28 @@ namespace danog\MadelineProto;
|
||||
|
||||
if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
|
||||
/**
|
||||
* Manages storage of VoIP server config
|
||||
* Manages storage of VoIP server config.
|
||||
*/
|
||||
class VoIPServerConfig extends VoIPServerConfigInternal
|
||||
{
|
||||
/**
|
||||
* The configuration
|
||||
* The configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_config = [];
|
||||
/**
|
||||
* The default configuration
|
||||
* The default configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_configDefault = [];
|
||||
|
||||
/**
|
||||
* Update shared call settings
|
||||
* Update shared call settings.
|
||||
*
|
||||
* @param array $config The settings
|
||||
*
|
||||
* @param array $config The settings
|
||||
* @return void
|
||||
*/
|
||||
public static function update(array $config)
|
||||
@ -48,8 +49,9 @@ if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
|
||||
self::$_config = $config;
|
||||
self::updateInternal(self::getFinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared call settings
|
||||
* Get shared call settings.
|
||||
*
|
||||
* @return array The settings
|
||||
*/
|
||||
@ -59,9 +61,10 @@ if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update default shared call settings
|
||||
* Update default shared call settings.
|
||||
*
|
||||
* @param array $configDefault The settings
|
||||
*
|
||||
* @param array $configDefault The settings
|
||||
* @return void
|
||||
*/
|
||||
public static function updateDefault(array $configDefault)
|
||||
@ -69,8 +72,9 @@ if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
|
||||
self::$_configDefault = $configDefault;
|
||||
self::updateInternal(self::getFinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default shared call settings
|
||||
* Get default shared call settings.
|
||||
*
|
||||
* @return array The settings
|
||||
*/
|
||||
@ -80,7 +84,7 @@ if (class_exists('\\danog\\MadelineProto\\VoIPServerConfigInternal')) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get final settings
|
||||
* Get final settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -42,6 +42,7 @@ trait ApiStart
|
||||
$lines[count($lines) - 1] .= array_shift($chunk);
|
||||
$lines = array_merge($lines, $chunk);
|
||||
}
|
||||
|
||||
return array_shift($lines);
|
||||
};
|
||||
echo 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)
|
||||
@ -96,7 +97,7 @@ Note that you can also provide the API parameters directly in the code using the
|
||||
return yield $this->my_telegram_org_wrapper->get_app_async();
|
||||
}
|
||||
yield $this->web_api_echo_async();
|
||||
} else if (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
|
||||
} elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
|
||||
$app['api_id'] = (int) $_POST['api_id'];
|
||||
$app['api_hash'] = $_POST['api_hash'];
|
||||
$this->getting_api_id = false;
|
||||
|
@ -26,16 +26,19 @@ trait DialogHandler
|
||||
if ($this->authorization['user']['bot']) {
|
||||
$res = [];
|
||||
foreach ($this->chats as $chat) {
|
||||
$res []= $this->gen_all($chat)['Peer'];
|
||||
$res[] = $this->gen_all($chat)['Peer'];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
$res = [];
|
||||
foreach (yield $this->get_full_dialogs_async($force) as $dialog) {
|
||||
$res []= $dialog['peer'];
|
||||
$res[] = $dialog['peer'];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_full_dialogs_async($force = true)
|
||||
{
|
||||
if ($force || !isset($this->dialog_params['offset_date']) || is_null($this->dialog_params['offset_date']) || !isset($this->dialog_params['offset_id']) || is_null($this->dialog_params['offset_id']) || !isset($this->dialog_params['offset_peer']) || is_null($this->dialog_params['offset_peer']) || !isset($this->dialog_params['count']) || is_null($this->dialog_params['count'])) {
|
||||
@ -48,45 +51,45 @@ trait DialogHandler
|
||||
$datacenter = $this->datacenter->curdc;
|
||||
$dialogs = [];
|
||||
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['getting_dialogs']);
|
||||
while ($this->dialog_params['count'] < $res['count']) {
|
||||
$res = yield $this->method_call_async_read('messages.getDialogs', $this->dialog_params, ['datacenter' => $datacenter, 'FloodWaitLimit' => 100]);
|
||||
$last_peer = 0;
|
||||
$last_date = 0;
|
||||
$last_id = 0;
|
||||
$res['messages'] = array_reverse($res['messages']);
|
||||
foreach (array_reverse($res['dialogs']) as $dialog) {
|
||||
$id = $this->get_id($dialog['peer']);
|
||||
if (!isset($dialogs[$id])) {
|
||||
$dialogs[$id] = $dialog;
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['getting_dialogs']);
|
||||
while ($this->dialog_params['count'] < $res['count']) {
|
||||
$res = yield $this->method_call_async_read('messages.getDialogs', $this->dialog_params, ['datacenter' => $datacenter, 'FloodWaitLimit' => 100]);
|
||||
$last_peer = 0;
|
||||
$last_date = 0;
|
||||
$last_id = 0;
|
||||
$res['messages'] = array_reverse($res['messages']);
|
||||
foreach (array_reverse($res['dialogs']) as $dialog) {
|
||||
$id = $this->get_id($dialog['peer']);
|
||||
if (!isset($dialogs[$id])) {
|
||||
$dialogs[$id] = $dialog;
|
||||
}
|
||||
if (!$last_date) {
|
||||
if (!$last_peer) {
|
||||
$last_peer = $id;
|
||||
}
|
||||
if (!$last_date) {
|
||||
if (!$last_peer) {
|
||||
$last_peer = $id;
|
||||
}
|
||||
if (!$last_id) {
|
||||
$last_id = $dialog['top_message'];
|
||||
}
|
||||
foreach ($res['messages'] as $message) {
|
||||
if ($this->get_id($message) === $last_peer && $last_id === $message['id']) {
|
||||
$last_date = $message['date'];
|
||||
break;
|
||||
}
|
||||
if (!$last_id) {
|
||||
$last_id = $dialog['top_message'];
|
||||
}
|
||||
foreach ($res['messages'] as $message) {
|
||||
if ($this->get_id($message) === $last_peer && $last_id === $message['id']) {
|
||||
$last_date = $message['date'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($last_date) {
|
||||
$this->dialog_params['offset_date'] = $last_date;
|
||||
$this->dialog_params['offset_peer'] = $last_peer;
|
||||
$this->dialog_params['offset_id'] = $last_id;
|
||||
$this->dialog_params['count'] = count($dialogs);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!isset($res['count'])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($last_date) {
|
||||
$this->dialog_params['offset_date'] = $last_date;
|
||||
$this->dialog_params['offset_peer'] = $last_peer;
|
||||
$this->dialog_params['offset_id'] = $last_id;
|
||||
$this->dialog_params['count'] = count($dialogs);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!isset($res['count'])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $dialogs;
|
||||
}
|
||||
|
@ -20,8 +20,6 @@
|
||||
namespace danog\MadelineProto\Wrappers;
|
||||
|
||||
use danog\MadelineProto\MTProtoTools\PasswordCalculator;
|
||||
use danog\MadelineProto\VoIPServerConfig;
|
||||
use function Amp\Promise\wait;
|
||||
|
||||
/**
|
||||
* Manages logging in and out.
|
||||
@ -103,7 +101,9 @@ trait Login
|
||||
if ($e->rpc === 'SESSION_PASSWORD_NEEDED') {
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_2fa_enabled'], \danog\MadelineProto\Logger::NOTICE);
|
||||
$this->authorization = yield $this->method_call_async_read('account.getPassword', [], ['datacenter' => $this->datacenter->curdc]);
|
||||
if (!isset($this->authorization['hint'])) $this->authorization['hint'] = '';
|
||||
if (!isset($this->authorization['hint'])) {
|
||||
$this->authorization['hint'] = '';
|
||||
}
|
||||
$this->authorized = self::WAITING_PASSWORD;
|
||||
|
||||
return $this->authorization;
|
||||
@ -159,6 +159,7 @@ trait Login
|
||||
$res = yield $this->get_self_async();
|
||||
|
||||
$this->startUpdateSystem();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
namespace danog\MadelineProto\Wrappers;
|
||||
|
||||
use Amp\Deferred;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
@ -38,14 +37,17 @@ trait Loop
|
||||
{
|
||||
if (is_callable($max_forks)) {
|
||||
$this->logger->logger('Running async callable');
|
||||
|
||||
return yield $max_forks();
|
||||
}
|
||||
if ($max_forks instanceof Promise) {
|
||||
$this->logger->logger('Resolving async promise');
|
||||
|
||||
return yield $max_forks;
|
||||
}
|
||||
if (in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler'])) {
|
||||
$this->logger->logger('Getupdates event handler is enabled, exiting from loop', \danog\MadelineProto\Logger::FATAL_ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!is_callable($this->loop_callback) || (is_array($this->loop_callback) && $this->loop_callback[1] === 'onLoop' && !method_exists(...$this->loop_callback))) {
|
||||
@ -53,6 +55,7 @@ trait Loop
|
||||
}
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$needs_restart = true;
|
||||
|
||||
try {
|
||||
set_time_limit(-1);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
@ -61,13 +64,13 @@ trait Loop
|
||||
$this->logger->logger($needs_restart ? 'Will self-restart' : 'Will not self-restart');
|
||||
|
||||
$backtrace = debug_backtrace(0);
|
||||
$lockfile = dirname(end($backtrace)['file']) . '/bot.lock';
|
||||
$lockfile = dirname(end($backtrace)['file']).'/bot.lock';
|
||||
unset($backtrace);
|
||||
$try_locking = true;
|
||||
if (!file_exists($lockfile)) {
|
||||
touch($lockfile);
|
||||
$lock = fopen('bot.lock', 'r+');
|
||||
} else if (isset($GLOBALS['lock'])) {
|
||||
} elseif (isset($GLOBALS['lock'])) {
|
||||
$try_locking = false;
|
||||
$lock = $GLOBALS['lock'];
|
||||
} else {
|
||||
@ -79,7 +82,7 @@ trait Loop
|
||||
while (!$locked) {
|
||||
$locked = flock($lock, LOCK_EX | LOCK_NB);
|
||||
if (!$locked) {
|
||||
$this->closeConnection("Bot is already running");
|
||||
$this->closeConnection('Bot is already running');
|
||||
if ($try++ >= 30) {
|
||||
exit;
|
||||
}
|
||||
@ -92,13 +95,13 @@ trait Loop
|
||||
flock($lock, LOCK_UN);
|
||||
fclose($lock);
|
||||
if ($needs_restart) {
|
||||
$a = fsockopen((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? 'tls' : 'tcp') . '://' . $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT']);
|
||||
fwrite($a, $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . ' ' . $_SERVER['SERVER_PROTOCOL'] . "\r\n" . 'Host: ' . $_SERVER['SERVER_NAME'] . "\r\n\r\n");
|
||||
$this->logger->logger("Self-restarted");
|
||||
$a = fsockopen((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? 'tls' : 'tcp').'://'.$_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT']);
|
||||
fwrite($a, $_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI'].' '.$_SERVER['SERVER_PROTOCOL']."\r\n".'Host: '.$_SERVER['SERVER_NAME']."\r\n\r\n");
|
||||
$this->logger->logger('Self-restarted');
|
||||
}
|
||||
});
|
||||
|
||||
$this->closeConnection("Bot was started");
|
||||
$this->closeConnection('Bot was started');
|
||||
}
|
||||
if (!$this->settings['updates']['handle_updates']) {
|
||||
$this->settings['updates']['handle_updates'] = true;
|
||||
@ -133,6 +136,7 @@ trait Loop
|
||||
yield $this->waitUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public function closeConnection($message = 'OK!')
|
||||
{
|
||||
if (php_sapi_name() === 'cli' || isset($GLOBALS['exited']) || headers_sent()) {
|
||||
@ -143,7 +147,7 @@ trait Loop
|
||||
header('Connection: close');
|
||||
ignore_user_abort(true);
|
||||
ob_start();
|
||||
echo '<html><body><h1>' . $message . '</h1></body</html>';
|
||||
echo '<html><body><h1>'.$message.'</h1></body</html>';
|
||||
$size = ob_get_length();
|
||||
header("Content-Length: $size");
|
||||
header('Content-Type: text/html');
|
||||
|
@ -45,6 +45,7 @@ trait Start
|
||||
$lines[count($lines) - 1] .= array_shift($chunk);
|
||||
$lines = array_merge($lines, $chunk);
|
||||
}
|
||||
|
||||
return array_shift($lines);
|
||||
};
|
||||
if (strpos(yield $readline('Do you want to login as user or bot (u/b)? '), 'b') !== false) {
|
||||
|
@ -15,16 +15,16 @@ final class APITest extends TestCase
|
||||
$MadelineProto = new \danog\MadelineProto\API(
|
||||
[
|
||||
'app_info' => [
|
||||
'api_id' => 25628,
|
||||
'api_hash' => '1fe17cda7d355166cdaa71f04122873c'
|
||||
'api_id' => 25628,
|
||||
'api_hash' => '1fe17cda7d355166cdaa71f04122873c',
|
||||
],
|
||||
'connection_settings' => [
|
||||
'all' => [
|
||||
'ipv6' => $ipv6,
|
||||
'test_mode' => $test_mode,
|
||||
'protocol' => $protocol,
|
||||
'ipv6' => $ipv6,
|
||||
'test_mode' => $test_mode,
|
||||
'protocol' => $protocol,
|
||||
'obfuscated' => $obfuscated,
|
||||
'transport' => $transport,
|
||||
'transport' => $transport,
|
||||
],
|
||||
],
|
||||
]
|
||||
@ -33,6 +33,7 @@ final class APITest extends TestCase
|
||||
$this->assertContainsEquals('_', $pong, 'pong');
|
||||
$this->assertContainsEquals('ping_id', $pong, $ping['ping_id']);
|
||||
}
|
||||
|
||||
public function protocolProvider(): \Generator
|
||||
{
|
||||
foreach ([false, true] as $test_mode) {
|
||||
@ -43,7 +44,9 @@ final class APITest extends TestCase
|
||||
continue;
|
||||
}
|
||||
foreach (['tcp_abridged', 'tcp_intermediate', 'tcp_intermediate_padded', 'tcp_full'] as $protocol) {
|
||||
if ($protocol === 'tcp_full' && $obfuscated) continue;
|
||||
if ($protocol === 'tcp_full' && $obfuscated) {
|
||||
continue;
|
||||
}
|
||||
yield [$transport, $obfuscated, $protocol, $test_mode, $ipv6];
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ foreach (\danog\MadelineProto\Lang::$current_lang as $key => $value) {
|
||||
if (!$param_name && strpos($key, 'object_') === 0) {
|
||||
$value = str_replace('Update ', '', $value).' update';
|
||||
}
|
||||
//} elseif (ctype_lower($value[0])) {
|
||||
//} elseif (ctype_lower($value[0])) {
|
||||
} else {
|
||||
\danog\MadelineProto\Lang::$lang[$lang_code][$key] = readline($value.' => ');
|
||||
if (\danog\MadelineProto\Lang::$lang[$lang_code][$key] === '') {
|
||||
|
Loading…
Reference in New Issue
Block a user