Bugfixes and added support for downloading only specified ranges of a file
This commit is contained in:
parent
7343ae83cf
commit
3b8cc9d5ee
@ -341,7 +341,7 @@ The first parameter of these functions must always be a [messageMediaPhoto](http
|
|||||||
$output_file_name = $MadelineProto->download_to_dir($message_media, '/tmp/dldir');
|
$output_file_name = $MadelineProto->download_to_dir($message_media, '/tmp/dldir');
|
||||||
$custom_output_file_name = $MadelineProto->download_to_file($message_media, '/tmp/dldir/customname.ext');
|
$custom_output_file_name = $MadelineProto->download_to_file($message_media, '/tmp/dldir/customname.ext');
|
||||||
$stream = fopen('php://output', 'w'); // Stream to browser like with echo
|
$stream = fopen('php://output', 'w'); // Stream to browser like with echo
|
||||||
$MadelineProto->download_to_stream($message_media, $stream);
|
$MadelineProto->download_to_stream($message_media, $stream, $cb, $offset, $endoffset); // offset and endoffset are optional parameters that specify the byte from which to start downloading and the byte where to stop downloading (the latter non-inclusive), if not specified default to 0 and the size of the file
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
---
|
|
||||||
title: MadelineProto documentation
|
|
||||||
description: PHP implementation of telegram's MTProto protocol
|
|
||||||
---
|
|
||||||
# MadelineProto
|
# MadelineProto
|
||||||
[![StyleCI](https://styleci.io/repos/61838413/shield)](https://styleci.io/repos/61838413)
|
[![StyleCI](https://styleci.io/repos/61838413/shield)](https://styleci.io/repos/61838413)
|
||||||
[![Build Status](https://travis-ci.org/danog/MadelineProto.svg?branch=master)](https://travis-ci.org/danog/MadelineProto)
|
[![Build Status](https://travis-ci.org/danog/MadelineProto.svg?branch=master)](https://travis-ci.org/danog/MadelineProto)
|
||||||
@ -345,7 +341,7 @@ The first parameter of these functions must always be a [messageMediaPhoto](http
|
|||||||
$output_file_name = $MadelineProto->download_to_dir($message_media, '/tmp/dldir');
|
$output_file_name = $MadelineProto->download_to_dir($message_media, '/tmp/dldir');
|
||||||
$custom_output_file_name = $MadelineProto->download_to_file($message_media, '/tmp/dldir/customname.ext');
|
$custom_output_file_name = $MadelineProto->download_to_file($message_media, '/tmp/dldir/customname.ext');
|
||||||
$stream = fopen('php://output', 'w'); // Stream to browser like with echo
|
$stream = fopen('php://output', 'w'); // Stream to browser like with echo
|
||||||
$MadelineProto->download_to_stream($message_media, $stream);
|
$MadelineProto->download_to_stream($message_media, $stream, $cb, $offset, $endoffset); // offset and endoffset are optional parameters that specify the byte from which to start downloading and the byte where to stop downloading (the latter non-inclusive), if not specified default to 0 and the size of the file
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
{
|
{
|
||||||
foreach ($this->datacenter->sockets as $id => &$socket) {
|
foreach ($this->datacenter->sockets as $id => &$socket) {
|
||||||
\danog\MadelineProto\Logger::log('Resetting session id and seq_no in DC '.$id.'...');
|
\danog\MadelineProto\Logger::log('Resetting session id and seq_no in DC '.$id.'...');
|
||||||
$socket->session_id = \phpseclib\Crypt\Random::string(8);
|
$socket->session_id = \danog\MadelineProto\Tools::random(8);
|
||||||
$socket->seq_no = 0;
|
$socket->seq_no = 0;
|
||||||
$socket->incoming_messages = [];
|
$socket->incoming_messages = [];
|
||||||
$socket->outgoing_messages = [];
|
$socket->outgoing_messages = [];
|
||||||
@ -275,7 +275,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
public function init_authorization()
|
public function init_authorization()
|
||||||
{
|
{
|
||||||
if ($this->datacenter->session_id == null) {
|
if ($this->datacenter->session_id == null) {
|
||||||
$this->datacenter->session_id = \phpseclib\Crypt\Random::string(8);
|
$this->datacenter->session_id = \danog\MadelineProto\Tools::random(8);
|
||||||
}
|
}
|
||||||
if ($this->datacenter->temp_auth_key == null || $this->datacenter->auth_key == null) {
|
if ($this->datacenter->temp_auth_key == null || $this->datacenter->auth_key == null) {
|
||||||
if ($this->datacenter->auth_key == null) {
|
if ($this->datacenter->auth_key == null) {
|
||||||
|
@ -43,7 +43,7 @@ trait AuthKeyHandler
|
|||||||
* Vector long $server_public_key_fingerprints : This is a list of public RSA key fingerprints
|
* Vector long $server_public_key_fingerprints : This is a list of public RSA key fingerprints
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
$nonce = \phpseclib\Crypt\Random::string(16);
|
$nonce = \danog\MadelineProto\Tools::random(16);
|
||||||
$ResPQ = $this->method_call('req_pq',
|
$ResPQ = $this->method_call('req_pq',
|
||||||
[
|
[
|
||||||
'nonce' => $nonce,
|
'nonce' => $nonce,
|
||||||
@ -103,7 +103,7 @@ trait AuthKeyHandler
|
|||||||
$p_bytes = \danog\PHP\Struct::pack('>I', (string) $p);
|
$p_bytes = \danog\PHP\Struct::pack('>I', (string) $p);
|
||||||
$q_bytes = \danog\PHP\Struct::pack('>I', (string) $q);
|
$q_bytes = \danog\PHP\Struct::pack('>I', (string) $q);
|
||||||
|
|
||||||
$new_nonce = \phpseclib\Crypt\Random::string(32);
|
$new_nonce = \danog\MadelineProto\Tools::random(32);
|
||||||
|
|
||||||
$data_unserialized = [
|
$data_unserialized = [
|
||||||
'pq' => $pq_bytes,
|
'pq' => $pq_bytes,
|
||||||
@ -121,7 +121,7 @@ trait AuthKeyHandler
|
|||||||
* Encrypt serialized object
|
* Encrypt serialized object
|
||||||
*/
|
*/
|
||||||
$sha_digest = sha1($p_q_inner_data, true);
|
$sha_digest = sha1($p_q_inner_data, true);
|
||||||
$random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($p_q_inner_data) - strlen($sha_digest));
|
$random_bytes = \danog\MadelineProto\Tools::random(255 - strlen($p_q_inner_data) - strlen($sha_digest));
|
||||||
$to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes;
|
$to_encrypt = $sha_digest.$p_q_inner_data.$random_bytes;
|
||||||
$encrypted_data = $this->key->encrypt($to_encrypt);
|
$encrypted_data = $this->key->encrypt($to_encrypt);
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ trait AuthKeyHandler
|
|||||||
|
|
||||||
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
||||||
\danog\MadelineProto\Logger::log('Generating b...');
|
\danog\MadelineProto\Logger::log('Generating b...');
|
||||||
$b = new \phpseclib\Math\BigInteger(\phpseclib\Crypt\Random::string(256), 256);
|
$b = new \phpseclib\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
|
||||||
\danog\MadelineProto\Logger::log('Generating g_b...');
|
\danog\MadelineProto\Logger::log('Generating g_b...');
|
||||||
$g_b = $g->powMod($b, $dh_prime);
|
$g_b = $g->powMod($b, $dh_prime);
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ trait AuthKeyHandler
|
|||||||
* encrypt client_DH_inner_data
|
* encrypt client_DH_inner_data
|
||||||
*/
|
*/
|
||||||
$data_with_sha = sha1($data, true).$data;
|
$data_with_sha = sha1($data, true).$data;
|
||||||
$data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string($this->posmod(-strlen($data_with_sha), 16));
|
$data_with_sha_padded = $data_with_sha.\danog\MadelineProto\Tools::random($this->posmod(-strlen($data_with_sha), 16));
|
||||||
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
||||||
|
|
||||||
\danog\MadelineProto\Logger::log('Executing set_client_DH_params...');
|
\danog\MadelineProto\Logger::log('Executing set_client_DH_params...');
|
||||||
@ -481,7 +481,7 @@ trait AuthKeyHandler
|
|||||||
public function bind_temp_auth_key($expires_in)
|
public function bind_temp_auth_key($expires_in)
|
||||||
{
|
{
|
||||||
\danog\MadelineProto\Logger::log('Binding authorization keys...');
|
\danog\MadelineProto\Logger::log('Binding authorization keys...');
|
||||||
$nonce = \danog\PHP\Struct::unpack('<q', \phpseclib\Crypt\Random::string(8))[0];
|
$nonce = \danog\PHP\Struct::unpack('<q', \danog\MadelineProto\Tools::random(8))[0];
|
||||||
$expires_at = time() + $expires_in;
|
$expires_at = time() + $expires_in;
|
||||||
$temp_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->datacenter->temp_auth_key['id'])[0];
|
$temp_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->datacenter->temp_auth_key['id'])[0];
|
||||||
$perm_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->datacenter->auth_key['id'])[0];
|
$perm_auth_key_id = \danog\PHP\Struct::unpack('<q', $this->datacenter->auth_key['id'])[0];
|
||||||
@ -499,9 +499,9 @@ trait AuthKeyHandler
|
|||||||
|
|
||||||
$message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
|
$message_id = \danog\PHP\Struct::pack('<Q', $int_message_id);
|
||||||
$seq_no = 0;
|
$seq_no = 0;
|
||||||
$encrypted_data = \phpseclib\Crypt\Random::string(16).$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
|
$encrypted_data = \danog\MadelineProto\Tools::random(16).$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
|
||||||
$message_key = substr(sha1($encrypted_data, true), -16);
|
$message_key = substr(sha1($encrypted_data, true), -16);
|
||||||
$padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16));
|
$padding = \danog\MadelineProto\Tools::random($this->posmod(-strlen($encrypted_data), 16));
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->auth_key['auth_key']);
|
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);
|
$encrypted_message = $this->datacenter->auth_key['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ trait MessageHandler
|
|||||||
$seq_no = $this->generate_seq_no($content_related);
|
$seq_no = $this->generate_seq_no($content_related);
|
||||||
$encrypted_data = \danog\PHP\Struct::pack('<q', $this->datacenter->temp_auth_key['server_salt']).$this->datacenter->session_id.$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
|
$encrypted_data = \danog\PHP\Struct::pack('<q', $this->datacenter->temp_auth_key['server_salt']).$this->datacenter->session_id.$message_id.\danog\PHP\Struct::pack('<II', $seq_no, strlen($message_data)).$message_data;
|
||||||
$message_key = substr(sha1($encrypted_data, true), -16);
|
$message_key = substr(sha1($encrypted_data, true), -16);
|
||||||
$padding = \phpseclib\Crypt\Random::string($this->posmod(-strlen($encrypted_data), 16));
|
$padding = \danog\MadelineProto\Tools::random($this->posmod(-strlen($encrypted_data), 16));
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->temp_auth_key['auth_key']);
|
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->datacenter->temp_auth_key['auth_key']);
|
||||||
$message = $this->datacenter->temp_auth_key['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
$message = $this->datacenter->temp_auth_key['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||||
$this->datacenter->outgoing_messages[$int_message_id]['seq_no'] = $seq_no;
|
$this->datacenter->outgoing_messages[$int_message_id]['seq_no'] = $seq_no;
|
||||||
|
@ -25,12 +25,18 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function get_updates_update_handler($update)
|
public function get_updates_update_handler($update)
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this->updates[$this->updates_key++] = $update;
|
$this->updates[$this->updates_key++] = $update;
|
||||||
//\danog\MadelineProto\Logger::log('Stored ', $update);
|
//\danog\MadelineProto\Logger::log('Stored ', $update);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_updates($params = [])
|
public function get_updates($params = [])
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$time = microtime(true);
|
$time = microtime(true);
|
||||||
$this->force_get_updates_difference();
|
$this->force_get_updates_difference();
|
||||||
$default_params = ['offset' => 0, 'limit' => null, 'timeout' => 0];
|
$default_params = ['offset' => 0, 'limit' => null, 'timeout' => 0];
|
||||||
@ -75,6 +81,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function get_channel_difference($channel)
|
public function get_channel_difference($channel)
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!$this->get_channel_state($channel)['sync_loading']) {
|
if (!$this->get_channel_state($channel)['sync_loading']) {
|
||||||
$this->get_channel_state($channel)['sync_loading'] = true;
|
$this->get_channel_state($channel)['sync_loading'] = true;
|
||||||
$this->get_channel_state($channel)['pending_pts_updates'] = [];
|
$this->get_channel_state($channel)['pending_pts_updates'] = [];
|
||||||
@ -133,6 +142,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function get_updates_difference()
|
public function get_updates_difference()
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!$this->get_update_state()['sync_loading']) {
|
if (!$this->get_update_state()['sync_loading']) {
|
||||||
$this->get_update_state()['sync_loading'] = true;
|
$this->get_update_state()['sync_loading'] = true;
|
||||||
$this->get_update_state()['pending_pts_updates'] = [];
|
$this->get_update_state()['pending_pts_updates'] = [];
|
||||||
@ -313,6 +325,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function pop_pending_seq_update()
|
public function pop_pending_seq_update()
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$next_seq = $this->get_update_state()['seq'] + 1;
|
$next_seq = $this->get_update_state()['seq'] + 1;
|
||||||
if (empty($this->get_update_state()['pending_seq_updates'][$next_seq]['updates'])) {
|
if (empty($this->get_update_state()['pending_seq_updates'][$next_seq]['updates'])) {
|
||||||
return false;
|
return false;
|
||||||
@ -332,6 +347,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function pop_pending_pts_update($channel_id)
|
public function pop_pending_pts_update($channel_id)
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($channel_id === false) {
|
if ($channel_id === false) {
|
||||||
$cur_state = &$this->get_update_state();
|
$cur_state = &$this->get_update_state();
|
||||||
} else {
|
} else {
|
||||||
@ -363,6 +381,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function handle_multiple_update($updates, $options = [], $channel = false)
|
public function handle_multiple_update($updates, $options = [], $channel = false)
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($channel === false) {
|
if ($channel === false) {
|
||||||
foreach ($updates as $update) {
|
foreach ($updates as $update) {
|
||||||
switch ($update['_']) {
|
switch ($update['_']) {
|
||||||
@ -383,6 +404,9 @@ trait UpdateHandler
|
|||||||
|
|
||||||
public function handle_update_messages($messages, $channel = false)
|
public function handle_update_messages($messages, $channel = false)
|
||||||
{
|
{
|
||||||
|
if (!$this->settings['updates']['handle_updates']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
foreach ($messages as $message) {
|
foreach ($messages as $message) {
|
||||||
$this->save_update(['_' => $channel == false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel == false ? $this->get_update_state()['pts'] : $this->get_channel_state($channel)['pts'], 'pts_count' => 0]);
|
$this->save_update(['_' => $channel == false ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => $channel == false ? $this->get_update_state()['pts'] : $this->get_channel_state($channel)['pts'], 'pts_count' => 0]);
|
||||||
}
|
}
|
||||||
|
@ -252,16 +252,16 @@ trait TL
|
|||||||
if ($current_argument['name'] == 'random_id') {
|
if ($current_argument['name'] == 'random_id') {
|
||||||
switch ($current_argument['type']) {
|
switch ($current_argument['type']) {
|
||||||
case 'long':
|
case 'long':
|
||||||
$serialized .= \phpseclib\Crypt\Random::string(8);
|
$serialized .= \danog\MadelineProto\Tools::random(8);
|
||||||
continue 2;
|
continue 2;
|
||||||
case 'int':
|
case 'int':
|
||||||
$serialized .= \phpseclib\Crypt\Random::string(4);
|
$serialized .= \danog\MadelineProto\Tools::random(4);
|
||||||
continue 2;
|
continue 2;
|
||||||
case 'Vector t':
|
case 'Vector t':
|
||||||
if (isset($arguments['id'])) {
|
if (isset($arguments['id'])) {
|
||||||
$serialized .= \danog\PHP\Struct::pack('<i', $this->constructors->find_by_predicate('vector')['id']);
|
$serialized .= \danog\PHP\Struct::pack('<i', $this->constructors->find_by_predicate('vector')['id']);
|
||||||
$serialized .= \danog\PHP\Struct::pack('<i', count($arguments['id']));
|
$serialized .= \danog\PHP\Struct::pack('<i', count($arguments['id']));
|
||||||
$serialized .= \phpseclib\Crypt\Random::string(8 * count($arguments['id']));
|
$serialized .= \danog\MadelineProto\Tools::random(8 * count($arguments['id']));
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,10 @@ namespace danog\MadelineProto;
|
|||||||
*/
|
*/
|
||||||
trait Tools
|
trait Tools
|
||||||
{
|
{
|
||||||
|
public static function random($length) {
|
||||||
|
if ($length === 0) return '';
|
||||||
|
return \danog\MadelineProto\Tools::random($length);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* posmod(numeric,numeric) : numeric
|
* posmod(numeric,numeric) : numeric
|
||||||
* Works just like the % (modulus) operator, only returns always a postive number.
|
* Works just like the % (modulus) operator, only returns always a postive number.
|
||||||
|
@ -424,7 +424,7 @@ trait FilesHandler
|
|||||||
$part_num = 0;
|
$part_num = 0;
|
||||||
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
$method = $file_size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
|
||||||
$constructor = $file_size > 10 * 1024 * 1024 ? 'inputFileBig' : 'inputFile';
|
$constructor = $file_size > 10 * 1024 * 1024 ? 'inputFileBig' : 'inputFile';
|
||||||
$file_id = \danog\PHP\Struct::unpack('<q', \phpseclib\Crypt\Random::string(8))[0];
|
$file_id = \danog\PHP\Struct::unpack('<q', \danog\MadelineProto\Tools::random(8))[0];
|
||||||
$f = fopen($file, 'r');
|
$f = fopen($file, 'r');
|
||||||
fseek($f, 0);
|
fseek($f, 0);
|
||||||
while (ftell($f) !== $file_size) {
|
while (ftell($f) !== $file_size) {
|
||||||
@ -451,6 +451,7 @@ trait FilesHandler
|
|||||||
|
|
||||||
public function get_download_info($message_media)
|
public function get_download_info($message_media)
|
||||||
{
|
{
|
||||||
|
if (!isset($message_media['_']) && isset($message_media['InputFileLocation']) && isset($message_media['size'])) return $message_media;
|
||||||
$res = [];
|
$res = [];
|
||||||
switch ($message_media['_']) {
|
switch ($message_media['_']) {
|
||||||
case 'messageMediaPhoto':
|
case 'messageMediaPhoto':
|
||||||
@ -460,6 +461,7 @@ trait FilesHandler
|
|||||||
$res['name'] = $photo['location']['volume_id'].'_'.$photo['location']['local_id'];
|
$res['name'] = $photo['location']['volume_id'].'_'.$photo['location']['local_id'];
|
||||||
$res['size'] = $photo['size'];
|
$res['size'] = $photo['size'];
|
||||||
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret']];
|
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $photo['location']['volume_id'], 'local_id' => $photo['location']['local_id'], 'secret' => $photo['location']['secret']];
|
||||||
|
$res['mime'] = 'image/jpeg';
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
|
|
||||||
@ -492,7 +494,7 @@ trait FilesHandler
|
|||||||
}
|
}
|
||||||
$res['name'] .= '_'.$message_media['document']['id'];
|
$res['name'] .= '_'.$message_media['document']['id'];
|
||||||
$res['size'] = $message_media['document']['size'];
|
$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']];
|
$res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $message_media['document']['id'], 'access_hash' => $message_media['document']['access_hash'], 'version' => $message_media['document']['version']];
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
@ -506,7 +508,7 @@ trait FilesHandler
|
|||||||
{
|
{
|
||||||
$info = $this->get_download_info($message_media);
|
$info = $this->get_download_info($message_media);
|
||||||
|
|
||||||
return $this->download_to_file($message_media, $dir.'/'.$info['name'].$info['ext'], $cb);
|
return $this->download_to_file($info, $dir.'/'.$info['name'].$info['ext'], $cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download_to_file($message_media, $file, $cb = null)
|
public function download_to_file($message_media, $file, $cb = null)
|
||||||
@ -515,13 +517,15 @@ trait FilesHandler
|
|||||||
touch($file);
|
touch($file);
|
||||||
}
|
}
|
||||||
$stream = fopen($file, 'w');
|
$stream = fopen($file, 'w');
|
||||||
fseek($stream, filesize($file));
|
$info = $this->get_download_info($message_media);
|
||||||
$this->download_to_stream($message_media, $stream, $cb);
|
|
||||||
|
|
||||||
|
$this->download_to_stream($info, $stream, $cb, filesize($file), $info['size']);
|
||||||
|
|
||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download_to_stream($message_media, $stream, $cb = null)
|
public function download_to_stream($message_media, $stream, $cb = null, $offset = 0, $end = -1)
|
||||||
{
|
{
|
||||||
if ($cb === null) {
|
if ($cb === null) {
|
||||||
$cb = function ($percent) {
|
$cb = function ($percent) {
|
||||||
@ -529,10 +533,17 @@ trait FilesHandler
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
$info = $this->get_download_info($message_media);
|
$info = $this->get_download_info($message_media);
|
||||||
$offset = ftell($stream);
|
if ($end === -1) $end = $info['size'];
|
||||||
|
if (stream_get_meta_data($stream)['seekable']) fseek($stream, $offset);
|
||||||
|
$size = $end - $offset;
|
||||||
$part_size = 512 * 1024;
|
$part_size = 512 * 1024;
|
||||||
while (fwrite($stream, $this->API->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset += $part_size, 'limit' => $part_size], null, true)['bytes']) != false) {
|
$percent = 0;
|
||||||
$cb(ftell($stream) * 100 / $info['size']);
|
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);
|
||||||
|
fwrite($stream, $this->API->method_call('upload.getFile', ['location' => $info['InputFileLocation'], 'offset' => $offset, 'limit' => $real_part_size], null, true)['bytes']);
|
||||||
|
\danog\MadelineProto\Logger::log($offset, $size, ftell($stream));
|
||||||
|
$cb($percent = ($offset += $real_part_size) * 100 / $size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user