mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 09:58:59 +01:00
Async magnaluna and more async bugfixes (#667)
This commit is contained in:
parent
005d762a8f
commit
a951ae380f
2
docs
2
docs
@ -1 +1 @@
|
||||
Subproject commit ddb2e4f76938b69ceac6e4615901c642accae1ef
|
||||
Subproject commit dc05dc5cebfcec90ac7851928c522a4d635dbab6
|
371
magna.php
371
magna.php
@ -38,8 +38,117 @@ $MadelineProto->inputEncryptedFileVideo = $MadelineProto->upload_encrypted('test
|
||||
$MadelineProto->inputEncryptedFileAudio = $MadelineProto->upload_encrypted('tests/mosconi.mp3');
|
||||
}*/
|
||||
|
||||
use danog\MadelineProto\Loop\Impl\ResumableSignalLoop;
|
||||
class MessageLoop extends ResumableSignalLoop
|
||||
{
|
||||
const INTERVAL = 10;
|
||||
private $timeout;
|
||||
private $call;
|
||||
public function __construct($API, $call, $timeout = self::INTERVAL)
|
||||
{
|
||||
$this->API = $API;
|
||||
$this->call = $call;
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
public function loop()
|
||||
{
|
||||
$MadelineProto = $this->API;
|
||||
$logger = &$MadelineProto->logger;
|
||||
|
||||
while (true) {
|
||||
$result = yield $this->waitSignal($this->pause($this->timeout));
|
||||
if ($result) {
|
||||
$logger->logger("Got signal in $this, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
yield $MadelineProto->messages->editMessage(['id' => $this->call->mId, 'peer' => $this->call->getOtherID(), 'message' => 'Total running calls: '.count($MadelineProto->getEventHandler()->calls).PHP_EOL.PHP_EOL.$this->call->getDebugString()]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->logger($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
public function __toString(): string
|
||||
{
|
||||
return "VoIP message loop ".$this->call->getOtherId();
|
||||
}
|
||||
}
|
||||
class StatusLoop extends ResumableSignalLoop
|
||||
{
|
||||
const INTERVAL = 2;
|
||||
private $timeout;
|
||||
private $call;
|
||||
public function __construct($API, $call, $timeout = self::INTERVAL)
|
||||
{
|
||||
$this->API = $API;
|
||||
$this->call = $call;
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
public function loop()
|
||||
{
|
||||
$MadelineProto = $this->API;
|
||||
$logger = &$MadelineProto->logger;
|
||||
$call = $this->call;
|
||||
|
||||
while (true) {
|
||||
$result = yield $this->waitSignal($this->pause($this->timeout));
|
||||
if ($result) {
|
||||
$logger->logger("Got signal in $this, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
try {
|
||||
/*yield $this->messages->sendMedia([
|
||||
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
|
||||
'peer' => $call->getOtherID(), 'message' => 'Call statistics by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => "/tmp/stats".$call->getCallID()['id'].".txt",
|
||||
'attributes' => [
|
||||
['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"]
|
||||
]
|
||||
],
|
||||
]);*/
|
||||
yield $MadelineProto->messages->sendMedia([
|
||||
'reply_to_msg_id' => $this->call->mId,
|
||||
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => '/tmp/logs'.$call->getCallID()['id'].'.log',
|
||||
'attributes' => [
|
||||
['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto->logger($e);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
$MadelineProto->logger($e);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
$MadelineProto->logger($e);
|
||||
}
|
||||
@unlink('/tmp/logs'.$call->getCallID()['id'].'.log');
|
||||
@unlink('/tmp/stats'.$call->getCallID()['id'].'.txt');
|
||||
$MadelineProto->getEventHandler()->cleanUpCall($call->getOtherID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
public function __toString(): string
|
||||
{
|
||||
return "VoIP status loop ".$this->call->getOtherId();
|
||||
}
|
||||
}
|
||||
|
||||
class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
{
|
||||
const ADMINS = [101374607]; // @danogentili, creator of MadelineProto
|
||||
private $messageLoops = [];
|
||||
private $statusLoops = [];
|
||||
private $programmed_call;
|
||||
private $my_users;
|
||||
public function configureCall($call)
|
||||
{
|
||||
include 'songs.php';
|
||||
@ -50,16 +159,74 @@ class EventHandler extends \danog\MadelineProto\EventHandler
|
||||
//$call->configuration["stats_dump_file_path"] = "/tmp/stats".$call->getCallID()['id'].".txt"; // Default is /dev/null
|
||||
$call->parseConfig();
|
||||
$call->playOnHold($songs);
|
||||
//$this->messages->sendMessage(['message' => var_export($call->configuration, true), 'peer' => $call->getOtherID()]);
|
||||
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
|
||||
if ($call->accept() === false) {
|
||||
$MadelineProto->logger('DID NOT ACCEPT A CALL');
|
||||
}
|
||||
}
|
||||
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$this->calls[$call->getOtherID()] = $call;
|
||||
try {
|
||||
$call->mId = yield $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id'];
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger($e);
|
||||
}
|
||||
$this->messageLoops[$call->getOtherID()] = new MessageLoop($this, $call);
|
||||
$this->statusLoops[$call->getOtherID()] = new StatusLoop($this, $call);
|
||||
$this->messageLoops[$call->getOtherID()]->start();
|
||||
$this->statusLoops[$call->getOtherID()]->start();
|
||||
}
|
||||
//yield $this->messages->sendMessage(['message' => var_export($call->configuration, true), 'peer' => $call->getOtherID()]);
|
||||
}
|
||||
public function cleanUpCall($user)
|
||||
{
|
||||
if (isset($this->calls[$user])) {
|
||||
unset($this->calls[$user]);
|
||||
}
|
||||
if (isset($this->messageLoops[$user])) {
|
||||
$this->messageLoops[$user]->signal(true);
|
||||
unset($this->messageLoops[$user]);
|
||||
}
|
||||
if (isset($this->statusLoops[$user])) {
|
||||
$this->statusLoops[$user]->signal(true);
|
||||
unset($this->statusLoops[$user]);
|
||||
}
|
||||
}
|
||||
public function makeCall($user)
|
||||
{
|
||||
try {
|
||||
if (isset($this->calls[$user])) {
|
||||
if ($this->calls[$user]->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
yield $this->cleanUpCall($user);
|
||||
} else {
|
||||
yield $this->messages->sendMessage(['peer' => $user, 'message' => "I'm already in a call with you!"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
yield $this->configureCall(yield $this->requestCall($user));
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
try {
|
||||
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
|
||||
$e = 'Please disable call privacy settings to make me call you';
|
||||
}/* elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
|
||||
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
|
||||
$this->programmed_call[] = [$user, time() + 1 + $t];
|
||||
$e = "I'll call you back in $t seconds.\nYou can also call me right now.";
|
||||
}*/
|
||||
yield $this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
yield $this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleMessage($chat_id, $from_id, $message)
|
||||
{
|
||||
try {
|
||||
if (!isset($this->my_users[$from_id]) || $message === '/start') {
|
||||
$this->my_users[$from_id] = true;
|
||||
$message = '/call';
|
||||
$this->messages->sendMessage(['no_webpage' => true, 'peer' => $chat_id, 'message' => "Hi, I'm @magnaluna the webradio.
|
||||
yield $this->messages->sendMessage(['no_webpage' => true, 'peer' => $chat_id, 'message' => "Hi, I'm @magnaluna the webradio.
|
||||
|
||||
Call _me_ to listen to some **awesome** music, or send /call to make _me_ call _you_ (don't forget to disable call privacy settings!).
|
||||
|
||||
@ -80,50 +247,48 @@ Source code: https://github.com/danog/MadelineProto
|
||||
Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'parse_mode' => 'Markdown']);
|
||||
}
|
||||
if (!isset($this->calls[$from_id]) && $message === '/call') {
|
||||
$call = $this->request_call($from_id);
|
||||
$this->configureCall($call);
|
||||
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$this->calls[$call->getOtherID()] = $call;
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
|
||||
}
|
||||
yield $this->makeCall($from_id);
|
||||
}
|
||||
if (strpos($message, '/program') === 0) {
|
||||
$time = strtotime(str_replace('/program ', '', $message));
|
||||
if ($time === false) {
|
||||
$this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
|
||||
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
|
||||
} else if ($time - time() <= 0) {
|
||||
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']);
|
||||
} else {
|
||||
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'OK']);
|
||||
$this->programmed_call[] = [$from_id, $time];
|
||||
$this->messages->sendMessage(['peer' => $chat_id, 'message' => 'OK']);
|
||||
$key = count($this->programmed_call) - 1;
|
||||
yield $this->sleep($time - time());
|
||||
yield $this->makeCall($from_id);
|
||||
unset($this->programmed_call[$key]);
|
||||
}
|
||||
}
|
||||
if ($message === '/broadcast' && $from_id === 101374607) {
|
||||
if ($message === '/broadcast' && in_array(self::ADMINS, $from_id)) {
|
||||
$time = time() + 100;
|
||||
$message = explode(' ', $message, 2);
|
||||
unset($message[0]);
|
||||
$message = implode(' ', $message);
|
||||
foreach ($this->get_dialogs() as $peer) {
|
||||
$this->times_messages[] = [$peer, $time, $message];
|
||||
if (isset($peer['user_id'])) {
|
||||
$this->programmed_call[] = [$peer['user_id'], $time];
|
||||
}
|
||||
$time += 30;
|
||||
$params = ['multiple' => true];
|
||||
foreach (yield $this->get_dialogs() as $peer) {
|
||||
$params []= ['peer' => $peer, 'message' => $message];
|
||||
}
|
||||
yield $this->messages->sendMessage($params);
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
try {
|
||||
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
|
||||
$e = 'Please disable call privacy settings to make me call you';
|
||||
} elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
|
||||
} /*elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
|
||||
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
|
||||
$this->programmed_call[] = [$from_id, time() + 1 + $t];
|
||||
$e = "Too many people used the /call function. I'll call you back in $t seconds.\nYou can also call me right now.";
|
||||
}
|
||||
$this->messages->sendMessage(['peer' => $chat_id, 'message' => (string) $e]);
|
||||
$e = "Too many people used the /call function. I'll be able to call you in $t seconds.\nYou can also call me right now";
|
||||
}*/
|
||||
yield $this->messages->sendMessage(['peer' => $chat_id, 'message' => (string) $e]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
}
|
||||
echo $e;
|
||||
$this->logger($e);
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
echo $e;
|
||||
$this->logger($e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,19 +297,19 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
if ($update['message']['out'] || $update['message']['to_id']['_'] !== 'peerUser' || !isset($update['message']['from_id'])) {
|
||||
return;
|
||||
}
|
||||
\danog\MadelineProto\Logger::log($update);
|
||||
$chat_id = $from_id = $this->get_info($update)['bot_api_id'];
|
||||
$message = isset($update['message']['message']) ? $update['message']['message'] : '';
|
||||
$this->handleMessage($chat_id, $from_id, $message);
|
||||
$this->logger->logger($update);
|
||||
$chat_id = $from_id = yield $this->get_info($update)['bot_api_id'];
|
||||
$message = $update['message']['message'] ?? '';
|
||||
yield $this->handleMessage($chat_id, $from_id, $message);
|
||||
}
|
||||
|
||||
public function onUpdateNewEncryptedMessage($update)
|
||||
{
|
||||
return;
|
||||
$chat_id = $this->get_info($update)['InputEncryptedChat'];
|
||||
$from_id = $this->get_secret_chat($chat_id)['user_id'];
|
||||
$chat_id = yield $this->get_info($update)['InputEncryptedChat'];
|
||||
$from_id = yield $this->get_secret_chat($chat_id)['user_id'];
|
||||
$message = isset($update['message']['decrypted_message']['message']) ? $update['message']['decrypted_message']['message'] : '';
|
||||
$this->handleMessage($chat_id, $from_id, $message);
|
||||
yield $this->handleMessage($chat_id, $from_id, $message);
|
||||
}
|
||||
|
||||
public function onUpdateEncryption($update)
|
||||
@ -155,132 +320,45 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p
|
||||
if ($update['chat']['_'] !== 'encryptedChat') {
|
||||
return;
|
||||
}
|
||||
$chat_id = $this->get_info($update)['InputEncryptedChat'];
|
||||
$from_id = $this->get_secret_chat($chat_id)['user_id'];
|
||||
$chat_id = yield $this->get_info($update)['InputEncryptedChat'];
|
||||
$from_id = yield $this->get_secret_chat($chat_id)['user_id'];
|
||||
$message = '';
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
return;
|
||||
}
|
||||
$this->handleMessage($chat_id, $from_id, $message);
|
||||
yield $this->handleMessage($chat_id, $from_id, $message);
|
||||
}
|
||||
|
||||
public function onUpdatePhoneCall($update)
|
||||
{
|
||||
if (is_object($update['phone_call']) && isset($update['phone_call']->madeline) && $update['phone_call']->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) {
|
||||
$this->configureCall($update['phone_call']);
|
||||
if ($update['phone_call']->accept() === false) {
|
||||
echo 'DID NOT ACCEPT A CALL';
|
||||
}
|
||||
$this->calls[$update['phone_call']->getOtherID()] = $update['phone_call'];
|
||||
|
||||
try {
|
||||
$this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL])['id']];
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
}
|
||||
yield $this->configureCall($update['phone_call']);
|
||||
}
|
||||
}
|
||||
|
||||
public function onAny($update)
|
||||
/*public function onAny($update)
|
||||
{
|
||||
\danog\MadelineProto\Logger::log($update);
|
||||
}
|
||||
$this->logger->logger($update);
|
||||
}*/
|
||||
|
||||
public function onLoop()
|
||||
public function __construct($API)
|
||||
{
|
||||
foreach ($this->programmed_call as $key => $pair) {
|
||||
list($user, $time) = $pair;
|
||||
if ($time < time()) {
|
||||
if (!isset($this->calls[$user])) {
|
||||
try {
|
||||
$call = $this->request_call($user);
|
||||
$this->configureCall($call);
|
||||
if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$this->calls[$call->getOtherID()] = $call;
|
||||
$this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']];
|
||||
}
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
try {
|
||||
if ($e->rpc === 'USER_PRIVACY_RESTRICTED') {
|
||||
$e = 'Please disable call privacy settings to make me call you';
|
||||
} elseif (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
|
||||
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
|
||||
$this->programmed_call[] = [$user, time() + 1 + $t];
|
||||
$e = "I'll call you back in $t seconds.\nYou can also call me right now.";
|
||||
}
|
||||
$this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
parent::__construct($API);
|
||||
$this->programmed_call = [];
|
||||
foreach ($this->programmed_call as $key => list($user, $time)) {
|
||||
continue;
|
||||
$sleepTime = $time <= time() ? 0 : $time - time();
|
||||
$this->callFork((function () use ($sleepTime, $key, $user) {
|
||||
yield $this->sleep($sleepTime);
|
||||
yield $this->makeCall($user);
|
||||
unset($this->programmed_call[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
foreach ($this->times_messages as $key => $pair) {
|
||||
list($peer, $time, $message) = $pair;
|
||||
if ($time < time()) {
|
||||
try {
|
||||
$this->messages->sendMessage(['peer' => $peer, 'message' => $message]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
if (strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
|
||||
$t = str_replace('FLOOD_WAIT_', '', $e->rpc);
|
||||
$this->times_messages[] = [$peer, time() + 1 + $t, $message];
|
||||
}
|
||||
echo $e;
|
||||
}
|
||||
unset($this->times_messages[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
\danog\MadelineProto\Logger::log(count($this->calls).' calls running!');
|
||||
foreach ($this->calls as $key => $call) {
|
||||
if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
try {
|
||||
if (isset($this->times[$call->getOtherID()][1])) {
|
||||
/*$this->messages->sendMedia([
|
||||
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
|
||||
'peer' => $call->getOtherID(), 'message' => 'Call statistics by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => "/tmp/stats".$call->getCallID()['id'].".txt",
|
||||
'attributes' => [
|
||||
['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"]
|
||||
]
|
||||
],
|
||||
]);*/
|
||||
$this->messages->sendMedia([
|
||||
'reply_to_msg_id' => $this->times[$call->getOtherID()][1],
|
||||
'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna',
|
||||
'media' => [
|
||||
'_' => 'inputMediaUploadedDocument',
|
||||
'file' => '/tmp/logs'.$call->getCallID()['id'].'.log',
|
||||
'attributes' => [
|
||||
['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
echo $e;
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
echo $e;
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
echo $e;
|
||||
}
|
||||
@unlink('/tmp/logs'.$call->getCallID()['id'].'.log');
|
||||
@unlink('/tmp/stats'.$call->getCallID()['id'].'.txt');
|
||||
unset($this->calls[$key]);
|
||||
} elseif (isset($this->times[$call->getOtherID()]) && $this->times[$call->getOtherID()][0] < time()) {
|
||||
$this->times[$call->getOtherID()][0] += 30 + count($this->calls);
|
||||
|
||||
try {
|
||||
$this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
echo $e;
|
||||
}
|
||||
}
|
||||
})());
|
||||
}
|
||||
}
|
||||
public function __sleep()
|
||||
{
|
||||
return ['programmed_call', 'my_users'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) {
|
||||
@ -295,16 +373,11 @@ if (!class_exists('\\danog\\MadelineProto\\VoIPServerConfig')) {
|
||||
'audio_congestion_window' => 4 * 1024,
|
||||
]
|
||||
);
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd().'/MadelineProto.log']]);
|
||||
$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_level' => 5, 'logger_param' => getcwd().'/MadelineProto.log'], 'updates' => ['getdifference_interval' => 10], 'serialization' => ['serialization_interval' => 30], 'flood_timeout' => ['wait_if_lt' => 86400]]);
|
||||
$MadelineProto->start();
|
||||
|
||||
if (!isset($MadelineProto->programmed_call)) {
|
||||
$MadelineProto->programmed_call = [];
|
||||
}
|
||||
|
||||
foreach (['my_users', 'times', 'times_messages', 'calls'] as $key) {
|
||||
if (!isset($MadelineProto->{$key})) {
|
||||
$MadelineProto->{$key} = [];
|
||||
foreach (['calls', 'programmed_call', 'my_users'] as $key) {
|
||||
if (isset($MadelineProto->API->storage[$key])) {
|
||||
unset($MadelineProto->API->storage[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,10 @@ class API extends APIFactory
|
||||
$deferred->resolve();
|
||||
yield $this->API->initAsync();
|
||||
$this->APIFactory();
|
||||
\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
|
||||
//\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
|
||||
$this->asyncInitPromise = null;
|
||||
$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
|
||||
\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
|
||||
//$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
|
||||
//\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
|
||||
|
||||
return;
|
||||
@ -162,9 +162,9 @@ class API extends APIFactory
|
||||
yield $this->API->initAsync();
|
||||
$this->APIFactory();
|
||||
$this->asyncInitPromise = null;
|
||||
\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
|
||||
$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
|
||||
\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
|
||||
//\danog\MadelineProto\Logger::log('Ping...', Logger::ULTRA_VERBOSE);
|
||||
//$pong = yield $this->ping(['ping_id' => 3], ['async' => true]);
|
||||
//\danog\MadelineProto\Logger::log('Pong: '.$pong['ping_id'], Logger::ULTRA_VERBOSE);
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
|
||||
}
|
||||
|
||||
|
@ -215,13 +215,13 @@ class Connection
|
||||
$this->disconnect();
|
||||
yield $this->API->datacenter->dcConnectAsync($this->ctx->getDc());
|
||||
if ($this->API->hasAllAuth() && !$this->hasPendingCalls()) {
|
||||
$this->callFork((function () {
|
||||
/*$this->callFork((function () {
|
||||
try {
|
||||
$this->API->method_call_async_read('ping', ['ping_id' => $this->random_int()], ['datacenter' => $this->datacenter]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->API->logger("Got an error while pinging on reconnect: $e", Logger::FATAL_ERROR);
|
||||
}
|
||||
})());
|
||||
})());*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,6 @@ class FeedLoop extends ResumableSignalLoop
|
||||
|
||||
$this->state->pts($update['pts']);
|
||||
}
|
||||
|
||||
$this->save($update);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ use danog\MadelineProto\Async\AsyncConstruct;
|
||||
use danog\MadelineProto\Loop\Update\FeedLoop;
|
||||
use danog\MadelineProto\Loop\Update\SeqLoop;
|
||||
use danog\MadelineProto\Loop\Update\UpdateLoop;
|
||||
use danog\MadelineProto\Loop\Generic\PeriodicLoop;
|
||||
use danog\MadelineProto\MTProtoTools\CombinedUpdatesState;
|
||||
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
|
||||
use danog\MadelineProto\MTProtoTools\UpdatesState;
|
||||
@ -149,6 +150,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
private $supportUser = 0;
|
||||
public $referenceDatabase;
|
||||
public $phoneConfigWatcherId;
|
||||
private $callCheckerLoop;
|
||||
public $feeders = [];
|
||||
public $updaters = [];
|
||||
public $destructing = false; // Avoid problems with exceptions thrown by forked strands, see tools
|
||||
@ -208,6 +210,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$this->logger->logger(\danog\MadelineProto\Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE);
|
||||
$this->construct_TL($this->settings['tl_schema']['src'], [$this, $this->referenceDatabase]);
|
||||
yield $this->connect_to_all_dcs_async();
|
||||
$this->startLoops();
|
||||
$this->datacenter->curdc = 2;
|
||||
if ((!isset($this->authorization['user']['bot']) || !$this->authorization['user']['bot']) && $this->datacenter->sockets[$this->datacenter->curdc]->temp_auth_key !== null) {
|
||||
try {
|
||||
@ -292,6 +295,20 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
|
||||
return true;
|
||||
}
|
||||
public function startLoops()
|
||||
{
|
||||
if (!$this->callCheckerLoop) {
|
||||
$this->callCheckerLoop = new PeriodicLoop($this, [$this, 'checkCalls'], 'call check', 10);
|
||||
}
|
||||
$this->callCheckerLoop->start();
|
||||
}
|
||||
public function stopLoops()
|
||||
{
|
||||
if ($this->callCheckerLoop) {
|
||||
$this->callCheckerLoop->signal(true);;
|
||||
$this->callCheckerLoop = null;
|
||||
}
|
||||
}
|
||||
public function __wakeup()
|
||||
{
|
||||
$backtrace = debug_backtrace(0, 3);
|
||||
@ -469,6 +486,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
$controller->setMadeline($this);
|
||||
}
|
||||
}
|
||||
$this->startLoops();
|
||||
if (yield $this->get_self_async()) {
|
||||
$this->authorized = self::LOGGED_IN;
|
||||
}
|
||||
@ -490,6 +508,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->stopLoops();
|
||||
if ($this->phoneConfigWatcherId) {
|
||||
Loop::cancel($this->phoneConfigWatcherId);
|
||||
}
|
||||
@ -1143,6 +1162,7 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function __debugInfo()
|
||||
{
|
||||
return ['MadelineProto instance '.spl_object_hash($this)];
|
||||
|
@ -83,7 +83,7 @@ trait AuthKeyHandler
|
||||
* ***********************************************************************
|
||||
* Compute p and q
|
||||
*/
|
||||
$pq = new \phpseclib\Math\BigInteger((string) $pq_bytes, 256);
|
||||
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
|
||||
$q = new \phpseclib\Math\BigInteger(0);
|
||||
$p = new \phpseclib\Math\BigInteger(\danog\PrimeModule::auto_single($pq->__toString()));
|
||||
if (!$p->equals(\danog\MadelineProto\Magic::$zero)) {
|
||||
@ -256,8 +256,8 @@ trait AuthKeyHandler
|
||||
throw new \danog\MadelineProto\SecurityException('wrong server nonce');
|
||||
}
|
||||
$g = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
|
||||
$g_a = new \phpseclib\Math\BigInteger((string) $server_DH_inner_data['g_a'], 256);
|
||||
$dh_prime = new \phpseclib\Math\BigInteger((string) $server_DH_inner_data['dh_prime'], 256);
|
||||
$g_a = new \phpseclib\Math\BigInteger($server_DH_inner_data['g_a'], 256);
|
||||
$dh_prime = new \phpseclib\Math\BigInteger($server_DH_inner_data['dh_prime'], 256);
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Time delta
|
||||
|
@ -605,7 +605,6 @@ trait ResponseHandler
|
||||
if ($actual_updates) {
|
||||
$updates = $actual_updates;
|
||||
}
|
||||
|
||||
$this->logger->logger('Parsing updates ('.$updates['_'].') received via the socket...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
switch ($updates['_']) {
|
||||
case 'updates':
|
||||
|
@ -63,11 +63,6 @@ trait UpdateHandler
|
||||
if (!$this->settings['updates']['run_callback']) {
|
||||
$this->settings['updates']['run_callback'] = true;
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
|
||||
$params = array_merge(self::DEFAULT_GETUPDATES_PARAMS, $params);
|
||||
|
||||
|
@ -49,7 +49,7 @@ class RSA
|
||||
{
|
||||
\danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['rsa_encrypting'], Logger::VERBOSE);
|
||||
|
||||
return (new \phpseclib\Math\BigInteger((string) $data, 256))->powMod($this->e, $this->n)->toBytes();
|
||||
return (new \phpseclib\Math\BigInteger($data, 256))->powMod($this->e, $this->n)->toBytes();
|
||||
}
|
||||
/**
|
||||
* Accesses a private variable from an object
|
||||
|
@ -41,7 +41,7 @@ trait AuthKeyHandler
|
||||
$dh_config = yield $this->get_dh_config_async();
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
||||
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
|
||||
$params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256);
|
||||
$this->check_G($params['g_a'], $dh_config['p']);
|
||||
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||
//$this->logger->logger($key);
|
||||
@ -87,7 +87,7 @@ trait AuthKeyHandler
|
||||
return false;
|
||||
}
|
||||
$dh_config = yield $this->get_dh_config_async();
|
||||
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
|
||||
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
|
||||
$this->check_G($params['g_a_or_b'], $dh_config['p']);
|
||||
$key = ['auth_key' => str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||
unset($this->temp_requested_secret_chats[$params['id']]);
|
||||
@ -139,10 +139,10 @@ trait AuthKeyHandler
|
||||
$my_exchange_id = new \phpseclib\Math\BigInteger($this->secret_chats[$chat]['rekeying'][1], -256);
|
||||
$other_exchange_id = new \phpseclib\Math\BigInteger($params['exchange_id'], -256);
|
||||
//$this->logger->logger($my, $params);
|
||||
if ($my_exchange_id->compare($other_exchange_id) > 0) {
|
||||
if ($my_exchange_id > $other_exchange_id) {
|
||||
return;
|
||||
}
|
||||
if ($my_exchange_id->compare($other_exchange_id) === 0) {
|
||||
if ($my_exchange_id === $other_exchange_id) {
|
||||
$this->secret_chats[$chat]['rekeying'] = [0];
|
||||
|
||||
return;
|
||||
@ -152,7 +152,7 @@ trait AuthKeyHandler
|
||||
$dh_config = yield $this->get_dh_config_async();
|
||||
$this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$b = new \phpseclib\Math\BigInteger($this->random(256), 256);
|
||||
$params['g_a'] = new \phpseclib\Math\BigInteger((string) $params['g_a'], 256);
|
||||
$params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256);
|
||||
$this->check_G($params['g_a'], $dh_config['p']);
|
||||
$key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
|
||||
@ -175,7 +175,7 @@ trait AuthKeyHandler
|
||||
}
|
||||
$this->logger->logger('Committing rekeying of secret chat '.$chat.'...', \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = yield $this->get_dh_config_async();
|
||||
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
|
||||
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
|
||||
$this->check_G($params['g_b'], $dh_config['p']);
|
||||
$key = ['auth_key' => str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)];
|
||||
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
|
||||
|
@ -129,7 +129,7 @@ trait Tools
|
||||
throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
|
||||
}
|
||||
|
||||
$big = new BigInteger((string) $value, -256);
|
||||
$big = new BigInteger($value, -256);
|
||||
return (string) $big;
|
||||
}
|
||||
|
||||
|
@ -49,11 +49,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
$user = yield $this->get_info_async($user);
|
||||
if (!isset($user['InputUser']) || $user['InputUser']['_'] === 'inputUserSelf') {
|
||||
throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
|
||||
@ -81,11 +76,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception();
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
if ($this->call_status($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
|
||||
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id']));
|
||||
|
||||
@ -126,11 +116,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
|
||||
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id']));
|
||||
|
||||
@ -138,7 +123,7 @@ trait AuthKeyHandler
|
||||
}
|
||||
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
|
||||
$dh_config = yield $this->get_dh_config_async();
|
||||
$params['g_b'] = new \phpseclib\Math\BigInteger((string) $params['g_b'], 256);
|
||||
$params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256);
|
||||
$this->check_G($params['g_b'], $dh_config['p']);
|
||||
$key = str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
||||
$res = (yield $this->method_call_async_read('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]))['phone_call'];
|
||||
@ -163,11 +148,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
if ($this->call_status($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
|
||||
$this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id']));
|
||||
|
||||
@ -178,7 +158,7 @@ trait AuthKeyHandler
|
||||
if (hash('sha256', $params['g_a_or_b'], true) != $this->calls[$params['id']]->storage['g_a_hash']) {
|
||||
throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
|
||||
}
|
||||
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger((string) $params['g_a_or_b'], 256);
|
||||
$params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256);
|
||||
$this->check_G($params['g_a_or_b'], $dh_config['p']);
|
||||
$key = str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT);
|
||||
if (substr(sha1($key, true), -8) != $params['key_fingerprint']) {
|
||||
@ -204,11 +184,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
if (isset($this->calls[$id])) {
|
||||
return $this->calls[$id]->getCallState();
|
||||
}
|
||||
@ -221,11 +196,6 @@ trait AuthKeyHandler
|
||||
if (!class_exists('\\danog\\MadelineProto\\VoIP')) {
|
||||
throw new \danog\MadelineProto\Exception(['extension', 'libtgvoip']);
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
|
||||
return $this->calls[$call];
|
||||
}
|
||||
@ -262,6 +232,9 @@ trait AuthKeyHandler
|
||||
in_array($this->settings['updates']['callback'], [['danog\\MadelineProto\\API', 'get_updates_update_handler'], 'get_updates_update_handler']) ? $this->get_updates_update_handler($update) : $this->settings['updates']['callback']($update);
|
||||
}
|
||||
unset($this->calls[$call['id']]);
|
||||
}
|
||||
public function checkCalls()
|
||||
{
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
|
@ -165,11 +165,6 @@ trait Loop
|
||||
$callback = $this->loop_callback;
|
||||
$callback();
|
||||
}
|
||||
array_walk($this->calls, function ($controller, $id) {
|
||||
if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
|
||||
$controller->discard();
|
||||
}
|
||||
});
|
||||
yield $this->waitUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ $settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: [];
|
||||
*/
|
||||
echo 'Loading MadelineProto...'.PHP_EOL;
|
||||
$MadelineProto = new \danog\MadelineProto\API(getcwd().'/testing.madeline', $settings);
|
||||
|
||||
$MadelineProto->fileGetContents('https://google.com');
|
||||
$MadelineProto->start();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user