Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
49
Help us understand the problem. What are the problem?
@s3pt3mb3r

GoでDiscordの簡易botを作ろう

はじめに

GoでDiscordのbotを作ろうとしたところ、日本語の記事が一切見あたらなかったので申し訳程度のメモですが、記そうと思います。

  • 送信されたメッセージに応じて処理を行う。
  • 通話チャンネルに出入りする。
  • 通話チャンネルで音声入力を監視する。

を実装したbotを作っていきます。

注意 (2020/05/21)

この記事は投稿してから数年が経過してるので、ライブラリの更新状況によっては仕様が変わっている可能性があります。多分ある程度参考にはなると思うんですが、もしエラーが出たらライブラリのgodocとかをチェックしてみてくださいね!!!!!

Go側の準備

ライブラリは https://github.com/bwmarrin/discordgo を使います。

go get github.com/bwmarrin/discordgo

をしておいてください。

Discord側の準備

1.まずDiscord-My Appsにアクセスして、NewAppボタンをクリック。
dis.jpg

2.続いて、アプリケーションの名前(アイコン、アプリケーションの説明)を入力してCreateAppをクリック。
(ここでいうアプリケーションの名前がBotの名前になります)
スクリーンショット 2017-08-03 11.29.04.png

3.Create a Bot UserをクリックしたのちYes, do itをクリックしてボットユーザーを作成!
スクリーンショット 2017-08-03 11.32.38.png

4.するとbotの詳細画面がでるので、

  • APP DETAILS以下のClientID
  • APP BOT USERのclick to revealをクリックして表示されるToken

を控えておきましょう。その後save changesで設定を保存しましょう

スクリーンショット 2017-08-03 11.34.18.png

5.

https://discordapp.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&scope=bot&permissions=0

に、YOUR_CLIENT_IDを手順4で控えたClient IDに置き換えてアクセスしましょう。
(上の画像なら342494499286679553と置き換える)
botを追加したいサーバーを選択して認証をクリック。
これでbotがサーバーに追加されました。
スクリーンショット 2017-08-03 11.48.29.png

これで準備は整いました

プログラム

以下プログラム本文です。

  • YOUR_TOKEN
  • YOUR_CLIENT_ID
  • VOICE_CHANNEL_ID

を各々の値に変更して使用してください

main.go
package main

import (
    "fmt"
    "time"
    "github.com/bwmarrin/discordgo"
    "log"
    "strings"
)

var(
    Token = "Bot YOUR_TOKEN" //"Bot"という接頭辞がないと401 unauthorizedエラーが起きます
    BotName = "<@YOUR_CLIENT_ID>"
    stopBot = make(chan bool)
    vcsession *discordgo.VoiceConnection
    HelloWorld = "!helloworld"
    ChannelVoiceJoin = "!vcjoin"
    ChannelVoiceLeave = "!vcleave"
)

func main() {
        //Discordのセッションを作成
    discord, err := discordgo.New()
    discord.Token = Token
    if err != nil {
        fmt.Println("Error logging in")
        fmt.Println(err)
    }

    discord.AddHandler(onMessageCreate) //全てのWSAPIイベントが発生した時のイベントハンドラを追加
    // websocketを開いてlistening開始
    err = discord.Open()
    if err != nil {
        fmt.Println(err)
    }
    defer discord.Close()

    fmt.Println("Listening...")
    <-stopBot //プログラムが終了しないようロック
    return
}

func onMessageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {

    if err != nil {
        log.Println("Error getting channel: ", err)
        return
    }
        fmt.Printf("%20s %20s %20s > %s\n", m.ChannelID, time.Now().Format(time.Stamp), m.Author.Username, m.Content)

    switch {
        case strings.HasPrefix(m.Content, fmt.Sprintf("%s %s", BotName, HelloWorld)): //Bot宛に!helloworld コマンドが実行された時
            sendMessage(s, m.ChannelID, "Hello world!")

        case strings.HasPrefix(m.Content, fmt.Sprintf("%s %s", BotName, ChannelVoiceJoin)):

            //今いるサーバーのチャンネル情報の一覧を喋らせる処理を書いておきますね
                    //c, err := s.State.Channel(m.ChannelID) //チャンネル取得
            //guildChannels, _ := s.GuildChannels(c.GuildID)
            //var sendText string
            //for _, a := range guildChannels{
                //sendText += fmt.Sprintf("%vチャンネルの%v(IDは%v)\n", a.Type, a.Name, a.ID)
            //}
            //sendMessage(s, c, sendText) チャンネルの名前、ID、タイプ(通話orテキスト)をBOTが話す

            //VOICE CHANNEL IDには、botを参加させたい通話チャンネルのIDを代入してください
            //コメントアウトされた上記の処理を使うことでチャンネルIDを確認できます
            vcsession, _ = s.ChannelVoiceJoin(c.GuildID, "VOICE_CHANNEL_ID", false, false)
            vcsession.AddHandler(onVoiceReceived) //音声受信時のイベントハンドラ

        case strings.HasPrefix(m.Content, fmt.Sprintf("%s %s", BotName, ChannelVoiceLeave)):
            vcsession.Disconnect() //今いる通話チャンネルから抜ける
    }
}

//メッセージを受信した時の、声の初めと終わりにPrintされるようだ
func onVoiceReceived(vc *discordgo.VoiceConnection, vs *discordgo.VoiceSpeakingUpdate) {
    log.Print("しゃべったあああああ")
}

//メッセージを送信する関数
func sendMessage(s *discordgo.Session, channelID string, msg string) {
    _, err := s.ChannelMessageSend(c.ID, msg)

    log.Println(">>> " + msg)
    if err != nil {
        log.Println("Error sending message: ", err)
    }
}

まとめ

以上GoでDiscordのBotをつくるための手順でした。
あとはドキュメントを見ながらお好みに改造してください!
質問がございましたらコメントにて教えてください。

本記事はあくまでも現状GoでDiscordのBotをつくる日本語の記事がなかったため、至らない部分があることを十分承知した上で書かせていただいたものです。英語の資料やコードを読める方はそちらを読んでいただくほうが賢明かと思います。
何かコードに関して、追加情報等ございましたら、コメントにて教えていただけると大変助かります。

追記

このライブラリにはdiscordのグループがあります。https://discord.gg/0f1SbxBZjYoCtNPP (公用語は英語)

また、このライブラリの作者の方がdgvoiceというライブラリを作られていて、これを使うことでmp3ファイルの音源を通話チャンネルで流すことができます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
49
Help us understand the problem. What are the problem?