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.
* 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).
* **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!
* 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)).
@ -169,4 +170,5 @@ group calls
native calls
dnssec
mytelegramorg docs
web files
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)
* [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 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)
* [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)
@ -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)
* [Creating a client](https://docs.madelineproto.xyz/docs/CREATING_A_CLIENT.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)
* [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)
* [Logout](https://docs.madelineproto.xyz/docs/LOGIN.html#logout)
* [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);
$doc = new \danog\MadelineProto\AnnotationsBuilder($logger, $docs[2]);
$doc = new \danog\MadelineProto\AnnotationsBuilder($logger, $docs[1]);
$doc->mk_annotations();
foreach ($docs as $settings) {

View File

@ -23,6 +23,42 @@ use danog\MadelineProto\Async\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
*

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) {
$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;
$has_http_wait = true;
}

View File

@ -253,7 +253,7 @@ class MTProto extends AsyncConstruct implements TLCallback
{
return $this->datacenter->fileGetContents($url);
}
public function __wakeup()
{
$backtrace = debug_backtrace(0, 3);
@ -906,9 +906,11 @@ class MTProto extends AsyncConstruct implements TLCallback
public function startUpdateSystem($anyway = false)
{
if ($this->asyncInitPromise || $anyway) {
if ($this->asyncInitPromise || !$anyway) {
$this->logger("Not starting update system");
return;
}
$this->logger("Starting update system");
if (!isset($this->seqUpdater)) {
$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\timeout;
use function Amp\Promise\wait;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
/**
* Some tools.
@ -331,7 +333,26 @@ trait Tools
{
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)
{
return is_array($var) ||

View File

@ -19,7 +19,6 @@
namespace danog\MadelineProto\Wrappers;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
/**
@ -30,45 +29,31 @@ trait ApiStart
public function api_start_async($settings)
{
if (php_sapi_name() === 'cli') {
$stdin = getStdin();
$stdout = getStdout();
$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);
};
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
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)
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 $this->readLine('Your choice (m/a): '), 'm') !== false) {
yield $stdout->write('1) Login to my.telegram.org
2) Go to API development tools
3) App title: your app\'s name, can be anything
Short name: your app\'s short name, can be anything
URL: your app/website\'s URL, or t.me/yourusername
Platform: anything
Description: Describe your app here
4) Click on create application'.PHP_EOL;
$app['api_id'] = yield $readline('5) Enter your API ID: ');
$app['api_hash'] = yield $readline('6) Enter your API hash: ');
4) Click on create application'.PHP_EOL);
$app['api_id'] = yield $this->readLine('5) Enter your API ID: ');
$app['api_hash'] = yield $this->readLine('6) Enter your API hash: ');
return $app;
} else {
$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->complete_login_async(yield $readline('Enter the verification code you received in 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 $this->readLine('Enter the verification code you received in telegram: '));
if (!yield $this->my_telegram_org_wrapper->has_app_async()) {
$app_title = yield $readline('Enter the app\'s name, can be anything: ');
$short_name = yield $readline('Enter the app\'s short name, can be anything: ');
$url = yield $readline('Enter the app/website\'s URL, or t.me/yourusername: ');
$description = yield $readline('Describe your app: ');
$app_title = yield $this->readLine('Enter the app\'s name, can be anything: ');
$short_name = yield $this->readLine('Enter the app\'s short name, can be anything: ');
$url = yield $this->readLine('Enter the app/website\'s URL, or t.me/yourusername: ');
$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]);
} else {
$app = yield $this->my_telegram_org_wrapper->get_app_async();

View File

@ -33,31 +33,16 @@ trait Start
return yield $this->get_self_async();
}
if (php_sapi_name() === 'cli') {
$stdin = getStdin();
$stdout = getStdout();
$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: '));
if (strpos(yield $this->readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) {
yield $this->bot_login_async(yield $this->readLine('Enter your bot token: '));
} else {
yield $this->phone_login_async(yield $readline('Enter your phone number: '));
$authorization = yield $this->complete_phone_login_async(yield $readline('Enter the phone code: '));
yield $this->phone_login_async(yield $this->readLine('Enter your phone number: '));
$authorization = yield $this->complete_phone_login_async(yield $this->readLine('Enter the phone code: '));
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') {
$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();

View File

@ -51,11 +51,6 @@ try {
$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
*/
@ -64,7 +59,6 @@ if ($MadelineProto->get_self() === false) {
} else {
$MadelineProto->bot_login(getenv('BOT_TOKEN'));
}
}
//var_dump(count($MadelineProto->get_pwr_chat('@madelineproto')['participants']));