Stability fixes

This commit is contained in:
Daniil Gentili 2018-02-19 11:48:43 +00:00
parent c0e4afc646
commit ebceeda29b
11 changed files with 90 additions and 115 deletions

10
bot.php
View File

@ -13,7 +13,7 @@ If not, see <http://www.gnu.org/licenses/>.
set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelineProto/')); set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelineProto/'));
require 'vendor/autoload.php'; require 'vendor/autoload.php';
$settings = ['app_info' => ['api_id' => 6, 'api_hash' => 'eb06d4abfb49dc3eeb1aeb98ae0f581e']]; //, 'connection_settings' => ['all' => ['test_mode' => true]]]; $settings = ['app_info' => ['api_id' => 6, 'api_hash' => 'eb06d4abfb49dc3eeb1aeb98ae0f581e']];//, 'connection_settings' => ['all' => ['test_mode' => true]]];
try { try {
$MadelineProto = new \danog\MadelineProto\API('bot.madeline'); $MadelineProto = new \danog\MadelineProto\API('bot.madeline');
@ -37,7 +37,7 @@ while (true) {
case 'updateNewMessage': case 'updateNewMessage':
case 'updateNewChannelMessage': case 'updateNewChannelMessage':
if (isset($update['update']['message']['out']) && $update['update']['message']['out']) { if (isset($update['update']['message']['out']) && $update['update']['message']['out']) {
continue; // continue;
} }
$res = json_encode($update, JSON_PRETTY_PRINT); $res = json_encode($update, JSON_PRETTY_PRINT);
if ($res == '') { if ($res == '') {
@ -45,16 +45,16 @@ while (true) {
} }
try { try {
$MadelineProto->messages->sendMessage(['peer' => $update['update']['_'] === 'updateNewMessage' ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => $res, 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); // $MadelineProto->messages->sendMessage(['peer' => $update['update']['_'] === 'updateNewMessage' ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => $res, 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]); $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
} }
try { try {
if (isset($update['update']['message']['media']) && ($update['update']['message']['media']['_'] == 'messageMediaPhoto' || $update['update']['message']['media']['_'] == 'messageMediaDocument')) { if (isset($update['update']['message']['media']) && ($update['update']['message']['media']['_'] == 'messageMediaPhoto' || $update['update']['message']['media']['_'] == 'messageMediaDocument')) {
$time = time(); $time = microtime(true);
$file = $MadelineProto->download_to_dir($update['update']['message']['media'], '/tmp'); $file = $MadelineProto->download_to_dir($update['update']['message']['media'], '/tmp');
$MadelineProto->messages->sendMessage(['peer' => isset($update['update']['message']['from_id']) ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => 'Downloaded to '.$file.' in '.(time() - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); $MadelineProto->messages->sendMessage(['peer' => isset($update['update']['message']['from_id']) ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
} }
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]); $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);

View File

@ -54,27 +54,22 @@ if ($MadelineProto === false) {
\danog\MadelineProto\Logger::log(['Registering new user'], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Registering new user'], \danog\MadelineProto\Logger::NOTICE);
$authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): ')); $authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): '));
} }
echo 'Serializing MadelineProto to s.madeline...'.PHP_EOL;
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL;
} else { } else {
$MadelineProto->bot_login(getenv('BOT_TOKEN')); $MadelineProto->bot_login(getenv('BOT_TOKEN'));
} }
} }
$message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION')); $message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION'));
echo 'Serializing MadelineProto to s.madeline...'.PHP_EOL; $MadelineProto->session = 's.madeline';
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL;
$sent = [-440592694 => true]; $sent = [-440592694 => true];
$offset = 0; $offset = 0;
while (true) { while (true) {
try { try {
$updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout $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
//\danog\MadelineProto\Logger::log([$updates]); //\danog\MadelineProto\Logger::log([$updates]);
foreach ($updates as $update) { foreach ($updates as $update) {
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL;
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id $offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
switch ($update['update']['_']) { switch ($update['update']['_']) {
/*case 'updateNewChannelMessage': /*case 'updateNewChannelMessage':
@ -87,11 +82,11 @@ while (true) {
} }
break;*/ break;*/
case 'updateNewEncryptedMessage': case 'updateNewEncryptedMessage':
//var_dump($MadelineProto->download_to_dir($update['update']['message'], '.')); var_dump($MadelineProto->download_to_dir($update['update']['message'], '.'));
if (isset($sent[$update['update']['message']['chat_id']])) { if (isset($sent[$update['update']['message']['chat_id']])) {
continue; continue;
} }
$secret = $update['update']['message']['chat_id']; $secret = $update['update']['message']['chat_id'];
$secret_media = []; $secret_media = [];
// Photo uploaded as document, secret chat // Photo uploaded as document, secret chat
@ -133,7 +128,6 @@ $secret = $update['update']['message']['chat_id'];
while ($i < $argv[1]) { while ($i < $argv[1]) {
echo "SENDING MESSAGE $i TO ".$update['update']['message']['chat_id'].PHP_EOL; echo "SENDING MESSAGE $i TO ".$update['update']['message']['chat_id'].PHP_EOL;
$MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => (string) ($i++)]]); $MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => (string) ($i++)]]);
\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto);
} }
$sent[$update['update']['message']['chat_id']] = true; $sent[$update['update']['message']['chat_id']] = true;
} }
@ -144,5 +138,4 @@ $secret = $update['update']['message']['chat_id'];
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
//sleep(1); //sleep(1);
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL;
} }

