Telegram(テレグラム)上で動くbotをPythonで作ってみた
プッシュ通知

Telegram(テレグラム)とは

Telegramは、スマートフォンやパソコンで使える無料のメッセージアプリです。LINEなどと同様、ユーザー同士での個別チャット、グループチャット、音声通話、ファイルや写真の共有が可能です。一般的なメッセージアプリよりもメッセージの暗号化に注力されており、プライバシーを重視する方にとって有用です。

加えてTelegramは、2018年に独自のブロックチェーンプラットフォーム『TON(Telegram Open Network)』を開発しましたが、規制の問題により2020年にプロジェクトを中止しました。TONは2021年8月にTON(The Open Network)に改名され、Telegramとは独立した運営チームであるTON財団へプロジェクトが引き継がれました。

Telegram botとは

Telegramはオープンソースのため、iOS、アンドロイド、デスクトップ等の全てのアプリケーションのソースコードが閲覧可能となっています。ソースコードの一覧はこちらのTelegram公式ページに記載されています。

このような特徴を活用し、ユーザーはボットやカスタムAPIを使用して独自の機能を開発することが可能となっています。その中で最も手軽に実装できるのが、Telegram botです。

Telegram botは、Telegram上で動作する自動化されたアカウントです。Telegram botはユーザーとの対話や特定のタスクを自動的に実行するためにプログラムされています。

タスクの具体例としては、リマインダーの設定、相場情報の検知と共有、などが挙げられます。今回の記事では、関心のあるトピックやキーワードに関連するニュースを教えてもらうようなbotを作成してみたので、その作成過程を共有します。

Telegram botの作成方法

BotFatherをチャットに追加する

まずは自身のプログラムからBotにアクセスするためのトークンを取得します。

トークンの取得は、Telegram botを作成するためのbot『@BotFather』を用いて行います。

まずはTelegramのチャットに@BotFatherを追加します。

botのAPIトークンを取得する

BotFatherを追加して会話をスタートさせたら、/newbotコマンドを実行しましょう。

この操作で新しいbotの作成処理が開始されます。そうするとbotの名前の設定に移りますので、設定したいbot名を入力してください(以下の例では、今回はtest botと設定しています)。

最後にbotのユーザー名の設定をして完了です(ユーザー名はTelegram上の全てのユーザーやbotにおいて一意に定まらなければなりません。以下の例では、test_aiueo_botと設定しています)。

ここまでの操作を行うと、トークンが発行されます。

上記の画像の矢印で示した部分がトークンです。

トークンを用いてプログラムを書く

上記の手順に従うことで、Botにアクセスするためのトークンが取得できます。

後はお好みのプログラミング言語で、行いたい処理を書き、デプロイしましょう。

Telegram Bot作成時に参考にする公式ドキュメント上では、Java、C#、Python、Go、TypeScriptでのチュートリアルボットの実装例が紹介されています。

ニュース検索botを作ってみた

動作環境

Microsoft Windows バージョン22H2

Python 3.10.4

Telegram bot API 7.4

作成したbotの概要

ユーザーにトピックやキーワードを入力してもらうことで、関連するニュース情報を返信するTelegram botを作成してみました。

作成に必要な処理

NewsAPIのAPIキーを取得する

ニュースの取得に際して、NewsAPIというAPIサービスを利用します。

会員登録とログインをすると、APIキーを取得できます。

1日1000回のAPIリクエストが可能となっており、ログイン後のページでは簡易的なダッシュボートの閲覧が可能です。

処理機構を書く

今回のbotの処理は、3つのPythonファイルにより動作しています。

個別具体的なコードの解説は行いませんが、要点をかいつまんで紹介していきます。

※本記事で紹介しているTelegram botは、ローカルのPCをサーバーとして使用する想定です。

そのため、セキュリティの観点からは不適切なコードの記載方法がありますのでご了承ください。

まずメインの処理機構(main.py)のコードは以下の通りです。

Telegram上での動作(ユーザーが入力したメッセージの取得、それに対する返信)をメインに記載しています。

import requests
import time
import json
from news_file import get_news_from_keyword, get_news_from_topic
import sys

# Saved in local file
import keys

# Get Telegram key, Saved in another file
telegram_key = keys.get_telegram_key()
base_url = 'https://api.telegram.org/bot' + str(telegram_key)

offset = 0

