Style fixes

This commit is contained in:
Daniil Gentili 2019-06-04 14:55:58 +02:00 committed by GitHub
parent 832df205c4
commit a1daca04da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 576 additions and 369 deletions

View File

@ -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
View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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)) {

View File

@ -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 = '';
}

View File

@ -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;

View File

@ -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) {

View File

@ -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]);
}
}

View File

@ -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;
}
}

View 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);

View File

@ -54,6 +54,7 @@ class AsyncParameters extends Parameters
public function getParameters()
{
$callable = $this->callable;
return yield $callable();
}
}

View File

@ -42,7 +42,6 @@ class CombinedAPI
$realpaths = Serialization::realpaths($session);
$this->session = $realpaths['file'];
foreach ($paths as $path => $settings) {
$this->addInstance($path, $settings);
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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';

View File

@ -38,6 +38,7 @@ class FileCallback implements FileCallbackInterface
public function __invoke($percent)
{
$callback = $this->callback;
return $callback($percent);
}
}

View File

@ -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(''));

View File

@ -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 = [];

View File

@ -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}");
}
}

View File

@ -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]);

View File

@ -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;
}

View File

@ -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))) {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -40,7 +40,7 @@ interface LoopInterface
public function loop();
/**
* Get name of the loop
* Get name of the loop.
*
* @return string
*/

View File

@ -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}";
}
}

View File

@ -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';
}
}

View File

@ -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}";
}
}

View File

@ -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');
}
}

View File

@ -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);

View File

@ -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') {

View File

@ -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)
{

View File

@ -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!');
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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));
}
}

View File

@ -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];

View File

@ -43,6 +43,7 @@ class RPCErrorException extends \Exception
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;
}

View File

@ -27,8 +27,6 @@ class Serialization
public static function serialize_all($exception)
{
echo $exception.PHP_EOL;
return;
}
public static function realpaths($file)

View File

@ -18,9 +18,7 @@
namespace danog\MadelineProto\Stream\Async;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
/**
* Buffered stream helper trait.

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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.
*

View File

@ -98,9 +98,10 @@ class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
return $buffer;
}
/**
* @inheritDoc
*
* {@inheritdoc}
*
* @return \Amp\Socket\Socket
*/
public function getSocket(): \Amp\Socket\Socket

View File

@ -106,9 +106,10 @@ class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
return $buffer;
}
/**
* @inheritDoc
*
* {@inheritdoc}
*
* @return \Amp\Socket\Socket
*/
public function getSocket(): \Amp\Socket\Socket

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -87,9 +87,10 @@ class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterf
return $buffer;
}
/**
* @inheritDoc
*
* {@inheritdoc}
*
* @return \Amp\Socket\Socket
*/
public function getSocket(): \Amp\Socket\Socket

View File

@ -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

View File

@ -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

View File

@ -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
*/

View File

@ -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;

View File

@ -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

View File

@ -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
*/

View File

@ -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);

View File

@ -29,6 +29,7 @@ class Exception extends \Exception
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;
}

View File

@ -29,6 +29,7 @@ class Exception extends \Exception
if (php_sapi_name() !== 'cli') {
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
}
return $result;
}

View File

@ -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'])) {

View File

@ -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);
}

View File

@ -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) ||

View File

@ -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')) {

View File

@ -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
*/

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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');

View File

@ -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) {

View File

@ -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];
}
}

View File

@ -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] === '') {