Feature #3146
Updated by Gregory Magarshak 9 months ago
Welcome to your first homework. I am not just teaching you Telegram and giving you random homework, I will be giving you mini-projects so at the end of this course / sprint, you'll have a re-usable framework inside Qbix that you can re-use for many projects, and also have access to the full power of the Qbix platform at the same time :) The lesson, code samples and related links can be found at https://issues.qbix.com/projects/telegram/wiki Feel free to refer to that wiki, it will grow. h2. Information / Discussion Read this: https://issues.qbix.com/projects/telegram/wiki/Telegram_Plugin h2. Set up Telegram Bot WebHook in PHP For now, just practice setting up a web-server which is accessible from the internet. You have a couple options to make your local computer accessible from the Internet: 1) Dynamic DNS from https://www.duckdns.org/ 2) SSH Tunnel simply mapping a remote port to a port on your machine, then have your NGinx listen on that port: https://serverfault.com/questions/1004529/access-an-http-server-as-localhost-from-an-external-pc-over-ssh Anyway, practice calling @setWebhook@ method from PHP installer script. https://core.telegram.org/bots/api#setwebhook You shouldn't use HTTP (port 80) but rather HTTPS (port 443). Please generate a self-signed certificate, and Post it to @setWebhook()@: https://core.telegram.org/bots/self-signed and https://stackoverflow.com/a/44550366 Also please generate and send @secret_token@ along, which will send along a header X-Telegram-Bot-Api-Secret-Token with each request. h2. Registering webhook Add a hook @plugins/Telegram/handlers/after/Q_Plugin_install.php@ analogous to what we already have in @Users_after_Q_Plugin_install@ or @Streams_after_Q_Plugin_install@ This hook will run whenever installer runs. It will <pre> $extra = Q_Plugin::extra('Telegram', 'plugin', 'Users'); $apps = Q_Config::get('Users', 'apps', 'telegram', array()); foreach ($apps as $app) { if (!empty($extra[$app])) { continue; // already installed for this app } $extra[$app] = array('setWebhook' => true); $extra = Q_Plugin::extra('Telegram', 'plugin', 'Users', $extra); $token = Q::ifset($app, 'token', null); $secret = Q::ifset($app, 'secret', Q_Config::get('Q', 'internal', 'secret', '')); if (!$token) continue; $cert = Q::ifset($app, 'cert', null); if ($certfile) { $certificate(file_get_contents($cert)); } $url = Q_Request::baseUrl('telegram.php'); $secret_token = "$app\t$secret"; // will come in header X-Telegram-Bot-Api-Secret-Token $result = Telegram_Bot::setWebhook(@compact('token', 'url', 'certificate', 'secret_token')); if ($result['error']) { throw new Telegram_Exception_Webhook(@compact('app', 'url', 'token', 'certificate')); } } </pre> So now it registers webhooks that will call the controller @telegram.php@ h2. Handling updates Make @telegram.php@ controller call @Telegram_Dispatcher::dispatch($update)@ method when a request comes from a telegram bot. It's similar to how @index.php@ controller calls @Q_Dispatcher::dispatch($uri)@ when a web request comes in from a browser, but the dispatcher will be much simpler. @Telegram_Dispatcher::dispatch($update)@ should look at @header('X-Telegram-Bot-Api-Secret-Token')@ and @$parts = explode("\t", $header)@ to determine @$appId = reset($parts)@. Now do @$params = compact('appId', 'update')@. And call @Q::event("Telegram/update", $params)@ similar to how @Q_Dispatcher@ calls @Q::event("Q/response")@. The handler of @Telegram/update"@ event, in turn, would determine the update type (from a "growing list of types":https://core.telegram.org/bots/api#update such as "message" and "edited_message"), and then fire @Q::event("Telegram/update/$appId/$updatetype)", $params@ similar to how Q/response handler fires event @"$module/$action/response/$slotname@. So now, different plugins would be able to add handlers for these events. Suppose I had an app / bot on telegram with appId = "MyCoolBot" and internal appId "Calendars". Then as a developer of "Calendars" plugin module, I would implement events such as: * @Telegram/update/Calendars/message@ * @Telegram/update/Calendars/edited_message@ * @Telegram/update/Calendars/callback_query@ Artem can help you Please manually test at least these 3, by using the "inline keyboard code from our lesson":https://issues.qbix.com/projects/telegram/wiki/Lesson_1_Code h2. Implementing the actual bots Plugins will be able to implement any kind of complex logic to interact with a user. They might use @AI@ plugin with ChatGPT. They might query a database. They will probably store a context for each user, of what they remember about this user and conversation with him. But for now, we don't care what the plugins will do. We just built the support for them: installer, addWebhook, and handlers. For the end of this homework, I'd ask you to use @Telegram_Bot::sendVideo()@ method that Artem will implement. I mean, it's a simple method, that you can implement too. But I gave it to Artem to practice calling @sendVideo@, @sendDocument@, etc.