feature image

2024年12月19日 | ブログ記事

Hubotであそぼ

この記事はアドベントカレンダー2024 19日目の記事です。

こんにちは、@Hueterです。
こたつにでぬくぬくしながらこのブログ記事を書いているのですが、手だけはキンキンに冷えております。
つらいね。

まえおき

裏話

紆余曲折があり...(暇な人だけ読んでください)

そう、あれは先輩と飯を食べているとき...
アドベントカレンダー担当なのにブログ記事を書かないのはどうなのかと思い、今まで作ってみたいと思って放置していたBOT製作をしてみることに。

BOTを作るにしても、GoやPython、Rustなど様々な言語がありますが決められなかったので先輩にいろんな言語を出してもらってそこからランダムに選ぶことに。

結果...

本当にランダムなのか疑いたくなりましたね。まあ運命ということで。

ということでJavascriptのHubotでBOTを作ります

...これまでの流れは何だったのかって?いや、これには水たまりよりも浅く砂山よりも低い理由があったりなかったり。
C++のBOTはtraPの先輩で既に作っている人がいたのですが、その人が残したWikiに怖い一言が。

俺はどうしてもC++を使ってtraQbotを作りたいんだという奇特な方でなければ別の言語を使って作ることをおすすめします
他の言語での開発の方が絶対に楽です 主に環境構築の面で

これを見て、はじめてのBOT作成でこれに手を出すべきなのか?という考えになってしまい、その上復活のHubot?とかいう気になる記事を見つけてしまったので、Hubotを作る機運になってしまいました。(後でこの先輩から「Wikiにはこう書いたけど、多分そんなつらくないよ」と言われたのですがすでに方向転換した後でした。)C++のBOTはまたの機会にやるかもです。

本題

Hubotというものを使ってBOTを作っていきます。BOTはtraP内SNSのtraQとDiscordの二つについて作ってみました。ただ、こちらはBOTのセットアップまでの記事なので「Hubotはもう動かせて高度なことがしたいよ」って人は他の記事を参考にしてください。

また、様々なサイトでいろんなコマンドを実行してインストールしていたので、余計なものや抜けているものがあったりするかも知れません。そのことを頭の片隅にでも置いて見てください。

開発環境

BOTを動かすサーバーはtraPの内製サービスであるNeoShowcaseを使っていきます。そのため、サーバー周りの設定はあまり参考にならないかもしれません。NeoShowcaseについてもっと知りたい方は以下の記事を見てください。
【NeoShowcase】traPには内製の作品公開プラットフォームがあります

Hubotとは

Hubot
Hubot(ひゅぼっと)は、GitHub社が開発した、オープンソースのボットフレームワークです。2011年10月26日にv1.0.0がリリースされて、日本では2016-2017年ごろにブームを迎えていましたが、いつの間にか忘れられてCoffeeScriptとともに表舞台から消え去っていたらしいです。メンテナンスも2019年4月17日のv3.3.2以降完全に停止していましたが、突如2023年4月18日にv3.4.0がリリースされ、そこから怒涛の開発が行われていました。v11.0.0にて完全にCoffeeScriptが廃止され、今やv11.xまで来ています。何があったんでしょうね?

そんなこんなで、いろいろ変わった(かもしれない)Hubotをせっかくだし触ってみようということでBOT作っていきまっしょい。

BOTを作る

インスタンスの作成

公式のドキュメント Getting Started With Hubot を参考にやっていきます。
これからの操作はNode.jsとnpmが必要なので、見ながら作業したい人はこれらを入れてきてください。ここでNode.jsのバージョンをv23.xにするとExperimentalWarningが出てしまうのでv20.xでやることをお勧めします。

まず、今回の作業ディレクトリを作って移動します。このディレクトリ内でnpm initを実行しpackage.jsonを作成します。

$ mkdir -p /path/to/hubot # hubotである必要はない 好きな場所・名前のディレクトリでOK
$ cd /path/to/hubot
$ npm init

mkdir-pオプションは、複数階層のディレクトリを同時に生成することができるオプションです。
npm initを実行すると以下のように入力を求められるので必要に応じて入力してEnter。

package name:            # デフォルトで今のディレクトリ。基本エンター押すだけでいい
version: (1.0.0)         # このBOTのバージョン
description: hubot test  # このBOTの説明
git repository: git@github.com/.... # gitのリポジトリ なければそのままEnter
author: Hueter          # 制作者の名前
license: (ISC)           # そのままEnterでよい

ここまで入力できたら一旦ディレクトリの階層を一つ上がった後、npx hubot --create {directory-name}でHubotインスタンスを作成します。この時に--adapter {adapter-name}を最後に追加することで様々なチャットサービスに対応したBOTを作ることができます。

$ cd ..
$ npx hubot --create myhubot --adapter @hubot-friends/hubot-discord

