Implemented bot API object conversion, file locking for serialization, bot API file ids
This commit is contained in:
parent
f93d956d0e
commit
38d6ee07b3
1
.gitignore
vendored
1
.gitignore
vendored
@ -86,3 +86,4 @@ docs_md
|
||||
|
||||
.env
|
||||
composer.lock
|
||||
b.php
|
||||
|
@ -236,7 +236,7 @@ To specify a custom callback change the correct value in the settings. The speci
|
||||
|
||||
### Uploading and downloading files
|
||||
|
||||
MadelineProto provides wrapper methods to upload and download files.
|
||||
MadelineProto provides wrapper methods to upload and download files that support bot API file ids.
|
||||
|
||||
Every method described in this section accepts a last optional paramater with a callable function that will be called during the upload/download using the first parameter to pass a floating point number indicating the upload/download status in percentage.
|
||||
|
||||
@ -249,12 +249,13 @@ $inputFile = $MadelineProto->upload('file', 'optional new file name.ext');
|
||||
$MadelineProto->messages->sendMedia(['peer' => '@pwrtelegramgroup', 'media' => $inputMedia]);
|
||||
```
|
||||
|
||||
To convert the result of sendMedia to a bot API file id select the messageMedia object from the output of the method and pass it to `$MadelineProto->API->MTProto_to_botAPI()`.
|
||||
|
||||
See tests/testing.php for more examples.
|
||||
|
||||
|
||||
There are multiple download methods that allow you to download a file to a directory, to a file or to a stream.
|
||||
The first parameter of these functions must always be a [messageMediaPhoto](https://daniil.it/MadelineProto/API_docs/constructors/messageMediaPhoto.html) or a [messageMediaDocument](https://daniil.it/MadelineProto/API_docs/constructors/messageMediaDocument.html) object. These objects are usually received in updates, see `bot.php` for examples
|
||||
The first parameter of these functions must always be either a [messageMediaPhoto](https://daniil.it/MadelineProto/API_docs/constructors/messageMediaPhoto.html) or a [messageMediaDocument](https://daniil.it/MadelineProto/API_docs/constructors/messageMediaDocument.html) object or a bot API file id. These objects are usually received in updates, see `bot.php` for examples
|
||||
|
||||
|
||||
```
|
||||
@ -305,6 +306,8 @@ See tests/testing.php for more examples.
|
||||
|
||||
Methods that allow sending message entities (messages.sendMessage for example) also have an additional parse_mode parameter that enables or disables html/markdown parsing of the message to be sent. See the method-specific documentation for more info.
|
||||
|
||||
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.
|
||||
|
||||
Note that when you login as a bot, MadelineProto also logins using the [PWRTelegram](https://pwrtelegram.xyz) API, to allow persistant storage of peers, even after a logout and another login.
|
||||
|
||||
### Storing sessions
|
||||
|
54
id.php
54
id.php
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016-2017 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
//require '../db:id.php';
|
||||
|
||||
//$select = $pdo->prepare('SELECT * FROM ul');
|
||||
//$select->execute();
|
||||
//$pdores = $select->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
function foreach_offset_length($string)
|
||||
{
|
||||
$res = [];
|
||||
$strlen = strlen($string);
|
||||
for ($offset = 0; $offset < strlen($string); $offset++) {
|
||||
for ($length = $strlen - $offset; $length > 0; $length--) {
|
||||
$s = substr($string, $offset, $length);
|
||||
$number = (string) (new \phpseclib\Math\BigInteger(strrev($s), 256));
|
||||
//$number = ord($s);
|
||||
$res[] = ['number' => $number, 'offset' => $offset, 'length' => $length];
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
$res = [];
|
||||
$pdores = [['file_id' => 'AwADBAADiQEAAo_aCgYAAc-fglzxcY0C']];
|
||||
foreach ($pdores as $r) {
|
||||
$base256 = base64url_decode($r['file_id']);
|
||||
$res = foreach_offset_length($base256);
|
||||
if (!isset($same)) {
|
||||
$same = $res;
|
||||
} else {
|
||||
foreach ($same as $key => $s) {
|
||||
if (!in_array($s, $res)) {
|
||||
unset($same[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var_dump($res);
|
||||
function base64url_decode($data)
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
169
pwrtelegram_debug_bot.php
Executable file
169
pwrtelegram_debug_bot.php
Executable file
@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016-2017 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
$settings = [];
|
||||
$token='';
|
||||
try {
|
||||
$MadelineProto = \danog\MadelineProto\Serialization::deserialize('b.madeline');
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto = new \danog\MadelineProto\API($settings);
|
||||
$authorization = $MadelineProto->bot_login($token);
|
||||
\danog\MadelineProto\Logger::log([$authorization], \danog\MadelineProto\Logger::NOTICE);
|
||||
}
|
||||
function base64url_decode($data)
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
function rle_decode($string) {
|
||||
$base256 = '';
|
||||
$last = '';
|
||||
foreach (str_split($string) as $cur) {
|
||||
if ($last === chr(0)) {
|
||||
$base256 .= str_repeat($last, ord($cur));
|
||||
$last = '';
|
||||
} else {
|
||||
$base256 .= $last;
|
||||
$last = $cur;
|
||||
}
|
||||
}
|
||||
$string = $base256.$last;
|
||||
return $string;
|
||||
}
|
||||
|
||||
function foreach_offset_length($string)
|
||||
{
|
||||
/* $a = [];
|
||||
$b = [];
|
||||
foreach ([2, 3, 4] as $r) {
|
||||
$a []= chr(0).chr($r);
|
||||
$b []= str_repeat(chr(0), $r);
|
||||
}
|
||||
$string = str_replace($a, $b, $string);*/
|
||||
$res = [];
|
||||
$strlen = strlen($string);
|
||||
for ($offset = 0; $offset < strlen($string); $offset++) {
|
||||
// for ($length = $strlen - $offset; $length > 0; $length--) {
|
||||
foreach (['i' => 4, 'q' => 8] as $c => $length) {
|
||||
$s = substr($string, $offset, $length);
|
||||
if (strlen($s) === $length) {
|
||||
$number = \danog\PHP\Struct::unpack('<'.$c, $s)[0];
|
||||
//$number = ord($s);
|
||||
$res[] = ['number' => $number, 'offset' => $offset, 'length' => $length];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res = ['offset' => 0, 'files' => []];
|
||||
function getfiles($token, &$params) {
|
||||
foreach (json_decode(file_get_contents('https://api.telegram.org/bot'.$token.'/getupdates?offset='.$params['offset']), true)['result'] as $update) {
|
||||
$params['offset'] = $update['update_id']+1;
|
||||
if (isset($update['message']['audio'])) {
|
||||
$params['files'][$update['message']['message_id']] = $update['message']['audio']['file_id'];
|
||||
}
|
||||
if (isset($update['message']['document'])) {
|
||||
$params['files'][$update['message']['message_id']] = $update['message']['document']['file_id'];
|
||||
}
|
||||
if (isset($update['message']['video'])) {
|
||||
$params['files'][$update['message']['message_id']] = $update['message']['video']['file_id'];
|
||||
}
|
||||
if (isset($update['message']['sticker'])) {
|
||||
$params['files'][$update['message']['message_id']] = $update['message']['sticker']['file_id'];
|
||||
}
|
||||
if (isset($update['message']['voice'])) {
|
||||
$params['files'][$update['message']['message_id']] = $update['message']['voice']['file_id'];
|
||||
}
|
||||
if (isset($update['message']['photo'])) {
|
||||
$params['files'][$update['message']['message_id']] = end($update['message']['photo'])['file_id'];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
while (true) {
|
||||
$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
|
||||
//var_dump($updates);
|
||||
foreach ($updates as $update) {
|
||||
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
|
||||
//var_dump($update);
|
||||
switch ($update['update']['_']) {
|
||||
case 'updateNewMessage':
|
||||
if (isset($update['update']['message']['out']) && $update['update']['message']['out']) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (isset($update['update']['message']['media'])) {
|
||||
getfiles($token, $res);
|
||||
$bot_api_id = $message = $res['files'][$update['update']['message']['id']];
|
||||
$bot_api_id_b256 = base64url_decode($bot_api_id);
|
||||
$bot_api_id_rledecoded = rle_decode($bot_api_id_b256);
|
||||
$message .= PHP_EOL.PHP_EOL.
|
||||
'First 4 bytes: '.ord($bot_api_id_rledecoded[0]).' '.ord($bot_api_id_rledecoded[1]).' '.ord($bot_api_id_rledecoded[2]).' '.ord($bot_api_id_rledecoded[3]).PHP_EOL.
|
||||
'First 4 bytes (single integer): '.(\danog\PHP\Struct::unpack('<i', substr($bot_api_id_rledecoded, 0, 4))[0]).PHP_EOL.
|
||||
'bytes 8-16: '.(\danog\PHP\Struct::unpack('<q', substr($bot_api_id_rledecoded, 8, 8))[0]).PHP_EOL.
|
||||
'bytes 16-24: '.(\danog\PHP\Struct::unpack('<q', substr($bot_api_id_rledecoded, 16, 8))[0]).PHP_EOL.
|
||||
'Last byte: '.ord(substr($bot_api_id_rledecoded, -1)).PHP_EOL.
|
||||
'Total length: '.strlen($bot_api_id_b256).PHP_EOL.
|
||||
'Total length (rledecoded): '.strlen($bot_api_id_rledecoded).PHP_EOL.
|
||||
PHP_EOL.'<b>param (value): start-end (length)</b><br>'.PHP_EOL;
|
||||
//var_dump($update);
|
||||
$bot_api = foreach_offset_length($bot_api_id_rledecoded);
|
||||
$mtproto = $MadelineProto->get_download_info($update['update']['message']['media'])['InputFileLocation'];
|
||||
$m = [];
|
||||
unset($mtproto['_']);
|
||||
if (isset($mtproto['version']))unset($mtproto['version']);
|
||||
if (isset($update['update']['message']['media']['photo'])) $mtproto['id'] = $update['update']['message']['media']['photo']['id'];
|
||||
if (isset($update['update']['message']['media']['photo'])) $mtproto['access_hash'] = $update['update']['message']['media']['photo']['access_hash'];
|
||||
if (isset($update['update']['message']['media']['document'])) $mtproto['id'] = $update['update']['message']['media']['document']['id'];
|
||||
if (isset($update['update']['message']['media']['document'])) $mtproto['access_hash'] = $update['update']['message']['media']['document']['access_hash'];
|
||||
//var_dump($mtproto);
|
||||
foreach ($mtproto as $key => $n) {
|
||||
foreach ($bot_api as $bn) {
|
||||
if ($bn['number'] === $n) {
|
||||
$m [$bn['offset']+$bn['length']]= $key." (".$n."): ".$bn['offset'].'-'.($bn['offset']+$bn['length']).' ('.$bn['length'].')'.PHP_EOL;
|
||||
unset($mtproto[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($m);
|
||||
foreach ($m as $key => $bn) {
|
||||
$message .= $bn;
|
||||
}
|
||||
foreach ($mtproto as $key => $n) {
|
||||
$message .= $key." (".$n."): not found".PHP_EOL;
|
||||
}
|
||||
$MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $message, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'html']);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
}
|
||||
try {
|
||||
if (isset($update['update']['message']['media']) && $update['update']['message']['media'] == 'messageMediaPhoto' && $update['update']['message']['media'] == 'messageMediaDocument') {
|
||||
$time = time();
|
||||
// $file = $MadelineProto->download_to_dir($update['update']['message']['media'], '/tmp');
|
||||
// $MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_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']]]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('b.madeline', $MadelineProto).' bytes'.PHP_EOL;
|
||||
}
|
@ -37,10 +37,10 @@ class API extends APIFactory
|
||||
$this->APIFactory();
|
||||
|
||||
\danog\MadelineProto\Logger::log(['Ping...'], Logger::ULTRA_VERBOSE);
|
||||
$pong = $this->ping([3]);
|
||||
$pong = $this->ping(['ping_id' => 3]);
|
||||
\danog\MadelineProto\Logger::log(['Pong: '.$pong['ping_id']], Logger::ULTRA_VERBOSE);
|
||||
\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE);
|
||||
$this->future_salts = $this->get_future_salts([3]);
|
||||
//\danog\MadelineProto\Logger::log(['Getting future salts...'], Logger::ULTRA_VERBOSE);
|
||||
//$this->future_salts = $this->get_future_salts(['num' => 3]);
|
||||
$this->API->v = $this->API->getV();
|
||||
\danog\MadelineProto\Logger::log(['MadelineProto is ready!'], Logger::NOTICE);
|
||||
}
|
||||
|
@ -93,6 +93,6 @@ class APIFactory
|
||||
{
|
||||
$this->API->get_config();
|
||||
|
||||
return $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : []);
|
||||
return $this->API->method_call($this->namespace.$name, (isset($arguments[0]) && is_array($arguments[0])) ? $arguments[0] : [], (isset($arguments[1]) && is_array($arguments[1])) ? $arguments[1] : []);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ class MTProto extends PrimeModule
|
||||
use \danog\MadelineProto\MTProtoTools\SeqNoHandler;
|
||||
use \danog\MadelineProto\MTProtoTools\UpdateHandler;
|
||||
use \danog\MadelineProto\TL\TL;
|
||||
use \danog\MadelineProto\TL\Files;
|
||||
use \danog\MadelineProto\Tools;
|
||||
|
||||
public $settings = [];
|
||||
|
@ -508,7 +508,7 @@ trait AuthKeyHandler
|
||||
$padding = $this->random($this->posmod(-strlen($encrypted_data), 16));
|
||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->auth_key['auth_key']);
|
||||
$encrypted_message = $this->datacenter->auth_key['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||
$res = $this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], $int_message_id);
|
||||
$res = $this->method_call('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], ['message_id' => $int_message_id]);
|
||||
if ($res === true) {
|
||||
\danog\MadelineProto\Logger::log(['Successfully binded temporary and permanent authorization keys.'], \danog\MadelineProto\Logger::NOTICE);
|
||||
|
||||
|
@ -17,17 +17,22 @@ namespace danog\MadelineProto\MTProtoTools;
|
||||
*/
|
||||
trait CallHandler
|
||||
{
|
||||
public function method_call($method, $args = [], $message_id = null, $heavy = false)
|
||||
public function method_call($method, $args = [], $aargs = ['message_id' => null, 'heavy' => false])
|
||||
{
|
||||
if (!is_array($args)) {
|
||||
throw new \danog\MadelineProto\Exception("Arguments aren't an array.");
|
||||
}
|
||||
if (!is_array($aargs)) {
|
||||
throw new \danog\MadelineProto\Exception("Additonal arguments aren't an array.");
|
||||
}
|
||||
$args = $this->botAPI_to_MTProto($args);
|
||||
$serialized = $this->serialize_method($method, $args);
|
||||
$content_related = $this->content_related($method);
|
||||
for ($count = 1; $count <= $this->settings['max_tries']['query']; $count++) {
|
||||
try {
|
||||
\danog\MadelineProto\Logger::log(['Calling method (try number '.$count.' for '.$method.')...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
|
||||
$args = $this->get_named_method_args($method, $args);
|
||||
$int_message_id = $this->send_message($this->serialize_method($method, $args), $this->content_related($method), $message_id);
|
||||
$int_message_id = $this->send_message($serialized, $content_related, $aargs);
|
||||
if ($method === 'http_wait') {
|
||||
return true;
|
||||
}
|
||||
@ -53,7 +58,7 @@ trait CallHandler
|
||||
continue;
|
||||
}
|
||||
$server_answer = $this->datacenter->incoming_messages[$this->datacenter->outgoing_messages[$int_message_id]['response']]['content']; // continue was not called, so I got a response
|
||||
if ($heavy) {
|
||||
if (isset($aargs['heavy']) && $aargs['heavy']) {
|
||||
$this->datacenter->incoming_messages[$this->datacenter->outgoing_messages[$int_message_id]['response']]['content'] = [];
|
||||
}
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
@ -125,6 +130,9 @@ trait CallHandler
|
||||
$server_answer = $server_answer['_'] === 'boolTrue';
|
||||
break;
|
||||
}
|
||||
if (isset($aargs['botAPI']) && $aargs['botAPI']) {
|
||||
$server_answer = $this->MTProto_to_botAPI($server_answer, $args);
|
||||
}
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$last_error = $e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine();
|
||||
\danog\MadelineProto\Logger::log(['An error occurred while calling method '.$method.': '.$last_error.'. Recreating connection and retrying to call method...'], \danog\MadelineProto\Logger::WARNING);
|
||||
@ -136,7 +144,7 @@ trait CallHandler
|
||||
sleep(1); // To avoid flooding
|
||||
continue;
|
||||
} finally {
|
||||
if ($heavy && isset($int_message_id)) {
|
||||
if (isset($aargs['heavy']) && $aargs['heavy'] && isset($int_message_id)) {
|
||||
$this->datacenter->outgoing_messages[$int_message_id]['args'] = [];
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,12 @@ trait MessageHandler
|
||||
* Forming the message frame and sending message to server
|
||||
* :param message: byte string to send.
|
||||
*/
|
||||
public function send_message($message_data, $content_related, $int_message_id = null)
|
||||
public function send_message($message_data, $content_related, $aargs = [])
|
||||
{
|
||||
if ($int_message_id === null) {
|
||||
if (!isset($aargs['message_id']) || $aargs['message_id'] === null) {
|
||||
$int_message_id = $this->generate_message_id();
|
||||
} else {
|
||||
$int_message_id = $aargs['message_id'];
|
||||
}
|
||||
if (!is_int($int_message_id)) {
|
||||
throw new \danog\MadelineProto\Exception("Specified message id isn't an integer");
|
||||
|
@ -316,7 +316,7 @@ trait PeerHandler
|
||||
$res['bot_info'] = $full['full']['bot_info'];
|
||||
}
|
||||
if (isset($full['full']['profile_photo']['sizes'])) {
|
||||
$res['photo'] = end($full['full']['profile_photo']['sizes']);
|
||||
$res['photo'] = $this->photosize_to_botapi(end($full['full']['profile_photo']['sizes']), $full['User']);
|
||||
}
|
||||
$bio = '';
|
||||
if ($full['type'] === 'user' && isset($res['username']) && !isset($res['about']) && $fullfetch) {
|
||||
@ -338,7 +338,7 @@ trait PeerHandler
|
||||
}
|
||||
|
||||
if (isset($full['full']['chat_photo']['sizes'])) {
|
||||
$res['photo'] = end($full['full']['chat_photo']['sizes']);
|
||||
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), $full['Chat']);
|
||||
}
|
||||
if (isset($full['full']['exported_invite']['link'])) {
|
||||
$res['invite'] = $full['full']['exported_invite']['link'];
|
||||
@ -361,7 +361,7 @@ trait PeerHandler
|
||||
}
|
||||
|
||||
if (isset($full['full']['chat_photo']['sizes'])) {
|
||||
$res['photo'] = end($full['full']['chat_photo']['sizes']);
|
||||
$res['photo'] = $this->photosize_to_botapi(end($full['full']['chat_photo']['sizes']), $full['Chat']);
|
||||
}
|
||||
if (isset($full['full']['exported_invite']['link'])) {
|
||||
$res['invite'] = $full['full']['exported_invite']['link'];
|
||||
|
@ -51,7 +51,11 @@ class Serialization
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$unserialized = unserialize(file_get_contents($filename));
|
||||
$file = fopen($filename, 'r+');
|
||||
flock($file, LOCK_EX);
|
||||
$unserialized = unserialize(stream_get_contents($file));
|
||||
flock($file, LOCK_UN);
|
||||
fclose($file);
|
||||
} else {
|
||||
throw new Exception('File does not exist');
|
||||
}
|
||||
|
153
src/danog/MadelineProto/TL/Extension.php
Normal file
153
src/danog/MadelineProto/TL/Extension.php
Normal file
@ -0,0 +1,153 @@
|
||||
'wmlc' => [
|
||||
0 => 'application/wmlc',
|
||||
],
|
||||
'dcr' => [
|
||||
0 => 'application/x-director',
|
||||
],
|
||||
'dvi' => [
|
||||
0 => 'application/x-dvi',
|
||||
],
|
||||
'gtar' => [
|
||||
0 => 'application/x-gtar',
|
||||
],
|
||||
'php' => [
|
||||
0 => 'application/x-httpd-php',
|
||||
1 => 'application/php',
|
||||
2 => 'application/x-php',
|
||||
3 => 'text/php',
|
||||
4 => 'text/x-php',
|
||||
5 => 'application/x-httpd-php-source',
|
||||
],
|
||||
'swf' => [
|
||||
0 => 'application/x-shockwave-flash',
|
||||
],
|
||||
'sit' => [
|
||||
0 => 'application/x-stuffit',
|
||||
],
|
||||
'z' => [
|
||||
0 => 'application/x-compress',
|
||||
],
|
||||
'mid' => [
|
||||
0 => 'audio/midi',
|
||||
],
|
||||
'aif' => [
|
||||
0 => 'audio/x-aiff',
|
||||
1 => 'audio/aiff',
|
||||
],
|
||||
'ram' => [
|
||||
0 => 'audio/x-pn-realaudio',
|
||||
],
|
||||
'rpm' => [
|
||||
0 => 'audio/x-pn-realaudio-plugin',
|
||||
],
|
||||
'ra' => [
|
||||
0 => 'audio/x-realaudio',
|
||||
],
|
||||
'rv' => [
|
||||
0 => 'video/vnd.rn-realvideo',
|
||||
],
|
||||
'jp2' => [
|
||||
0 => 'image/jp2',
|
||||
1 => 'video/mj2',
|
||||
2 => 'image/jpx',
|
||||
3 => 'image/jpm',
|
||||
],
|
||||
'tiff' => [
|
||||
0 => 'image/tiff',
|
||||
],
|
||||
'eml' => [
|
||||
0 => 'message/rfc822',
|
||||
],
|
||||
'pem' => [
|
||||
0 => 'application/x-x509-user-cert',
|
||||
1 => 'application/x-pem-file',
|
||||
],
|
||||
'p10' => [
|
||||
0 => 'application/x-pkcs10',
|
||||
1 => 'application/pkcs10',
|
||||
],
|
||||
'p12' => [
|
||||
0 => 'application/x-pkcs12',
|
||||
],
|
||||
'p7a' => [
|
||||
0 => 'application/x-pkcs7-signature',
|
||||
],
|
||||
'p7c' => [
|
||||
0 => 'application/pkcs7-mime',
|
||||
1 => 'application/x-pkcs7-mime',
|
||||
],
|
||||
'p7r' => [
|
||||
0 => 'application/x-pkcs7-certreqresp',
|
||||
],
|
||||
'p7s' => [
|
||||
0 => 'application/pkcs7-signature',
|
||||
],
|
||||
'crt' => [
|
||||
0 => 'application/x-x509-ca-cert',
|
||||
1 => 'application/pkix-cert',
|
||||
],
|
||||
'crl' => [
|
||||
0 => 'application/pkix-crl',
|
||||
1 => 'application/pkcs-crl',
|
||||
],
|
||||
'pgp' => [
|
||||
0 => 'application/pgp',
|
||||
],
|
||||
'gpg' => [
|
||||
0 => 'application/gpg-keys',
|
||||
],
|
||||
'rsa' => [
|
||||
0 => 'application/x-pkcs7',
|
||||
],
|
||||
'ics' => [
|
||||
0 => 'text/calendar',
|
||||
],
|
||||
'zsh' => [
|
||||
0 => 'text/x-scriptzsh',
|
||||
],
|
||||
'cdr' => [
|
||||
0 => 'application/cdr',
|
||||
1 => 'application/coreldraw',
|
||||
2 => 'application/x-cdr',
|
||||
3 => 'application/x-coreldraw',
|
||||
4 => 'image/cdr',
|
||||
5 => 'image/x-cdr',
|
||||
6 => 'zz-application/zz-winassoc-cdr',
|
||||
],
|
||||
'wma' => [
|
||||
0 => 'audio/x-ms-wma',
|
||||
],
|
||||
'vcf' => [
|
||||
0 => 'text/x-vcard',
|
||||
],
|
||||
'srt' => [
|
||||
0 => 'text/srt',
|
||||
],
|
||||
'vtt' => [
|
||||
0 => 'text/vtt',
|
||||
],
|
||||
'ico' => [
|
||||
0 => 'image/x-icon',
|
||||
1 => 'image/x-ico',
|
||||
2 => 'image/vnd.microsoft.icon',
|
||||
],
|
||||
'csv' => [
|
||||
0 => 'text/x-comma-separated-values',
|
||||
1 => 'text/comma-separated-values',
|
||||
2 => 'application/vnd.msexcel',
|
||||
],
|
||||
'json' => [
|
||||
0 => 'application/json',
|
||||
1 => 'text/json',
|
||||
],
|
||||
];
|
||||
|
||||
public function upload($file, $file_name = '', $cb = null)
|
||||
{
|
||||
if (!file_exists($file)) {
|
||||
throw new \danog\MadelineProto\Exception('Given file does not exist!');
|
||||
}
|
||||
if (empty($file_name)) {
|
||||
$file_name = basename($file);
|
||||
}
|
||||
$file_size = filesize($file);
|
705
src/danog/MadelineProto/TL/Files.php
Normal file
705
src/danog/MadelineProto/TL/Files.php
Normal file
@ -0,0 +1,705 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016-2017 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto\TL;
|
||||
|
||||
/**
|
||||
* Manages serialization of file ids
|
||||
*/
|
||||
trait Files
|
||||
{
|
||||
public $all_mimes = [
|
||||
'png' => [
|
||||
0 => 'image/png',
|
||||
1 => 'image/x-png',
|
||||
],
|
||||
'bmp' => [
|
||||
0 => 'image/bmp',
|
||||
1 => 'image/x-bmp',
|
||||
2 => 'image/x-bitmap',
|
||||
3 => 'image/x-xbitmap',
|
||||
4 => 'image/x-win-bitmap',
|
||||
5 => 'image/x-windows-bmp',
|
||||
6 => 'image/ms-bmp',
|
||||
7 => 'image/x-ms-bmp',
|
||||
8 => 'application/bmp',
|
||||
9 => 'application/x-bmp',
|
||||
10 => 'application/x-win-bitmap',
|
||||
],
|
||||
'gif' => [
|
||||
0 => 'image/gif',
|
||||
],
|
||||
'jpeg' => [
|
||||
0 => 'image/jpeg',
|
||||
1 => 'image/pjpeg',
|
||||
],
|
||||
'xspf' => [
|
||||
0 => 'application/xspf+xml',
|
||||
],
|
||||
'vlc' => [
|
||||
0 => 'application/videolan',
|
||||
],
|
||||
'wmv' => [
|
||||
0 => 'video/x-ms-wmv',
|
||||
1 => 'video/x-ms-asf',
|
||||
],
|
||||
'au' => [
|
||||
0 => 'audio/x-au',
|
||||
],
|
||||
'ac3' => [
|
||||
0 => 'audio/ac3',
|
||||
],
|
||||
'flac' => [
|
||||
0 => 'audio/x-flac',
|
||||
],
|
||||
'ogg' => [
|
||||
0 => 'audio/ogg',
|
||||
1 => 'video/ogg',
|
||||
2 => 'application/ogg',
|
||||
],
|
||||
'kmz' => [
|
||||
0 => 'application/vnd.google-earth.kmz',
|
||||
],
|
||||
'kml' => [
|
||||
0 => 'application/vnd.google-earth.kml+xml',
|
||||
],
|
||||
'rtx' => [
|
||||
0 => 'text/richtext',
|
||||
],
|
||||
'rtf' => [
|
||||
0 => 'text/rtf',
|
||||
],
|
||||
'jar' => [
|
||||
0 => 'application/java-archive',
|
||||
1 => 'application/x-java-application',
|
||||
2 => 'application/x-jar',
|
||||
],
|
||||
'zip' => [
|
||||
0 => 'application/x-zip',
|
||||
1 => 'application/zip',
|
||||
2 => 'application/x-zip-compressed',
|
||||
3 => 'application/s-compressed',
|
||||
4 => 'multipart/x-zip',
|
||||
],
|
||||
'7zip' => [
|
||||
0 => 'application/x-compressed',
|
||||
],
|
||||
'xml' => [
|
||||
0 => 'application/xml',
|
||||
1 => 'text/xml',
|
||||
],
|
||||
'svg' => [
|
||||
0 => 'image/svg+xml',
|
||||
],
|
||||
'3g2' => [
|
||||
0 => 'video/3gpp2',
|
||||
],
|
||||
'3gp' => [
|
||||
0 => 'video/3gp',
|
||||
1 => 'video/3gpp',
|
||||
],
|
||||
'mp4' => [
|
||||
0 => 'video/mp4',
|
||||
],
|
||||
'm4a' => [
|
||||
0 => 'audio/x-m4a',
|
||||
],
|
||||
'f4v' => [
|
||||
0 => 'video/x-f4v',
|
||||
],
|
||||
'flv' => [
|
||||
0 => 'video/x-flv',
|
||||
],
|
||||
'webm' => [
|
||||
0 => 'video/webm',
|
||||
],
|
||||
'aac' => [
|
||||
0 => 'audio/x-acc',
|
||||
],
|
||||
'm4u' => [
|
||||
0 => 'application/vnd.mpegurl',
|
||||
],
|
||||
'pdf' => [
|
||||
0 => 'application/pdf',
|
||||
1 => 'application/octet-stream',
|
||||
],
|
||||
'pptx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
],
|
||||
'ppt' => [
|
||||
0 => 'application/powerpoint',
|
||||
1 => 'application/vnd.ms-powerpoint',
|
||||
2 => 'application/vnd.ms-office',
|
||||
3 => 'application/msword',
|
||||
],
|
||||
'docx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
],
|
||||
'xlsx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
1 => 'application/vnd.ms-excel',
|
||||
],
|
||||
'xl' => [
|
||||
0 => 'application/excel',
|
||||
],
|
||||
'xls' => [
|
||||
0 => 'application/msexcel',
|
||||
1 => 'application/x-msexcel',
|
||||
2 => 'application/x-ms-excel',
|
||||
3 => 'application/x-excel',
|
||||
4 => 'application/x-dos_ms_excel',
|
||||
5 => 'application/xls',
|
||||
6 => 'application/x-xls',
|
||||
],
|
||||
'xsl' => [
|
||||
0 => 'text/xsl',
|
||||
],
|
||||
'mpeg' => [
|
||||
0 => 'video/mpeg',
|
||||
],
|
||||
'mov' => [
|
||||
0 => 'video/quicktime',
|
||||
],
|
||||
'avi' => [
|
||||
0 => 'video/x-msvideo',
|
||||
1 => 'video/msvideo',
|
||||
2 => 'video/avi',
|
||||
3 => 'application/x-troff-msvideo',
|
||||
],
|
||||
'movie' => [
|
||||
0 => 'video/x-sgi-movie',
|
||||
],
|
||||
'log' => [
|
||||
0 => 'text/x-log',
|
||||
],
|
||||
'txt' => [
|
||||
0 => 'text/plain',
|
||||
],
|
||||
'css' => [
|
||||
0 => 'text/css',
|
||||
],
|
||||
'html' => [
|
||||
0 => 'text/html',
|
||||
],
|
||||
'wav' => [
|
||||
0 => 'audio/x-wav',
|
||||
1 => 'audio/wave',
|
||||
2 => 'audio/wav',
|
||||
],
|
||||
'xhtml' => [
|
||||
0 => 'application/xhtml+xml',
|
||||
],
|
||||
'tar' => [
|
||||
0 => 'application/x-tar',
|
||||
],
|
||||
'tgz' => [
|
||||
0 => 'application/x-gzip-compressed',
|
||||
],
|
||||
'psd' => [
|
||||
0 => 'application/x-photoshop',
|
||||
1 => 'image/vnd.adobe.photoshop',
|
||||
],
|
||||
'exe' => [
|
||||
0 => 'application/x-msdownload',
|
||||
],
|
||||
'js' => [
|
||||
0 => 'application/x-javascript',
|
||||
],
|
||||
'mp3' => [
|
||||
0 => 'audio/mpeg',
|
||||
1 => 'audio/mpg',
|
||||
2 => 'audio/mpeg3',
|
||||
3 => 'audio/mp3',
|
||||
],
|
||||
'rar' => [
|
||||
0 => 'application/x-rar',
|
||||
1 => 'application/rar',
|
||||
2 => 'application/x-rar-compressed',
|
||||
],
|
||||
'gzip' => [
|
||||
0 => 'application/x-gzip',
|
||||
],
|
||||
'hqx' => [
|
||||
0 => 'application/mac-binhex40',
|
||||
1 => 'application/mac-binhex',
|
||||
2 => 'application/x-binhex40',
|
||||
3 => 'application/x-mac-binhex40',
|
||||
],
|
||||
'cpt' => [
|
||||
0 => 'application/mac-compactpro',
|
||||
],
|
||||
'bin' => [
|
||||
0 => 'application/macbinary',
|
||||
1 => 'application/mac-binary',
|
||||
2 => 'application/x-binary',
|
||||
3 => 'application/x-macbinary',
|
||||
],
|
||||
'oda' => [
|
||||
0 => 'application/oda',
|
||||
],
|
||||
'ai' => [
|
||||
0 => 'application/postscript',
|
||||
],
|
||||
'smil' => [
|
||||
0 => 'application/smil',
|
||||
],
|
||||
'mif' => [
|
||||
0 => 'application/vnd.mif',
|
||||
],
|
||||
'wbxml' => [
|
||||
0 => 'application/wbxml',
|
||||
],
|
||||
'wmlc' => [
|
||||
0 => 'application/wmlc',
|
||||
],
|
||||
'dcr' => [
|
||||
0 => 'application/x-director',
|
||||
],
|
||||
'dvi' => [
|
||||
0 => 'application/x-dvi',
|
||||
],
|
||||
'gtar' => [
|
||||
0 => 'application/x-gtar',
|
||||
],
|
||||
'php' => [
|
||||
0 => 'application/x-httpd-php',
|
||||
1 => 'application/php',
|
||||
2 => 'application/x-php',
|
||||
3 => 'text/php',
|
||||
4 => 'text/x-php',
|
||||
5 => 'application/x-httpd-php-source',
|
||||
],
|
||||
'swf' => [
|
||||
0 => 'application/x-shockwave-flash',
|
||||
],
|
||||
'sit' => [
|
||||
0 => 'application/x-stuffit',
|
||||
],
|
||||
'z' => [
|
||||
0 => 'application/x-compress',
|
||||
],
|
||||
'mid' => [
|
||||
0 => 'audio/midi',
|
||||
],
|
||||
'aif' => [
|
||||
0 => 'audio/x-aiff',
|
||||
1 => 'audio/aiff',
|
||||
],
|
||||
'ram' => [
|
||||
0 => 'audio/x-pn-realaudio',
|
||||
],
|
||||
'rpm' => [
|
||||
0 => 'audio/x-pn-realaudio-plugin',
|
||||
],
|
||||
'ra' => [
|
||||
0 => 'audio/x-realaudio',
|
||||
],
|
||||
'rv' => [
|
||||
0 => 'video/vnd.rn-realvideo',
|
||||
],
|
||||
'jp2' => [
|
||||
0 => 'image/jp2',
|
||||
1 => 'video/mj2',
|
||||
2 => 'image/jpx',
|
||||
3 => 'image/jpm',
|
||||
],
|
||||
'tiff' => [
|
||||
0 => 'image/tiff',
|
||||
],
|
||||
'eml' => [
|
||||
0 => 'message/rfc822',
|
||||
],
|
||||
'pem' => [
|
||||
0 => 'application/x-x509-user-cert',
|
||||
1 => 'application/x-pem-file',
|
||||
],
|
||||
'p10' => [
|
||||
0 => 'application/x-pkcs10',
|
||||
1 => 'application/pkcs10',
|
||||
],
|
||||
'p12' => [
|
||||
0 => 'application/x-pkcs12',
|
||||
],
|
||||
'p7a' => [
|
||||
0 => 'application/x-pkcs7-signature',
|
||||
],
|
||||
'p7c' => [
|
||||
0 => 'application/pkcs7-mime',
|
||||
1 => 'application/x-pkcs7-mime',
|
||||
],
|
||||
'p7r' => [
|
||||
0 => 'application/x-pkcs7-certreqresp',
|
||||
],
|
||||
'p7s' => [
|
||||
0 => 'application/pkcs7-signature',
|
||||
],
|
||||
'crt' => [
|
||||
0 => 'application/x-x509-ca-cert',
|
||||
1 => 'application/pkix-cert',
|
||||
],
|
||||
'crl' => [
|
||||
0 => 'application/pkix-crl',
|
||||
1 => 'application/pkcs-crl',
|
||||
],
|
||||
'pgp' => [
|
||||
0 => 'application/pgp',
|
||||
],
|
||||
'gpg' => [
|
||||
0 => 'application/gpg-keys',
|
||||
],
|
||||
'rsa' => [
|
||||
0 => 'application/x-pkcs7',
|
||||
],
|
||||
'ics' => [
|
||||
0 => 'text/calendar',
|
||||
],
|
||||
'zsh' => [
|
||||
0 => 'text/x-scriptzsh',
|
||||
],
|
||||
'cdr' => [
|
||||
0 => 'application/cdr',
|
||||
1 => 'application/coreldraw',
|
||||
2 => 'application/x-cdr',
|
||||
3 => 'application/x-coreldraw',
|
||||
4 => 'image/cdr',
|
||||
5 => 'image/x-cdr',
|
||||
6 => 'zz-application/zz-winassoc-cdr',
|
||||
],
|
||||
'wma' => [
|
||||
0 => 'audio/x-ms-wma',
|
||||
],
|
||||
'vcf' => [
|
||||
0 => 'text/x-vcard',
|
||||
],
|
||||
'srt' => [
|
||||
0 => 'text/srt',
|
||||
],
|
||||
'vtt' => [
|
||||
0 => 'text/vtt',
|
||||
],
|
||||
'ico' => [
|
||||
0 => 'image/x-icon',
|
||||
1 => 'image/x-ico',
|
||||
2 => 'image/vnd.microsoft.icon',
|
||||
],
|
||||
'csv' => [
|
||||
0 => 'text/x-comma-separated-values',
|
||||
1 => 'text/comma-separated-values',
|
||||
2 => 'application/vnd.msexcel',
|
||||
],
|
||||
'json' => [
|
||||
0 => 'application/json',
|
||||
1 => 'text/json',
|
||||
],
|
||||
];
|
||||
|
||||
public function upload($file, $file_name = '', $cb = null)
|
||||
{
|
||||
if (!file_exists($file)) {
|
||||
throw new \danog\MadelineProto\Exception('Given file does not exist!');
|
||||
}
|
||||
if (empty($file_name)) {
|
||||
$file_name = basename($file);
|
||||
}
|
||||
$file_size = filesize($file);
|
||||
if ($file_size > 1500 * 1024 * 1024) {
|
||||
throw new \danog\MadelineProto\Exception('Given file is too big!');
|
||||
}
|
||||
if ($cb === null) {
|
||||
$cb = function ($percent) {
|
||||
\danog\MadelineProto\Logger::log(['Upload status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
||||
};
|
||||
}
|
||||
$part_size = 512 * 1024;
|
||||
$part_total_num = (int) ceil($file_size / $part_size);
|
||||
$part_num = 0;
|
||||
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
||||
$constructor = $file_size > 10 * 1024 * 1024 ? 'inputFileBig' : 'inputFile';
|
||||
$file_id = \danog\PHP\Struct::unpack('<q', $this->random(8))[0];
|
||||
$f = fopen($file, 'r');
|
||||
fseek($f, 0);
|
||||
while (ftell($f) !== $file_size) {
|
||||
if (!$this->method_call($method, ['file_id' => $file_id, 'file_part' => $part_num++, 'file_total_parts' => $part_total_num, 'bytes' => stream_get_contents($f, $part_size)], ['heavy' => true])) {
|
||||
throw new \danog\MadelineProto\Exception('An error occurred while uploading file part '.$part_num);
|
||||
}
|
||||
$cb(ftell($f) * 100 / $file_size);
|
||||
}
|
||||
fclose($f);
|
||||
|
||||
return ['_' => $constructor, 'id' => $file_id, 'parts' => $part_total_num, 'name' => $file_name, 'md5_checksum' => md5_file($file)];
|
||||
}
|
||||
|
||||
public function get_extension_from_mime($mime)
|
||||
{
|
||||
foreach ($this->all_mimes as $key => $value) {
|
||||
if (array_search($mime, $value) !== false) {
|
||||
return '.'.$key;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
public function base64url_decode($data)
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
|
||||
public function base64url_encode($data)
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
function rle_decode($string) {
|
||||
$new = '';
|
||||
$last = '';
|
||||
$null = chr(0);
|
||||
foreach (str_split($string) as $cur) {
|
||||
if ($last === $null) {
|
||||
$new .= str_repeat($last, ord($cur));
|
||||
$last = '';
|
||||
} else {
|
||||
$new .= $last;
|
||||
$last = $cur;
|
||||
}
|
||||
}
|
||||
$string = $new.$last;
|
||||
return $string;
|
||||
}
|
||||
|
||||
function rle_encode($string) {
|
||||
$new = '';
|
||||
$count = 0;
|
||||
$null = chr(0);
|
||||
foreach (str_split($string) as $cur) {
|
||||
if ($cur === $null) {
|
||||
$count++;
|
||||
} else {
|
||||
if ($count > 0) {
|
||||
$new .= $null.chr($count);
|
||||
$count = 0;
|
||||
}
|
||||
$new .= $cur;
|
||||
}
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
public function photosize_to_botapi($photo, $message_media, $thumbnail = false) {
|
||||
$ext = $this->get_extension_from_location(['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']], '.jpg');
|
||||
$data = \danog\PHP\Struct::pack('<iiqqqqib', $thumbnail ? 0 : 2, $photo['location']['dc_id'], $thumbnail ? 0 : $message_media['id'], $thumbnail ? 0 : $message_media['access_hash'],$photo['location']['volume_id'],$photo['location']['secret'], $photo['location']['local_id'], 2);
|
||||
return [
|
||||
'file_id' => $this->base64url_encode($this->rle_encode($data)),
|
||||
'width' => $photo['w'],
|
||||
'height' => $photo['h'],
|
||||
'file_size' => isset($photo['size']) ? $photo['size'] : strlen($photo['bytes']),
|
||||
'mime_type' => 'image/jpeg',
|
||||
'file_name' => $photo['location']['volume_id'].'_'.$photo['location']['local_id'].$ext
|
||||
];
|
||||
}
|
||||
public function unpack_file_id($file_id) {
|
||||
$file_id = $this->rle_decode($this->base64url_decode($file_id));
|
||||
$res = [];
|
||||
$type = \danog\PHP\Struct::unpack('<i', substr($file_id, 0, 4))[0];
|
||||
switch ($type) {
|
||||
case 0:
|
||||
$constructor = ['_' => 'photo', 'sizes' => []];
|
||||
list($type, $constructor['sizes'][0]['location']['dc_id'], $constructor['id'], $constructor['access_hash'], $constructor['sizes'][0]['location']['volume_id'],$constructor['sizes'][0]['location']['secret'],$constructor['sizes'][0]['location']['local_id'], $verify) = \danog\PHP\Struct::unpack('<iiqqqqib', $file_id);
|
||||
if ($verify !== 2) {
|
||||
throw new Exception('Invalid last byte');
|
||||
}
|
||||
$res['type'] = 'photo';
|
||||
$res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
|
||||
return $res;
|
||||
case 2:
|
||||
$constructor = ['_' => 'photo', 'sizes' => []];
|
||||
list($type, $constructor['sizes'][0]['location']['dc_id'], $constructor['id'], $constructor['access_hash'], $constructor['sizes'][0]['location']['volume_id'],$constructor['sizes'][0]['location']['secret'],$constructor['sizes'][0]['location']['local_id'], $verify) = \danog\PHP\Struct::unpack('<iiqqqqib', $file_id);
|
||||
if ($verify !== 2) {
|
||||
throw new Exception('Invalid last byte');
|
||||
}
|
||||
$res['type'] = 'photo';
|
||||
$res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
|
||||
return $res;
|
||||
case 3:
|
||||
$constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true]]];
|
||||
list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack('<iiqqb', $file_id);
|
||||
if ($verify !== 2) {
|
||||
throw new Exception('Invalid last byte');
|
||||
}
|
||||
$res['type'] = 'voice';
|
||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||
return $res;
|
||||
case 4:
|
||||
$res['type'] = 'videos';
|
||||
$constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeVideo']]];
|
||||
list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack('<iiqqb', $file_id);
|
||||
if ($verify !== 2) {
|
||||
throw new Exception('Invalid last byte');
|
||||
}
|
||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||
return $res;
|
||||
case 5:
|
||||
$res['type'] = 'document';
|
||||
$constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => []];
|
||||
list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack('<iiqqb', $file_id);
|
||||
if ($verify !== 2) {
|
||||
throw new Exception('Invalid last byte');
|
||||
}
|
||||
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
|
||||
return $res;
|
||||
default:
|
||||
throw new Exception("Invalid file type detected (".$type.')');
|
||||
}
|
||||
}
|
||||
public function get_extension_from_location($location, $default) {
|
||||
$this->switch_dc($location['dc_id']);
|
||||
$res = $this->method_call('upload.getFile', ['location' => $location, 'offset' => 0, 'limit' => 1],['heavy' => true]);
|
||||
switch ($res['type']['_']) {
|
||||
case 'storage.fileJpeg': return '.jpg';
|
||||
case 'storage.fileGif': return '.gif';
|
||||
case 'storage.filePng': return '.png';
|
||||
case 'storage.filePdf': return '.pdf';
|
||||
case 'storage.fileMp3': return '.mp3';
|
||||
case 'storage.fileMov': return '.mov';
|
||||
case 'storage.fileMp4': return '.mp4';
|
||||
case 'storage.fileWebp': return '.webp';
|
||||
default: return $default;
|
||||
}
|
||||
}
|
||||
public function get_download_info($message_media)
|
||||
{
|
||||
if (is_string($message_media)) {
|
||||
$message_media = $this->unpack_file_id($message_media)['MessageMedia'];
|
||||
}
|
||||
if (!isset($message_media['_'])) {
|
||||
return $message_media;
|
||||
}
|
||||
$res = [];
|
||||
switch ($message_media['_']) {
|
||||
case 'messageMediaPhoto':
|
||||
$photo = end($message_media['photo']['sizes']);
|
||||
$res['name'] = $photo['location']['volume_id'].'_'.$photo['location']['local_id'];
|
||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']];
|
||||
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
||||
$res['mime'] = 'image/jpeg';
|
||||
return $res;
|
||||
case 'photoSize':
|
||||
case 'photoCachedSize':
|
||||
$res['name'] = $message_media['location']['volume_id'].'_'.$message_media['location']['local_id'];
|
||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $message_media['location']['volume_id'], 'local_id' => $message_media['location']['local_id'], 'secret' => $message_media['location']['secret'], 'dc_id' => $message_media['location']['dc_id']];
|
||||
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], '.jpg');
|
||||
$res['mime'] = 'image/jpeg';
|
||||
return $res;
|
||||
case 'messageMediaDocument':
|
||||
foreach ($message_media['document']['attributes'] as $attribute) {
|
||||
switch ($attribute['_']) {
|
||||
case 'documentAttributeFilename':
|
||||
$pathinfo = pathinfo($attribute['file_name']);
|
||||
if (isset($pathinfo['extension'])) $res['ext'] = '.'.$pathinfo['extension'];
|
||||
$res['name'] = $pathinfo['filename'];
|
||||
break;
|
||||
case 'documentAttributeAudio':
|
||||
$audio = $attribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
||||
$res['name'] = $audio['title'];
|
||||
if (isset($audio['performer'])) {
|
||||
$res['name'] .= ' - '.$audio['performer'];
|
||||
}
|
||||
}
|
||||
$res ['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $message_media['document']['id'], 'access_hash' => $message_media['document']['access_hash'], 'version' => isset($message_media['document']['version']) ? $message_media['document']['version'] : 0, 'dc_id' => $message_media['document']['dc_id']];
|
||||
if (!isset($res['ext'])) {
|
||||
$res['ext'] = $this->get_extension_from_location($res['InputFileLocation'], $this->get_extension_from_mime($message_media['document']['mime_type']));
|
||||
}
|
||||
if (!isset($res['name'])) {
|
||||
$res['name'] = $message_media['document']['access_hash'];
|
||||
}
|
||||
$res['name'] .= '_'.$message_media['document']['id'];
|
||||
$res['mime'] = $message_media['document']['mime_type'];
|
||||
return $res;
|
||||
default:
|
||||
throw new \danog\MadelineProto\Exception('Invalid constructor provided: '.$message_media['_']);
|
||||
}
|
||||
}
|
||||
|
||||
public function download_to_dir($message_media, $dir, $cb = null)
|
||||
{
|
||||
$info = $this->get_download_info($message_media);
|
||||
|
||||
return $this->download_to_file($info, $dir.'/'.$info['name'].$info['ext'], $cb);
|
||||
}
|
||||
|
||||
public function download_to_file($message_media, $file, $cb = null)
|
||||
{
|
||||
$file = str_replace('//', '/', $file);
|
||||
$info = $this->get_download_info($message_media);
|
||||
if (!file_exists($file)) touch ($file);
|
||||
$stream = fopen($file, 'r+b');
|
||||
flock($stream, LOCK_EX);
|
||||
$this->download_to_stream($info, $stream, $cb, filesize($file), -1);
|
||||
flock($stream, LOCK_UN);
|
||||
fclose($stream);
|
||||
clearstatcache();
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public function download_to_stream($message_media, $stream, $cb = null, $offset = 0, $end = -1)
|
||||
{
|
||||
if ($cb === null) {
|
||||
$cb = function ($percent) {
|
||||
\danog\MadelineProto\Logger::log(['Download status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
||||
};
|
||||
}
|
||||
$info = $this->get_download_info($message_media);
|
||||
if (stream_get_meta_data($stream)['seekable']) {
|
||||
fseek($stream, $offset);
|
||||
}
|
||||
$downloaded_size = 0;
|
||||
$size = $end - $offset;
|
||||
$part_size = 512 * 1024;
|
||||
$percent = 0;
|
||||
if (isset($info['InputFileLocation']['dc_id'])) {
|
||||
$this->switch_dc($info['InputFileLocation']['dc_id']);
|
||||
}
|
||||
$end = false;
|
||||
while (true) {
|
||||
//$real_part_size = (($offset + $part_size > $end) && $end !== -1) ? $part_size - (($offset + $part_size) - $end) : $part_size;
|
||||
try {
|
||||
$res = $this->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset, 'limit' => $part_size],['heavy' => true]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
if ($e->getMessage() === 'OFFSET_INVALID') break; else throw $e;
|
||||
}
|
||||
while ($res['type']['_'] === 'storage.fileUnknown' && $res['bytes'] === '') {
|
||||
$dc = 1;
|
||||
$this->switch_dc($dc);
|
||||
$res = $this->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset, 'limit' => $real_part_size], ['heavy' => true]);
|
||||
$dc++;
|
||||
}
|
||||
if ($res['bytes'] === '') {
|
||||
break;
|
||||
}
|
||||
if ($end !== -1 && strlen($res['bytes']) + $downloaded_size > $size) {
|
||||
$res['bytes'] = substr($res['bytes'], 0, (strlen($res['bytes']) + $downloaded_size) - $size);
|
||||
$end = true;
|
||||
}
|
||||
$offset += strlen($res['bytes']);
|
||||
$downloaded_size += strlen($res['bytes']);
|
||||
\danog\MadelineProto\Logger::log([fwrite($stream, $res['bytes'])], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
if ($end) break;
|
||||
//\danog\MadelineProto\Logger::log([$offset, $size, ftell($stream)], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
if ($end !== -1) $cb($percent = $downloaded_size * 100 / $size);
|
||||
}
|
||||
if ($end === -1) $cb(100);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -230,11 +230,289 @@ trait TL
|
||||
{
|
||||
return html_entity_decode(str_replace('<br />', "\n", $stuff));
|
||||
}
|
||||
public function parse_buttons($rows) {
|
||||
$newrows = [];
|
||||
$key = 0;
|
||||
$button_key = 0;
|
||||
foreach ($rows as $row) {
|
||||
$newrows[$key] = ['_' => 'keyboardButtonRow', 'buttons' => []];
|
||||
foreach ($row as $button) {
|
||||
$newrows[$key]['buttons'][$button_key] = ['_' => 'keyboardButton', 'text' => $button['text']];
|
||||
if (isset($button['url'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonUrl';
|
||||
$newrows[$key]['buttons'][$button_key]['url'] = $button['url'];
|
||||
} else if (isset($button['callback_data'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonCallback';
|
||||
$newrows[$key]['buttons'][$button_key]['data'] = $button['callback_data'];
|
||||
} else if (isset($button['switch_inline_query'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonSwitchInline';
|
||||
$newrows[$key]['buttons'][$button_key]['same_peer'] = false;
|
||||
$newrows[$key]['buttons'][$button_key]['query'] = $button['switch_inline_query'];
|
||||
} else if (isset($button['switch_inline_query_current_chat'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonSwitchInline';
|
||||
$newrows[$key]['buttons'][$button_key]['same_peer'] = true;
|
||||
$newrows[$key]['buttons'][$button_key]['query'] = $button['switch_inline_query_current_chat'];
|
||||
} else if (isset($button['callback_game'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonGame';
|
||||
$newrows[$key]['buttons'][$button_key]['text'] = $button['callback_game'];
|
||||
} else if (isset($button['request_contact'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonRequestPhone';
|
||||
} else if (isset($button['request_location'])) {
|
||||
$newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonRequestGeoLocation';
|
||||
}
|
||||
$button_key++;
|
||||
}
|
||||
$key++;
|
||||
}
|
||||
return $newrows;
|
||||
}
|
||||
|
||||
public function serialize_params($tl, $arguments)
|
||||
{
|
||||
$serialized = '';
|
||||
public function parse_reply_markup($markup) {
|
||||
if (isset($markup['force_reply']) && $markup['force_reply']) {
|
||||
$markup['_'] = 'replyKeyboardForceReply';
|
||||
unset($markup['force_reply']);
|
||||
}
|
||||
if (isset($markup['remove_keyboard']) && $markup['remove_keyboard']) {
|
||||
$markup['_'] = 'replyKeyboardHide';
|
||||
unset($markup['remove_keyboard']);
|
||||
}
|
||||
if (isset($markup['keyboard'])) {
|
||||
$markup['_'] = 'replyKeyboardMarkup';
|
||||
if (isset($markup['resize_keyboard'])) {
|
||||
$markup['resize'] = $markup['resize_keyboard'];
|
||||
unset($markup['resize_keyboard']);
|
||||
}
|
||||
if (isset($markup['one_time_keyboard'])) {
|
||||
$markup['single_use'] = $markup['one_time_keyboard'];
|
||||
unset($markup['one_time_keyboard']);
|
||||
}
|
||||
$markup['rows'] = $this->parse_buttons($markup['keyboard']);
|
||||
unset($markup['keyboard']);
|
||||
}
|
||||
if (isset($markup['inline_keyboard'])) {
|
||||
$markup['_'] = 'replyInlineMarkup';
|
||||
$markup['rows'] = $this->parse_buttons($markup['inline_keyboard']);
|
||||
unset($markup['inline_keyboard']);
|
||||
}
|
||||
return $markup;
|
||||
}
|
||||
public function MTProto_to_botAPI($data, $sent_arguments = []) {
|
||||
$newd = [];
|
||||
if (!isset($data['_'])) {
|
||||
foreach ($data as $key => $element) {
|
||||
$newd[$key] = $this->MTProto_to_botAPI($element, $sent_arguments);
|
||||
}
|
||||
return $newd;
|
||||
}
|
||||
switch ($data['_']) {
|
||||
case 'updateShortSentMessage':
|
||||
$newd['message_id'] = $data['id'];
|
||||
$newd['date'] = $data['date'];
|
||||
$newd['text'] = $sent_arguments['message'];
|
||||
if ($data['out']) $newd['from'] = $this->get_pwr_chat($this->datacenter->authorization['user']);
|
||||
$newd['chat'] = $this->get_pwr_chat($sent_arguments['peer']);
|
||||
if (isset($data['entities'])) $newd['entities'] = $this->MTProto_to_botAPI($data['entities'], $sent_arguments);
|
||||
if (isset($data['media'])) $newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
||||
return $newd;
|
||||
|
||||
case 'updateNewChannelMessage':
|
||||
case 'updateNewMessage':
|
||||
return $this->MTProto_to_botAPI($data['message']);
|
||||
|
||||
case 'message':
|
||||
$newd['message_id'] = $data['id'];
|
||||
$newd['date'] = $data['date'];
|
||||
$newd['text'] = $data['message'];
|
||||
$newd['post'] = $data['post'];
|
||||
$newd['silent'] = $data['silent'];
|
||||
if (isset($data['from_id'])) $newd['from'] = $this->get_pwr_chat($data['from_id']);
|
||||
$newd['chat'] = $this->get_pwr_chat($data['to_id']);
|
||||
if (isset($data['entities'])) $newd['entities'] = $this->MTProto_to_botAPI($data['entities'], $sent_arguments);
|
||||
if (isset($data['views'])) $newd['views'] = $data['views'];
|
||||
if (isset($data['edit_date'])) $newd['edit_date'] = $data['edit_date'];
|
||||
if (isset($data['via_bot_id'])) $newd['via_bot'] = $this->get_pwr_chat($data['via_bot_id']);
|
||||
if (isset($data['fwd_from']['from_id'])) $newd['froward_from'] = $this->get_pwr_chat($data['fwd_from']['from_id']);
|
||||
if (isset($data['fwd_from']['channel_id'])) $newd['forward_from_chat'] = $this->get_pwr_chat($data['fwd_from']['channel_id']);
|
||||
if (isset($data['fwd_from']['date'])) $newd['forward_date'] = $data['fwd_from']['date'];
|
||||
if (isset($data['fwd_from']['channel_post'])) $newd['forward_from_message_id'] = $data['fwd_from']['channel_post'];
|
||||
|
||||
if (isset($data['media'])) $newd = array_merge($newd, $this->MTProto_to_botAPI($data['media'], $sent_arguments));
|
||||
return $newd;
|
||||
|
||||
case 'messageEntityMention':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'mention';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityHashtag':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'hashtag';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityBotCommand':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'bot_command';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityUrl':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'url';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityEmail':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'email';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityBold':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'bold';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityItalic':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'italic';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityCode':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'code';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityPre':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'pre';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityTextUrl':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'text_url';
|
||||
return $data;
|
||||
|
||||
case 'messageEntityMentionName':
|
||||
unset($data['_']);
|
||||
$data['type'] = 'text_mention';
|
||||
$data['user'] = $this->get_pwr_chat($data['user_id']);
|
||||
unset($data['user_id']);
|
||||
return $data;
|
||||
|
||||
case 'messageMediaPhoto':
|
||||
$res['caption'] = $data['caption'];
|
||||
$res['photo'] = [];
|
||||
foreach ($data['photo']['sizes'] as $key => $photo) {
|
||||
$res['photo'][$key] = $this->photosize_to_botapi($photo, $data['photo']);
|
||||
}
|
||||
return $res;
|
||||
case 'messageMediaEmpty':
|
||||
return [];
|
||||
|
||||
case 'messageMediaDocument':
|
||||
$type = 5;
|
||||
$type_name = 'document';
|
||||
$res = [];
|
||||
if ($data['document']['thumb']['_'] === 'photoSize') $res['thumb'] = $this->photosize_to_botapi($data['document']['thumb'], $data['document'], true);
|
||||
foreach ($data['document']['attributes'] as $attribute) {
|
||||
switch ($attribute['_']) {
|
||||
case 'documentAttributeFilename':
|
||||
$pathinfo = pathinfo($attribute['file_name']);
|
||||
$res['ext'] = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
|
||||
$res['file_name'] = $pathinfo['filename'];
|
||||
break;
|
||||
|
||||
case 'documentAttributeAudio':
|
||||
$audio = $attribute;
|
||||
$type_name = 'audio';
|
||||
if ($attribute['voice']) {
|
||||
$type = 3;
|
||||
$type_name = 'voice';
|
||||
}
|
||||
$res['duration'] = $attribute['duration'];
|
||||
if (isset($attribute['performer'])) $res['performer'] = $attribute['performer'];
|
||||
if (isset($attribute['title'])) $res['title'] = $attribute['title'];
|
||||
if (isset($attribute['waveform'])) $res['title'] = $attribute['waveform'];
|
||||
break;
|
||||
|
||||
case 'documentAttributeVideo':
|
||||
$type = 4;
|
||||
$type_name = 'video';
|
||||
$res['width'] = $attribute['w'];
|
||||
$res['height'] = $attribute['h'];
|
||||
$res['duration'] = $attribute['duration'];
|
||||
break;
|
||||
|
||||
case 'documentAttributeImageSize':
|
||||
$res['width'] = $attribute['w'];
|
||||
$res['height'] = $attribute['h'];
|
||||
break;
|
||||
|
||||
case 'documentAttributeAnimated':
|
||||
$res['animated'] = true;
|
||||
break;
|
||||
|
||||
case 'documentAttributeHasStickers':
|
||||
$res['has_stickers'] = true;
|
||||
break;
|
||||
|
||||
case 'documentAttributeSticker':
|
||||
$type_name = 'sticker';
|
||||
$res['mask'] = $attribute['mask'];
|
||||
$res['emoji'] = $attribute['alt'];
|
||||
$res['sticker_set'] = $attribute['stickerset'];
|
||||
if (isset($attribute['mask_coords'])) $res['mask_coords'] = $attribute['mask_coords'];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (isset($audio) && isset($audio['title']) && !isset($res['file_name'])) {
|
||||
$res['file_name'] = $audio['title'];
|
||||
if (isset($audio['performer'])) {
|
||||
$res['file_name'] .= ' - '.$audio['performer'];
|
||||
}
|
||||
}
|
||||
if (!isset($res['file_name'])) {
|
||||
$res['file_name'] = $data['document']['access_hash'];
|
||||
}
|
||||
$res['file_name'] .= '_'.$data['document']['id'];
|
||||
if (isset($res['ext'])) {
|
||||
$res['file_name'] .= $res['ext'];
|
||||
unset($res['ext']);
|
||||
} else {
|
||||
$res['file_name'] .= $this->get_extension_from_mime($data['document']['mime_type']);
|
||||
}
|
||||
$res['file_size'] = $data['document']['size'];
|
||||
$res['mime_type'] = $data['document']['mime_type'];
|
||||
$res['file_id'] = $this->base64url_encode($this->rle_encode(\danog\PHP\Struct::pack('<iiqqb', $type, $data['document']['dc_id'], $data['document']['id'], $data['document']['access_hash'], 2)));
|
||||
return [$type_name => $res, 'caption' => $data['caption']];
|
||||
default:
|
||||
throw new Exception("Can't convert ".$data['_'].' to a bot API object');
|
||||
}
|
||||
}
|
||||
public function botAPI_to_MTProto($arguments) {
|
||||
if (isset($arguments['disable_web_page_preview'])) {
|
||||
$arguments['no_webpage'] = $arguments['disable_web_page_preview'];
|
||||
}
|
||||
if (isset($arguments['disable_notification'])) {
|
||||
$arguments['silent'] = $arguments['disable_notification'];
|
||||
}
|
||||
if (isset($arguments['reply_to_message_id'])) {
|
||||
$arguments['reply_to_msg_id'] = $arguments['reply_to_message_id'];
|
||||
}
|
||||
if (isset($arguments['chat_id'])) {
|
||||
$arguments['peer'] = $arguments['chat_id'];
|
||||
}
|
||||
if (isset($arguments['text'])) {
|
||||
$arguments['message'] = $arguments['text'];
|
||||
}
|
||||
if (isset($arguments['reply_markup'])) {
|
||||
$arguments['reply_markup'] = $this->parse_reply_markup($arguments['reply_markup']);
|
||||
}
|
||||
if (isset($arguments['parse_mode'])) {
|
||||
$arguments = $this->parse_mode($arguments);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
public function parse_mode($arguments) {
|
||||
if (preg_match('/markdown/i', $arguments['parse_mode'])) {
|
||||
$arguments['message'] = str_replace("\n", '', \Parsedown::instance()->line($arguments['message']));
|
||||
$arguments['parse_mode'] = 'HTML';
|
||||
@ -299,8 +577,13 @@ trait TL
|
||||
}
|
||||
}
|
||||
$arguments['message'] = $nmessage;
|
||||
unset($arguments['parse_mode']);
|
||||
}
|
||||
}
|
||||
return $arguments;
|
||||
}
|
||||
public function serialize_params($tl, $arguments)
|
||||
{
|
||||
$serialized = '';
|
||||
$flags = 0;
|
||||
foreach ($tl['params'] as $cur_flag) {
|
||||
if ($cur_flag['flag']) {
|
||||
|
@ -17,561 +17,27 @@ namespace danog\MadelineProto\Wrappers;
|
||||
*/
|
||||
trait FilesHandler
|
||||
{
|
||||
public $all_mimes = [
|
||||
'png' => [
|
||||
0 => 'image/png',
|
||||
1 => 'image/x-png',
|
||||
],
|
||||
'bmp' => [
|
||||
0 => 'image/bmp',
|
||||
1 => 'image/x-bmp',
|
||||
2 => 'image/x-bitmap',
|
||||
3 => 'image/x-xbitmap',
|
||||
4 => 'image/x-win-bitmap',
|
||||
5 => 'image/x-windows-bmp',
|
||||
6 => 'image/ms-bmp',
|
||||
7 => 'image/x-ms-bmp',
|
||||
8 => 'application/bmp',
|
||||
9 => 'application/x-bmp',
|
||||
10 => 'application/x-win-bitmap',
|
||||
],
|
||||
'gif' => [
|
||||
0 => 'image/gif',
|
||||
],
|
||||
'jpeg' => [
|
||||
0 => 'image/jpeg',
|
||||
1 => 'image/pjpeg',
|
||||
],
|
||||
'xspf' => [
|
||||
0 => 'application/xspf+xml',
|
||||
],
|
||||
'vlc' => [
|
||||
0 => 'application/videolan',
|
||||
],
|
||||
'wmv' => [
|
||||
0 => 'video/x-ms-wmv',
|
||||
1 => 'video/x-ms-asf',
|
||||
],
|
||||
'au' => [
|
||||
0 => 'audio/x-au',
|
||||
],
|
||||
'ac3' => [
|
||||
0 => 'audio/ac3',
|
||||
],
|
||||
'flac' => [
|
||||
0 => 'audio/x-flac',
|
||||
],
|
||||
'ogg' => [
|
||||
0 => 'audio/ogg',
|
||||
1 => 'video/ogg',
|
||||
2 => 'application/ogg',
|
||||
],
|
||||
'kmz' => [
|
||||
0 => 'application/vnd.google-earth.kmz',
|
||||
],
|
||||
'kml' => [
|
||||
0 => 'application/vnd.google-earth.kml+xml',
|
||||
],
|
||||
'rtx' => [
|
||||
0 => 'text/richtext',
|
||||
],
|
||||
'rtf' => [
|
||||
0 => 'text/rtf',
|
||||
],
|
||||
'jar' => [
|
||||
0 => 'application/java-archive',
|
||||
1 => 'application/x-java-application',
|
||||
2 => 'application/x-jar',
|
||||
],
|
||||
'zip' => [
|
||||
0 => 'application/x-zip',
|
||||
1 => 'application/zip',
|
||||
2 => 'application/x-zip-compressed',
|
||||
3 => 'application/s-compressed',
|
||||
4 => 'multipart/x-zip',
|
||||
],
|
||||
'7zip' => [
|
||||
0 => 'application/x-compressed',
|
||||
],
|
||||
'xml' => [
|
||||
0 => 'application/xml',
|
||||
1 => 'text/xml',
|
||||
],
|
||||
'svg' => [
|
||||
0 => 'image/svg+xml',
|
||||
],
|
||||
'3g2' => [
|
||||
0 => 'video/3gpp2',
|
||||
],
|
||||
'3gp' => [
|
||||
0 => 'video/3gp',
|
||||
1 => 'video/3gpp',
|
||||
],
|
||||
'mp4' => [
|
||||
0 => 'video/mp4',
|
||||
],
|
||||
'm4a' => [
|
||||
0 => 'audio/x-m4a',
|
||||
],
|
||||
'f4v' => [
|
||||
0 => 'video/x-f4v',
|
||||
],
|
||||
'flv' => [
|
||||
0 => 'video/x-flv',
|
||||
],
|
||||
'webm' => [
|
||||
0 => 'video/webm',
|
||||
],
|
||||
'aac' => [
|
||||
0 => 'audio/x-acc',
|
||||
],
|
||||
'm4u' => [
|
||||
0 => 'application/vnd.mpegurl',
|
||||
],
|
||||
'pdf' => [
|
||||
0 => 'application/pdf',
|
||||
1 => 'application/octet-stream',
|
||||
],
|
||||
'pptx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
],
|
||||
'ppt' => [
|
||||
0 => 'application/powerpoint',
|
||||
1 => 'application/vnd.ms-powerpoint',
|
||||
2 => 'application/vnd.ms-office',
|
||||
3 => 'application/msword',
|
||||
],
|
||||
'docx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
],
|
||||
'xlsx' => [
|
||||
0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
1 => 'application/vnd.ms-excel',
|
||||
],
|
||||
'xl' => [
|
||||
0 => 'application/excel',
|
||||
],
|
||||
'xls' => [
|
||||
0 => 'application/msexcel',
|
||||
1 => 'application/x-msexcel',
|
||||
2 => 'application/x-ms-excel',
|
||||
3 => 'application/x-excel',
|
||||
4 => 'application/x-dos_ms_excel',
|
||||
5 => 'application/xls',
|
||||
6 => 'application/x-xls',
|
||||
],
|
||||
'xsl' => [
|
||||
0 => 'text/xsl',
|
||||
],
|
||||
'mpeg' => [
|
||||
0 => 'video/mpeg',
|
||||
],
|
||||
'mov' => [
|
||||
0 => 'video/quicktime',
|
||||
],
|
||||
'avi' => [
|
||||
0 => 'video/x-msvideo',
|
||||
1 => 'video/msvideo',
|
||||
2 => 'video/avi',
|
||||
3 => 'application/x-troff-msvideo',
|
||||
],
|
||||
'movie' => [
|
||||
0 => 'video/x-sgi-movie',
|
||||
],
|
||||
'log' => [
|
||||
0 => 'text/x-log',
|
||||
],
|
||||
'txt' => [
|
||||
0 => 'text/plain',
|
||||
],
|
||||
'css' => [
|
||||
0 => 'text/css',
|
||||
],
|
||||
'html' => [
|
||||
0 => 'text/html',
|
||||
],
|
||||
'wav' => [
|
||||
0 => 'audio/x-wav',
|
||||
1 => 'audio/wave',
|
||||
2 => 'audio/wav',
|
||||
],
|
||||
'xhtml' => [
|
||||
0 => 'application/xhtml+xml',
|
||||
],
|
||||
'tar' => [
|
||||
0 => 'application/x-tar',
|
||||
],
|
||||
'tgz' => [
|
||||
0 => 'application/x-gzip-compressed',
|
||||
],
|
||||
'psd' => [
|
||||
0 => 'application/x-photoshop',
|
||||
1 => 'image/vnd.adobe.photoshop',
|
||||
],
|
||||
'exe' => [
|
||||
0 => 'application/x-msdownload',
|
||||
],
|
||||
'js' => [
|
||||
0 => 'application/x-javascript',
|
||||
],
|
||||
'mp3' => [
|
||||
0 => 'audio/mpeg',
|
||||
1 => 'audio/mpg',
|
||||
2 => 'audio/mpeg3',
|
||||
3 => 'audio/mp3',
|
||||
],
|
||||
'rar' => [
|
||||
0 => 'application/x-rar',
|
||||
1 => 'application/rar',
|
||||
2 => 'application/x-rar-compressed',
|
||||
],
|
||||
'gzip' => [
|
||||
0 => 'application/x-gzip',
|
||||
],
|
||||
'hqx' => [
|
||||
0 => 'application/mac-binhex40',
|
||||
1 => 'application/mac-binhex',
|
||||
2 => 'application/x-binhex40',
|
||||
3 => 'application/x-mac-binhex40',
|
||||
],
|
||||
'cpt' => [
|
||||
0 => 'application/mac-compactpro',
|
||||
],
|
||||
'bin' => [
|
||||
0 => 'application/macbinary',
|
||||
1 => 'application/mac-binary',
|
||||
2 => 'application/x-binary',
|
||||
3 => 'application/x-macbinary',
|
||||
],
|
||||
'oda' => [
|
||||
0 => 'application/oda',
|
||||
],
|
||||
'ai' => [
|
||||
0 => 'application/postscript',
|
||||
],
|
||||
'smil' => [
|
||||
0 => 'application/smil',
|
||||
],
|
||||
'mif' => [
|
||||
0 => 'application/vnd.mif',
|
||||
],
|
||||
'wbxml' => [
|
||||
0 => 'application/wbxml',
|
||||
],
|
||||
'wmlc' => [
|
||||
0 => 'application/wmlc',
|
||||
],
|
||||
'dcr' => [
|
||||
0 => 'application/x-director',
|
||||
],
|
||||
'dvi' => [
|
||||
0 => 'application/x-dvi',
|
||||
],
|
||||
'gtar' => [
|
||||
0 => 'application/x-gtar',
|
||||
],
|
||||
'php' => [
|
||||
0 => 'application/x-httpd-php',
|
||||
1 => 'application/php',
|
||||
2 => 'application/x-php',
|
||||
3 => 'text/php',
|
||||
4 => 'text/x-php',
|
||||
5 => 'application/x-httpd-php-source',
|
||||
],
|
||||
'swf' => [
|
||||
0 => 'application/x-shockwave-flash',
|
||||
],
|
||||
'sit' => [
|
||||
0 => 'application/x-stuffit',
|
||||
],
|
||||
'z' => [
|
||||
0 => 'application/x-compress',
|
||||
],
|
||||
'mid' => [
|
||||
0 => 'audio/midi',
|
||||
],
|
||||
'aif' => [
|
||||
0 => 'audio/x-aiff',
|
||||
1 => 'audio/aiff',
|
||||
],
|
||||
'ram' => [
|
||||
0 => 'audio/x-pn-realaudio',
|
||||
],
|
||||
'rpm' => [
|
||||
0 => 'audio/x-pn-realaudio-plugin',
|
||||
],
|
||||
'ra' => [
|
||||
0 => 'audio/x-realaudio',
|
||||
],
|
||||
'rv' => [
|
||||
0 => 'video/vnd.rn-realvideo',
|
||||
],
|
||||
'jp2' => [
|
||||
0 => 'image/jp2',
|
||||
1 => 'video/mj2',
|
||||
2 => 'image/jpx',
|
||||
3 => 'image/jpm',
|
||||
],
|
||||
'tiff' => [
|
||||
0 => 'image/tiff',
|
||||
],
|
||||
'eml' => [
|
||||
0 => 'message/rfc822',
|
||||
],
|
||||
'pem' => [
|
||||
0 => 'application/x-x509-user-cert',
|
||||
1 => 'application/x-pem-file',
|
||||
],
|
||||
'p10' => [
|
||||
0 => 'application/x-pkcs10',
|
||||
1 => 'application/pkcs10',
|
||||
],
|
||||
'p12' => [
|
||||
0 => 'application/x-pkcs12',
|
||||
],
|
||||
'p7a' => [
|
||||
0 => 'application/x-pkcs7-signature',
|
||||
],
|
||||
'p7c' => [
|
||||
0 => 'application/pkcs7-mime',
|
||||
1 => 'application/x-pkcs7-mime',
|
||||
],
|
||||
'p7r' => [
|
||||
0 => 'application/x-pkcs7-certreqresp',
|
||||
],
|
||||
'p7s' => [
|
||||
0 => 'application/pkcs7-signature',
|
||||
],
|
||||
'crt' => [
|
||||
0 => 'application/x-x509-ca-cert',
|
||||
1 => 'application/pkix-cert',
|
||||
],
|
||||
'crl' => [
|
||||
0 => 'application/pkix-crl',
|
||||
1 => 'application/pkcs-crl',
|
||||
],
|
||||
'pgp' => [
|
||||
0 => 'application/pgp',
|
||||
],
|
||||
'gpg' => [
|
||||
0 => 'application/gpg-keys',
|
||||
],
|
||||
'rsa' => [
|
||||
0 => 'application/x-pkcs7',
|
||||
],
|
||||
'ics' => [
|
||||
0 => 'text/calendar',
|
||||
],
|
||||
'zsh' => [
|
||||
0 => 'text/x-scriptzsh',
|
||||
],
|
||||
'cdr' => [
|
||||
0 => 'application/cdr',
|
||||
1 => 'application/coreldraw',
|
||||
2 => 'application/x-cdr',
|
||||
3 => 'application/x-coreldraw',
|
||||
4 => 'image/cdr',
|
||||
5 => 'image/x-cdr',
|
||||
6 => 'zz-application/zz-winassoc-cdr',
|
||||
],
|
||||
'wma' => [
|
||||
0 => 'audio/x-ms-wma',
|
||||
],
|
||||
'vcf' => [
|
||||
0 => 'text/x-vcard',
|
||||
],
|
||||
'srt' => [
|
||||
0 => 'text/srt',
|
||||
],
|
||||
'vtt' => [
|
||||
0 => 'text/vtt',
|
||||
],
|
||||
'ico' => [
|
||||
0 => 'image/x-icon',
|
||||
1 => 'image/x-ico',
|
||||
2 => 'image/vnd.microsoft.icon',
|
||||
],
|
||||
'csv' => [
|
||||
0 => 'text/x-comma-separated-values',
|
||||
1 => 'text/comma-separated-values',
|
||||
2 => 'application/vnd.msexcel',
|
||||
],
|
||||
'json' => [
|
||||
0 => 'application/json',
|
||||
1 => 'text/json',
|
||||
],
|
||||
];
|
||||
|
||||
public function upload($file, $file_name = '', $cb = null)
|
||||
{
|
||||
if (!file_exists($file)) {
|
||||
throw new \danog\MadelineProto\Exception('Given file does not exist!');
|
||||
}
|
||||
if (empty($file_name)) {
|
||||
$file_name = basename($file);
|
||||
}
|
||||
$file_size = filesize($file);
|
||||
if ($file_size > 1500 * 1024 * 1024) {
|
||||
throw new \danog\MadelineProto\Exception('Given file is too big!');
|
||||
}
|
||||
if ($cb === null) {
|
||||
$cb = function ($percent) {
|
||||
\danog\MadelineProto\Logger::log(['Upload status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
||||
};
|
||||
}
|
||||
$part_size = 512 * 1024;
|
||||
$part_total_num = (int) ceil($file_size / $part_size);
|
||||
$part_num = 0;
|
||||
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
||||
$constructor = $file_size > 10 * 1024 * 1024 ? 'inputFileBig' : 'inputFile';
|
||||
$file_id = \danog\PHP\Struct::unpack('<q', $this->API->random(8))[0];
|
||||
$f = fopen($file, 'r');
|
||||
fseek($f, 0);
|
||||
while (ftell($f) !== $file_size) {
|
||||
if (!$this->API->method_call($method, ['file_id' => $file_id, 'file_part' => $part_num++, 'file_total_parts' => $part_total_num, 'bytes' => stream_get_contents($f, $part_size)], null, true)) {
|
||||
throw new \danog\MadelineProto\Exception('An error occurred while uploading file part '.$part_num);
|
||||
}
|
||||
$cb(ftell($f) * 100 / $file_size);
|
||||
}
|
||||
fclose($f);
|
||||
|
||||
return ['_' => $constructor, 'id' => $file_id, 'parts' => $part_total_num, 'name' => $file_name, 'md5_checksum' => md5_file($file)];
|
||||
public function upload($file, $file_name = '', $cb = null) {
|
||||
return $this->API->upload($file, $file_name, $cb);
|
||||
}
|
||||
|
||||
public function get_extension_from_mime($mime)
|
||||
{
|
||||
foreach ($this->all_mimes as $key => $value) {
|
||||
if (array_search($mime, $value) !== false) {
|
||||
return '.'.$key;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
return $this->API->get_extension_from_mime($mime);
|
||||
}
|
||||
|
||||
public function get_download_info($message_media)
|
||||
{
|
||||
if (!isset($message_media['_']) && isset($message_media['InputFileLocation']) && isset($message_media['size'])) {
|
||||
return $message_media;
|
||||
}
|
||||
$res = [];
|
||||
switch ($message_media['_']) {
|
||||
case 'messageMediaPhoto':
|
||||
$res['caption'] = $message_media['caption'];
|
||||
$res['ext'] = '.jpg';
|
||||
$photo = end($message_media['photo']['sizes']);
|
||||
$res['name'] = $photo['location']['volume_id'].'_'.$photo['location']['local_id'];
|
||||
$res['size'] = $photo['size'];
|
||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret'], 'dc_id' => $photo['location']['dc_id']];
|
||||
$res['mime'] = 'image/jpeg';
|
||||
|
||||
return $res;
|
||||
|
||||
case 'photoSize':
|
||||
case 'photoCachedSize':
|
||||
$res['ext'] = '.jpg';
|
||||
$res['name'] = $message_media['location']['volume_id'].'_'.$message_media['location']['local_id'];
|
||||
$res['size'] = $message_media['size'];
|
||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $message_media['location']['volume_id'], 'local_id' => $message_media['location']['local_id'], 'secret' => $message_media['location']['secret'], 'dc_id' => $message_media['location']['dc_id']];
|
||||
$res['mime'] = 'image/jpeg';
|
||||
|
||||
return $res;
|
||||
|
||||
case 'messageMediaDocument':
|
||||
$res['caption'] = $message_media['caption'];
|
||||
foreach ($message_media['document']['attributes'] as $attribute) {
|
||||
switch ($attribute['_']) {
|
||||
case 'documentAttributeFilename':
|
||||
$pathinfo = pathinfo($attribute['file_name']);
|
||||
$res['ext'] = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
|
||||
$res['name'] = $pathinfo['filename'];
|
||||
break;
|
||||
|
||||
case 'documentAttributeAudio':
|
||||
$audio = $attribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
|
||||
$res['name'] = $audio['title'];
|
||||
if (isset($audio['performer'])) {
|
||||
$res['name'] .= ' - '.$audio['performer'];
|
||||
}
|
||||
}
|
||||
if (!isset($res['ext'])) {
|
||||
$res['ext'] = $this->get_extension_from_mime($message_media['document']['mime_type']);
|
||||
}
|
||||
if (!isset($res['name'])) {
|
||||
$res['name'] = $message_media['document']['id'];
|
||||
}
|
||||
$res['name'] .= '_'.$message_media['document']['id'];
|
||||
$res['size'] = $message_media['document']['size'];
|
||||
$res['mime'] = $message_media['document']['mime_type'];
|
||||
$res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $message_media['document']['id'], 'access_hash' => $message_media['document']['access_hash'], 'version' => $message_media['document']['version'], 'dc_id' => $message_media['document']['dc_id']];
|
||||
|
||||
return $res;
|
||||
|
||||
default:
|
||||
throw new \danog\MadelineProto\Exception('Invalid constructor provided: '.$message_media['_']);
|
||||
}
|
||||
return $this->API->get_download_info($message_media);
|
||||
}
|
||||
|
||||
public function download_to_dir($message_media, $dir, $cb = null)
|
||||
{
|
||||
$info = $this->get_download_info($message_media);
|
||||
|
||||
return $this->download_to_file($info, $dir.'/'.$info['name'].$info['ext'], $cb);
|
||||
return $this->API->download_to_dir($message_media, $dir, $cb);
|
||||
}
|
||||
|
||||
public function download_to_file($message_media, $file, $cb = null)
|
||||
{
|
||||
$file = str_replace('//', '/', $file);
|
||||
$info = $this->get_download_info($message_media);
|
||||
$stream = fopen($file, 'wb');
|
||||
$this->download_to_stream($info, $stream, $cb, filesize($file), $info['size']);
|
||||
fclose($stream);
|
||||
clearstatcache();
|
||||
|
||||
return $file;
|
||||
return $this->API->download_to_file($message_media, $file, $cb);
|
||||
}
|
||||
|
||||
public function download_to_stream($message_media, $stream, $cb = null, $offset = 0, $end = -1)
|
||||
{
|
||||
if ($cb === null) {
|
||||
$cb = function ($percent) {
|
||||
\danog\MadelineProto\Logger::log(['Download status: '.$percent.'%'], \danog\MadelineProto\Logger::NOTICE);
|
||||
};
|
||||
}
|
||||
$info = $this->get_download_info($message_media);
|
||||
if ($end === -1) {
|
||||
$end = $info['size'];
|
||||
}
|
||||
if (stream_get_meta_data($stream)['seekable']) {
|
||||
fseek($stream, $offset);
|
||||
}
|
||||
$size = $end - $offset;
|
||||
$part_size = 512 * 1024;
|
||||
$percent = 0;
|
||||
if (isset($info['InputFileLocation']['dc_id'])) {
|
||||
$this->API->switch_dc($info['InputFileLocation']['dc_id']);
|
||||
}
|
||||
|
||||
while ($percent < 100) {
|
||||
$real_part_size = ($offset + $part_size > $end) ? $part_size - (($offset + $part_size) - $end) : $part_size;
|
||||
\danog\MadelineProto\Logger::log([$real_part_size, $offset], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
$res = $this->API->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset, 'limit' => $real_part_size], null, true);
|
||||
$dc = 1;
|
||||
while ($res['type']['_'] === 'storage.fileUnknown' && $res['bytes'] === '') {
|
||||
$this->API->switch_dc($dc);
|
||||
$res = $this->API->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset, 'limit' => $real_part_size], null, true);
|
||||
$dc++;
|
||||
}
|
||||
|
||||
\danog\MadelineProto\Logger::log([fwrite($stream, $res['bytes'])], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
\danog\MadelineProto\Logger::log([$offset, $size, ftell($stream)], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
|
||||
$cb($percent = ($offset += $real_part_size) * 100 / $size);
|
||||
}
|
||||
|
||||
return true;
|
||||
return $this->API->download_to_stream($message_media, $stream, $cb);
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ if ($MadelineProto === false) {
|
||||
$MadelineProto->bot_login(getenv('BOT_TOKEN'));
|
||||
}
|
||||
}
|
||||
$message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre)' : ('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)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION'));
|
||||
|
||||
$flutter = 'https://storage.pwrtelegram.xyz/pwrtelegrambot/document/file_6570.mp4';
|
||||
$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
|
||||
@ -99,12 +99,12 @@ $time = time();
|
||||
$inputFile = $MadelineProto->upload('tests/60', 'magic'); // This gets an inputFile object with file name magic
|
||||
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']]];
|
||||
|
||||
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
|
||||
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => 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);
|
||||
foreach ($media as $type => $inputMedia) {
|
||||
\danog\MadelineProto\Logger::log([$MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia])], \danog\MadelineProto\Logger::NOTICE);
|
||||
$type = $MadelineProto->invokeWithoutUpdates(['query' => $MadelineProto->API->serialize_method('messages.sendMedia', ['peer' => $peer, 'media' => $inputMedia])]);
|
||||
var_dump($MadelineProto->API->MTProto_to_botAPI(end($type['updates'])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ $mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an arra
|
||||
$mention = $mention['user_id']; // Selects only the numeric user id
|
||||
|
||||
foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) {
|
||||
$sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => 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);
|
||||
}
|
||||
sleep(5);
|
||||
|
Loading…
x
Reference in New Issue
Block a user