Add async readline

This commit is contained in:
Daniil Gentili 2019-06-05 15:38:32 +02:00
parent 3b26ae40a1
commit 08a502cb2f
11 changed files with 2212 additions and 179 deletions

View File

@ -27,6 +27,7 @@ And now, on to the **API changes**:
* First of all, we've got several bucketloads of telegram API changes, that can be viewed in the first posts. * First of all, we've got several bucketloads of telegram API changes, that can be viewed in the first posts.
* Dropped support for PHP 5 and PHP 7.0: these versions of PHP have [officially reached their EOL](http://php.net/eol.php), so MadelineProto will not support them anymore. * Dropped support for PHP 5 and PHP 7.0: these versions of PHP have [officially reached their EOL](http://php.net/eol.php), so MadelineProto will not support them anymore.
You can use MadelineProto with PHP 7.3 (or PHP 7.2, PHP 7.1 is supported but not recommended). You can use MadelineProto with PHP 7.3 (or PHP 7.2, PHP 7.1 is supported but not recommended).
* **Dropped support for get_updates**: it won't work properly on async, and I really recommend you stop using it
* You can now use the `@support` username in sendMessage and other methods to send messages to the support user! * You can now use the `@support` username in sendMessage and other methods to send messages to the support user!
* Now MadelineProto will automatically try to get the access hash of users not present in the internal peer database (this should reduce errors)! * Now MadelineProto will automatically try to get the access hash of users not present in the internal peer database (this should reduce errors)!
* If any file cannot be downloaded to due issues with the tg media server that is hosting it, it will be automatically sent to the `@support` user ([settings](https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsdownloadreport_broken_media)). * If any file cannot be downloaded to due issues with the tg media server that is hosting it, it will be automatically sent to the `@support` user ([settings](https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsdownloadreport_broken_media)).
@ -169,4 +170,5 @@ group calls
native calls native calls
dnssec dnssec
mytelegramorg docs mytelegramorg docs
web files
telegram passport telegram passport

View File

@ -65,6 +65,7 @@ Tip: if you receive an error (or nothing), [send us](https://t.me/pwrtelegramgro
* [MadelineProto and AMPHP async APIs](https://docs.madelineproto.xyz/docs/ASYNC.html#madelineproto-and-amphp-async-apis) * [MadelineProto and AMPHP async APIs](https://docs.madelineproto.xyz/docs/ASYNC.html#madelineproto-and-amphp-async-apis)
* [Helper methods](https://docs.madelineproto.xyz/docs/ASYNC.html#helper-methods) * [Helper methods](https://docs.madelineproto.xyz/docs/ASYNC.html#helper-methods)
* [Async sleep](https://docs.madelineproto.xyz/docs/ASYNC.html#async-sleep-does-not-block-the-main-thread) * [Async sleep](https://docs.madelineproto.xyz/docs/ASYNC.html#async-sleep-does-not-block-the-main-thread)
* [Async readline](https://docs.madelineproto.xyz/docs/ASYNC.html#async-readline-does-not-block-the-main-thread)
* [MadelineProto artax HTTP client](https://docs.madelineproto.xyz/docs/ASYNC.html#madelineproto-artax-http-client) * [MadelineProto artax HTTP client](https://docs.madelineproto.xyz/docs/ASYNC.html#madelineproto-artax-http-client)
* [Async forking](https://docs.madelineproto.xyz/docs/ASYNC.html#async-forking-does-single-thread-forking) * [Async forking](https://docs.madelineproto.xyz/docs/ASYNC.html#async-forking-does-single-thread-forking)
* [Combining async operations](https://docs.madelineproto.xyz/docs/ASYNC.html#combining-async-operations) * [Combining async operations](https://docs.madelineproto.xyz/docs/ASYNC.html#combining-async-operations)
@ -76,8 +77,10 @@ Tip: if you receive an error (or nothing), [send us](https://t.me/pwrtelegramgro
* [GenericLoop](https://docs.madelineproto.xyz/docs/ASYNC.html#genericloop) * [GenericLoop](https://docs.madelineproto.xyz/docs/ASYNC.html#genericloop)
* [Creating a client](https://docs.madelineproto.xyz/docs/CREATING_A_CLIENT.html) * [Creating a client](https://docs.madelineproto.xyz/docs/CREATING_A_CLIENT.html)
* [Logging in](https://docs.madelineproto.xyz/docs/LOGIN.html) * [Logging in](https://docs.madelineproto.xyz/docs/LOGIN.html)
* [Getting permission to use the telegram API](https://docs.madelineproto.xyz/docs/LOGIN.html#getting-permission-to-use-the-telegram-api)
* [Automatic](https://docs.madelineproto.xyz/docs/LOGIN.html#automatic-now-fully-async) * [Automatic](https://docs.madelineproto.xyz/docs/LOGIN.html#automatic-now-fully-async)
* [Manual (user)](https://docs.madelineproto.xyz/docs/LOGIN.html#manual-user) * [Manual (user)](https://docs.madelineproto.xyz/docs/LOGIN.html#manual-user)
* [API ID](https://docs.madelineproto.xyz/docs/LOGIN.html#api-id)
* [Manual (bot)](https://docs.madelineproto.xyz/docs/LOGIN.html#manual-bot) * [Manual (bot)](https://docs.madelineproto.xyz/docs/LOGIN.html#manual-bot)
* [Logout](https://docs.madelineproto.xyz/docs/LOGIN.html#logout) * [Logout](https://docs.madelineproto.xyz/docs/LOGIN.html#logout)
* [Changing 2FA password](https://docs.madelineproto.xyz/docs/LOGIN.html#changing-2fa-password) * [Changing 2FA password](https://docs.madelineproto.xyz/docs/LOGIN.html#changing-2fa-password)

View File

@ -73,7 +73,7 @@ description: Documentation of old mtproto layers
'.$layer_list); '.$layer_list);
$doc = new \danog\MadelineProto\AnnotationsBuilder($logger, $docs[2]); $doc = new \danog\MadelineProto\AnnotationsBuilder($logger, $docs[1]);
$doc->mk_annotations(); $doc->mk_annotations();
foreach ($docs as $settings) { foreach ($docs as $settings) {

View File

@ -23,6 +23,42 @@ use danog\MadelineProto\Async\AsyncConstruct;
class APIFactory extends AsyncConstruct class APIFactory extends AsyncConstruct
{ {
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var langpack
*/
public $langpack;
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var phone
*/
public $phone;
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var stickers
*/
public $stickers;
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var payments
*/
public $payments;
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var bots
*/
public $bots;
/**
* @internal this is a internal property generated by build_docs.php, don't change manually
*
* @var channels
*/
public $channels;
/** /**
* @internal this is a internal property generated by build_docs.php, don't change manually * @internal this is a internal property generated by build_docs.php, don't change manually
* *

File diff suppressed because it is too large Load Diff

View File

@ -162,7 +162,7 @@ class WriteLoop extends ResumableSignalLoop
} }
} }
if ($API->is_http($datacenter) && !$has_http_wait) { if ($API->is_http($datacenter) && !$has_http_wait) {
$connection->pending_outgoing[$connection->pending_outgoing_key++] = ['_' => 'http_wait', 'serialized_body' => yield $this->API->serialize_object_async(['type' => ''], ['_' => 'http_wait', 'max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 1], 'http_wait'), 'content_related' => true, 'unencrypted' => false, 'method' => true]; $connection->pending_outgoing[$connection->pending_outgoing_key++] = ['_' => 'http_wait', 'serialized_body' => yield $this->API->serialize_object_async(['type' => ''], ['_' => 'http_wait', 'max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'http_wait'), 'content_related' => true, 'unencrypted' => false, 'method' => true];
$connection->pending_outgoing_key %= Connection::PENDING_MAX; $connection->pending_outgoing_key %= Connection::PENDING_MAX;
$has_http_wait = true; $has_http_wait = true;
} }

View File

@ -253,7 +253,7 @@ class MTProto extends AsyncConstruct implements TLCallback
{ {
return $this->datacenter->fileGetContents($url); return $this->datacenter->fileGetContents($url);
} }
public function __wakeup() public function __wakeup()
{ {
$backtrace = debug_backtrace(0, 3); $backtrace = debug_backtrace(0, 3);
@ -906,9 +906,11 @@ class MTProto extends AsyncConstruct implements TLCallback
public function startUpdateSystem($anyway = false) public function startUpdateSystem($anyway = false)
{ {
if ($this->asyncInitPromise || $anyway) { if ($this->asyncInitPromise || !$anyway) {
$this->logger("Not starting update system");
return; return;
} }
$this->logger("Starting update system");
if (!isset($this->seqUpdater)) { if (!isset($this->seqUpdater)) {
$this->seqUpdater = new SeqLoop($this); $this->seqUpdater = new SeqLoop($this);

View File

@ -29,6 +29,8 @@ use function Amp\Promise\first;
use function Amp\Promise\some; use function Amp\Promise\some;
use function Amp\Promise\timeout; use function Amp\Promise\timeout;
use function Amp\Promise\wait; use function Amp\Promise\wait;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
/** /**
* Some tools. * Some tools.
@ -331,7 +333,26 @@ trait Tools
{ {
return new \Amp\Delayed($time * 1000); return new \Amp\Delayed($time * 1000);
} }
public function readLine($prompt = '')
{
return $this->call($this->readLineAsync($prompt));
}
public function readLineAsync($prompt = '')
{
$stdin = getStdin();
$stdout = getStdout();
if ($prompt) {
yield $stdout->write($prompt);
}
static $lines = [''];
while (count($lines) < 2 && ($chunk = yield $stdin->read()) !== null) {
$chunk = explode("\n", str_replace(["\r", "\n\n"], "\n", $chunk));
$lines[count($lines) - 1] .= array_shift($chunk);
$lines = array_merge($lines, $chunk);
}
return array_shift($lines);
}
public function is_array_or_alike($var) public function is_array_or_alike($var)
{ {
return is_array($var) || return is_array($var) ||

View File

@ -19,7 +19,6 @@
namespace danog\MadelineProto\Wrappers; namespace danog\MadelineProto\Wrappers;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout; use function Amp\ByteStream\getStdout;
/** /**
@ -30,45 +29,31 @@ trait ApiStart
public function api_start_async($settings) public function api_start_async($settings)
{ {
if (php_sapi_name() === 'cli') { if (php_sapi_name() === 'cli') {
$stdin = getStdin();
$stdout = getStdout(); $stdout = getStdout();
$readline = function ($prompt = null) use ($stdout, $stdin) { yield $stdout->write('You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)
if ($prompt) { Note that you can also provide the API parameters directly in the code using the settings: https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id'.PHP_EOL);
yield $stdout->write($prompt); if (strpos(yield $this->readLine('Your choice (m/a): '), 'm') !== false) {
} yield $stdout->write('1) Login to my.telegram.org
static $lines = [''];
while (count($lines) < 2 && ($chunk = yield $stdin->read()) !== null) {
$chunk = explode("\n", str_replace(["\r", "\n\n"], "\n", $chunk));
$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)
Note that you can also provide the API parameters directly in the code using the settings: https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id'.PHP_EOL;
if (strpos(yield $readline('Your choice (m/a): '), 'm') !== false) {
echo '1) Login to my.telegram.org
2) Go to API development tools 2) Go to API development tools
3) App title: your app\'s name, can be anything 3) App title: your app\'s name, can be anything
Short name: your app\'s short name, can be anything Short name: your app\'s short name, can be anything
URL: your app/website\'s URL, or t.me/yourusername URL: your app/website\'s URL, or t.me/yourusername
Platform: anything Platform: anything
Description: Describe your app here Description: Describe your app here
4) Click on create application'.PHP_EOL; 4) Click on create application'.PHP_EOL);
$app['api_id'] = yield $readline('5) Enter your API ID: '); $app['api_id'] = yield $this->readLine('5) Enter your API ID: ');
$app['api_hash'] = yield $readline('6) Enter your API hash: '); $app['api_hash'] = yield $this->readLine('6) Enter your API hash: ');
return $app; return $app;
} else { } else {
$this->my_telegram_org_wrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings); $this->my_telegram_org_wrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings);
yield $this->my_telegram_org_wrapper->login_async(yield $readline('Enter a phone number that is already registered on Telegram: ')); yield $this->my_telegram_org_wrapper->login_async(yield $this->readLine('Enter a phone number that is already registered on Telegram: '));
yield $this->my_telegram_org_wrapper->complete_login_async(yield $readline('Enter the verification code you received in telegram: ')); yield $this->my_telegram_org_wrapper->complete_login_async(yield $this->readLine('Enter the verification code you received in telegram: '));
if (!yield $this->my_telegram_org_wrapper->has_app_async()) { if (!yield $this->my_telegram_org_wrapper->has_app_async()) {
$app_title = yield $readline('Enter the app\'s name, can be anything: '); $app_title = yield $this->readLine('Enter the app\'s name, can be anything: ');
$short_name = yield $readline('Enter the app\'s short name, can be anything: '); $short_name = yield $this->readLine('Enter the app\'s short name, can be anything: ');
$url = yield $readline('Enter the app/website\'s URL, or t.me/yourusername: '); $url = yield $this->readLine('Enter the app/website\'s URL, or t.me/yourusername: ');
$description = yield $readline('Describe your app: '); $description = yield $this->readLine('Describe your app: ');
$app = yield $this->my_telegram_org_wrapper->create_app_async(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]); $app = yield $this->my_telegram_org_wrapper->create_app_async(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]);
} else { } else {
$app = yield $this->my_telegram_org_wrapper->get_app_async(); $app = yield $this->my_telegram_org_wrapper->get_app_async();

View File

@ -33,31 +33,16 @@ trait Start
return yield $this->get_self_async(); return yield $this->get_self_async();
} }
if (php_sapi_name() === 'cli') { if (php_sapi_name() === 'cli') {
$stdin = getStdin(); if (strpos(yield $this->readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) {
$stdout = getStdout(); yield $this->bot_login_async(yield $this->readLine('Enter your bot token: '));
$readline = function ($prompt = null) use ($stdout, $stdin) {
if ($prompt) {
yield $stdout->write($prompt);
}
static $lines = [''];
while (count($lines) < 2 && ($chunk = yield $stdin->read()) !== null) {
$chunk = explode("\n", str_replace(["\r", "\n\n"], "\n", $chunk));
$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) {
yield $this->bot_login_async(yield $readline('Enter your bot token: '));
} else { } else {
yield $this->phone_login_async(yield $readline('Enter your phone number: ')); yield $this->phone_login_async(yield $this->readLine('Enter your phone number: '));
$authorization = yield $this->complete_phone_login_async(yield $readline('Enter the phone code: ')); $authorization = yield $this->complete_phone_login_async(yield $this->readLine('Enter the phone code: '));
if ($authorization['_'] === 'account.password') { if ($authorization['_'] === 'account.password') {
$authorization = yield $this->complete_2fa_login_async(yield $readline('Please enter your password (hint '.$authorization['hint'].'): ')); $authorization = yield $this->complete_2fa_login_async(yield $this->readLine('Please enter your password (hint '.$authorization['hint'].'): '));
} }
if ($authorization['_'] === 'account.needSignup') { if ($authorization['_'] === 'account.needSignup') {
$authorization = yield $this->complete_signup_async(yield $readline('Please enter your first name: '), yield $readline('Please enter your last name (can be empty): ')); $authorization = yield $this->complete_signup_async(yield $this->readLine('Please enter your first name: '), yield $this->readLine('Please enter your last name (can be empty): '));
} }
} }
$this->serialize(); $this->serialize();

View File

@ -51,11 +51,6 @@ try {
$MadelineProto->accept_tos(); $MadelineProto->accept_tos();
} }
} }
/*
* If this session is not logged in, login
*/
if ($MadelineProto->get_self() === false) {
/* /*
* If a BOT_TOKEN is defined in .env, use it to login, else prompt for login info * If a BOT_TOKEN is defined in .env, use it to login, else prompt for login info
*/ */
@ -64,7 +59,6 @@ if ($MadelineProto->get_self() === false) {
} else { } else {
$MadelineProto->bot_login(getenv('BOT_TOKEN')); $MadelineProto->bot_login(getenv('BOT_TOKEN'));
} }
}
//var_dump(count($MadelineProto->get_pwr_chat('@madelineproto')['participants'])); //var_dump(count($MadelineProto->get_pwr_chat('@madelineproto')['participants']));