SlackやDiscordのアダプタはHubotのREADMEにあるので必要に応じて変更してください。traQのアダプタは先輩が作成したhubot-traqを利用していきました。ありがたい。ひとまず今後はDiscordのBOTを作っていく前提で話を進めていきます。

これでBOTの大枠ができましたが、package.json内に追加で以下のコードを追加します。

{
  ...,
  "engines": {
    "node": "20.x"
  },
  ...
}

また、今回のBOT作成では使わないpackageが入ってしまっているので消していきます。具体的には、package.json内のdependenciesからhubotとアダプタ以外を消し、external-scripts.json[]の中身を全削除します。その後、npm installを実行することでpackage-lock.jsonpackage.jsonと同期させます。これで良し。

今回はこれでいいですが、他のpackageを利用したい場合はnpm install {package-name}でインストールした後external-scripts.json内にpackage名を列挙すればいいです。npm search hubot-scripts githubを実行するとコミュニティでメンテナンスされている数多くのスクリプトを検索できるので興味があれば調べてみてください。

今までの変更を加え、以下のようになっていればOKです。順番が逆になっているとかは気にしなくて大丈夫です。

{
  "name": "myhubot",
  "version": "1.0.0",
  "description": "A simple helpful robot for your Company",
  "main": "index.js",
  "scripts": {
    "start": "hubot --adapter @hubot-friends/hubot-discord",
    "test": "node --test"
  },
  "keywords": [],
  "author": "Hueter",
  "license": "ISC",
  "dependencies": {
    "@hubot-friends/hubot-discord": "^4.0.4",
    "hubot": "^11.3.2"
  },
  "engines": {
    "node": "20.x"
  }
}

仮スクリプトを書く

hubot/docs/Scriptingを参考にやっていきます。
スクリプトは./scriptsというディレクトリ内に記述していきます。今までの操作をしていればすでにディレクトリが存在し.mjsファイルがあるのでそのファイルを編集してもいいですし新たに作成しても大丈夫です。ファイル形式は.js.mjsが対応していますが今回は
.mjsで書いていきます。.js.mjsで少し記法が異なるので.jsで書こうとしている人は注意してください。

基本的なコード構造は以下のようなものです。初めにあるコメントアウトされている部分などは消しても何とかなりはしましたがひとまず残しておきます。

'use strict'

// Description:
//   Test script
//
// Commands:
//   hubot helo - Responds with Hello World!.
//
// Notes:
//   This is a test script.
//

export default async (robot) => {
  // your code here
}

新たなコードはexport default async (robot) =>{ ... }の中に書き加えていきます。

ひとまず動作確認のために以下のように変更します。

...
...

export default async robot => {
  robot.respond(/hoge$/i, async res => {
    await res.reply("fuga");
  });
  robot.respond(/ping$/i, async res => {
    await res.reply("pong");
  });
}

手元でBOTを起動

ここまで出来たら、一度手元でBOTを動かしてみましょう。npx hubotで起動できます。ただ、おそらくHubot> {"level":50,"time":...}と出てきますがEnterを一度押してHubot> の状態にしましょう。このエラーメッセージは出ても気にしなくても大丈夫です。この状態でhogepingと打ちEenterで送信するとそれぞれfugapongと返って来ます。こんな感じにBOTの動作を確認できます。

余談

エラーメッセージについて、消さずとも動作はしますが、とりあえず私が遭遇したエラーメッセージについて消し方を載せておきます。Hubot> {"level":50,"time":...}msgの中にエラーメッセージがあるのでそこを見てください。

using deprecated documentation syntax

ES2015 で Hubot のスクリプトを書くと using deprecated documentation syntax って怒られる件について
つまるところmain.mjsの最初に以下を追加するだけです。Commandsの中身は空でもいいですし、下みたいにふざけてもエラーメッセージは消えます。また、Commandsである必要もなさそうでDescriptionやNotesでも大丈夫でした。詳しいことは公式ドキュメントを見てください。

// Commands:
//  ぬるぽ - ガッ!
//

src/scripts does not exist

書いてある通り、src/scriptsのディレクトリがないということでディレクトリを作ればエラーメッセージは消えます。ただ、中身のないディレクトリを作るのはいまいちなので私は無視して作りました。
Hubotではsrc/scriptsscriptsの二つのディレクトリの中にあるコードを読むようになっているのでそのディレクトリがなかったら怒るということですね。この読み込みはnode_modules/hubot/bin/Hubot.mjsloadScripts内にあるawait robot.load(pathResolve('.', 'src', 'scripts'))でscriptsを読み取るフォルダを設定していたのでここをコメントアウトすることでもエラーメッセージは消えます。が、node_modulesの中身はGithubに上げずBOT起動時に生成するようにしたので今回は無理ですね。

Gitにあげる

BOTをサーバー上で動かそうとすると大抵Gitに上げないといけないのでGitに上げていきます。(まあ、ローカル環境にしかコードがなかったら他の場所にあるサーバーがコードを参照できないのでそれはそうという話)今回はGithubを使います。まず、不要なファイルをGitに上げないために.gitignoreNode.gitignoreからコピペして作成します。そして、Githubで空のリポジトリを作り、以下のようなコマンドを実行してGitに上げます。ここのコマンドは各自のGithubからコピペして実行する方が確実です。

