2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GoogleAppsScriptで発言した内容に応答するTelegram BOTを作る

Last updated at Posted at 2021-09-25

はじめに

この記事ではTelegramのBotに話しかけると、自分の名前を読んで応答してくれるBotについて解説します。

BOTアカウントの登録

@BotFatherに話しかけます。
GoogleAppsScriptでTelegram BOTを作る ~第1回 はじめてのTelegram BOT - Qiita を参考にしてください。

GASでスクリプトを作成する

@新しいSpreadsheetを作成するURLに飛びます。
Spreadsheetを開いたら、ツール→スクリプトエディタを開きます。
「無題のスプレッドシート」になっているので、そこは適当にわかりやすい名前に変えておきましょう。今回は「GAS Bot Test」とします。
Screenshot of GAS Bot test - プロジェクト編集者 - Apps Script.jpg

Botに発言させてみよう

Botに発言させるためにはTelegramのsendmessageというAPIを使用します。
APIの仕様はTelegram Bot API#sendmessageをみてください。これをみると、chat_id(発言するチャットルームのID)とtext(発言内容)が必須だとわかります。ここではチャットルームを新たに作成して、そこでBotに発言をさせてみましょう。
Telegramのクライアントを起動して、三 → New Groupをして適当に部屋を作ります。
チャットルームのIDを調べる方法はいくつかありますが、こここでは@RawDataBotを部屋に呼んでみましょう。そして、発言すると以下のような発言をすると思います。
この場合は-33333333がchat_idになります。

{
    "update_id": 814822145,
    "message": {
        "message_id": 851345,
        "from": {
            "id": 220219021,
            "is_bot": false,
            "first_name": "k32ru",
            "username": "k32ru",
            "language_code": "ja"
        },
        "chat": {
            "id": -33333333,  ←この部分です。
            "title": "bot test room",
            "type": "group",
            "all_members_are_administrators": true
        },
        "date": 1632575759,
        "text": "test"
    }
}

チャットルームのIDがわかったら、Botに発言するために、GASに以下を書いて見ましょう。

//以下2行は自分のに変更してください。
const botToken = "2007692564:xxxxxxxxxxx"
const chat_id = "-33333333"
const telegramUrl = "https://api.telegram.org/bot" + botToken;


