Telegram-ға bot жазамыз (jas.kz ava боты)

Көптен бері эксперимент жасауға қол тимей жүр еді. Сондай уақыт бүгін пайда болып бірінші назар Telegram боттарына түсті. Telegram-ның пайдаланушылар саны жақында 100 миллионнан асқанын оқыған боларсыздар. Ол не бағдарлама деп сұрасаңыздар «Whatsapp секілді, бірақ whatsapp-тан әлдеқайда ілгері кеткен мессенджер» деп жауап берер едім. Оның бағдарламалаушыларға ұнаған тұсы API-ның бар болуында, яғни мессенджерге боттар жазу мүмкіндігі. Соған орай қазір өте көптеген боттар бар (аудармашылар, анықтамалықтар және т.с.с). Telegram бағдарламалаушылары оны боттар революциясы деп те атап жүр.

Жай ғана «Hello world» жазу мүлдем қызық емес. Сондықтан да практикалық аз ғана болса да мағынасы бар нәрсе істеуді ойладым. Ең бірінші көзге түскен ол jas.kz онлайн аватарлар қызметі болды. Пайдаланушыдан сурет қабылдап, оның таңдауы бойынша суретті өңдеп беретін бот жазамыз.

Код жазуды бастамас бұрын, ботты телеграмның өзінде жасап алу керек. Ол үшін @BotFather (иә, иә, барлық боттардың әкесі) деп аталатын арнайы бот бар. Сол боттардың әкесінде ботты құрамыз:



Мұндағы негізгі мәлімет, ол — токен. Токен арқылы біз ботпен қарым-қатынас жасай аламыз (хат алу, хат жіберу). Токенді көшіріп бір жерге сақтап қойсаңыз болады.Боттардың адамдардан бірнеше айырмашылығы бар. Оның бірі, боттардың логині "_bot" деп аяқталады. Мен ботқа @JasAva деп ат қоя салдым. Жалпы мұнда қиын ештеңе жоқ. Егер қаласаңыз бот туралы бір-екі сөз жазып қойсаңыз да болады:



Бұл түсініктеме сөйлем ботты іздеу кезінде көрініп тұратын болады:



Енді бот толығымен қызметке дайын. Енді онымен қала қарым қатынас жасауға болады? Ол үшін core.telegram.org/bots/api парақшасына жүгінетін боламыз. Бұл бетте телеграм ботымен қандай әрекеттер жасауға болатыны жазылған. Барлық әрекеттер https сұраныс арқылы жүргізіледі. Сұраныстар келесі түрде болуы керек:
    https://api.telegram.org/bot<token>/METHOD_NAME


Мұндағы token дегеніміз, жоғарыда көшіріп алған токеніміз. Ал «METHOD_NAME» ботпен сөйлесу үшін қажетті методтар. Мысалы:
https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getMe


Мұндай сұраныс сізге боттың өзі туралы мәлімет беретін болады:
{
    "ok": true
    "result": {
        "id": 123456
        "first_name": "JasAva"
        "username": "JasAva_bot"
    }
}


Осы секілді келесі методтарды пайдалануға болады:
  • sendMessage — хат жіберу
  • forwardMessage — хатқа жауап беру
  • sendPhoto — сурет жіберу
  • sendAudio — дыбыс жіберу
  • sendDocument — файл жіберу
  • sendSticker — стикер
  • sendVideo — видео
  • getUpdates — жаңартылуларды алу
  • setWebhook — webhook орнату
  • getFile — файлды жүктеп алу үшін қажет

Енді пайдаланушымен қалай байланыс орнатамыз? Ол үшін бізге getUpdates методы қажет. Негізі чаттардан жаңартылуларды алудың екі әдісі бар:
  • getUpdates қайта-қайта орындау арқылы, жаңартуларды тексеріп, хаттарға жауап беріп отыру
  • webhook пайдалану

Webhook — ол чатта жаңартылу болған кезде телеграм шақыратын url. Яғни, бұл сіздің сервисіңіз. Біреу хат жазғанда сіздің осы сервисіңіз шақырылатын болады. Сөйтіп сіз тек өзгеріс болған кезде ғана жауап қайтара аласыз. Бірақ негізгі шектеу, ол webhook қауіпсіздік мақсатында https болуы керек. Менің қолымда дәл қазір https сервер жоқ, сондықтан да getUpdates әдісін пайдаланатын боламыз.

Ол үшін мынадай сұраныс жіберу керек:
https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getUpdates