View File

@ -45,7 +45,6 @@ if (!extension_loaded('pthreads')) {
{ {
if (in_array($name, [\SO_RCVTIMEO, \SO_SNDTIMEO])) { if (in_array($name, [\SO_RCVTIMEO, \SO_SNDTIMEO])) {
$this->timeout = ['sec' => (int) $value, 'usec' => (int) (($value - (int) $value) * 1000000)]; $this->timeout = ['sec' => (int) $value, 'usec' => (int) (($value - (int) $value) * 1000000)];
stream_set_timeout($this->sock, $this->timeout['sec'], $this->timeout['usec']);
return true; return true;
} }
@ -83,8 +82,10 @@ if (!extension_loaded('pthreads')) {
if ($this->domain === AF_INET6 && strpos($address, ':') !== false) { if ($this->domain === AF_INET6 && strpos($address, ':') !== false) {
$address = '['.$address.']'; $address = '['.$address.']';
} }
$errno = 0;
$this->sock = fsockopen($this->protocol.'://'.$address, $port); $errstr = '';
$this->sock = fsockopen($this->protocol.'://'.$address, $port, $errno, $errstr, $this->timeout['sec'] + ($this->timeout['usec']/1000000));
stream_set_timeout($this->sock, $this->timeout['sec'], $this->timeout['usec']);
return true; return true;
} }

View File

@ -51,7 +51,6 @@ class Connection
public function __magic_construct($proxy, $extra, $ip, $port, $protocol, $timeout, $ipv6) public function __magic_construct($proxy, $extra, $ip, $port, $protocol, $timeout, $ipv6)
{ {
// Can use: // Can use:
/* /*
- tcp_full - tcp_full
@ -77,11 +76,11 @@ class Connection
if ($has_proxy && $this->extra !== []) { if ($has_proxy && $this->extra !== []) {
$this->sock->setExtra($this->extra); $this->sock->setExtra($this->extra);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
if (!$this->sock->connect($ip, $port)) { if (!$this->sock->connect($ip, $port)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
$this->sock->setBlocking(true); $this->sock->setBlocking(true);
$this->write(chr(239)); $this->write(chr(239));
break; break;
@ -90,11 +89,11 @@ class Connection
if ($has_proxy && $this->extra !== []) { if ($has_proxy && $this->extra !== []) {
$this->sock->setExtra($this->extra); $this->sock->setExtra($this->extra);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
if (!$this->sock->connect($ip, $port)) { if (!$this->sock->connect($ip, $port)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
$this->sock->setBlocking(true); $this->sock->setBlocking(true);
$this->write(str_repeat(chr(238), 4)); $this->write(str_repeat(chr(238), 4));
break; break;
@ -104,11 +103,11 @@ class Connection
if ($has_proxy && $this->extra !== []) { if ($has_proxy && $this->extra !== []) {
$this->sock->setExtra($this->extra); $this->sock->setExtra($this->extra);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
if (!$this->sock->connect($ip, $port)) { if (!$this->sock->connect($ip, $port)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
$this->sock->setBlocking(true); $this->sock->setBlocking(true);
$this->out_seq_no = -1; $this->out_seq_no = -1;
@ -119,11 +118,11 @@ class Connection
if ($has_proxy && $this->extra !== []) { if ($has_proxy && $this->extra !== []) {
$this->sock->setExtra($this->extra); $this->sock->setExtra($this->extra);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
if (!$this->sock->connect($ip, $port)) { if (!$this->sock->connect($ip, $port)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
$this->sock->setBlocking(true); $this->sock->setBlocking(true);
do { do {
$random = $this->random(64); $random = $this->random(64);
@ -166,13 +165,11 @@ class Connection
if ($has_proxy && $this->extra !== []) { if ($has_proxy && $this->extra !== []) {
$this->sock->setExtra($this->extra); $this->sock->setExtra($this->extra);
} }
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
if (!$this->sock->connect($this->parsed['host'], $port)) { if (!$this->sock->connect($this->parsed['host'], $port)) {
throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']);
} }
if (!\danog\MadelineProto\Logger::$has_thread) {
$this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
$this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
}
$this->sock->setBlocking(true); $this->sock->setBlocking(true);
break; break;
case 'udp': case 'udp':

View File

@ -63,8 +63,13 @@ class DataCenter
} }
$dc_config_number = isset($this->settings[$dc_number]) ? $dc_number : 'all'; $dc_config_number = isset($this->settings[$dc_number]) ? $dc_number : 'all';
$test = $this->settings[$dc_config_number]['test_mode'] ? 'test' : 'main'; $test = $this->settings[$dc_config_number]['test_mode'] ? 'test' : 'main';
$x = 0;
do {
$ipv6 = $this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4'; $ipv6 = $this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4';
if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) { if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) {
unset($this->sockets[$dc_number]); unset($this->sockets[$dc_number]);
@ -96,50 +101,33 @@ class DataCenter
$address = $this->settings[$dc_config_number]['protocol'].'://'.$address.'/api'; $address = $this->settings[$dc_config_number]['protocol'].'://'.$address.'/api';
} }
\danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['dc_con_test_start'], $dc_number, $test, $ipv6, $this->settings[$dc_config_number]['protocol'])], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['dc_con_test_start'], $dc_number, $test, $ipv6, $this->settings[$dc_config_number]['protocol'])], \danog\MadelineProto\Logger::VERBOSE);
foreach (array_unique([$port, 443, 80, 88]) as $port) {
$x = 0; \danog\MadelineProto\Logger::log(['Trying connection on port '.$port.'...'], \danog\MadelineProto\Logger::WARNING);
do { try {
try { if (isset($this->sockets[$dc_number]->old)) {
if (isset($this->sockets[$dc_number]->old)) { $this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
$this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); unset($this->sockets[$dc_number]->old);
unset($this->sockets[$dc_number]->old); } else {
} else { $this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']);
$this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); }
\danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING);
return true;
} catch (\danog\MadelineProto\Exception $e) {
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
} }
\danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING);
return true;
} catch (\danog\MadelineProto\Exception $e) {
} catch (\danog\MadelineProto\NothingInTheSocketException $e) {
} }
switch ($x) { switch ($x) {
case 0: case 0:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 443...'], \danog\MadelineProto\Logger::WARNING); $this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
$port = 443; \danog\MadelineProto\Logger::log(['Connection failed, retrying connection with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
continue; continue;
case 1: case 1:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 80...'], \danog\MadelineProto\Logger::WARNING); $this->settings[$dc_config_number]['proxy'] = '\Socket';
$port = 80; \danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
continue; continue;
case 2: case 2:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 88...'], \danog\MadelineProto\Logger::WARNING); $this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6'];
$port = 88; \danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING);
continue;
case 3:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 443 without the proxy...'], \danog\MadelineProto\Logger::WARNING);
$port = 443;
$this->settings[$dc_config_number]['proxy'] = '\Socket';
continue;
case 4:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 80 without the proxy...'], \danog\MadelineProto\Logger::WARNING);
$port = 80;
$this->settings[$dc_config_number]['proxy'] = '\Socket';
continue;
case 5:
\danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 88 without the proxy...'], \danog\MadelineProto\Logger::WARNING);
$port = 88;
$this->settings[$dc_config_number]['proxy'] = '\Socket';
continue; continue;
default: default:
return false; return false;

View File

@ -46,7 +46,7 @@ class MTProto
/* /*
const V = 71; const V = 71;
*/ */
const V = 89; const V = 90;
const NOT_LOGGED_IN = 0; const NOT_LOGGED_IN = 0;
const WAITING_CODE = 1; const WAITING_CODE = 1;

View File

@ -22,6 +22,7 @@ trait AuthKeyHandler
{ {
public function create_auth_key($expires_in, $datacenter) public function create_auth_key($expires_in, $datacenter)
{ {
$req_pq = strpos($datacenter, 'cdn') ? 'req_pq' : 'req_pq_multi';
for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) { for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) {
try { try {
\danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['req_pq']], \danog\MadelineProto\Logger::VERBOSE); \danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['req_pq']], \danog\MadelineProto\Logger::VERBOSE);
@ -44,7 +45,7 @@ trait AuthKeyHandler
* ] * ]
*/ */
$nonce = $this->random(16); $nonce = $this->random(16);
$ResPQ = $this->method_call('req_pq_multi', $ResPQ = $this->method_call($req_pq,
[ [
'nonce' => $nonce, 'nonce' => $nonce,
], ],
@ -370,6 +371,7 @@ trait AuthKeyHandler
$res_authorization['server_salt'] = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0); $res_authorization['server_salt'] = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0);
$res_authorization['auth_key'] = $auth_key_str; $res_authorization['auth_key'] = $auth_key_str;
$res_authorization['id'] = substr($auth_key_sha, -8); $res_authorization['id'] = substr($auth_key_sha, -8);
$res_authorization['connection_inited'] = false;
\danog\MadelineProto\Logger::log(['Auth key generated'], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log(['Auth key generated'], \danog\MadelineProto\Logger::NOTICE);
@ -398,6 +400,7 @@ trait AuthKeyHandler
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING); \danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
\danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING); \danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING);
$req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi';
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
if ($e->rpc === 'RPC_CALL_FAIL') { if ($e->rpc === 'RPC_CALL_FAIL') {
throw $e; throw $e;
@ -595,15 +598,17 @@ trait AuthKeyHandler
$socket->temp_auth_key = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id); $socket->temp_auth_key = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id);
if (!$cdn) { if (!$cdn) {
$this->bind_temp_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id); $this->bind_temp_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id);
$config = $this->write_client_info('help.getConfig', [], ['datacenter' => $id]); $config = $this->method_call('help.getConfig', [], ['datacenter' => $id]);
$this->sync_authorization($id); $this->sync_authorization($id);
$this->get_config($config); $this->get_config($config);
} }
} else { } else {
$socket->temp_auth_key = $socket->auth_key; $socket->temp_auth_key = $socket->auth_key;
$config = $this->write_client_info('help.getConfig', [], ['datacenter' => $id]); if (!$cdn) {
$this->sync_authorization($id); $config = $this->method_call('help.getConfig', [], ['datacenter' => $id]);
$this->get_config($config); $this->sync_authorization($id);
$this->get_config($config);
}
} }
} elseif (!$cdn) { } elseif (!$cdn) {
$this->sync_authorization($id); $this->sync_authorization($id);

View File

@ -349,10 +349,10 @@ trait Files
if (isset($message_media['cdn_key'])) { if (isset($message_media['cdn_key'])) {
$ivec = substr($message_media['cdn_iv'], 0, 12).pack('N', $offset >> 4); $ivec = substr($message_media['cdn_iv'], 0, 12).pack('N', $offset >> 4);
$res['bytes'] = $this->ctr_encrypt($res['bytes'], $message_media['cdn_key'], $ivec); $res['bytes'] = $this->ctr_encrypt($res['bytes'], $message_media['cdn_key'], $ivec);
$this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $datacenter);
} }
if (isset($message_media['key'])) { if (isset($message_media['key'])) {
$res['bytes'] = $ige->decrypt($res['bytes']); $res['bytes'] = $ige->decrypt($res['bytes']);
$this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $datacenter);
} }
if ($start_at) { if ($start_at) {
$res['bytes'] = substr($res['bytes'], $start_at); $res['bytes'] = substr($res['bytes'], $start_at);
@ -399,17 +399,19 @@ trait Files
private function check_cdn_hash($file, $offset, $data, &$datacenter) private function check_cdn_hash($file, $offset, $data, &$datacenter)
{ {
if (!isset($this->cdn_hashes[$file][$offset])) { while (strlen($data)) {
$this->add_cdn_hashes($this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => &$datacenter])); if (!isset($this->cdn_hashes[$file][$offset])) {
$this->add_cdn_hashes($this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => &$datacenter]));
}
if (!isset($this->cdn_hashes[$file][$offset])) {
throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset '.$offset);
}
if (hash('sha256', substr($data, 0, $this->cdn_hashes[$file][$offset]['limit']), true) !== $this->cdn_hashes[$file][$offset]['hash']) {
throw new \danog\MadelineProto\SecurityException('CDN hash mismatch for offset '.$offset);
}
$data = substr($data, $this->cdn_hashes[$file][$offset]['limit']);
$offset += $this->cdn_hashes[$file][$offset]['limit'];
} }
if (!isset($this->cdn_hashes[$file][$offset])) {
throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset '.$offset);
}
if (hash('sha256', $data, true) !== $this->cdn_hashes[$file][$offset]['hash']) {
throw new \danog\MadelineProto\SecurityException('CDN hashe mismatch for offset '.$offset);
}
unset($this->cdn_hashes[$file][$offset]);
return true; return true;
} }

