15
12

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 1 year has passed since last update.

GASとGlitchでDiscord botを作る(無料)

Last updated at Posted at 2022-04-24

初Qiita記事

概要

実現したいこと

botに送られたメッセージをGASでいろいろ処理して返信できるbotを作りたい。無料で。
とりあえず今回はGAS経由でオウム返しをするbotを作る。

利用するサービス

すべて無料で利用可能。すばらしい!

処理の流れ

無料版Glitch はアクセスがないと5分で落ちます。24時間稼働のために、GASの時限トリガーで5分ごとにアクセスし続けます。Discord.jsはバージョン13を使います。

多分こんな感じ。

実践

botの作成

自分のDiscordサーバーにbot用のチャンネルを用意します。Discord Portal からbotを作成し、TokenとclientIdを控えます。botを自分のDiscordサーバーに追加します。scopeはbotとapplication.commandsを選べばOK.

GASのコード

GAS自体の説明は省略。新しくプロジェクトを作成し、code.gsを書きます。

code.js
//GASのプロパティを使いやすいように
//プロパティを使うことで機密情報のべた書きを避けられます
const P = {
  prop: PropertiesService.getScriptProperties(),
  get(key) {
    return this.prop.getProperty(key);
  }
  set(key, value) {
    this.prop.setProperty(key, value);
  }
}


//5分おきにこの関数を実行するように時限トリガーを設定
const retainGlitch = () => {
  //あらかじめ設定しておいたプロパティを呼び出す
  const glitchURL = P.get('glitchURL')

  const data = {}
  const headers = { 'Content-Type': 'application/json; charset=UTF-8' }
  const params = {
    method: 'post',
    payload: JSON.stringify(data),
    headers: headers,
    muteHttpExceptions: true
  }
  //特に中身のないデータをGlitchへPOST
  response = UrlFetchApp.fetch(glitchURL, params);
  console.log(response);
}


//Glitchからのメッセージが入ったPOSTを受け取る
const doPost = e => {
  const message = JSON.parse(e.postData.contents);

  //返信データを作成
  const messageObj = {
    'messageType': 'send',
    'content': 'via GAS: ' + message.content
  }
  const payload = JSON.stringify(messageObj);

  //json形式データを返す
  const output = ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON);
  return output.setContent(payload);
};

これをエディタから、だれでもアクセスできるWEBアプリとして公開し、URLを控えます。

Glitchのコード

Glitchのアカウントを作成します。New Projectからglitch-hello-nodeのapp starterを選びます。package.json内の"engines: { "node": "12.x" }"engines: { "node": "16.x" }に書き換えます。画面下のTERMINALを開き、$ npm i discord.js$ npm i axiosを実行します。エラーが出てうまくいかなければ、$ rm package-lock.json$ npm initなどを実行してみてください。

.env
# このファイル内に機密情報を書く
# = の前後には空白を開けない
# ''や""で値を囲まない

DISCORD_BOT_TOKEN={botのToken}
GAS_URL={GASのURL}
main.js
//モジュールのインポート
const http = require("http"); 
const axios = require('axios');
const discord = require("discord.js");
let client;


const connectDiscord = () => {
  client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS] });
  client.login(process.env.DISCORD_BOT_TOKEN);
  client.on("ready", () => console.log("bot is ready!"));

  //送信者がbot自身でないとき、GASへPOSTする関数を実行
  client.on("messageCreate", (message) => !message.author.bot ? sendGAS(message) : "");

  if (process.env.DISCORD_BOT_TOKEN == undefined) {
    console.log("please set ENV: DISCORD_BOT_TOKEN");
    process.exit(0);
  }
};


// GASにデータをPOSTする関数
const sendGAS = (message) => {
  const jsonData = {
    author: message.author,
    content: message.content,
    channel: message.channel,
  };
  const post = async () => {
    try {
      await axios({
        method: "post",
        url: process.env.GAS_URL,
        data: jsonData,
        responseType: "json",
      }).then((response) => {
        const msg = response.data;
        
        //送信方法を振り分け
        switch (msg.messagetype) {
          case "nothing": //何もしない
            break;

          case "reply": //返信
            message.reply(msg.content);
            break;

          case "send": //ただ送る
          default:
            message.channel.send(msg.content);
            break;
        }
      });
    } catch (error) {
      message.reply("an error occurred: " + error);
    }
  };
  post();
};

//実行
connectDiscord();

//GASからのPOSTリクエストを受け取る用
http
  .createServer( (request, response) => {
    console.log('post from gas')
    response.end("Discord bot is active now.");
  })
  .listen(3000);

package.jsonのAdd Packageからaxiosを検索して追加します。WEBエディタ上のShareボタンを押すと表示されるLive siteのリンクを、GASのglitchURLに設定します。

一旦以下の関数を書いて実行すれば設定完了です。

code.js
const setURL = () => P.set('glitchURL', 'your_project_url');

結果と振り返り

想定通りに動きました。
スクリーンショット (47).png

  • ローカル環境を使わないのは非常にお手軽。

  • GASだけで作れるLINE botのほうが楽だった。

  • requestやrequest-promiseモジュールが非推奨とのことで、axiosというのを使ってみた。

  • GASをAPIのようにつかうのは初めてだった。ContentServiceHtmlServiceでないと値を返せないみたい。

参考にしたサイト

追記

  • Discord.js v13用に書き替えました。
  • console.log()とかでやたらめったらアロー関数を使ってるのはなんでだっけ...? (←コメントを残さないバカ)
  • axiosではなくで標準のhttpsモジュールを使うほうがいいかも
  • 逆に受け取り側はhttpモジュールではなくexpressを使ったほうがいいかな
  • セミコロンの有無統一しようぜ
15
12
1

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
15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?