Full async docs
This commit is contained in:
parent
af0458d42d
commit
279e3d0d66
@ -17,7 +17,8 @@ description: bot_login parameters, return type and example
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$authorization = $this->bot_login($token);
|
||||
$authorization = [yield](ASYNC.html) $this->bot_login($token);
|
||||
```
|
||||
|
@ -17,18 +17,19 @@ description: complete_2FA_login parameters, return type and example
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
[yield](ASYNC.html) $MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
if ($authorization['_'] === 'account.noPassword') {
|
||||
throw new \danog\MadelineProto\Exception('2FA is enabled but no password is set!');
|
||||
}
|
||||
if ($authorization['_'] === 'account.password') {
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -19,18 +19,19 @@ You must then use [complete_2FA_login](complete_2FA_login.md) or [complete_signu
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
[yield](ASYNC.html) $MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
if ($authorization['_'] === 'account.noPassword') {
|
||||
throw new \danog\MadelineProto\Exception('2FA is enabled but no password is set!');
|
||||
}
|
||||
if ($authorization['_'] === 'account.password') {
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -18,18 +18,20 @@ description: complete_signup parameters, return type and example
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
[yield](ASYNC.html) $MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
if ($authorization['_'] === 'account.noPassword') {
|
||||
throw new \danog\MadelineProto\Exception('2FA is enabled but no password is set!');
|
||||
}
|
||||
if ($authorization['_'] === 'account.password') {
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
@ -5,7 +5,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
---
|
||||
# Async
|
||||
|
||||
MadelineProto now features async, for **incredible speed improvements**, and parallel processing **without** buggy and slow threading/multiprocessing.
|
||||
MadelineProto now features async, for **incredible speed improvements**, and parallel processing.
|
||||
Powered by [amphp](https://amphp.org), MadelineProto wraps the AMPHP APIs to provide a simpler generator-based async API.
|
||||
|
||||
* [Usage](#usage)
|
||||
@ -18,6 +18,8 @@ Powered by [amphp](https://amphp.org), MadelineProto wraps the AMPHP APIs to pro
|
||||
* [Ignored async](#ignored-async)
|
||||
* [Blocking async](#blocking-async)
|
||||
* [MadelineProto and AMPHP async APIs](#madelineproto-and-amphp-async-apis)
|
||||
* [Helper methods](#helper-methods)
|
||||
* [MadelineProto async loop APIs](#async-loop-apis)
|
||||
|
||||
## Usage
|
||||
|
||||
@ -94,6 +96,7 @@ This **will not work**, because the result of a function that uses `yield` is no
|
||||
If the generator is not __passed to the AMPHP event loop__, execution of the function will not be resumed: when MadelineProto asynchronously obtains the result of the get_info, execution of the function is never resumed, and the line with sendMessage is never called.
|
||||
To avoid this problem, only call asynchronous functions in the event/callback update handler, or in functions called by the event/callback update handler, or inside a function passed to loop.
|
||||
You can also call asynchronous functions created by you, within other asynchronous functions.
|
||||
Generators in MadelineProto are equivalent to promises, which is a paradigm you may have used in other languages.
|
||||
|
||||
### Async in [event handler](https://docs.madelineproto.xyz/docs/UPDATES.html#event-driven):
|
||||
```php
|
||||
@ -158,7 +161,7 @@ $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'b
|
||||
|
||||
You can use the async version of MadelineProto functions **without** yield if you don't want the request to block, and you don't need the result of the function.
|
||||
This is allowed, but the order of the function calls will not be guaranteed: you can use [call queues](https://docs.madelineproto.xyz/docs/USING_METHODS.html#queues) if you want to make sure the order of the calls remains the same.
|
||||
|
||||
See [async forking](#async-forking-does-async-single-thread-forking).
|
||||
|
||||
### Blocking async
|
||||
```php
|
||||
@ -176,10 +179,86 @@ When using AMPHP libraries, you just have to use them with yield, no need to sta
|
||||
|
||||
Also, you should read the AMPHP docs, especially the [event loop docs](https://amphp.org/amp/event-loop/api): AMPHP provides multiple helper methods for executing actions repeatedly every N seconds in a non-blocking manner, or to defer execution of certain actions (aka async cron).
|
||||
|
||||
MadelineProto also provides a few generic async helper methods:
|
||||
### Helper methods
|
||||
|
||||
MadelineProto also provides a few generic async helper methods: when possible, always use MadelineProto's wrapped versions of the [amphp combinators](https://amphp.org/amp/promises/combinators) and [amphp helpers](https://amphp.org/amp/promises/miscellaneous) instead of original amphp methods (`all`, `any`, `some`, `first`, ...).
|
||||
|
||||
#### Async sleep (does not block the main thread)
|
||||
```php
|
||||
yield $MadelineProto->sleep(3);
|
||||
// Async sleep
|
||||
```
|
||||
|
||||
#### Async forking (does async single-thread forking)
|
||||
|
||||
Useful if you need to start a process in the background and you want throwed exceptions to surface up.
|
||||
These exceptions will exit the event loop, turning off the script unless you wrap `$MadelineProto->loop()` with a try-catch.
|
||||
Use it when you do not need the result of a method (see [ignored async](#ignored-async)), but you want eventual errors to crash the script.
|
||||
Otherwise, just use the method without yield.
|
||||
|
||||
```php
|
||||
// Exceptions will surface out of the event loop()
|
||||
$MadelineProto->callFork($MadelineProto->messages->sendMessage([...]));
|
||||
// Exceptions will be ignored
|
||||
$MadelineProto->messages->sendMessage([...]);
|
||||
|
||||
// Like the first one, but the call will be deferred to the next event loop tick
|
||||
$MadelineProto->callForkDefer($MadelineProto->messages->sendMessage([...]));
|
||||
```
|
||||
|
||||
Ignoring exceptions is usually not good practice, so it's best to wrap the method you're calling in a closure with a try-catch with some error handling code inside of it, calling it right after that and passing it to callFork:
|
||||
|
||||
```php
|
||||
$MadelineProto->callFork((function () use ($MadelineProto) {
|
||||
try {
|
||||
$MadelineProto->messages->sendMessage([...])
|
||||
} catch (\Exception $e) {
|
||||
// Handle by logging and stuff
|
||||
}
|
||||
})());
|
||||
```
|
||||
|
||||
#### Combining async operations
|
||||
|
||||
These methods can be used to execute multiple async operations simultaneously and wait for the result of all of them.
|
||||
Each method has different error handling techniques, see the [amphp docs](https://amphp.org/amp/promises/combinators).
|
||||
Note that if you just take the result of these methods without yielding it, you can use it as a normal promise/generator.
|
||||
|
||||
```
|
||||
$promise1 = $MadelineProto->messages->sendMessage(...);
|
||||
$promise2 = $MadelineProto->messages->sendMessage(...);
|
||||
// $promise3 = ...;
|
||||
|
||||
// Equivalent to Amp\Promise\all(), but works with generators, too
|
||||
$results = yield $MadelineProto->all([$promise1, $promise2, $generator3]);
|
||||
|
||||
// Equivalent to Amp\Promise\first(), but works with generators, too
|
||||
$results = yield $MadelineProto->first([$promise1, $promise2, $generator3]);
|
||||
|
||||
// Equivalent to Amp\Promise\any(), but works with generators, too
|
||||
$results = yield $MadelineProto->any([$promise1, $promise2, $generator3]);
|
||||
|
||||
// Equivalent to Amp\Promise\some(), but works with generators, too
|
||||
$results = yield $MadelineProto->some([$promise1, $promise2, $generator3]);
|
||||
|
||||
```
|
||||
|
||||
#### Handling timeouts
|
||||
|
||||
These methods can be used to wait for a certain amount of time for a result, and then throw an `Amp\TimeoutException` or simply continue execution if no result was obtained.
|
||||
|
||||
```
|
||||
// Waits for the result for 2 seconds and then throws an \Amp\TimeoutException
|
||||
$result = yield $MadelineProto->timeout($promise, 2)
|
||||
|
||||
// Waits for the result for 2 seconds, returns the result or null (which is the result of sleep())
|
||||
$result = yield $MadelineProto->first([$promise, $MadelineProto->sleep(2)]);
|
||||
```
|
||||
|
||||
### Async loop APIs
|
||||
|
||||
MadelineProto provides a very useful async loop APIs, for executing operations periodically or on demand.
|
||||
It's a more flexible and powerful alternative to AMPHP's [repeat](https://amphp.org/amp/event-loop/api#repeat), allowing dynamically changeable repeat periods, resumes and signaling.
|
||||
|
||||
|
||||
|
||||
<a href="https://docs.madelineproto.xyz/docs/CREATING_A_CLIENT.html">Next section</a>
|
||||
|
@ -13,7 +13,7 @@ if (!file_exists('input.raw')) {
|
||||
echo 'Downloading example song'.PHP_EOL;
|
||||
copy('https://github.com/danog/MadelineProto/raw/master/input.raw', 'input.raw');
|
||||
}
|
||||
$call = $MadelineProto->request_call('@danogentili')->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
|
||||
$call = [yield](ASYNC.html) $MadelineProto->request_call('@danogentili')->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
|
||||
|
||||
// We need to receive updates in order to avoid closing the script before the call has ended
|
||||
while ($call->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
|
@ -13,7 +13,7 @@ There are various methods that can be used to fetch info about chats, based on b
|
||||
|
||||
## get_pwr_chat
|
||||
```php
|
||||
$pwr_chat = $MadelineProto->get_pwr_chat(-100214891824);
|
||||
$pwr_chat = [yield](ASYNC.html) $MadelineProto->get_pwr_chat(-100214891824);
|
||||
foreach ($pwr_chat['participants'] as $participant) {
|
||||
\danog\MadelineProto\Logger::log($participant);
|
||||
}
|
||||
@ -27,7 +27,7 @@ Use `get_pwr_chat` to get full chat info, including the full list of members, se
|
||||
|
||||
## get_full_info
|
||||
```php
|
||||
$full_chat = $MadelineProto->get_full_info(-10028941842);
|
||||
$full_chat = [yield](ASYNC.html) $MadelineProto->get_full_info(-10028941842);
|
||||
```
|
||||
|
||||
You can also use `get_full_info` to get full chat info, without the full list of members, see [here for the parameters and the result](https://docs.madelineproto.xyz/get_full_info.html).
|
||||
@ -38,7 +38,7 @@ You can also use `get_full_info` to get full chat info, without the full list of
|
||||
|
||||
## get_info
|
||||
```php
|
||||
$chat = $MadelineProto->get_info(-10028941842);
|
||||
$chat = [yield](ASYNC.html) $MadelineProto->get_info(-10028941842);
|
||||
```
|
||||
|
||||
You can also use `get_info` to get chat info, see [here for the parameters and the result](https://docs.madelineproto.xyz/get_info.html)
|
||||
|
@ -83,6 +83,8 @@ Created by [Daniil Gentili](https://daniil.it), licensed under AGPLv3, based on
|
||||
|
||||
While writing this client, I looked at many projects for inspiration and help. Here's the full list:
|
||||
|
||||
[tgl](https://github.com/tdlib/td)
|
||||
|
||||
[tgl](https://github.com/vysheng/tgl)
|
||||
|
||||
[Kotlogram](https://github.com/badoualy/kotlogram)
|
||||
|
@ -8,23 +8,34 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
There are two ways to get a list of all chats, depending if you logged in as a user, or as a bot.
|
||||
|
||||
* [As user](#user-get_dialogs)
|
||||
* [Full dialog info](#user-get_full_dialogs)
|
||||
* [As bot](#bot-internal-peer-database)
|
||||
|
||||
## User: get_dialogs
|
||||
```php
|
||||
$dialogs = $MadelineProto->get_dialogs();
|
||||
$dialogs = [yield](ASYNC.html) $MadelineProto->get_dialogs();
|
||||
foreach ($dialogs as $peer) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Hi! Testing MadelineProto broadcasting!']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Hi! Testing MadelineProto broadcasting!']);
|
||||
}
|
||||
```
|
||||
|
||||
`get_dialogs` will return a full list of all chats you're member of, see [here for the parameters and the result](https://docs.madelineproto.xyz/get_dialogs.html)
|
||||
|
||||
## User: get_full_dialogs
|
||||
```php
|
||||
$dialogs = [yield](ASYNC.html) $MadelineProto->get_full_dialogs();
|
||||
foreach ($dialogs as $dialog) {
|
||||
\danog\MadelineProto\Logger::log($dialog);
|
||||
}
|
||||
```
|
||||
|
||||
`get_full_dialogs` will return a full list of all chats you're member of, including dialog info (such as the pinned/last message ID, unread count, tag count, notification settings and message drafts) see [here for the parameters and the result](https://docs.madelineproto.xyz/get_full_dialogs.html)
|
||||
|
||||
## Bot: internal peer database
|
||||
```php
|
||||
foreach ($MadelineProto->API->chats as $bot_api_id => $chat) {
|
||||
try {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $chat, 'message' => "Hi $bot_api_id! Testing MadelineProto broadcasting!"]);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => $chat, 'message' => "Hi $bot_api_id! Testing MadelineProto broadcasting!"]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
echo $e;
|
||||
}
|
||||
|
@ -9,9 +9,11 @@ MadelineProto can do everything official clients can do, and more!
|
||||
|
||||
* It allows you to do everything official clients can do, programmatically!
|
||||
|
||||
* It is [fully async](https://docs.madelineproto.xyz/docs/ASYNC.html)!
|
||||
|
||||
* *It can make phone calls!* [See here for instructions](https://docs.madelineproto.xyz/docs/CALLS.html)
|
||||
|
||||
* It can be proxied!
|
||||
* It can be proxied (MTProxy, HTTP, socks5 and more)!
|
||||
|
||||
* It is very fast!
|
||||
|
||||
|
@ -46,7 +46,7 @@ To disable automatic uploads by file name, set `$MadelineProto->settings['upload
|
||||
|
||||
### [inputMediaUploadedPhoto](https://docs.madelineproto.xyz/API_docs/constructors/inputMediaUploadedPhoto.html)
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedPhoto',
|
||||
@ -61,7 +61,7 @@ Can be used to upload photos: simply provide the photo's file path in the `file`
|
||||
|
||||
### [inputMediaUploadedDocument](https://docs.madelineproto.xyz/API_docs/constructors/inputMediaUploadedDocument.html)
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -83,7 +83,7 @@ To actually set the document type, provide one or more [DocumentAttribute](https
|
||||
### [documentAttributeFilename](https://docs.madelineproto.xyz/API_docs/constructors/documentAttributeFilename.html) to send a document
|
||||
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -100,7 +100,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
### [documentAttributeImageSize](https://docs.madelineproto.xyz/API_docs/constructors/documentAttributeImageSize.html) to send a photo as document
|
||||
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -117,7 +117,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
|
||||
### [documentAttributeAnimated](https://docs.madelineproto.xyz/API_docs/constructors/documentAttributeAnimated.html) to send a gif
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -133,7 +133,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
|
||||
### [documentAttributeVideo](https://docs.madelineproto.xyz/API_docs/constructors/documentAttributeVideo.html) to send a video
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -154,7 +154,7 @@ You might want to manually provide square `w` (width) and `h` (height) parameter
|
||||
### [documentAttributeAudio](https://docs.madelineproto.xyz/API_docs/constructors/documentAttributeAudio.html) to send an audio file
|
||||
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -174,7 +174,7 @@ Set the `voice` parameter to true to send a voice message.
|
||||
## Uploading files
|
||||
|
||||
```php
|
||||
$MessageMedia = $MadelineProto->messages->uploadMedia([
|
||||
$MessageMedia = [yield](ASYNC.html) $MadelineProto->messages->uploadMedia([
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedPhoto',
|
||||
'file' => 'faust.jpg'
|
||||
@ -189,7 +189,7 @@ The [$MadelineProto->messages->uploadMedia](https://docs.madelineproto.xyz/API_d
|
||||
The returned [MessageMedia](https://docs.madelineproto.xyz/API_docs/types/MessageMedia.html) object can then be reused to resend the document using sendMedia.
|
||||
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => $MessageMedia,
|
||||
'message' => '[This is the caption](https://t.me/MadelineProto)',
|
||||
@ -206,7 +206,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
Actual MessageMedia objects can also be converted to bot API file IDs like this:
|
||||
|
||||
```php
|
||||
$botAPI_file = $MadelineProto->MTProto_to_botAPI($MessageMedia);
|
||||
$botAPI_file = [yield](ASYNC.html) $MadelineProto->MTProto_to_botAPI($MessageMedia);
|
||||
```
|
||||
|
||||
`$botAPI_file` now contains a [bot API message](https://core.telegram.org/bots/api#message), to extract the file ID from it use the following code:
|
||||
@ -255,13 +255,13 @@ if (!isset($result['file_name'])) {
|
||||
`$MadelineProto->messages->uploadMedia` and bot API file IDs do not allow you to modify the type of the file to send: however, MadelineProto provides a method that can generate a file object that can be resent with multiple file types.
|
||||
|
||||
```php
|
||||
$inputFile = $MadelineProto->upload('filename.mp4');
|
||||
$inputFile = [yield](ASYNC.html) $MadelineProto->upload('filename.mp4');
|
||||
```
|
||||
|
||||
The generated `$inputFile` can later be reused thusly:
|
||||
|
||||
```php
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -273,7 +273,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
'message' => '[This is the caption](https://t.me/MadelineProto)',
|
||||
'parse_mode' => 'Markdown'
|
||||
]);
|
||||
$sentMessageVideo = $MadelineProto->messages->sendMedia([
|
||||
$sentMessageVideo = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => '@danogentili',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -298,7 +298,7 @@ There are multiple download methods that allow you to download a file to a direc
|
||||
|
||||
### Extracting download info
|
||||
```php
|
||||
$info = $MadelineProto->get_download_info($MessageMedia);
|
||||
$info = [yield](ASYNC.html) $MadelineProto->get_download_info($MessageMedia);
|
||||
```
|
||||
|
||||
`$MessageMedia` can be a [MessageMedia](https://docs.madelineproto.xyz/API_docs/types/MessageMedia.html) object or a bot API file ID.
|
||||
@ -310,7 +310,7 @@ $info = $MadelineProto->get_download_info($MessageMedia);
|
||||
|
||||
### Download to directory
|
||||
```php
|
||||
$output_file_name = $MadelineProto->download_to_dir($MessageMedia, '/tmp/');
|
||||
$output_file_name = [yield](ASYNC.html) $MadelineProto->download_to_dir($MessageMedia, '/tmp/');
|
||||
```
|
||||
|
||||
This downloads the given file to `/tmp`, and returns the full generated file path.
|
||||
@ -319,7 +319,7 @@ This downloads the given file to `/tmp`, and returns the full generated file pat
|
||||
|
||||
### Download to file
|
||||
```php
|
||||
$output_file_name = $MadelineProto->download_to_file($MessageMedia, '/tmp/myname.mp4');
|
||||
$output_file_name = [yield](ASYNC.html) $MadelineProto->download_to_file($MessageMedia, '/tmp/myname.mp4');
|
||||
```
|
||||
|
||||
This downloads the given file to `/tmp/myname.mp4`, and returns the full file path.
|
||||
@ -329,12 +329,12 @@ This downloads the given file to `/tmp/myname.mp4`, and returns the full file pa
|
||||
|
||||
### Download to browser with streams
|
||||
```php
|
||||
$info = $MadelineProto->get_download_info($MessageMedia);
|
||||
$info = [yield](ASYNC.html) $MadelineProto->get_download_info($MessageMedia);
|
||||
header('Content-Length: '.$info['size']);
|
||||
header('Content-Type: '.$info['mime']);
|
||||
|
||||
$stream = fopen('php://output', 'w');
|
||||
$MadelineProto->download_to_stream($MessageMedia, $stream, $cb, $offset, $endoffset);
|
||||
[yield](ASYNC.html) $MadelineProto->download_to_stream($MessageMedia, $stream, $cb, $offset, $endoffset);
|
||||
```
|
||||
|
||||
This downloads the given file to the browser, sending also information about the file's type and size.
|
||||
@ -356,14 +356,14 @@ To get the upload/download progress in real-time, use the `\danog\MadelineProto\
|
||||
|
||||
```php
|
||||
$peer = '@danogentili';
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => $peer,
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => new \danog\MadelineProto\FileCallback(
|
||||
'video.mp4',
|
||||
function ($progress) use ($MadelineProto, $peer) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Upload progress: '.$progress.'%']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Upload progress: '.$progress.'%']);
|
||||
}
|
||||
),
|
||||
'attributes' => [
|
||||
@ -374,12 +374,12 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
'parse_mode' => 'Markdown'
|
||||
]);
|
||||
|
||||
$output_file_name = $MadelineProto->download_to_file(
|
||||
$output_file_name = [yield](ASYNC.html) $MadelineProto->download_to_file(
|
||||
$sentMessage,
|
||||
new \danog\MadelineProto\FileCallback(
|
||||
'/tmp/myname.mp4',
|
||||
function ($progress) use ($MadelineProto, $peer) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Download progress: '.$progress.'%']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Download progress: '.$progress.'%']);
|
||||
}
|
||||
)
|
||||
);
|
||||
@ -408,11 +408,11 @@ class MyCallback implements \danog\MadelineProto\FileCallbackInterface
|
||||
}
|
||||
public function __invoke($progress)
|
||||
{
|
||||
$this->MadelineProto->messages->sendMessage(['peer' => $this->peer, 'message' => 'Progress: '.$progress.'%']);
|
||||
[yield](ASYNC.html) $this->MadelineProto->messages->sendMessage(['peer' => $this->peer, 'message' => 'Progress: '.$progress.'%']);
|
||||
}
|
||||
}
|
||||
$peer = '@danogentili';
|
||||
$sentMessage = $MadelineProto->messages->sendMedia([
|
||||
$sentMessage = [yield](ASYNC.html) $MadelineProto->messages->sendMedia([
|
||||
'peer' => $peer,
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
@ -425,7 +425,7 @@ $sentMessage = $MadelineProto->messages->sendMedia([
|
||||
'parse_mode' => 'Markdown'
|
||||
]);
|
||||
|
||||
$output_file_name = $MadelineProto->download_to_file(
|
||||
$output_file_name = [yield](ASYNC.html) $MadelineProto->download_to_file(
|
||||
$sentMessage,
|
||||
new MyCallback('/tmp/myname.mp4', $peer, $MadelineProto)
|
||||
);
|
||||
|
@ -23,7 +23,7 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
if (isset($update['message']['reply_markup']['rows'])) {
|
||||
foreach ($update['message']['reply_markup']['rows'] as $row) {
|
||||
foreach ($row['buttons'] as $button) {
|
||||
$button->click();
|
||||
[yield](ASYNC.html) $button->click();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,7 @@ $MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
|
||||
$MadelineProto->start();
|
||||
$MadelineProto->setEventHandler('\EventHandler');
|
||||
$MadelineProto->async(true);
|
||||
$MadelineProto->loop();
|
||||
```
|
||||
|
||||
@ -50,7 +51,7 @@ $text = $button['text'];
|
||||
And click them:
|
||||
|
||||
```php
|
||||
$button->click();
|
||||
[yield](ASYNC.html) $button->click();
|
||||
```
|
||||
|
||||
<a href="https://docs.madelineproto.xyz/docs/SECRET_CHATS.html">Next section</a>
|
@ -15,7 +15,7 @@ There are many ways you can login with MadelineProto.
|
||||
## Automatic
|
||||
|
||||
```php
|
||||
$MadelineProto->start();
|
||||
[yield](ASYNC.html) $MadelineProto->start();
|
||||
```
|
||||
|
||||
This will start an interactive login prompt via console (if running via CLI), or a login web UI (if running in the browser).
|
||||
@ -25,13 +25,13 @@ You will get to choose if login as user, or as bot.
|
||||
## Manual (user)
|
||||
|
||||
```php
|
||||
$MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = $MadelineProto->complete_phone_login(readline('Enter the phone code: '));
|
||||
[yield](ASYNC.html) $MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_phone_login(readline('Enter the phone code: '));
|
||||
if ($authorization['_'] === 'account.password') {
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
```
|
||||
|
||||
@ -46,7 +46,7 @@ If the account does not have an account, use `complete_signup` to signup, see [h
|
||||
## Manual (bot)
|
||||
|
||||
```php
|
||||
$MadelineProto->bot_login('34298141894:aflknsaflknLKNFS');
|
||||
[yield](ASYNC.html) $MadelineProto->bot_login('34298141894:aflknsaflknLKNFS');
|
||||
```
|
||||
|
||||
Use `bot_login` to login as a bot, see [here for the parameters and the result](https://docs.madelineproto.xyz/bot_login.html).
|
||||
@ -57,7 +57,7 @@ Note that when you login as a bot, MadelineProto also logins using the [PWRTeleg
|
||||
## Logout
|
||||
|
||||
```php
|
||||
$MadelineProto->logout();
|
||||
[yield](ASYNC.html) $MadelineProto->logout();
|
||||
```
|
||||
|
||||
**If** you want to logout, you can use the logout function, see [here for the parameters and the result](https://docs.madelineproto.xyz/logout.html).
|
||||
|
@ -5,7 +5,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
---
|
||||
# Requirements
|
||||
|
||||
MadelineProto requires the `mbstring`, `xml`, `gmp`, `curl` extensions to function properly.
|
||||
MadelineProto requires the `mbstring`, `xml`, `gmp` extensions to function properly.
|
||||
|
||||
To install MadelineProto dependencies on `Ubuntu`, `Debian`, `Devuan`, or any other `Debian-based` distro, run the following command in your command line:
|
||||
|
||||
@ -13,7 +13,7 @@ To install MadelineProto dependencies on `Ubuntu`, `Debian`, `Devuan`, or any ot
|
||||
sudo apt-get install python-software-properties software-properties-common
|
||||
sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
|
||||
sudo apt-get update
|
||||
sudo apt-get install php7.2 php7.2-dev php7.2-fpm php7.2-curl php7.2-xml php7.2-zip php7.2-gmp php7.2-cli php7.2-mbstring git -y
|
||||
sudo apt-get install php7.3 php7.3-dev php7.3-fpm php7.3-xml php7.3-zip php7.3-gmp php7.3-cli php7.3-mbstring git -y
|
||||
```
|
||||
|
||||
Next, follow the instructions on [voip.madelineproto.xyz](https://voip.madelineproto.xyz) and [prime.madelineproto.xyz](https://prime.madelineproto.xyz) to install libtgvoip and PrimeModule.
|
||||
|
@ -15,7 +15,7 @@ MadelineProto provides wrappers to work with secret chats.
|
||||
## Requesting secret chats
|
||||
|
||||
```php
|
||||
$secret_chat = $MadelineProto->request_secret_chat($InputUser);
|
||||
$secret_chat = [yield](ASYNC.html) $MadelineProto->request_secret_chat($InputUser);
|
||||
```
|
||||
|
||||
[`request_secret_chat`](https://docs.madelineproto.xyz/request_secret_chat.html) requests a secret secret chat to the [InputUser](https://docs.madelineproto.xyz/API_docs/types/InputUser.html), ID, or username specified, and returns the secret chat ID.
|
||||
@ -30,7 +30,7 @@ Before sending any message, you must check if the secret chat was accepted by th
|
||||
## Checking secret chat status
|
||||
|
||||
```php
|
||||
$status = $MadelineProto->secret_chat_status($chat);
|
||||
$status = [yield](ASYNC.html) $MadelineProto->secret_chat_status($chat);
|
||||
```
|
||||
|
||||
$status is 0 if the chat cannot be found in the local database, 1 if the chat was requested but not yet accepted, and 2 if it is a valid accepted secret chat.
|
||||
@ -42,7 +42,7 @@ $status is 0 if the chat cannot be found in the local database, 1 if the chat wa
|
||||
To send messages/files/service messages, simply use the sendEncrypted methods with objects that use the same layer used by the other client (specified by the number after the underscore in decryptedMessage object names, to obtain the layer that must be used for a secret chat use the following wrapper method).
|
||||
|
||||
```php
|
||||
$secret_chat = $MadelineProto->get_secret_chat($chat);
|
||||
$secret_chat = [yield](ASYNC.html) $MadelineProto->get_secret_chat($chat);
|
||||
/*
|
||||
[
|
||||
'key' => [ // The authorization key
|
||||
|
@ -8,7 +8,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
Here's how you can fetch info about the currently logged in user
|
||||
|
||||
```php
|
||||
$me = $MadelineProto->get_self();
|
||||
$me = [yield](ASYNC.html) $MadelineProto->get_self();
|
||||
|
||||
\danog\MadelineProto\Logger::log("Hi ".$me['first_name']."!");
|
||||
```
|
||||
|
@ -8,7 +8,7 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
You get the web template used for the `$MadelineProto->start()` web UI thusly:
|
||||
|
||||
```php
|
||||
$template = $MadelineProto->get_web_template();
|
||||
$template = [yield](ASYNC.html) $MadelineProto->get_web_template();
|
||||
```
|
||||
|
||||
By default, it is equal to:
|
||||
@ -31,7 +31,7 @@ By default, it is equal to:
|
||||
|
||||
To modify the web template, use:
|
||||
```php
|
||||
$MadelineProto->set_web_template($new_template);
|
||||
[yield](ASYNC.html) $MadelineProto->set_web_template($new_template);
|
||||
```
|
||||
|
||||
The new template must have a structure similar the the default template.
|
||||
|
@ -7,17 +7,15 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
|
||||
|
||||
Update handling can be done in different ways:
|
||||
|
||||
* [Event driven](#event-driven)
|
||||
* [Multi-account: Combined Event driven update handling](#combined-event-driven)
|
||||
* [Callback](#callback)
|
||||
* [Noop](#noop)
|
||||
* [Async Event driven](#async-event-driven)
|
||||
* [Multi-account: Async Combined Event driven update handling](#async-combined-event-driven)
|
||||
* [Async Callback](#async-callback)
|
||||
* [Noop (default)](#noop)
|
||||
|
||||
|
||||
IMPORTANT: Note that you should turn off update handling if you don't want to use it anymore because the default get_updates update handling stores updates in an array inside the MadelineProto object, without deleting old ones unless they are read using get_updates.
|
||||
```php
|
||||
$MadelineProto->settings['updates']['handle_updates'] = false;
|
||||
```
|
||||
|
||||
## Event driven
|
||||
## Async Event driven
|
||||
|
||||
```php
|
||||
class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
@ -30,13 +28,9 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
{
|
||||
\danog\MadelineProto\Logger::log("Received an update of type ".$update['_']);
|
||||
}
|
||||
public function onLoop()
|
||||
{
|
||||
\danog\MadelineProto\Logger::log("Working...");
|
||||
}
|
||||
public function onUpdateNewChannelMessage($update)
|
||||
{
|
||||
$this->onUpdateNewMessage($update);
|
||||
yield $this->onUpdateNewMessage($update);
|
||||
}
|
||||
public function onUpdateNewMessage($update)
|
||||
{
|
||||
@ -49,38 +43,47 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
}
|
||||
|
||||
try {
|
||||
$this->messages->sendMessage(['peer' => $update, 'message' => $res, 'reply_to_msg_id' => $update['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
|
||||
yield $this->messages->sendMessage(['peer' => $update, 'message' => $res, 'reply_to_msg_id' => $update['message']['id']]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
yield $this->messages->sendMessage(['peer' => '@danogentili', 'message' => $e]);
|
||||
}
|
||||
|
||||
try {
|
||||
if (isset($update['message']['media']) && ($update['message']['media']['_'] == 'messageMediaPhoto' || $update['message']['media']['_'] == 'messageMediaDocument')) {
|
||||
$time = microtime(true);
|
||||
$file = $this->download_to_dir($update, '/tmp');
|
||||
$this->messages->sendMessage(['peer' => $update, 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
|
||||
$file = yield $this->download_to_dir($update, '/tmp');
|
||||
yield $this->messages->sendMessage(['peer' => $update, 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['message']['id']]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
yield $this->messages->sendMessage(['peer' => '@danogentili', 'message' => $e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$MadelineProto = new \danog\MadelineProto\API('bot.madeline');
|
||||
|
||||
$MadelineProto->start();
|
||||
$MadelineProto->setEventHandler('\EventHandler');
|
||||
$MadelineProto->async(true);
|
||||
$MadelineProto->loop(function () use ($MadelineProto) {
|
||||
yield $MadelineProto->start();
|
||||
yield $MadelineProto->setEventHandler('\EventHandler');
|
||||
});
|
||||
$MadelineProto->loop();
|
||||
```
|
||||
|
||||
This will create an event handler class `EventHandler`, create a MadelineProto session, and set the event handler class to our newly created event handler.
|
||||
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, the corresponding `onUpdateType` event handler method is called. To get a list of all possible update types, [click here](https://docs.madelineproto.xyz/API_docs/types/Update.html).
|
||||
This yield syntax might be new to you, even if you already used MadelineProto in the past.
|
||||
It's a new syntax to allow async **parallel processing** of updates and HUGE speed improvements.
|
||||
It was recently introduced in MadelineProto, [here's a full explanation](ASYNC.html).
|
||||
If your code still relies on the old synchronous behaviour, it's still supported, but I HIGHLY recommend you switch to the new async syntax: it's __super__ easy, [just add a `yield` in front of method calls](ASYNC.html)!
|
||||
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, the corresponding `onUpdateType` event handler method is called.
|
||||
|
||||
To get a list of all possible update types, [click here](https://docs.madelineproto.xyz/API_docs/types/Update.html).
|
||||
|
||||
If such a method does not exist, the `onAny` event handler method is called.
|
||||
If the `onAny` event handler method does not exist, the update is ignored.
|
||||
The `onLoop` method, if it exists, will be called every time the update loop finishes one cycle, even if no update was received.
|
||||
It is useful for scheduling actions.
|
||||
The `onLoop` method is not recommended anymore, use AMPHP's [repeat](https://amphp.org/amp/event-loop/api#repeat) or MadelineProto's [async loop API](ASYNC.html#async-loop-apis) to schedule actions in a cron-like manner.
|
||||
|
||||
To access the `$MadelineProto` instance inside of the event handler, simply access `$this`:
|
||||
```php
|
||||
@ -91,10 +94,10 @@ If you intend to use your own constructor in the event handler, make sure to cal
|
||||
|
||||
The update handling loop is started by the `$MadelineProto->loop()` method, and it will automatically restart the script if execution time runs out.
|
||||
|
||||
To break out of the loop just call `die();`
|
||||
To break out of the loop just call `die();`, or throw an exception from within (make sure to catch it outside, in the `$MadelineProto->loop()` call).
|
||||
|
||||
|
||||
## Combined event driven
|
||||
## Async Combined event driven
|
||||
|
||||
```php
|
||||
class EventHandler extends \danog\MadelineProto\CombinedEventHandler
|
||||
@ -113,7 +116,7 @@ class EventHandler extends \danog\MadelineProto\CombinedEventHandler
|
||||
}
|
||||
public function onUpdateNewChannelMessage($update, $session)
|
||||
{
|
||||
$this->onUpdateNewMessage($update, $session);
|
||||
yield $this->onUpdateNewMessage($update, $session);
|
||||
}
|
||||
public function onUpdateNewMessage($update, $session)
|
||||
{
|
||||
@ -126,19 +129,19 @@ class EventHandler extends \danog\MadelineProto\CombinedEventHandler
|
||||
}
|
||||
|
||||
try {
|
||||
$this->{$session}->messages->sendMessage(['peer' => $update, 'message' => $res, 'reply_to_msg_id' => $update['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
|
||||
yield $this->{$session}->messages->sendMessage(['peer' => $update, 'message' => $res, 'reply_to_msg_id' => $update['message']['id']]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->{$session}->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
yield $this->{$session}->messages->sendMessage(['peer' => '@danogentili', 'message' => $e]);
|
||||
}
|
||||
|
||||
try {
|
||||
if (isset($update['message']['media']) && ($update['message']['media']['_'] == 'messageMediaPhoto' || $update['message']['media']['_'] == 'messageMediaDocument')) {
|
||||
$time = microtime(true);
|
||||
$file = $this->{$session}->download_to_dir($update, '/tmp');
|
||||
$this->{$session}->messages->sendMessage(['peer' => $update, 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
|
||||
$file = yield $this->{$session}->download_to_dir($update, '/tmp');
|
||||
yield $this->{$session}->messages->sendMessage(['peer' => $update, 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['message']['id']]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->{$session}->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
yield $this->{$session}->messages->sendMessage(['peer' => '@danogentili', 'message' => $e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,18 +159,27 @@ $CombinedMadelineProto->instances['user.madeline']->start();
|
||||
$CombinedMadelineProto->instances['user2.madeline']->start();
|
||||
|
||||
$CombinedMadelineProto->setEventHandler('\EventHandler');
|
||||
$CombinedMadelineProto->async(true);
|
||||
$CombinedMadelineProto->loop();
|
||||
```
|
||||
|
||||
This will create an event handler class `EventHandler`, create a **combined** MadelineProto session with session files `bot.madeline`, `user.madeline`, `user2.madeline`, and set the event handler class to our newly created event handler.
|
||||
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, the corresponding `onUpdateType` event handler method is called. To get a list of all possible update types, [click here](https://docs.madelineproto.xyz/API_docs/types/Update.html).
|
||||
This yield syntax might be new to you, even if you already used MadelineProto in the past.
|
||||
It's a new syntax to allow async **parallel processing** of updates and HUGE speed improvements.
|
||||
It was recently introduced in MadelineProto, [here's a full explanation](ASYNC.html).
|
||||
If your code still relies on the old synchronous behaviour, it's still supported, but I HIGHLY recommend you switch to the new async syntax: it's __super__ easy, [just add a `yield` in front of method calls](ASYNC.html)!
|
||||
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, the corresponding `onUpdateType` event handler method is called.
|
||||
|
||||
To get a list of all possible update types, [click here](https://docs.madelineproto.xyz/API_docs/types/Update.html).
|
||||
|
||||
If such a method does not exist, the `onAny` event handler method is called.
|
||||
If the `onAny` event handler method does not exist, the update is ignored.
|
||||
The first paramter of the event handler method will always be the [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html), the second parameter will always be the **session name**.
|
||||
|
||||
The `onLoop` method, if it exists, will be called every time the update loop finishes one cycle, even if no update was received.
|
||||
It is useful for scheduling actions.
|
||||
|
||||
The `onLoop` method is not recommended anymore, use AMPHP's [repeat](https://amphp.org/amp/event-loop/api#repeat) or MadelineProto's [async loop API](ASYNC.html#async-loop-apis) to schedule actions in a cron-like manner.
|
||||
|
||||
To access the `$MadelineProto` instance of the account that sent the update, from inside of the event handler, simply access `$this->{$session_name}` (`$session_name` is the second parameter value of the event handler method, or just the session filename):
|
||||
```php
|
||||
@ -179,23 +191,46 @@ If you intend to use your own constructor in the event handler, make sure to cal
|
||||
|
||||
The update handling loop is started by the `$MadelineProto->loop()` method, and it will automatically restart the script if execution time runs out.
|
||||
|
||||
To break out of the loop just call `die();`
|
||||
To break out of the loop just call `die();`, or throw an exception from within (make sure to catch it outside, in the `$MadelineProto->loop()` call).
|
||||
|
||||
|
||||
## Callback
|
||||
|
||||
## Async callback
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API('bot.madeline');
|
||||
|
||||
$MadelineProto->start();
|
||||
$MadelineProto->setCallback(function ($update) use ($MadelineProto) { \danog\MadelineProto\Logger::log("Received an update of type ".$update['_']); });
|
||||
$MadelineProto->setCallback(function ($update) use ($MadelineProto) {
|
||||
|
||||
if (isset($update['message']['out']) && $update['message']['out']) {
|
||||
return;
|
||||
}
|
||||
$res = json_encode($update, JSON_PRETTY_PRINT);
|
||||
if ($res == '') {
|
||||
$res = var_export($update, true);
|
||||
}
|
||||
|
||||
try {
|
||||
yield $MadelineProto->messages->sendMessage(['peer' => $update, 'message' => $res, 'reply_to_msg_id' => $update['message']['id']]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
yield $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e]);
|
||||
}
|
||||
});
|
||||
$MadelineProto->async(true);
|
||||
$MadelineProto->loop();
|
||||
```
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, the provided callback function is called.
|
||||
|
||||
The update handling loop is started by the `$MadelineProto->loop()` method, and it will automatically restart the script if execution time runs out.
|
||||
|
||||
To break out of the loop just call `die();`
|
||||
This yield syntax might be new to you, even if you already used MadelineProto in the past.
|
||||
It's a new syntax to allow async **parallel processing** of updates and HUGE speed improvements.
|
||||
It was recently introduced in MadelineProto, [here's a full explanation](ASYNC.html).
|
||||
If your code still relies on the old synchronous behaviour, it's still supported, but I HIGHLY recommend you switch to the new async syntax: it's __super__ easy, [just add a `yield` in front of method calls](ASYNC.html)!
|
||||
|
||||
To break out of the loop just call `die();`, or throw an exception from within (make sure to catch it outside, in the `$MadelineProto->loop()` call).
|
||||
|
||||
|
||||
|
||||
## Noop
|
||||
@ -207,5 +242,6 @@ $MadelineProto->start();
|
||||
$MadelineProto->setNoop();
|
||||
```
|
||||
When an [Update](https://docs.madelineproto.xyz/API_docs/types/Update.html) is received, nothing is done. This is useful if you need to populate the internal peer database with peers to avoid `This peer is not present in the internal peer database errors`, but don't need to handle updates.
|
||||
This is the default.
|
||||
|
||||
<a href="https://docs.madelineproto.xyz/docs/SETTINGS.html">Next section</a>
|
@ -25,12 +25,12 @@ A list of all of the methods that can be called with MadelineProto can be found
|
||||
If an object of type User, InputUser, Chat, InputChannel, Peer or InputPeer must be provided as a parameter to a method, you can substitute it with the user/group/channel's username (`@username`), bot API id (`-1029449`, `1249421`, `-100412412901`), or update.
|
||||
|
||||
```php
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'Testing MadelineProto...']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'Testing MadelineProto...']);
|
||||
```
|
||||
|
||||
If you want to check if a bot API id is a supergroup/channel ID:
|
||||
```php
|
||||
$Bool = $MadelineProto->is_supergroup($id);
|
||||
$Bool = [yield](ASYNC.html) $MadelineProto->is_supergroup($id);
|
||||
```
|
||||
|
||||
Uses logarithmic conversion to avoid problems on 32 bit systems.
|
||||
@ -38,7 +38,7 @@ Uses logarithmic conversion to avoid problems on 32 bit systems.
|
||||
|
||||
If you want to convert an MTProto API id to a supergroup/channel bot API ID:
|
||||
```php
|
||||
$bot_api_id = $MadelineProto->to_supergroup($id);
|
||||
$bot_api_id = [yield](ASYNC.html) $MadelineProto->to_supergroup($id);
|
||||
```
|
||||
|
||||
Uses logarithmic conversion to avoid problems on 32 bit systems.
|
||||
@ -49,7 +49,7 @@ Uses logarithmic conversion to avoid problems on 32 bit systems.
|
||||
If an object of type InputSecretChat must be provided as a parameter to a method, you can substitute it with the secret chat's id, the updateNewEncrypted message or the decryptedMessage:
|
||||
|
||||
```php
|
||||
$MadelineProto->messages->sendEncrypted(['peer' => $update, 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => 'Hi']]);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendEncrypted(['peer' => $update, 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => 'Hi']]);
|
||||
```
|
||||
|
||||
|
||||
@ -58,8 +58,8 @@ $MadelineProto->messages->sendEncrypted(['peer' => $update, 'message' => ['_' =>
|
||||
Methods that allow sending message entities ([messages.sendMessage](http://docs.madelineproto.xyz/API_docs/methods/messages_sendMessage.html) for example) also have an additional `parse_mode` parameter that enables or disables html/markdown parsing of the message to be sent.
|
||||
|
||||
```php
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => '[Testing Markdown in MadelineProto](https://docs.madelineproto.xyz)', 'parse_mode' => 'Markdown']);
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => '<a href="https://docs.madelineproto.xyz">Testing HTML in MadelineProto</a>', 'parse_mode' => 'HTML']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => '[Testing Markdown in MadelineProto](https://docs.madelineproto.xyz)', 'parse_mode' => 'Markdown']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => '<a href="https://docs.madelineproto.xyz">Testing HTML in MadelineProto</a>', 'parse_mode' => 'HTML']);
|
||||
```
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ $bot_API_markup = ['inline_keyboard' =>
|
||||
]
|
||||
]
|
||||
];
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel', 'reply_markup' => $bot_API_markup]);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel', 'reply_markup' => $bot_API_markup]);
|
||||
```
|
||||
|
||||
|
||||
@ -84,25 +84,27 @@ $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'l
|
||||
To convert the results of methods to bot API objects you must provide a second parameter to method wrappers, containing an array with the `botAPI` key set to true.
|
||||
|
||||
```php
|
||||
$bot_API_object = $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['botAPI' => true]);
|
||||
$bot_API_object = [yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['botAPI' => true]);
|
||||
```
|
||||
|
||||
MadelineProto also [supports bot API file IDs when working with files](FILES.html)
|
||||
|
||||
|
||||
## No result
|
||||
|
||||
Also see [ignored async](https://docs.madelineproto.xyz/docs/ASYNC.html#ignored-async).
|
||||
To disable fetching the result of a method, the array that must be provided as second parameter to method wrapper must have the `noResponse` key set to true.
|
||||
|
||||
```php
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['noResponse' => true]);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['noResponse' => true]);
|
||||
```
|
||||
|
||||
|
||||
## Queues
|
||||
Method calls may be executed at diferent times server-side: to avoid this, method calls can be queued:
|
||||
Method calls may be executed at diferent times server-side: to avoid this, method calls can be queued (this is especially useful when using [ignored async](https://docs.madelineproto.xyz/docs/ASYNC.html#ignored-async)):
|
||||
|
||||
```php
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['queue' => 'queue_name']);
|
||||
[yield](ASYNC.html) $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => 'lel'], ['queue' => 'queue_name']);
|
||||
```
|
||||
|
||||
If the queue if the specified queue name does not exist, it will be created.
|
||||
|
@ -12,10 +12,10 @@ Gets full list of dialogs
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->start();
|
||||
|
||||
$Peers = $MadelineProto->get_dialogs();
|
||||
$Peers = [yield](ASYNC.html) $MadelineProto->get_dialogs();
|
||||
```
|
||||
|
||||
Or, if you're into Lua:
|
||||
|
@ -17,10 +17,10 @@ description: get_full_info parameters, return type and example
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->start();
|
||||
|
||||
$Chat = $MadelineProto->get_full_info($id);
|
||||
$Chat = [yield](ASYNC.html) $MadelineProto->get_full_info($id);
|
||||
```
|
||||
|
||||
Or, if you're into Lua:
|
||||
|
@ -20,7 +20,7 @@ description: get_info parameters, return type and example
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto->start();
|
||||
|
||||
$Chat = $MadelineProto->get_info($id);
|
||||
$Chat = [yield](ASYNC.html) $MadelineProto->get_info($id);
|
||||
```
|
||||
|
||||
Or, if you're into Lua:
|
||||
|
@ -21,7 +21,7 @@ description: get_pwr_chat parameters, return type and example
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto->start();
|
||||
|
||||
$Chat = $MadelineProto->get_pwr_chat($id);
|
||||
$Chat = [yield](ASYNC.html) $MadelineProto->get_pwr_chat($id);
|
||||
```
|
||||
|
||||
Or, if you're into Lua:
|
||||
|
@ -17,7 +17,7 @@ No parameters
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto->start();
|
||||
|
||||
$User = $MadelineProto->get_self();
|
||||
$User = [yield](ASYNC.html) $MadelineProto->get_self();
|
||||
```
|
||||
|
||||
Or, if you're into Lua:
|
||||
|
@ -13,6 +13,6 @@ Logs you out
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto->logout();
|
||||
[yield](ASYNC.html) $MadelineProto->logout();
|
||||
```
|
||||
|
||||
|
@ -20,18 +20,20 @@ You must then use [complete_phone_login](complete_phone_login.md)
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
[yield](ASYNC.html) $MadelineProto->phone_login(readline('Enter your phone number: '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_phone_login(readline('Enter the code you received: '));
|
||||
if ($authorization['_'] === 'account.noPassword') {
|
||||
throw new \danog\MadelineProto\Exception('2FA is enabled but no password is set!');
|
||||
}
|
||||
if ($authorization['_'] === 'account.password') {
|
||||
$authorization = $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_2fa_login(readline('Please enter your password (hint '.$authorization['hint'].'): '));
|
||||
}
|
||||
if ($authorization['_'] === 'account.needSignup') {
|
||||
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
$authorization = [yield](ASYNC.html) $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
@ -19,7 +19,7 @@ Returns the call
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->start();
|
||||
|
||||
|
||||
|
@ -19,9 +19,10 @@ Returns the secret chat ID
|
||||
|
||||
|
||||
```php
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
|
||||
$MadelineProto->start();
|
||||
$MadelineProto->async(true);
|
||||
|
||||
$secret_chat_id = $MadelineProto->request_secret_chat('@danogentili');
|
||||
$secret_chat_id = [yield](ASYNC.html) $MadelineProto->request_secret_chat('@danogentili');
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user