2017-02-16 04:55:10 +01:00
#!/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 = [];
2017-02-16 04:55:47 +01:00
$token = '' ;
2017-02-16 04:55:10 +01:00
try {
$MadelineProto = \danog\MadelineProto\Serialization :: deserialize ( 'b.madeline' );
} catch ( \danog\MadelineProto\Exception $e ) {
2017-02-16 04:55:47 +01:00
$MadelineProto = new \danog\MadelineProto\API ( $settings );
$authorization = $MadelineProto -> bot_login ( $token );
\danog\MadelineProto\Logger :: log ([ $authorization ], \danog\MadelineProto\Logger :: NOTICE );
2017-02-16 04:55:10 +01:00
}
function base64url_decode ( $data )
{
return base64_decode ( str_pad ( strtr ( $data , '-_' , '+/' ), strlen ( $data ) % 4 , '=' , STR_PAD_RIGHT ));
}
2017-02-16 04:55:47 +01:00
function rle_decode ( $string )
{
2017-02-16 04:55:10 +01:00
$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 ;
2017-02-16 04:55:47 +01:00
2017-02-16 04:55:10 +01:00
return $string ;
}
function foreach_offset_length ( $string )
{
2017-02-16 04:55:47 +01:00
/* $a = [];
2017-02-16 04:55:10 +01:00
$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 ++ ) {
2017-02-16 04:55:47 +01:00
// for ($length = $strlen - $offset; $length > 0; $length--) {
2017-02-16 04:55:10 +01:00
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' => []];
2017-02-16 04:55:47 +01:00
function getfiles ( $token , & $params )
{
2017-02-16 04:55:10 +01:00
foreach ( json_decode ( file_get_contents ( 'https://api.telegram.org/bot' . $token . '/getupdates?offset=' . $params [ 'offset' ]), true )[ 'result' ] as $update ) {
2017-02-16 04:55:47 +01:00
$params [ 'offset' ] = $update [ 'update_id' ] + 1 ;
2017-02-16 04:55:10 +01:00
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 [ '_' ]);
2017-02-16 04:55:47 +01:00
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' ];
}
2017-02-16 04:55:10 +01:00
//var_dump($mtproto);
foreach ( $mtproto as $key => $n ) {
foreach ( $bot_api as $bn ) {
if ( $bn [ 'number' ] === $n ) {
2017-02-16 04:55:47 +01:00
$m [ $bn [ 'offset' ] + $bn [ 'length' ]] = $key . ' (' . $n . '): ' . $bn [ 'offset' ] . '-' . ( $bn [ 'offset' ] + $bn [ 'length' ]) . ' (' . $bn [ 'length' ] . ')' . PHP_EOL ;
2017-02-16 04:55:10 +01:00
unset ( $mtproto [ $key ]);
}
}
}
ksort ( $m );
foreach ( $m as $key => $bn ) {
$message .= $bn ;
}
foreach ( $mtproto as $key => $n ) {
2017-02-16 04:55:47 +01:00
$message .= $key . ' (' . $n . '): not found' . PHP_EOL ;
2017-02-16 04:55:10 +01:00
}
$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 ;
}