function hello(){
  sendText(chatid,"こんにちは!")
}
function sendText(id,text) {
  let url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + text;
  Logger.log(url);
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

コードを書いたら、コードを保存して、helloを選択して実行してみましょう。
実行したら、下に実行ログが出てきます。
最初の一行はLogger.log(url);の部分で、URLを組み立てたものを表示しています。
2行目はそれをTelegramサーバに送った結果を表示しています。"ok":trueとなっているので成功です。
部屋にも発言はされましたか?

	https://api.telegram.org/bot2007692564:xxxxxxxxxxx/sendMessage?chat_id=-33333333&text=こんにちは!
	{"ok":true,"result":{"message_id":3,"from":{"id":2044451845,"is_bot":true,"first_name":"k32ruk32ru","username":"k32ruk32ru_bot"},"chat":{"id":-33333333,"title":"bot test room","type":"group","all_members_are_administrators":true},"date":1632576114,"text":"\u3053\u3093\u306b\u3061\u306f\uff01"}}

今回の処理概要を図に書くとこんな感じです。
Screenshot of GASでTelegramBotを作成する方法(基礎編) - Google スライド.jpg

Botに応答してもらおう

いきなりですが、概略図を表示します。
今回の処理として必要なのは
①TelegramのBotを受け取って、それをGASに送る設定が必要です
②GASではそのデータを処理して、発言した人の名前を取り出します。
③発言した人の名前とチャットルームのIDを取り出して、TelegramのAPIを使って送信します。

image.png

①TelegramのBotを受け取って、それをGASに送る設定

Botの設定変更

TelegramのBOTは初期設定では、コマンド(/chatid 等/から始まる発言)しか受け取れません。つまり、チャットルームで「こんにちは」と発言しても、Botはその発言を拾う事ができません。
@BotFatherに話して/setprivacyと発言します。Choose a bot to change group messages settings(どのBOTの設定を変えるのか?)と聞かれるので、変更したいBOTを選びます。

'Enable' - your bot will only receive messages that either start with the '/' symbol or mention the bot by username. BOTは/とユーザからのメンテンションしか受け取れないよ
'Disable' - your bot will receive all messages that people send to groups.  BOTは発言した内容を受け取れるよ
Current status is: ENABLED

今回は、Disableと発言します。Success! The new status is: DISABLED. /helpと出れば成功です。

WebHook設定

BotがGASにデータを送るためには、送り先を決めなくてはいけません。そのために、GASをウエブアプリケーションとして動作させます。
上の青いボタンで「デプロイ」をクリックします。
image.png
「新しいデプロイ」を選択し、⚙から「ウエブアプリ」を選びます。
image.png
new deploy.png
説明を入れる箇所がでますが、いれなくても大丈夫です。アクセスできるユーザを「全員」にしてから「デプロイ」を押します。
以下のような画面になるので、ウエブアプリのURLをコピーします。
image.png
以下のコードを入力して、setWebhookを実行します。{"ok":true,"result":true,"description":"Webhook was set"}と出れば成功です。

var webAppUrl = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec"
function setWebhook() {
  let url = telegramUrl + "/setWebhook?url=" + webAppUrl;
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

ちなみに、WebHookを削除する場合には以下のようにurlのパラメータを空にします。

function delWebhook() {
  let url = telegramUrl + "/setWebhook?url=" + "";
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

また、現状何が設定されているのかわからなくなったら、以下を実行すると現状されているWebHookのURLがわかります。

function getWebhookInfo() {
  let url = telegramUrl + "/getWebhookinfo";
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

②GASで受けとデータを処理して発言した人の名前を取り出す

①でWebHookを設定したことにより、データはTelegramから届くようになりましたが、GASでデータを処理する必要があります。GASではdoPost(e)でデータを受け取ります。eに受信したデータが含まれています。届いたデータは以下のようになります。このようなデータの形はJSONと呼ばれており、データのやり取りによく使われる形式です。このデータを処理をして必要な情報を取り出します。

    "queryString": "",
    "parameter": {},
    "postData": {
        "contents": "{\"update_id\":265255108,\n\"message\":{\"message_id\":4,\"from\":{\"id\":220219021,\"is_bot\":false,\"first_name\":\"k32ru@Hiroshima,JPN\\ud83c\\uddef\\ud83c\\uddf5\\ud83d\\udc89\\ud83d\\udc89\",\"username\":\"k32ru\",\"language_code\":\"ja\"},\"chat\":{\"id\":220219021,\"first_name\":\"k32ru@Hiroshima,JPN\\ud83c\\uddef\\ud83c\\uddf5\\ud83d\\udc89\\ud83d\\udc89\",\"username\":\"k32ru\",\"type\":\"private\"},\"date\":1632559782,\"text\":\"test\"}}",
        "length": 388,
        "name": "postData",
        "type": "application/json"
    },
    "parameters": {},
    "contentLength": 388,
    "contextPath": ""
}

Telegramの発言内容はpostDatacontentsの中にあります。なので以下のようにして、一旦dataという変数に発言内容を入れます。

var data = JSON.parse(e.postData.contents);

今度はdataの中身はどのようになっているのかというと例としては以下のようになっています。

{
    "update_id": 814821658,
    "message": {
        "message_id": 851230,
        "from": {
            "id": 220219021,
            "is_bot": false,
            "first_name": "k32ru@Hiroshima,JPN",
            "username": "k32ru",
            "language_code": "ja"
        },
        "chat": {
            "id": -510239868,
            "title": "bot test room",
            "type": "group",
            "all_members_are_administrators": true
        },
        "date": 1632569162,
        "text": "\u3053\u3093\u306b\u3061\u306f" //こんにちは
    }
}

なので、以下のように必要な情報は取り出せます。

let data = JSON.parse(e.postData.contents);//発言を抽出  
let text = data.message.text;//発言内容 
let name = data.message.from.first_name;//発言者の表示名
let id   = data.message.chat.id//発言したチャットルーム

発言した人の名前とチャットルームのIDを取り出して、TelegramのAPIを使って送信する

Telegramにデータを送る部分についてはsendTextを使ったのでそれを利用します。
ユーザが発言した内容に対して、発言した人の名前をつけて応答すると以下のようになります。

function doPost(e) {
  //telegramからのデータ
  let data = JSON.parse(e.postData.contents);
  let text = data.message.text;
  let name = data.message.from.first_name;
  let id   = data.message.chat.id
  let answer = text  +  name + "さん!"
  sendText(id,answer);
  
}

ここまでできたら、動くかどうか試してみましょう。最初はデプロイ→新しいデプロイを選択しましたが、2回目以降は「デプロイを管理」を選択します。
なぜかというと、新しいデプロイにするとウエブアプリのURLが変わってしまうからです。コードではwebAppUrlで代入している部分が変わります。
そしたら、毎回WebHookを削除して、再度設定しないといけなくなるので、大変ですよね。
あとたまにあるのが、いつの間にか新しいウエブアプリのURLが出来ていて、WebHookでは古いURLを見ているためにソースを変えたはずなのに処理内容は古いままで頭を抱えるなんてこともあります。

「デプロイを管理」を選択肢、右上の✏をクリックします。
image.png
一番上にある「新バージョン」にして「デプロイ」を選びます。
image.png

これでデプロイは終わったので、さっそく試してみましょう。(非常に煽り耐性の高いBOTができました)
image.png

ここまでのソースを全部表示すると以下の様になります

const botToken = "2222222222:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const telegramUrl = "https://api.telegram.org/bot" + botToken;
const webAppUrl = "https://script.google.com/macros/s/yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy/exec"

const chat_id = "-33333333"
function getMe(){
  let url = telegramUrl + "/getMe"
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText)
}

function hello(){
  sendText(chat_id,"こんにちは!")
}
function sendText(id,text) {
  let url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + text;
  Logger.log(url);
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}
function setWebhook() {
  let url = telegramUrl + "/setWebhook?url=" + webAppUrl;
  let response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

function doPost(e) {
  //telegramからのデータ
  let data = JSON.parse(e.postData.contents);
  let text = data.message.text;
  let name = data.message.from.first_name;
  let id   = data.message.chat.id
  let answer = text  +  name + "さん!"
  sendText(id,answer);
  
}

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?