while True:
    try:
        url = base_url + '/getUpdates' + '?timeout=500&offset=' + str(offset)
        res = requests.get(url)
        res.raise_for_status()

        result_json = res.json()

        if 'result' not in result_json:
            print("No 'result' in response")
            time.sleep(1)
            continue

        if len(result_json['result']) == 0:
            continue

        result = result_json['result'][0]
        text = result['message']['text']
        

        # ending operation
        if text.lower() == 'end':
            break

        if text.lower().startswith('keyword'):
            keyword = text.split(' ')[1:]
            keyword = "%20".join(keyword)
            to_send = get_news_from_keyword(keyword)
        
        elif text.lower().startswith('topic'):
            topic = text.split(' ')[1:]
            topic = '%20'.join(topic)
            to_send = get_news_from_topic(topic)
        
        else:
            to_send = '\nニュース取得botの使い方📰\n\n'\
                '関心のあるトピックを"topic Topic_Name"の形式で入力してください。\n'\
                '入力例:『topic bitcoin』 \n\n\n'\
                '特定のキーワードで探したい場合は"keyword key"の形式で入力してください \n'\
                '入力例 : 『keyword telegram』 \n'

        sender = str(result['message']['from']['id'])
        username = result['message']['from'].get('username', 'No username')
        
        monitoring = f"{text} from @{username} (ID: {sender})"
        print(monitoring)
        
        if isinstance(to_send, str):
            reply_url = base_url + '/sendMessage?chat_id=' + str(sender) + '&text=' + str(to_send)
            requests.get(reply_url)
        
        elif isinstance(to_send, list):
            if len(to_send) == 0:
                header = str(text) + 'に関連したニュースは見つかりませんでした🥲'+'\n\n別のキーワードで探してみてください。'
                reply_url = base_url + '/sendMessage?chat_id=' + str(sender) + '&text=' + str(header)
                requests.get(reply_url)
            else:
                header = 'Top ' + str(len(to_send)) + ' results for you'
                reply_url = base_url + '/sendMessage?chat_id=' + str(sender) + '&text=' + str(header)
                requests.get(reply_url)

                for reply in to_send:
                    reply_url = base_url + '/sendMessage?chat_id=' + str(sender) + '&text=' + str(reply)
                    requests.get(reply_url)

        offset = result['update_id'] + 1

    except requests.exceptions.RequestException as e:
        print(f"HTTP error: {e}")
        time.sleep(1)

    except KeyError as e:
        print(f"Key error: {e}")
        time.sleep(1)

    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        time.sleep(1)

main.py内でインポートしているnews_file.pyのコードは以下の通りです。

キーワードまたはトピックに基づくニュース記事の取得を行っています。

import requests
import json

# Saved in local file
import keys


# Get NewsApi Key, Saved in different file
news_api_key = str(keys.get_news_api_key())
headers={'X-Api-Key':news_api_key}


def get_news_from_keyword(keyword):
    news_url = 'https://newsapi.org/v2/everything?language=en&q='+keyword

    response = requests.get(news_url,headers=headers).text
    response = json.loads(response)['articles']
    return_list=[]
    for r in response:
        source=r['source']['name']
        author=r['author']
        title=r['title']
        url=r['url']
        return_list.append('\n\nサイト名: '+str(source)+'\n著者 :'+str(author)+'\n記事タイトル: '+title+'\n\n記事リンク: '+str(url))
    if len(return_list)>3:
        return return_list[:3]

    return return_list

def get_news_from_topic(topic):
    
    news_url = 'https://newsapi.org/v2/everything?language=en&qInTitle='+topic
    response = requests.get(news_url,headers=headers).text
    response = json.loads(response)['articles']

    return_list=[]
    for r in response:
        source=r['source']['name']
        author=r['author']
        title=r['title']
        url=r['url']
        return_list.append('\n\nサイト名: '+str(source)+'\n著者 :'+str(author)+'\n記事タイトル: '+title+'\n\n記事リンク: '+str(url))
    
    if len(return_list)>3:
        return return_list[:3]
    
    return return_list

同じくmain.py内でインポートしているkeys.pyのコードは以下の通りです。

NewsAPIのAPIキーとTelegram botのトークンを記載し、main.pyとnews_file.pyに渡す(厳密には呼び出してもらう)役割のコードです。

news_api_key = 'ここにNewsAPIのAPIキーを入力する'
telegram_key = 'ここにBotのトークンを入力する'

def get_news_api_key():
	return news_api_key

def get_telegram_key():
	return telegram_key

終わりに

今回の記事では、Pythonを使ってTelegramボットを作成し、特定のキーワードやトピックに基づいてNews APIからニュース記事を取得する方法について説明しました。

このbotはより高度なカスタマイズを実装することも可能であり、具体的には以下のような機能が考えられます。

  • ニュースのカテゴリ選択機能の追加
  • ニュースの要約表示
  • マルチリンガル対応

Telegram botの開発は初心者でもとっつきやすいため、初学者のアウトプットの場としては最適だと思います。この記事を読んで関心を持った方は、ぜひTelegram bot作成にチャレンジしてみてはいかがでしょうか。

運営者情報

Stir lab運営元のSTIR (スター)は、ETHERSECURITY PACIFIC HOLDINGS PTE. LTD.(本社:シンガポール、代表取締役:加門昭平)及びその100%子会社である株式会社イーサセキュリティ(本社:東京都渋谷区、代表取締役:加門昭平、紫竹佑騎)が運営するWeb3 Consulting & Development Teamです。

 

X (Twitter)@Stir_Network_JP

LinkedInhttps://www.linkedin.com/company/14613801

運営元https://stir.network/

Twitterでフォローしよう

おすすめの記事