$ echo "# {repository-name}" >> README.md
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin git@github.com:Hueter57/{repository-name}.git
$ git push -u origin main

これでGitに上げられました。

Discordでアプリ作成

ここまですればターミナルとはお別れです。
Discordで新規アプリケーションを作っていきます。
Discord - Developer Documentationのサイトに行き、New Applicationからアプリの名前を入力してCreateを押すことで新規アプリが作成されます。アプリ名やアイコンは好きに決めましょう。

作成したアプリを開き、もろもろの設定をしていきます。BOTを公開するかしないかで少し操作が変わっていきます。今回は公開しない設定で行きます。

Installation

Install LinkNoneに変更します。

OAuth2

OAuth2 URL Generatorからbotにチェックを入れて下に出てきたURLに飛ぶことで、どのDiscordサーバーに今回作ったアプリを入れるかを決められます。この操作はサーバーの管理者権限がないとできないので、権限を付与してもらうか権限を持ってる人にお願いしましょう。

Bot

Authorization FlowPUBLICK BOTをOFFにします。これはInstall LinkNoneにしていないとできないので注意。そしてReset Tokenを押してDiscordアカウントのパスワードを入力することでTokenが作られるのでコピーしておきましょう。

このトークンが洩れると他者がこのBotを操作できてしまいます。絶対に公開しないでください!
万一公開してしまった場合は再度Reset Tokenを押してTokenを再生成してください!

サーバーにBOTを追加

ここまでくれば作成したBOTをサーバー上で動くようにしていきましょう。
今回はtraP内製サービスのNeoShowcaseを使っていきます。BOTのあるリポジトリやビルドの設定をした後、環境変数としてHUBOT_DISCORD_TOKENを追加し先ほどコピーしておいたTokenを値として設定します。

ここまでの操作が終わればBOTが起動するはずです。アプリを追加したDiscordサーバーに行きオンラインになっていれば大丈夫です。では早速動作確認をしていきましょう。

や っ た ぜ

このように返信してくれれば正常に動いています。

同様の手順でtraQ用に別に作ったのも動いて大満足です

少しだけスクリプトをいじってみる

動くことが確認できたので、少しスクリプトを変えてみましょう。まず、今のコードを見てみましょう。以下はメンションしてpingと送ったらpongが返ってくる部分です。

robot.respond(/ping$/i, async res => {
  await res.reply("pong");
});

このコードでpingpongの部分を変更することで反応する言葉とそれに答える言葉を変更することができます。他にも、メッセージの受け取り方法や返信方法もrespondreplyの部分を変更することで変えることができます。

ということでいろんな組み合わせを試してみました。
今回監視対象のチャンネルを指定していないのでhearとしてもメンションしなければ使えませんが、send,reply ,emoteは使えました。とはいってもやはりsendemoteは全く同じに見えますね...?なんでしょうか。私にはわかりませんでした。

終わりに

初めてのBOT制作できたが何とか完成できてよかったです。NeoShowcaseも初めて触るので一番最初にBOTが動くようになるまで1週間ぐらい格闘してましたね。ただ、先輩方やサークルの人の助けもあり何とか動かせました。感謝カンゲキ雨嵐です。

今回はNeoShowcaseを使いましたが、ここに至るまでに参考にしたサイトではGlitchとGoogle Apps Scriptを組み合わせて無料の範囲で動かしている人や、Herokuというサービスを使っている人がいました。参考資料に私が見てきたサイトを載せておくので見てみてください。

タイトルに準備編と書いたのでいつか応用編みたいなものも出せたらなと思いますが、これから先忙しくなってくるので投稿できるのは先になりそうです。新歓ブログリレーに間に合うといいなーと思って頑張っていきます。

それではみなさんも、良いHubotライフを~


明日は@Alt--erさんと@METCH722くんがブログを出してくれます。お楽しみに!


参考資料

Hueter icon
この記事を書いた人
Hueter

23B game班とSysAd班メインで活動中 まだまだ分からないことだらけ

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2021年5月19日
CPCTF2021を実現させたスコアサーバー
xxpoxx icon xxpoxx
2024年12月24日
クリスマスを充実して過ごすためのたった一つの方法
Naru820 icon Naru820
2024年12月11日
Nixで実行環境のライセンス違反を予防する話
comavius icon comavius
2024年4月14日
Spotifyのクライアントを自作しよう
d_etteiu8383 icon d_etteiu8383
2023年8月21日
名取さなになりたくてOBSと連携する配信画面を作った
d_etteiu8383 icon d_etteiu8383
2023年3月30日
みやぎハッカソン2023に参加しました(ずんだ食べ食べ委員会)
mehm8128 icon mehm8128
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記