View File

@ -246,7 +246,7 @@ trait ResponseHandler
case 'Updates': case 'Updates':
unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]); unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]);
$unset = true; $unset = true;
$this->handle_updates($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']); if (strpos($datacenter, 'cdn') === false) $this->handle_updates($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']);
$only_updates = true && $only_updates; $only_updates = true && $only_updates;
break; break;
default: default:

View File

@ -473,11 +473,11 @@ trait BotAPI
public function split_to_chunks($text) public function split_to_chunks($text)
{ {
$total_length = 4096; $max_length = 4096;
$text_arr = []; $text_arr = [];
foreach ($this->multipleExplodeKeepDelimiters(["\n"], $text) as $word) { foreach ($this->multipleExplodeKeepDelimiters(["\n"], $text) as $word) {
if (strlen($word) > 4096) { if (strlen($word) > $max_length) {
foreach (str_split($word, 4096) as $vv) { foreach (str_split($word, $max_length) as $vv) {
$text_arr[] = $vv; $text_arr[] = $vv;
} }
} else { } else {
@ -485,21 +485,13 @@ trait BotAPI
} }
} }
$i = 0; $i = 0;
$message[0] = ''; $message = [''];
foreach ($text_arr as $word) { foreach ($text_arr as $word) {
if (strlen($message[$i].$word.' ') <= $total_length) { if (strlen($message[$i].$word) <= $max_length) {
if ($text_arr[count($text_arr) - 1] == $word) { $message[$i] .= $word;
$message[$i] .= $word;
} else {
$message[$i] .= $word.' ';
}
} else { } else {
$i++; $i++;
if ($text_arr[count($text_arr) - 1] == $word) { $message[$i] = $word;
$message[$i] = $word;
} else {
$message[$i] = $word.' ';
}
} }
} }
@ -510,10 +502,13 @@ trait BotAPI
{ {
$initialArray = explode(chr(1), str_replace($delimiters, chr(1), $string)); $initialArray = explode(chr(1), str_replace($delimiters, chr(1), $string));
$finalArray = []; $finalArray = [];
$delimOffset = 0;
foreach ($initialArray as $item) { foreach ($initialArray as $item) {
$delimOffset += strlen($item);
if (strlen($item) > 0) { if (strlen($item) > 0) {
$finalArray[] = $item.$string[strpos($string, $item) + strlen($item)]; $finalArray[] = $item.($delimOffset < strlen($string) ? $string[$delimOffset] : '');
} }
$delimOffset++;
} }
return $finalArray; return $finalArray;

View File

@ -216,28 +216,22 @@ $time = time();
$inputFile = $MadelineProto->upload('tests/60', 'magic'); // This gets an inputFile object with file name magic $inputFile = $MadelineProto->upload('tests/60', 'magic'); // This gets an inputFile object with file name magic
var_dump(time() - $time); var_dump(time() - $time);
$media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => $inputFile, 'mime_type' => 'magic/magic', 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]]; $media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => $inputFile, 'mime_type' => 'magic/magic', 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]];
$message = 'yay';
$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $mention['user_id']; // Selects only the numeric user id
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]); $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]);
\danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE);
foreach ($media as $type => $inputMedia) { foreach ($media as $type => $inputMedia) {
$type = $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia]); $type = $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia, 'message' => '['.$message.'](mention:'.$mention.')', 'parse_mode' => 'markdown']);
} }
} }
//var_dump($MadelineProto->API->get_updates());
if ($bot_token = getenv('BOT_TOKEN')) {
$MadelineProto = new \danog\MadelineProto\API($settings);
$authorization = $MadelineProto->bot_login($bot_token);
\danog\MadelineProto\Logger::log([$authorization], \danog\MadelineProto\Logger::NOTICE);
}
$message = 'yay';
$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
$mention = $mention['user_id']; // Selects only the numeric user id
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]); $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]);
\danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE); \danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE);
} }
//var_dump($MadelineProto->API->get_updates());
var_dump('HERE');