Сонда сізге мынадай түрдегі нәтиже келеді:
{  
   "ok":true,
   "result":[  
      {  
         "update_id":472998850,
         "message":{  
            "message_id":3,
            "from":{  
               "id":148244324,
               "first_name":"Egemberdiev",
               "last_name":"Raimbek",
               "username":"skythet"
            },
            "chat":{  
               "id":148244324,
               "first_name":"Egemberdiev",
               "last_name":"Raimbek",
               "username":"skythet",
               "type":"private"
            },
            "date":1458275675,
            "text":"Тестілеу үшін хат"
         }
      },
      {  
         "update_id":472998851,
         "message":{  
            "message_id":4,
            "from":{  
               "id":148244324,
               "first_name":"Egemberdiev",
               "last_name":"Raimbek",
               "username":"skythet"
            },
            "chat":{  
               "id":148244324,
               "first_name":"Egemberdiev",
               "last_name":"Raimbek",
               "username":"skythet",
               "type":"private"
            },
            "date":1458275676,
            "text":"Екінші хат"
         }
      }
   ]
}


Бір жаңартылулар қайта-қайта келе бермес үшін getUpdates методында offset мәнін көрсетуге болады, мысалы:

https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getUpdates?offset=472998851

{  
   "ok":true,
   "result":[
      {  
         "update_id":472998851,
         "message":{ ... }
      }
   ]
}


Келген мәліметтердегі хаттарды қарай отырып сіз не істеу керектігін шеше аласыз. Пайдаланушыға хат жібересіз бе немесе келген мәліметтерді деректер қорына сақтап онымен бір жұмыс жасайсыз ба, өзіңіз білесіз. Болды, бар керек логика осы, өте қарапайым және кез-келген тілде іске асыру оңай. Шектеу тек бағдарламаушының уақыты мен фантазиясында ғана болса керек.

Оңай болғандықтан ба көптеген тілдерге әлдеқашан арнайы sdk-лар бар. Олар арқылы сіздің жұмысыңыз мүлдем жеңілдеп кетеді. Jas.kz ботын жазу үшін де мен мына sdk-ны пайдаландым: github.com/irazasyed/telegram-bot-sdk. Енді мен толық кодты келтірудің орнына жай ғана қалай жасалғанын сипаттап өтетін боламын (өйткені, ботты әрі қарай жетілдіру ойымда бар). Ең бірінші клиентті мына түрде құрып алу керек:
    $this->telegram = new Api('токен');


Жоғарыда айтқанымыздай ең бірінші істейтін әрекетіміз, ол жаңартылуларды алу:
    $response = $this->telegram->getUpdates(array('offset' => $this->_getUpdateOffset()));


Енді жаңартылуларды циклда қарап шығып пайдаланушыға жауап береміз:
    $lastUpdateID = 0; // бір келген жаңартылуларды қайта алмас үшін offset мәнін сақтап отырамыз
    foreach ($response as $update) {
        $lastUpdateID = $update->getUpdateId();
        $message = $update->getMessage();

        // егер пайдаланушы сурет жіберген болса
        // суретті сақтап алып
        // оған шаблон таңдау керектігін ұсынамыз
        if($message->getPhoto() != null) {
            $this->_saveUserImage($update->getMessage()); // мұнда суретті сақтаймыз
            $this->telegram->sendMessage(array(
                'chat_id' => $message->getChat()->getId(),
                'text' => 'Суретіңіз қабылданды, енді қажет шаблонды таңдаңыз'
            ));
            continue;
        };

        // ал егер пайдаланушы мына сөздердің 'ава', 'жаңа ава', 'жаңа ава жаса', 'аватар', 'маған жаңа ава жаса'
        // бірін терсе, оған сурет күтіп жатқандығымызды айтамыз
        if (in_array(mb_strtolower($message->getText()), $this->newAvaCommands)) {
            $this->telegram->sendMessage(array(
                'chat_id' => $message->getChat()->getId(),
                'text' => 'Жарайды, онда аватар жасау керек суретіңізді жіберіңіз'
            ));
        }

        // егер пайдаланушы шаблон нөмерін жіберсе, онда
        // алдын келген суретті jas.kz/ava сайты арқылы
        // өңдеп, пайдаланушыға жібереміз
        if (is_numeric($message->getText())) {
            $template = intval($message->getText());
            if ($template >= 1 && $template <= 18) {
                $this->_sendUserAva($message, $template);
            } else {
                $this->telegram->sendMessage(array(
                    'chat_id' => $message->getChat()->getId(),
                    'text' => 'Мен мұндай шаблонды білмеймін'
                ));
            }
        }
    }
    if ($lastUpdateID != 0) {
        $this->_setUpdateOffset($lastUpdateID);
    }


Осы біздің ботымыздың бар логикасы. Бірақ кодтың былапыттау екені айтпаса да түсінікті. Егер бұдан күрделірек бот жазсаңыз логиканы құрудың басқа әдісін қарастыру қажет. Сурет қалай жүктеп алынды, файлды қалай жүктеуге болады деген секілді сұрақтарды келесі жолы қарастырамыз. Осындай қысқа және былапыт код арқасында мынадай нәтиже алынды:


  • +1
1 пікір
kamyrov
Раимбек, енді керісінше мем генератор ботты жасап көрші), ең танымал мемдердің суреттерін салғызып, мәтінді енгізу арқылы мем жасап берсін)
Тек тіркелген қолданушылар ғана пікір қалдыра алады.