הטלגרם בוט הראשון שלי

04/10/2018

השבוע כתבתי לראשונה בוט טלגרם (זמין בקוד פתוח - קישור בהמשך הפוסט) אז אם גם אתם מתכננים או מחפשים דרך קלה לגשת לזה מקווה שהפוסט הזה ייתן לכם מוטיבציה.

1. לכתוב בוט לטלגרם זה ממש קל

הדבר הראשון שכדאי לדעת על פיתוח Telegram Bot זה שמדובר בסיפור ממש קל למי שיודע לכתוב קוד (והאמת גם למי שלא יודע לכתוב קוד - כי יש כלי Drag & Drop חמודים אבל הם לא כזה מעניינים כאן). הבוט הוא בסך הכל תוכנית מחשב שמתקשרת לשרת של טלגרם ומושכת ממנו רשימת עדכונים.

בנוסף יש לטלגרם API דרכו בוט יכול לשלוח הודעות למשתמשים, לקבוצות או לערוצים ולענות לבקשות שהגיעו אליו.

בגלל הבחירה שלהם שהבוט ימשוך את העדכונים שרלוונטים עבורו אין כמעט עבודת הכנה: אתם לא צריכים להרים שרת, לא צריכים להאזין להודעות מטלגרם ובטח לא צריכים לדאוג מה אם הבוט יתרסק. במקום זה הבוט עולה, שואל מה חדש, עונה לכמה משתמשים ויכול לרדת חזרה או להישאר ולהמשיך למשוך הודעות ב Long Polling.

2. איזה שפה שתרצו

לטלגרם יש די הרבה דוגמאות בקוד פתוח ותבניות לבוטים במגוון עצום של שפות תכנות. אפשר למצוא אותם כאן:

https://core.telegram.org/bots/samples

בשבילכם אדביק כאן קוד של שני בוטים פשוטים בפייתון וב JavaScript מתוך דפי הדוגמאות. נתחיל עם פייתון:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Simple Bot to reply to Telegram messages.

