Improved 2FA
This commit is contained in:
parent
6b5775da79
commit
37a9133a6f
@ -144,6 +144,7 @@ Tip: if you receive an error (or nothing), [send us](https://t.me/pwrtelegramgro
|
||||
* [Full chat info with full list of participants](https://docs.madelineproto.xyz/docs/CHAT_INFO.html#get_pwr_chat-now-fully-async)
|
||||
* [Full chat info](https://docs.madelineproto.xyz/docs/CHAT_INFO.html#get_full_info-now-fully-async)
|
||||
* [Reduced chat info (very fast)](https://docs.madelineproto.xyz/docs/CHAT_INFO.html#get_info-now-fully-async)
|
||||
* [Just the chat ID (extremely fast)](https://docs.madelineproto.xyz/docs/CHAT_INFO.html#get_id-now-fully-async)
|
||||
* [Getting all chats (dialogs)](https://docs.madelineproto.xyz/docs/DIALOGS.html)
|
||||
* [Dialog list](https://docs.madelineproto.xyz/docs/DIALOGS.html#get_dialogs-now-fully-async)
|
||||
* [Full dialog info](https://docs.madelineproto.xyz/docs/DIALOGS.html#get_full_dialogs-now-fully-async)
|
||||
|
2
docs
2
docs
@ -1 +1 @@
|
||||
Subproject commit 7414ae3e537b26a15b75d2a00ef6f93e702d2cd8
|
||||
Subproject commit ddb2e4f76938b69ceac6e4615901c642accae1ef
|
@ -390,6 +390,8 @@ trait AuthKeyHandler
|
||||
$req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi';
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$this->logger->logger('An RPCErrorException occurred while generating the authorization key: '.$e->getMessage().' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logger('An exception occurred while generating the authorization key: '.$e.PHP_EOL.' Retrying (try number '.$retry_id_total.')...', \danog\MadelineProto\Logger::WARNING);
|
||||
}
|
||||
}
|
||||
if (strpos($datacenter, 'cdn') === false) {
|
||||
|
@ -25,24 +25,77 @@ use danog\MadelineProto\Tools;
|
||||
use phpseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Manages password calculation.
|
||||
* Manages SRP password calculation
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
class PasswordCalculator
|
||||
{
|
||||
use AuthKeyHandler;
|
||||
use Tools;
|
||||
|
||||
/**
|
||||
* The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $new_algo;
|
||||
/**
|
||||
* A secure random string that can be used to compute the password
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $secure_random = '';
|
||||
|
||||
/**
|
||||
* The algorithm to use for calculatuing the hash of the current password (a PasswordKdfAlgo object)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $current_algo;
|
||||
|
||||
/**
|
||||
* SRP b parameter
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $srp_B;
|
||||
/**
|
||||
* SRP b parameter for hashing
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $srp_BForHash;
|
||||
/**
|
||||
* SRP ID
|
||||
*
|
||||
* @var [type]
|
||||
*/
|
||||
private $srp_id;
|
||||
/**
|
||||
* Logger
|
||||
*
|
||||
* @var \danog\MadelineProto\Logger
|
||||
*/
|
||||
public $logger;
|
||||
|
||||
// This is needed do not remove this
|
||||
public function __construct($logger) { $this->logger = $logger; }
|
||||
/**
|
||||
* Initialize logger
|
||||
*
|
||||
* @param \danog\MadelineProto\Logger $logger
|
||||
*/
|
||||
public function __construct($logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Popupate 2FA configuration
|
||||
*
|
||||
* @param array $object 2FA configuration object obtained using account.getPassword
|
||||
* @return void
|
||||
*/
|
||||
public function addInfo(array $object)
|
||||
{
|
||||
if ($object['_'] !== 'account.password') {
|
||||
@ -101,16 +154,39 @@ class PasswordCalculator
|
||||
$this->secure_random = $object['secure_random'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random string (eventually prefixed by the specified string)
|
||||
*
|
||||
* @param string $prefix Prefix
|
||||
* @return string Salt
|
||||
*/
|
||||
public function createSalt(string $prefix = ''): string
|
||||
{
|
||||
return $prefix.$this->random(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash specified data using the salt with SHA256
|
||||
*
|
||||
* The result will be the SHA256 hash of the salt concatenated with the data concatenated with the salt
|
||||
*
|
||||
* @param string $data Data to hash
|
||||
* @param string $salt Salt
|
||||
* @return string Hash
|
||||
*/
|
||||
public function hashSha256(string $data, string $salt): string
|
||||
{
|
||||
return hash('sha256', $salt.$data.$salt, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the specified password
|
||||
*
|
||||
* @param string $password Password
|
||||
* @param string $client_salt Client salt
|
||||
* @param string $server_salt Server salt
|
||||
* @return string Resulting hash
|
||||
*/
|
||||
public function hashPassword(string $password, string $client_salt, string $server_salt): string
|
||||
{
|
||||
$buf = $this->hashSha256($password, $client_salt);
|
||||
@ -120,9 +196,15 @@ class PasswordCalculator
|
||||
return $this->hashSha256($hash, $server_salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the InputCheckPassword object for checking the validity of a password using account.checkPassword
|
||||
*
|
||||
* @param string $password The password
|
||||
* @return array InputCheckPassword object
|
||||
*/
|
||||
public function getCheckPassword(string $password): array
|
||||
{
|
||||
if ($password === '') {
|
||||
if ($password === '' || !$this->current_algo) {
|
||||
return ['_' => 'inputCheckPasswordEmpty'];
|
||||
}
|
||||
$client_salt = $this->current_algo['salt1'];
|
||||
@ -166,9 +248,20 @@ class PasswordCalculator
|
||||
return ['_' => 'inputCheckPasswordSRP', 'srp_id' => $id, 'A' => $AForHash, 'M1' => $M1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameters to be passed to the account.updatePasswordSettings to update/set a 2FA password
|
||||
*
|
||||
* The input params array can contain password, new_password, email and hint params.
|
||||
*
|
||||
* @param array $params Input params
|
||||
* @return array account.updatePasswordSettings parameters
|
||||
*/
|
||||
public function getPassword(array $params): array
|
||||
{
|
||||
$return = ['password' => $this->getCheckPassword(isset($params['password']) ? $params['password'] : ''), 'new_settings' => ['_' => 'account.passwordInputSettings', 'new_algo' => ['_' => 'passwordKdfAlgoUnknown'], 'new_password_hash' => '', 'hint' => '']];
|
||||
$oldPassword = $this->getCheckPassword($params['password'] ?? '');
|
||||
|
||||
$return = ['password' => $oldPassword, 'new_settings' => ['_' => 'account.passwordInputSettings', 'new_algo' => ['_' => 'passwordKdfAlgoUnknown'], 'new_password_hash' => '', 'hint' => '']];
|
||||
|
||||
$new_settings = &$return['new_settings'];
|
||||
|
||||
if (isset($params['new_password']) && $params['new_password'] !== '') {
|
||||
@ -183,11 +276,11 @@ class PasswordCalculator
|
||||
$vForHash = str_pad($v->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
||||
|
||||
$new_settings['new_algo'] = [
|
||||
'_' => 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow',
|
||||
'_' => 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow',
|
||||
'salt1' => $client_salt,
|
||||
'salt2' => $server_salt,
|
||||
'g' => (int) $g->toString(),
|
||||
'p' => $pForHash,
|
||||
'g' => (int) $g->toString(),
|
||||
'p' => $pForHash,
|
||||
];
|
||||
$new_settings['new_password_hash'] = $vForHash;
|
||||
$new_settings['hint'] = $params['hint'];
|
||||
|
@ -175,6 +175,12 @@ class Magic
|
||||
//$this->logger->logger('Could not enable PHP logging');
|
||||
}
|
||||
}
|
||||
|
||||
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?allv3'), true);
|
||||
if (isset($res['ok']) && $res['ok']) {
|
||||
RPCErrorException::$errorMethodMap = $res['result'];
|
||||
RPCErrorException::$descriptions += $res['human_result'];
|
||||
}
|
||||
self::$inited = true;
|
||||
}
|
||||
}
|
||||
|
@ -25,21 +25,86 @@ class RPCErrorException extends \Exception
|
||||
private $fetched = false;
|
||||
public static $rollbar = true;
|
||||
|
||||
public function getMess()
|
||||
public static $descriptions = [
|
||||
'RPC_MCGET_FAIL' => 'Telegram is having internal issues, please try again later.',
|
||||
'RPC_CALL_FAIL' => 'Telegram is having internal issues, please try again later.',
|
||||
'USER_PRIVACY_RESTRICTED' => "The user's privacy settings do not allow you to do this",
|
||||
'CHANNEL_PRIVATE' => "You haven't joined this channel/supergroup",
|
||||
'USER_IS_BOT' => "Bots can't send messages to other bots",
|
||||
'BOT_METHOD_INVALID' => 'This method cannot be run by a bot',
|
||||
'PHONE_CODE_EXPIRED' => 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)',
|
||||
'USERNAME_INVALID' => 'The provided username is not valid',
|
||||
'ACCESS_TOKEN_INVALID' => 'The provided token is not valid',
|
||||
'ACTIVE_USER_REQUIRED' => 'The method is only available to already activated users',
|
||||
'FIRSTNAME_INVALID' => 'The first name is invalid',
|
||||
'LASTNAME_INVALID' => 'The last name is invalid',
|
||||
'PHONE_NUMBER_INVALID' => 'The phone number is invalid',
|
||||
'PHONE_CODE_HASH_EMPTY' => 'phone_code_hash is missing',
|
||||
'PHONE_CODE_EMPTY' => 'phone_code is missing',
|
||||
'PHONE_CODE_EXPIRED' => 'The confirmation code has expired',
|
||||
'API_ID_INVALID' => 'The api_id/api_hash combination is invalid',
|
||||
'PHONE_NUMBER_OCCUPIED' => 'The phone number is already in use',
|
||||
'PHONE_NUMBER_UNOCCUPIED' => 'The phone number is not yet being used',
|
||||
'USERS_TOO_FEW' => 'Not enough users (to create a chat, for example)',
|
||||
'USERS_TOO_MUCH' => 'The maximum number of users has been exceeded (to create a chat, for example)',
|
||||
'TYPE_CONSTRUCTOR_INVALID' => 'The type constructor is invalid',
|
||||
'FILE_PART_INVALID' => 'The file part number is invalid',
|
||||
'FILE_PARTS_INVALID' => 'The number of file parts is invalid',
|
||||
'MD5_CHECKSUM_INVALID' => 'The MD5 checksums do not match',
|
||||
'PHOTO_INVALID_DIMENSIONS' => 'The photo dimensions are invalid',
|
||||
'FIELD_NAME_INVALID' => 'The field with the name FIELD_NAME is invalid',
|
||||
'FIELD_NAME_EMPTY' => 'The field with the name FIELD_NAME is missing',
|
||||
'MSG_WAIT_FAILED' => 'A waiting call returned an error',
|
||||
'USERNAME_NOT_OCCUPIED' => 'The provided username is not occupied',
|
||||
'PHONE_NUMBER_BANNED' => 'The provided phone number is banned from telegram',
|
||||
'AUTH_KEY_UNREGISTERED' => 'The authorization key has expired',
|
||||
'INVITE_HASH_EXPIRED' => 'The invite link has expired',
|
||||
'USER_DEACTIVATED' => 'The user was deactivated',
|
||||
'USER_ALREADY_PARTICIPANT' => 'The user is already in the group',
|
||||
'MESSAGE_ID_INVALID' => 'The provided message id is invalid',
|
||||
'PEER_ID_INVALID' => 'The provided peer id is invalid',
|
||||
'CHAT_ID_INVALID' => 'The provided chat id is invalid',
|
||||
'MESSAGE_DELETE_FORBIDDEN' => "You can't delete one of the messages you tried to delete, most likely because it is a service message.",
|
||||
'CHAT_ADMIN_REQUIRED' => 'You must be an admin in this chat to do this',
|
||||
-429 => 'Too many requests',
|
||||
'PEER_FLOOD' => "You are spamreported, you can't do this",
|
||||
];
|
||||
public static $errorMethodMap = [];
|
||||
|
||||
private $caller = '';
|
||||
public static function localizeMessage($method, $code, $error)
|
||||
{
|
||||
if ($this->fetched === false) {
|
||||
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?method='.$additional[0].'&code='.$code.'&error='.$this->rpc), true);
|
||||
if (!$method || !$code || !$error) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$error = preg_replace('/\d+$/', "X", $error);
|
||||
|
||||
$description = self::$descriptions[$error] ?? '';
|
||||
|
||||
|
||||
if (!isset(self::$errorMethodMap[$code][$method][$error])
|
||||
|| !isset(self::$descriptions[$error])
|
||||
|| $code === 500
|
||||
) {
|
||||
$res = json_decode(@file_get_contents('https://rpc.pwrtelegram.xyz/?method='.$this->caller.'&code='.$this->code.'&error='.$this->rpc), true);
|
||||
if (isset($res['ok']) && $res['ok']) {
|
||||
$this->message = $res['result'];
|
||||
$description = $res['result'];
|
||||
|
||||
self::$descriptions[$error] = $description;
|
||||
self::$errorMethodMap[$code][$method][$error] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->message;
|
||||
if (!$description) {
|
||||
return $error;
|
||||
}
|
||||
return $description;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$result = sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], $this->getMess()." ({$this->code})", $this->rpc, $this->file, $this->line.PHP_EOL, \danog\MadelineProto\Magic::$revision.PHP_EOL.PHP_EOL).PHP_EOL.$this->getTLTrace().PHP_EOL;
|
||||
$result = sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], self::localizeMessage($this->caller, $this->code, $this->message)." ({$this->code})", $this->rpc, $this->file, $this->line.PHP_EOL, \danog\MadelineProto\Magic::$revision.PHP_EOL.PHP_EOL).PHP_EOL.$this->getTLTrace().PHP_EOL;
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
$result = str_replace(PHP_EOL, '<br>'.PHP_EOL, $result);
|
||||
}
|
||||
@ -50,147 +115,19 @@ class RPCErrorException extends \Exception
|
||||
public function __construct($message = null, $code = 0, $caller = '', Exception $previous = null)
|
||||
{
|
||||
$this->rpc = $message;
|
||||
switch ($message) {
|
||||
case 'RPC_MCGET_FAIL':
|
||||
case 'RPC_CALL_FAIL':
|
||||
$message = 'Telegram is having internal issues, please try again later.';
|
||||
break;
|
||||
case 'USER_PRIVACY_RESTRICTED':
|
||||
$message = "The user's privacy settings do not allow you to do this";
|
||||
break;
|
||||
case 'CHANNEL_PRIVATE':
|
||||
$message = "You haven't joined this channel/supergroup";
|
||||
break;
|
||||
case 'FLOOD_WAIT_666':
|
||||
$message = 'Spooky af m8';
|
||||
break;
|
||||
case 'USER_IS_BOT':
|
||||
$message = "Bots can't send messages to other bots";
|
||||
break;
|
||||
case 'BOT_METHOD_INVALID':
|
||||
$message = 'This method cannot be run by a bot';
|
||||
break;
|
||||
case 'PHONE_CODE_EXPIRED':
|
||||
$message = 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)';
|
||||
break;
|
||||
case 'USERNAME_INVALID':
|
||||
$message = 'The provided username is not valid';
|
||||
break;
|
||||
case 'ACCESS_TOKEN_INVALID':
|
||||
$message = 'The provided token is not valid';
|
||||
break;
|
||||
case 'ACTIVE_USER_REQUIRED':
|
||||
$message = 'The method is only available to already activated users';
|
||||
break;
|
||||
case 'FIRSTNAME_INVALID':
|
||||
$message = 'The first name is invalid';
|
||||
break;
|
||||
case 'LASTNAME_INVALID':
|
||||
$message = 'The last name is invalid';
|
||||
break;
|
||||
case 'PHONE_NUMBER_INVALID':
|
||||
$message = 'The phone number is invalid';
|
||||
break;
|
||||
case 'PHONE_CODE_HASH_EMPTY':
|
||||
$message = 'phone_code_hash is missing';
|
||||
break;
|
||||
case 'PHONE_CODE_EMPTY':
|
||||
$message = 'phone_code is missing';
|
||||
break;
|
||||
case 'PHONE_CODE_EXPIRED':
|
||||
$message = 'The confirmation code has expired';
|
||||
break;
|
||||
case 'API_ID_INVALID':
|
||||
$message = 'The api_id/api_hash combination is invalid';
|
||||
break;
|
||||
case 'PHONE_NUMBER_OCCUPIED':
|
||||
$message = 'The phone number is already in use';
|
||||
break;
|
||||
case 'PHONE_NUMBER_UNOCCUPIED':
|
||||
$message = 'The phone number is not yet being used';
|
||||
break;
|
||||
case 'USERS_TOO_FEW':
|
||||
$message = 'Not enough users (to create a chat, for example)';
|
||||
break;
|
||||
case 'USERS_TOO_MUCH':
|
||||
$message = 'The maximum number of users has been exceeded (to create a chat, for example)';
|
||||
break;
|
||||
case 'TYPE_CONSTRUCTOR_INVALID':
|
||||
$message = 'The type constructor is invalid';
|
||||
break;
|
||||
case 'FILE_PART_INVALID':
|
||||
$message = 'The file part number is invalid';
|
||||
break;
|
||||
case 'FILE_PARTS_INVALID':
|
||||
$message = 'The number of file parts is invalid';
|
||||
break;
|
||||
case 'MD5_CHECKSUM_INVALID':
|
||||
$message = 'The MD5 checksums do not match';
|
||||
break;
|
||||
case 'PHOTO_INVALID_DIMENSIONS':
|
||||
$message = 'The photo dimensions are invalid';
|
||||
break;
|
||||
case 'FIELD_NAME_INVALID':
|
||||
$message = 'The field with the name FIELD_NAME is invalid';
|
||||
break;
|
||||
case 'FIELD_NAME_EMPTY':
|
||||
$message = 'The field with the name FIELD_NAME is missing';
|
||||
break;
|
||||
case 'MSG_WAIT_FAILED':
|
||||
$message = 'A waiting call returned an error';
|
||||
break;
|
||||
case 'USERNAME_NOT_OCCUPIED':
|
||||
$message = 'The provided username is not occupied';
|
||||
break;
|
||||
case 'PHONE_NUMBER_BANNED':
|
||||
$message = 'The provided phone number is banned from telegram';
|
||||
break;
|
||||
case 'AUTH_KEY_UNREGISTERED':
|
||||
$message = 'The authorization key has expired';
|
||||
break;
|
||||
case 'INVITE_HASH_EXPIRED':
|
||||
$message = 'The invite link has expired';
|
||||
break;
|
||||
case 'USER_DEACTIVATED':
|
||||
$message = 'The user was deactivated';
|
||||
break;
|
||||
case 'USER_ALREADY_PARTICIPANT':
|
||||
$message = 'The user is already in the group';
|
||||
break;
|
||||
case 'MESSAGE_ID_INVALID':
|
||||
$message = 'The provided message id is invalid';
|
||||
break;
|
||||
case 'PEER_ID_INVALID':
|
||||
$message = 'The provided peer id is invalid';
|
||||
break;
|
||||
case 'CHAT_ID_INVALID':
|
||||
$message = 'The provided chat id is invalid';
|
||||
break;
|
||||
case 'MESSAGE_DELETE_FORBIDDEN':
|
||||
$message = "You can't delete one of the messages you tried to delete, most likely because it is a service message.";
|
||||
break;
|
||||
case 'CHAT_ADMIN_REQUIRED':
|
||||
$message = 'You must be an admin in this chat to do this';
|
||||
break;
|
||||
case -429:
|
||||
case 'PEER_FLOOD':
|
||||
$message = 'Too many requests';
|
||||
break;
|
||||
}
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->prettify_tl($caller);
|
||||
$this->caller = $caller;
|
||||
|
||||
$additional = [];
|
||||
foreach ($this->getTrace() as $level) {
|
||||
if (isset($level['function']) && $level['function'] === 'method_call') {
|
||||
$this->line = $level['line'];
|
||||
$this->file = $level['file'];
|
||||
$additional = $level['args'];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if ($this->rpc !== $message) {
|
||||
$this->fetched = true;
|
||||
}
|
||||
if (!self::$rollbar || !class_exists('\\Rollbar\\Rollbar')) {
|
||||
return;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ trait Login
|
||||
/**
|
||||
* Update the 2FA password
|
||||
*
|
||||
* The params can contain password, new_password, email and hint params.
|
||||
* The params array can contain password, new_password, email and hint params.
|
||||
*
|
||||
* @param array $params The params
|
||||
* @return void
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
|
||||
/*
|
||||
Copyright 2016-2019 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
@ -43,6 +45,7 @@ if (getenv('TEST_SECRET_CHAT') == '') {
|
||||
echo 'Loading settings...'.PHP_EOL;
|
||||
$settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
|
||||
|
||||
|
||||
/*
|
||||
* Load MadelineProto
|
||||
*/
|
||||
@ -58,6 +61,7 @@ try {
|
||||
$MadelineProto->accept_tos();
|
||||
}
|
||||
}
|
||||
|
||||
//var_dump(count($MadelineProto->get_pwr_chat('@madelineproto')['participants']));
|
||||
|
||||
/*
|
||||
@ -78,7 +82,7 @@ $message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sem
|
||||
/*
|
||||
* Try making a phone call
|
||||
*/
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to make a call? (y/n): '), 'y') !== false) {
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos(readline('Do you want to make a call? (y/n): '), 'y') !== false) {
|
||||
$controller = $MadelineProto->request_call(getenv('TEST_SECRET_CHAT'))->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw');
|
||||
while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_READY) {
|
||||
$MadelineProto->get_updates();
|
||||
@ -92,8 +96,8 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
|
||||
/*
|
||||
* Try receiving a phone call
|
||||
*/
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) {
|
||||
$howmany = $MadelineProto->readline('How many calls would you like me to handle? ');
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos(readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) {
|
||||
$howmany = readline('How many calls would you like me to handle? ');
|
||||
$offset = 0;
|
||||
while ($howmany > 0) {
|
||||
$updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
|
||||
@ -114,7 +118,7 @@ if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to
|
||||
/*
|
||||
* Secret chat usage
|
||||
*/
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos($MadelineProto->readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) {
|
||||
if (!getenv('TRAVIS_COMMIT') && stripos(readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) {
|
||||
/**
|
||||
* Request a secret chat.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user