mirror of
https://github.com/danog/MadelineProto.git
synced 2025-01-22 05:12:01 +01:00
Fixed bugs, updated docs, fixed serialization and deserialization of class, improved TL class
This commit is contained in:
parent
1dca7843a9
commit
c6f1642264
2
.gitignore
vendored
2
.gitignore
vendored
@ -66,3 +66,5 @@ vendor
|
||||
number.php
|
||||
token.php
|
||||
*~uploading*
|
||||
session.mad
|
||||
*.madeline
|
38
README.md
38
README.md
@ -17,7 +17,7 @@ This project is in beta state.
|
||||
|
||||
This project depends on [PHPStruct](https://github.com/danog/PHPStruct), [phpseclib](https://github.com/phpseclib/phpseclib), https://packagist.org/packages/paragonie/constant_time_encoding and https://packagist.org/packages/paragonie/random_compat
|
||||
|
||||
To install them all simply run:
|
||||
To install dependencies install composer and run:
|
||||
```
|
||||
composer update
|
||||
```
|
||||
@ -27,13 +27,13 @@ In the cloned repo.
|
||||
### Instantiation
|
||||
|
||||
```
|
||||
$madeline = new \danog\MadelineProto\API();
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
```
|
||||
|
||||
### Settings
|
||||
|
||||
The constructor accepts an optional parameter, which is the settings array.
|
||||
Here you can see its default value and explanations for every setting:
|
||||
The constructor accepts an optional parameter, which is the settings array. This array contains some other arrays, which are the settings for a specific MadelineProto function.
|
||||
Here you can see the default values for the settings\ arrays and explanations for every setting:
|
||||
```
|
||||
$settings = [
|
||||
'authorization' => [ // Authorization settings
|
||||
@ -116,14 +116,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
],
|
||||
],
|
||||
'logger' => [ // Logger settings
|
||||
/*
|
||||
* logger modes:
|
||||
* 0 - No logger
|
||||
* 1 - Log to the default logger destination
|
||||
* 2 - Log to file defined in second parameter
|
||||
* 3 - Echo logs
|
||||
*/
|
||||
'logger' => 1, // write to
|
||||
'logger' => 1, // 0 - No logger, 1 - Log to the default logger destination, 2 - Log to file defined in logger_param, 3 - Echo logs
|
||||
'logger_param' => '/tmp/MadelineProto.log',
|
||||
'logger' => 3, // overwrite previous setting and echo logs
|
||||
],
|
||||
@ -139,7 +132,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
];
|
||||
```
|
||||
|
||||
You can provide only part of any of the subsettings array, the rest will be automagically set to the default values of the specified subsettings array.
|
||||
You can provide part of any subsetting array, that way the remaining arrays will be automagically set to default and undefined values of specified subsetting arrays will be set to the default values.
|
||||
Example:
|
||||
```
|
||||
$settings = [
|
||||
@ -162,17 +155,16 @@ Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----',
|
||||
]
|
||||
// The remaining subsetting arrays are the set to the default ones
|
||||
// The remaining subsetting arrays are the set to default
|
||||
]
|
||||
```
|
||||
|
||||
The rest of the settings array and of the authorization array will be set to the default values specified in the default array.
|
||||
Note that only subsetting arrays or values of a subsetting array will be set to default.
|
||||
Note that only settings arrays or values of a settings array will be set to default.
|
||||
|
||||
The settings array can be accessed in the instantiated class like this:
|
||||
```
|
||||
$MadelineProto = new \danog\MadelineProto\API();
|
||||
$generated_settings = $MadelineProto->API->settings;
|
||||
var_dump($MadelineProto->API->settings);
|
||||
```
|
||||
|
||||
### Calling mtproto methods and available wrappers
|
||||
@ -205,6 +197,10 @@ $authorization = $MadelineProto->bot_login($token); // Note that every time you
|
||||
var_dump($authorization);
|
||||
```
|
||||
|
||||
### Storing sessions
|
||||
|
||||
An istance of MadelineProto can be safely serialized or unserialized.
|
||||
|
||||
### Exceptions
|
||||
|
||||
MadelineProto can throw three different exceptions:
|
||||
@ -233,16 +229,16 @@ src/danog/MadelineProto/
|
||||
TL/
|
||||
Exception - Handles exceptions in the TL namespace
|
||||
TL - Handles TL serialization and deserialization
|
||||
TLConstructor - Represents a TL Constructor
|
||||
TLMethod - Represents a TL method
|
||||
API - Wrapper class that istantiates the MTProto class, sets the error handler, provides a wrapper for calling mtproto methods directly as class submethods, and provides some simplified wrappers for logging in to telegram
|
||||
TLConstructor - Stores TL constructors
|
||||
TLMethod - Stores TL methods
|
||||
API - Wrapper class that instantiates the MTProto class, sets the error handler, provides a wrapper for calling mtproto methods directly as class submethods, and provides some simplified wrappers for logging in to telegram
|
||||
APIFactory - Provides a wrapper for calling namespaced mtproto methods directly as class submethods
|
||||
Connection - Handles tcp/udp/http connections and wrapping payloads generated by MTProtoTools/MessageHandler into the right message according to the protocol, stores authorization keys, session id and sequence number
|
||||
DataCenter - Handles mtproto datacenters (is a wrapper for Connection classes)
|
||||
DebugTools - Various debugging tools
|
||||
Exception - Handles exceptions and PHP errors
|
||||
RPCErrorException - Handles RPC errors
|
||||
MTProto - Extends MTProtoTools, handles initial connection, generation of authorization keys, istantiation of classes, writing of client info
|
||||
MTProto - Extends MTProtoTools, handles initial connection, generation of authorization keys, instantiation of classes, writing of client info
|
||||
MTProtoTools - Extends all of the classes in MTProtoTools/
|
||||
Logger - Static logging class
|
||||
prime.py and getpq.py - prime module (python) for p and q generation
|
||||
|
@ -23,6 +23,7 @@ class API extends APIFactory
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
$this->API = new MTProto($params);
|
||||
|
||||
\danog\MadelineProto\Logger::log('Running APIFactory...');
|
||||
$this->APIFactory();
|
||||
|
||||
\danog\MadelineProto\Logger::log('Ping...');
|
||||
@ -38,26 +39,28 @@ class API extends APIFactory
|
||||
|
||||
public function APIFactory()
|
||||
{
|
||||
\danog\MadelineProto\Logger::log('Running APIFactory...');
|
||||
foreach ($this->API->tl->methods->method_namespace as $namespace => $method) {
|
||||
$this->{$method} = new APIFactory($method, $this->API);
|
||||
foreach ($this->API->tl->methods->method_namespace as $namespace) {
|
||||
$this->{$namespace} = new APIFactory($namespace, $this->API);
|
||||
}
|
||||
}
|
||||
|
||||
public function logout()
|
||||
{
|
||||
$this->API->datacenter->authorized = false;
|
||||
$this->API->datacenter->authorization = null;
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
if (!$this->API->method_call('auth.logOut')) {
|
||||
throw new Exception('An error occurred while logging out!');
|
||||
}
|
||||
$this->API->datacenter->authorized = false;
|
||||
$this->API->datacenter->authorization = null;
|
||||
\danog\MadelineProto\Logger::log('Logged out successfully!');
|
||||
restore_error_handler();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function bot_login($token)
|
||||
{
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
if ($this->API->datacenter->authorized) {
|
||||
\danog\MadelineProto\Logger::log('This instance of MadelineProto is already logged in. Logging out first...');
|
||||
$this->logout();
|
||||
@ -73,12 +76,14 @@ class API extends APIFactory
|
||||
);
|
||||
$this->API->datacenter->authorized = true;
|
||||
\danog\MadelineProto\Logger::log('Logged in successfully!');
|
||||
restore_error_handler();
|
||||
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
|
||||
public function phone_login($number, $sms_type = 5)
|
||||
{
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
if ($this->API->datacenter->authorized) {
|
||||
\danog\MadelineProto\Logger::log('This instance of MadelineProto is already logged in. Logging out first...');
|
||||
$this->logout();
|
||||
@ -97,12 +102,14 @@ class API extends APIFactory
|
||||
$this->API->datacenter->authorization['phone_number'] = $number;
|
||||
$this->API->datacenter->waiting_code = true;
|
||||
\danog\MadelineProto\Logger::log('Code sent successfully! Once you receive the code you should use the complete_phone_login function.');
|
||||
restore_error_handler();
|
||||
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
|
||||
public function complete_phone_login($code)
|
||||
{
|
||||
set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']);
|
||||
if (!$this->API->datacenter->waiting_code) {
|
||||
throw new Exception("I'm not waiting for the code! Please call the phone_login method first");
|
||||
}
|
||||
@ -118,10 +125,15 @@ class API extends APIFactory
|
||||
$this->API->datacenter->waiting_code = false;
|
||||
$this->API->datacenter->authorized = true;
|
||||
\danog\MadelineProto\Logger::log('Logged in successfully!');
|
||||
restore_error_handler();
|
||||
|
||||
return $this->API->datacenter->authorization;
|
||||
}
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
return ["API"];
|
||||
}
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->APIFactory();
|
||||
|
@ -114,7 +114,7 @@ class Connection extends Tools
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->close_and_reopen();
|
||||
$this->__construct($this->ip, $this->port, $this->protocol, $this->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +159,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
$this->setup_logger();
|
||||
|
||||
// Connect to servers
|
||||
$this->mk_datacenter();
|
||||
\danog\MadelineProto\Logger::log('Istantiating DataCenter...');
|
||||
$this->datacenter = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
|
||||
|
||||
// Load rsa key
|
||||
\danog\MadelineProto\Logger::log('Loading RSA key...');
|
||||
@ -176,14 +177,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->setup_logger();
|
||||
$this->mk_datacenter();
|
||||
}
|
||||
|
||||
public function mk_datacenter()
|
||||
{
|
||||
// Connect to servers
|
||||
\danog\MadelineProto\Logger::log('Istantiating DataCenter...');
|
||||
$this->datacenter = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
|
||||
$this->datacenter->__construct($this->settings['connection'], $this->settings['connection_settings']);
|
||||
}
|
||||
|
||||
public function setup_logger()
|
||||
@ -278,5 +272,6 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
$test .= (isset($this->settings['connection'][$test][$ipv6][$id]) && $this->settings['connection'][$test][$ipv6][$id]['ip_address'] != $dc['ip_address']) ? '_bk' : '';
|
||||
$this->settings['connection'][$test][$ipv6][$id] = $dc;
|
||||
}
|
||||
unset($this->config['dc_options']);
|
||||
}
|
||||
}
|
||||
|
@ -80,21 +80,20 @@ class TL extends \danog\MadelineProto\Tools
|
||||
$flags = 0;
|
||||
foreach ($tl['params'] as $cur_flag) {
|
||||
if ($cur_flag['flag']) {
|
||||
$flag_pow = pow(2, $cur_flag['pow']);
|
||||
switch ($cur_flag['type']) {
|
||||
case 'true':
|
||||
case 'false':
|
||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) ? ($flags | $flag_pow) : ($flags & ~$flag_pow);
|
||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) ? ($flags | $cur_flag['pow']) : ($flags & ~$cur_flag['pow']);
|
||||
unset($arguments[$cur_flag['name']]);
|
||||
break;
|
||||
case 'Bool':
|
||||
$arguments[$cur_flag['name']] = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) && (($flags & $flag_pow) != 0);
|
||||
if (($flags & $flag_pow) == 0) {
|
||||
$arguments[$cur_flag['name']] = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']]) && (($flags & $cur_flag['pow']) != 0);
|
||||
if (($flags & $cur_flag['pow']) == 0) {
|
||||
unset($arguments[$cur_flag['name']]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null) ? ($flags | $flag_pow) : ($flags & ~$flag_pow);
|
||||
$flags = (isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null) ? ($flags | $cur_flag['pow']) : ($flags & ~$cur_flag['pow']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -102,7 +101,7 @@ class TL extends \danog\MadelineProto\Tools
|
||||
$arguments['flags'] = $flags;
|
||||
foreach ($tl['params'] as $current_argument) {
|
||||
if (!isset($arguments[$current_argument['name']])) {
|
||||
if ($current_argument['flag'] && (in_array($current_argument['type'], ['true', 'false']) || ($flags & pow(2, $current_argument['pow'])) == 0)) {
|
||||
if ($current_argument['flag'] && (in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) == 0)) {
|
||||
//\danog\MadelineProto\Logger::log('Skipping '.$current_argument['name'].' of type '.$current_argument['type'].'/'.$current_argument['subtype']);
|
||||
continue;
|
||||
}
|
||||
@ -182,12 +181,7 @@ class TL extends \danog\MadelineProto\Tools
|
||||
|
||||
return $concat;
|
||||
default:
|
||||
$tl_elem = $this->constructors->find_by_predicate($type);
|
||||
if ($tl_elem === false) {
|
||||
throw new Exception('Could not serialize type: '.$type);
|
||||
}
|
||||
|
||||
return \danog\PHP\Struct::pack('<i', $tl_elem['id']);
|
||||
return $this->serialize_generic($type, $value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -286,19 +280,18 @@ class TL extends \danog\MadelineProto\Tools
|
||||
$x = ['_' => $tl_elem['predicate']];
|
||||
foreach ($tl_elem['params'] as $arg) {
|
||||
if ($arg['flag']) {
|
||||
$flag_pow = pow(2, $arg['pow']);
|
||||
switch ($arg['type']) {
|
||||
case 'true':
|
||||
case 'false':
|
||||
|
||||
$x[$arg['name']] = ($x['flags'] & $flag_pow) == 1;
|
||||
$x[$arg['name']] = ($x['flags'] & $arg['pow']) == 1;
|
||||
continue 2;
|
||||
break;
|
||||
case 'Bool':
|
||||
$default = false;
|
||||
default:
|
||||
$default = null;
|
||||
if (($x['flags'] & $flag_pow) == 0) {
|
||||
if (($x['flags'] & $arg['pow']) == 0) {
|
||||
$x[$arg['name']] = $default;
|
||||
//\danog\MadelineProto\Logger::log('Skipping '.$arg['name'].' of type '.$arg['type'].'/'.$arg['subtype']);
|
||||
continue 2;
|
||||
|
@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace danog\MadelineProto\TL;
|
||||
|
||||
class TLConstructor
|
||||
class TLConstructor extends TLParams
|
||||
{
|
||||
public $id = [];
|
||||
public $predicate = [];
|
||||
@ -20,35 +20,14 @@ class TLConstructor
|
||||
public $params = [];
|
||||
public $key = 0;
|
||||
|
||||
|
||||
public function add($json_dict, $mtproto)
|
||||
{
|
||||
$this->id[$this->key] = (int) $json_dict['id'];
|
||||
$this->predicate[$this->key] = (string) ((($mtproto && $json_dict['predicate'] == 'message') ? 'MT' : '').$json_dict['predicate']);
|
||||
$this->type[$this->key] = $json_dict['type'];
|
||||
$this->params[$this->key] = $json_dict['params'];
|
||||
foreach ($this->params[$this->key] as &$param) {
|
||||
$param['flag'] = false;
|
||||
$param['subtype'] = null;
|
||||
if (preg_match('/^flags\.\d*\?/', $param['type'])) {
|
||||
$param['flag'] = true;
|
||||
$param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']);
|
||||
$param['type'] = preg_replace('/^flags\.\d*\?/', '', $param['type']);
|
||||
}
|
||||
if (preg_match('/vector<.*>/i', $param['type'])) {
|
||||
if (preg_match('/vector/', $param['type'])) {
|
||||
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
||||
$param['type'] = 'vector';
|
||||
}
|
||||
if (preg_match('/Vector/', $param['type'])) {
|
||||
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
||||
$param['type'] = 'Vector t';
|
||||
}
|
||||
if (preg_match('/^\%/', $param['subtype'])) {
|
||||
$param['subtype'] = lcfirst(preg_replace('/^\%/', '', $param['subtype']));
|
||||
}
|
||||
$param['subtype'] = (($mtproto && $param['subtype'] == 'message') ? 'MT' : '').$param['subtype'];
|
||||
}
|
||||
}
|
||||
$this->parse_params($this->key, $mtproto);
|
||||
$this->key++;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace danog\MadelineProto\TL;
|
||||
|
||||
class TLMethod
|
||||
class TLMethod extends TLParams
|
||||
{
|
||||
public $id = [];
|
||||
public $method = [];
|
||||
@ -32,28 +32,7 @@ class TLMethod
|
||||
$this->method_namespace[$namespace[0]] = $namespace[0];
|
||||
}
|
||||
|
||||
foreach ($this->params[$this->key] as &$param) {
|
||||
$param['flag'] = false;
|
||||
$param['subtype'] = null;
|
||||
if (preg_match('/^flags\.\d*\?/', $param['type'])) {
|
||||
$param['flag'] = true;
|
||||
$param['pow'] = preg_replace(['/^flags\./', '/\?.*/'], '', $param['type']);
|
||||
$param['type'] = preg_replace('/^flags\.\d*\?/', '', $param['type']);
|
||||
}
|
||||
if (preg_match('/vector<.*>/i', $param['type'])) {
|
||||
if (preg_match('/vector/', $param['type'])) {
|
||||
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
||||
$param['type'] = 'vector';
|
||||
}
|
||||
if (preg_match('/Vector/', $param['type'])) {
|
||||
$param['subtype'] = preg_replace(['/.*</', '/>$/'], '', $param['type']);
|
||||
$param['type'] = 'Vector t';
|
||||
}
|
||||
if (preg_match('/^\%/', $param['subtype'])) {
|
||||
$param['subtype'] = lcfirst(preg_replace('/^\%/', '', $param['subtype']));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->parse_params($this->key);
|
||||
$this->key++;
|
||||
}
|
||||
|
||||
|
13
testing.php
13
testing.php
@ -34,8 +34,17 @@ if (file_exists('number.php')) {
|
||||
$authorization = $MadelineProto->complete_phone_login($code);
|
||||
var_dump($authorization);
|
||||
}
|
||||
|
||||
echo 'Serializing MadelineProto to session.madeline...'.PHP_EOL;
|
||||
echo 'Wrote '.file_put_contents('session.madeline', serialize($MadelineProto)).' bytes'.PHP_EOL;
|
||||
|
||||
echo 'Deserializing MadelineProto from session.madeline...'.PHP_EOL;
|
||||
$unserialized = unserialize(file_get_contents('session.madeline'));
|
||||
|
||||
if (file_exists('token.php')) {
|
||||
include_once 'token.php';
|
||||
$MadelineProto->bot_login($token);
|
||||
$authorization = $unserialized->bot_login($token);
|
||||
var_dump($authorization);
|
||||
}
|
||||
echo 'Size of MadelineProto instance is '.strlen(var_export($MadelineProto, true)).' bytes'.PHP_EOL;
|
||||
echo 'Size of MadelineProto instance is '.strlen(serialize($unserialized)).' bytes'.PHP_EOL;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user