This is built on the API wrapper, see echobot2.py to see the same example built
on the telegram.ext bot framework.
This program is dedicated to the public domain under the CC0 license.
"""
import logging
import telegram
from telegram.error import NetworkError, Unauthorized
from time import sleep


update_id = None


def main():
    """Run the bot."""
    global update_id
    # Telegram Bot Authorization Token
    bot = telegram.Bot('TOKEN')

    # get the first pending update_id, this is so we can skip over it in case
    # we get an "Unauthorized" exception.
    try:
        update_id = bot.get_updates()[0].update_id
    except IndexError:
        update_id = None

    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    while True:
        try:
            echo(bot)
        except NetworkError:
            sleep(1)
        except Unauthorized:
            # The user has removed or blocked the bot.
            update_id += 1


def echo(bot):
    """Echo the message the user sent."""
    global update_id
    # Request updates after the last update_id
    for update in bot.get_updates(offset=update_id, timeout=10):
        update_id = update.update_id + 1

        if update.message:  # your bot can receive updates without messages
            # Reply to the message
            update.message.reply_text(update.message.text)


if __name__ == '__main__':
    main()

הפונקציה המרכזית של הבוט נקראת echo. הפונקציה רצה על כל העדכונים שהבוט קיבל מטלגרם ועבור כל עדכון בודקת אם מדובר בהודעה, ואם כן שולחת כתשובה את הטקסט המקורי של ההודעה. הבוט הזה פשוט יהדהד חזרה כל משפט שתגידו לו.

הדבר הכי נחמד שבשביל להפעיל את הבוט אין צורך להרים שרת או שום דבר בסגנון. מדובר על קובץ py יחיד שברגע שאתם מפעילים אותו הוא מתחבר לטלגרם ונשאר פועל כדי לקבל עדכונים נוספים בלולאה.

ב JavaScript הקוד נראה ממש דומה ואפילו יותר קצר:

const TeleBot = require('telebot');
const bot = new TeleBot('TELEGRAM_BOT_TOKEN');
bot.on('text', (msg) => msg.reply.text(msg.text));

bot.start();

התשתית של הבוטים לנוד מבוססת על כתיב אסינכרוני ולכן כל המעבר על העדכונים קורה מאחורי הקלעים.

בשני המקרים תצטרכו להפעיל את הבוט שלכם עם משהו שנקרא Telegram Bot Token. זה קוד סודי שמאפשר לתוכנית להזדהות בתור הבוט שיצרתם. אתם מקבלים אותו באמצעות פניה לבוט של טלגרם שנקרא BotFather. פשוט שלחו לו הודעה והוא כבר ייצור בשבילכם בוט וישלח בתגובה את המזהה הזה. כדאי כמובן להקפיד לשמור את המזהה הזה בסוד ולכן בתוכנית אמיתית לא תרצו לשמור אותו יחד עם קוד הפרויקט.

3. הבוט שלי: יודע לשלוח את הפוסט היומי אליכם לטלגרם

אז חשבתי לנצל את ההזדמנות של הבוטים ולכתוב אחד בשפה שאני פחות מכיר כדי ללמוד וככה הגעתי לכתוב בוט לטלגרם באליקסיר. כרגע אתם יכולים לשלוח לבוט הודעה והוא ישלח לכם קישור לפוסט החדש ביותר בבלוג. הבוט נקרא @TocodeBot אם בא לכם לקשקש איתו.

עיקר הקוד של הבוט נראה כך:

  command ["daily"] do
    url = "https://www.tocode.co.il/blog"
    headers = ["Accept": "application/json; Charset=utf-8"]
    options = [hackney: [pool: :default]]

    with {:ok, response} <- HTTPoison.get(url, headers, options),
         {:ok, appstate} <- Poison.decode(response.body),
         %{ "blog" => %{ "posts" => [%{"href" => href} | _] } } <- appstate do
           send_message "Your daily read: https://www.tocode.co.il#{href}"
    end
  end

יש פה פניה ב HTTP לשרת של ToCode כדי לקבל JSON עם רשימת הפוסטים החדשים, פיענוח של ה JSON ושליפת ה URL של הפוסט החדש ביותר ושליחת הודעה חזרה למי שפנה עם קישור לפוסט.

אם בא לכם להסתכל על הקוד המלא או להציע רעיונות נוספים מוזמנים לגיטהאב של הבוט בקישור:

https://github.com/ynonp/tocode_bot

4. מה עוד בוט יכול לעשות

לטלגרם יש עוד המון פונקציונאליות שלא התחלתי להסתכל עליה, בין השאר:

  1. בוטים יכולים לשחק משחקי HTML5 (בתוך הממשק של טלגרם).

  2. בוטים יכולים לקבל תשלום מלקוחות.

  3. בוטים יכולים לשאול שאלות, להציג רשימת תשובות ולהתיחס לתשובות של כל משתמש.

  4. בוטים יכולים לשלוח סטיקרים או תמונות מדליקות.

  5. בוטים יכולים להצטרף לקבוצה ולענות שם באופן אוטומטי להודעות שנשמעות להם מעניינות (ואפשר מתוך קוד הבוט להקשיב לכל ההודעות שעוברות בקבוצה ולהתיחס לאלה שנשמעות מעניינות).

  6. בוטים מקבלים עדכונים כשקורים דברים מעניינים מסביבם - למשל כשמשתמש חדש מצטרף לקבוצה.

  7. בוטים יכולים להאזין להודעות דרך Web hooks במקום למשוך עדכונים, מה שעוזר להם להגיב יותר מהר ולשרת שלכם להיות פחות עמוס אם אתם מפעילים המון בוטים.

הצעד הבא מבחינת הבוט שלי יהיה להבין איך לסנכרן בין הבוט לבין האותנטיקציה באתר כך שתוכלו לבצע פעולות באתר באמצעות שיחה עם הבוט - לדוגמא תוכלו לספר לבוט שאתם רוצים להצטרף לוובינר השבועי ובאופן אוטומטי הבוט ירשום אתכם.

ומה אתכם? יש לכם רעיון לבוט טלגרם שיכול לעזור לכם בחיים? או יותר טוב - רוצים לנסות לכתוב בוט ולהעביר על זה וובינר? ספרו בתגובות או במייל חוזר.