diff --git a/convert.php b/convert.php index 19a21da..620f4fc 100644 --- a/convert.php +++ b/convert.php @@ -1,4 +1,4 @@ -API = $API; - $this->call = $call; - $this->timeout = $timeout; - } - public function loop(): void - { - $MadelineProto = $this->API; - $logger = $MadelineProto->getLogger(); - - while (true) { - do { - $result = $this->waitSignal($this->pause($this->timeout)); - if ($result) { - $logger->logger("Got signal in $this, exiting"); - return; - } - } while (!isset($this->call->mId)); - $result = $this->waitSignal($this->pause($this->timeout)); - try { - $message = 'Total running calls: '.count($MadelineProto->getEventHandler()->calls).PHP_EOL.PHP_EOL.$this->call->getDebugString(); - $message .= PHP_EOL.PHP_EOL.PHP_EOL; - $message .= "Emojis: ".implode('', $this->call->getVisualization()); - - $MadelineProto->messages->editMessage(['id' => $this->call->mId, 'peer' => $this->call->otherID, 'message' => $message]); - } catch (RPCErrorException $e) { - $MadelineProto->logger($e); - } - } - } - public function __toString(): string - { - return "VoIP message loop ".$this->call->otherID; - } -} -class StatusLoop extends ResumableSignalLoop -{ - const INTERVAL = 2000; - private $timeout; - private $call; - private EventHandler $API; - public function __construct($API, $call, $timeout = self::INTERVAL) - { - $this->API = $API; - $this->call = $call; - $this->timeout = $timeout; - } - public function loop(): void - { - $MadelineProto = $this->API; - $logger = $MadelineProto->getLogger(); - $call = $this->call; - - while (true) { - $result = $this->waitSignal($this->pause($this->timeout)); - if ($result) { - $logger->logger("Got signal in $this, exiting"); - $MadelineProto->getEventHandler()->cleanUpCall($call->otherID); - return; - } - - if ($call->getCallState() === CallState::ENDED) { - $MadelineProto->getEventHandler()->cleanUpCall($call->otherID); - if (file_exists('/tmp/logs'.$call->getCallID()['id'].'.log')) { - @unlink('/tmp/logs'.$call->getCallID()['id'].'.log'); - try { - $me = $this->API->getEventHandler()->getMe(); - $MadelineProto->messages->sendMedia([ - 'reply_to_msg_id' => $this->call->mId, - 'peer' => $call->otherID, 'message' => "Debug info by $me", - 'media' => [ - '_' => 'inputMediaUploadedDocument', - 'file' => '/tmp/logs'.$call->getCallID()['id'].'.log', - 'attributes' => [ - ['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'], - ], - ], - ]); - } catch (Exception $e) { - $MadelineProto->logger($e); - } catch (RPCErrorException $e) { - $MadelineProto->logger($e); - } catch (Exception $e) { - $MadelineProto->logger($e); - } - } - if (file_exists('/tmp/stats'.$call->getCallID()['id'].'.txt')) { - @unlink('/tmp/stats'.$call->getCallID()['id'].'.txt'); - } - return; - } - } - } - public function __toString(): string - { - return "VoIP status loop ".$this->call->otherID; - } -}*/ - class MyEventHandler extends SimpleEventHandler { const ADMINS = [101374607]; // @danogentili, creator of MadelineProto - private $messageLoops = []; - private $statusLoops = []; - private $programmed_call; - private $my_users; - private $me; - public $calls = []; + private array $programmed_call; + private array $my_users; + private string $me; + /** @var array */ + private array $calls = []; + /** @var array */ + private array $messageIds = []; + /** @var list */ private array $songs = []; public function onStart(): void { @@ -174,9 +64,10 @@ class MyEventHandler extends SimpleEventHandler if (!$songs) { throw new \AssertionError('No songs defined! Convert some songs by sending them to https://t.me/libtgvoipbot and putting them in the current directory'); } - foreach ($songs as $song) { + foreach ($songs as &$song) { + $song = new LocalFile($song); try { - Ogg::validateOgg(new LocalFile($song)); + Ogg::validateOgg($song); } catch (Throwable $e) { throw new AssertionError("An error occurred during validation of $song, please convert the file using convert.php or @libtgvoipbot!", 0, $e); } @@ -185,7 +76,6 @@ class MyEventHandler extends SimpleEventHandler $this->programmed_call = []; foreach ($this->programmed_call as $key => [$user, $time]) { - continue; $sleepTime = $time <= time() ? 0 : $time - time(); Tools::callFork(function () use ($sleepTime, $key, $user): void { Tools::sleep($sleepTime); @@ -194,11 +84,13 @@ class MyEventHandler extends SimpleEventHandler }); } } + private int $lastLog = 0; /** * Handles updates to an in-progress broadcast. */ - public function onUpdateBroadcastProgress(Progress $progress): void + #[Handler] + public function broadcastProgress(Progress $progress): void { if (time() - $this->lastLog > 5 || $progress->status === Status::FINISHED) { $this->lastLog = time(); @@ -230,7 +122,28 @@ class MyEventHandler extends SimpleEventHandler { return self::ADMINS; } - public function configureCall(VoIP $call): void + #[Cron(period: 10)] + public function statusLoop(): void + { + foreach ($this->calls as $user => $call) { + if ($call->getCallState() === CallState::ENDED) { + unset($this->calls[$call->otherID], $this->messageIds[$call->otherID]); + + continue; + } + try { + $message = 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL; + $message .= PHP_EOL.PHP_EOL.PHP_EOL; + $message .= "Emojis: ".implode('', $call->getVisualization()); + + $this->messages->editMessage(['id' => $this->messageIds[$call->otherID], 'peer' => $user, 'message' => $message]); + } catch (RPCErrorException $e) { + $this->logger($e); + } + } + } + + private function configureCall(VoIP $call): void { $songs = $this->songs; $songs_length = count($songs); @@ -239,59 +152,32 @@ class MyEventHandler extends SimpleEventHandler shuffle($songs); } - foreach ($songs as &$song) { - $song = new LocalFile($song); - } - $call->playOnHold(...$songs); if ($call->getCallState() !== CallState::ENDED) { - $this->calls[$call->otherID] = $call; - /*try { - $message = 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString(); - //$message .= PHP_EOL; - //$message .= "Emojis: ".implode('', $call->getVisualization()); + try { + $message = 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL; + $message .= PHP_EOL.PHP_EOL.PHP_EOL; + $message .= "Emojis: ".implode('', $call->getVisualization()); - $call->mId = $this->messages->sendMessage(['peer' => $call->otherID, 'message' => $message])['id']; + $this->messages[$call->otherID] = $this->sendMessage(peer: $call->otherID, message: $message)->id; + $this->calls[$call->otherID] = $call; } catch (Throwable $e) { $this->logger($e); } - $this->messageLoops[$call->otherID] = new MessageLoop($this, $call); - $this->statusLoops[$call->otherID] = new StatusLoop($this, $call); - $this->messageLoops[$call->otherID]->start(); - $this->statusLoops[$call->otherID]->start();*/ - } - //$this->messages->sendMessage(['message' => var_export($call->configuration, true), 'peer' => $call->otherID]); - } - public function cleanUpCall($user): void - { - 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): void + private function makeCall(int $user): void { try { - if (isset($this->calls[$user])) { - if ($this->calls[$user]->getCallState() === CallState::ENDED) { - $this->cleanUpCall($user); - } else { - $this->messages->sendMessage(['peer' => $user, 'message' => "I'm already in a call with you!"]); - return; - } + if ($this->getCallByPeer($user)) { + $this->messages->sendMessage(['peer' => $user, 'message' => "I'm already in a call with you!"]); + return; } $this->configureCall($this->requestCall($user)); } catch (RPCErrorException $e) { try { if ($e->rpc === "CALL_PROTOCOL_COMPAT_LAYER_INVALID") { - $e = "Please call me using Telegram Desktop, Telegram for Mac or Telegram Android!"; + $e = "Please call me using Telegram Desktop, Telegram for Mac or Telegram Android!"; } if ($e->rpc === 'USER_PRIVACY_RESTRICTED') { $e = 'Please disable call privacy settings to make me call you (or call me yourself!)'; @@ -303,13 +189,16 @@ class MyEventHandler extends SimpleEventHandler $this->messages->sendMessage(['peer' => $user, 'message' => (string) $e]); } } - public function handleMessage($chat_id, $from_id, $message): void + #[Handler] + public function handleMessage(Incoming&Message $message): void { 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 {$this->me} the webradio. + $runCall = $message->message === '/call'; + if (!isset($this->my_users[$message->chatId]) || $message->message === '/start') { + $runCall = true; + $this->my_users[$message->chatId] = true; + $message->reply( + message: "Hi, I'm {$this->me} 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!). @@ -331,23 +220,26 @@ Propic art by magnaluna on [deviantart](https://magnaluna.deviantart.com). Note for iOS users: the official Telegram iOS app has a bug which prevents me from working properly, I'm looking into it, try calling from your Mac/Android/PC, instead! -", 'parse_mode' => 'Markdown']); +", + parseMode: ParseMode::MARKDOWN, + noWebpage: true + ); } - if (!isset($this->calls[$from_id]) && $message === '/call') { - $this->makeCall($from_id); + if (!$this->getCallByPeer($message->chatId) && $runCall && $message->chatId > 0) { + $this->makeCall($message->chatId); } - if (strpos($message, '/program') === 0) { - $time = strtotime(str_replace('/program ', '', $message)); + if (strpos($message->message, '/program') === 0 && $message->chatId > 0) { + $time = strtotime(str_replace('/program ', '', $message->message)); if ($time === false) { - $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']); + $message->reply('Invalid time provided'); } elseif ($time - time() <= 0) { - $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'Invalid time provided']); + $message->reply('Invalid time provided'); } else { - $this->messages->sendMessage(['peer' => $chat_id, 'message' => 'OK']); - $this->programmed_call[] = [$from_id, $time]; + $message->reply('OK'); + $this->programmed_call[] = [$message->chatId, $time]; $key = count($this->programmed_call) - 1; Tools::sleep($time - time()); - $this->makeCall($from_id); + $this->makeCall($message->chatId); unset($this->programmed_call[$key]); } } @@ -355,11 +247,11 @@ Note for iOS users: the official Telegram iOS app has a bug which prevents me fr 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); $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"; - }*/ - $this->messages->sendMessage(['peer' => $chat_id, 'message' => (string) $e]); + } + $message->reply((string) $e); } catch (RPCErrorException $e) { } $this->logger($e); @@ -368,43 +260,6 @@ Note for iOS users: the official Telegram iOS app has a bug which prevents me fr } } - public function onUpdateNewMessage($update): void - { - if ($update['message']['out'] || $update['message']['to_id']['_'] !== 'peerUser' || !isset($update['message']['from_id'])) { - return; - } - $this->logger($update); - $chat_id = $from_id = $this->getInfo($update)['bot_api_id']; - $message = $update['message']['message'] ?? ''; - $this->handleMessage($chat_id, $from_id, $message); - } - - public function onUpdateNewEncryptedMessage($update): void - { - return; - $chat_id = $this->getInfo($update)['InputEncryptedChat']; - $from_id = $this->getSecretChat($chat_id)['user_id']; - $message = $update['message']['decrypted_message']['message'] ?? ''; - $this->handleMessage($chat_id, $from_id, $message); - } - - public function onUpdateEncryption($update): void - { - return; - - try { - if ($update['chat']['_'] !== 'encryptedChat') { - return; - } - $chat_id = $this->getInfo($update)['InputEncryptedChat']; - $from_id = $this->getSecretChat($chat_id)['user_id']; - $message = ''; - } catch (Exception $e) { - return; - } - $this->handleMessage($chat_id, $from_id, $message); - } - #[Handler] public function incomingCall(VoIP&Incoming $voip): void { @@ -420,9 +275,16 @@ Note for iOS users: the official Telegram iOS app has a bug which prevents me fr $this->configureCall($voip); } + #[Handler] + public function endedCall(VoIP&Ended $voip): void + { + unset($this->calls[$voip->otherID], $this->messageIds[$voip->otherID]); + + } + public function __sleep(): array { - return ['programmed_call', 'my_users']; + return ['programmed_call', 'my_users', 'messageIds']; } }