DiscordのBotをRaspberry Piでポストするまでのメモ

# DiscordでBotを作りたい
表題の通りで、最近仲の良い友人たちの間で[Discord](https://discordapp.com/)を使っていて、こいつにBotを導入したかった。
応用は後で頑張るとして、まずは簡単なポスト（Ping - Pong）くらいできるようにしたい。

※余談だけど、Discord本当に良いのでSlackくらい流行ってほしい。

# 環境
常に動作させたかったので、自宅でおもちゃにしてるRaspberry Pi3で動作させることにした。

> Linux raspberrypi 4.4.38-v7+ #938 SMP Thu Dec 15 15:22:21 GMT 2016 armv7l GNU/Linux


# 何を使う？
BotといえばSlackなんですけど（？）、よくHubotが使われてました。
自分も一度使ったことあるけど、色々面倒（Herokuとか使う）だったので、もう少し小規模にできるものから始めようかなと。
いろいろ調べた感じ、以下の二つが簡単にDiscordのBotを作れそう。

* [discord.py](https://github.com/Rapptz/discord.py)
* [discordrb](https://github.com/meew0/discordrb)

名前からおわかりの通り、discord.pyはPython、discordrbはRubyによるDiscordのAPIラッパーらしい。

二つのサンプルコードを貼ってみます。


```python:discord.py.py
import discord
import asyncio

client = discord.Client()

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

@client.event
async def on_message(message):
    if message.content.startswith('!test'):
        counter = 0
        tmp = await client.send_message(message.channel, 'Calculating messages...')
        async for log in client.logs_from(message.channel, limit=100):
            if log.author == message.author:
                counter += 1

        await client.edit_message(tmp, 'You have {} messages.'.format(counter))
    elif message.content.startswith('!sleep'):
        await asyncio.sleep(5)
        await client.send_message(message.channel, 'Done sleeping')

client.run('token')
```



```ruby:discordrb.rb
require 'discordrb'

bot = Discordrb::Bot.new token: '<token here>', client_id: 168123456789123456

bot.message(with_text: 'Ping!') do |event|
  event.respond 'Pong!'
end

bot.run
```


# discordrbを使う
結論から言いますと、何故かdiscord.pyで上手く動作しなかったので、discordrbを使うことにした。なんでできなかったんだろう・・・

というわけで、以降はdiscordrbの簡単な導入方法になります。

# Bot実装
## discordrb導入
Linuxの場合導入自体はメチャクチャ簡単。

```
gem install discordrb
```

・・・といいつつ、エラーでdiscordrbがインストールできない！（エラー内容はメモるの忘れた）
検索したらrubyバージョン2.1.5なら大丈夫？とのことなので、先に[rvm](https://rvm.io/)を導入してからインストールすることに。

## rvmインストール
```
curl -L get.rvm.io | bash -s stable
```

上記のコマンドがコケたら、以下を実行してからもう一度試す。

```
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
```

rvmのインストールが完了したら、ターミナルを閉じるか以下のコマンドを実行。

```
source ~/.rvm/scripts/rvm
```

お目当てのrubyバージョンをインストール。

```
rvm install 2.1.5
```

どうやらここでrubyのコンパイルが入るらしく、えらい時間かかった。30分くらい。

環境によっては以下のインストールが必要みたいです。nazuna01107さんありがとうございます！
```
apt-get install ruby-dev
```


ここまできてやっと当初の目的であるdiscordrbをインストールできる。

## 再度、discordrbインストール

```
gem install discordrb
```


gemのインストールが完了したら、使用するソースで以下をrequireするだけ。

```ruby
require 'discordrb'
```

Windowsの人は[公式のドキュメント](https://github.com/meew0/discordrb)見て！

## DiscordにBotを登録
 [開発者ページ](https://discordapp.com/developers/applications/me)でBotの登録をします。
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/22110/cf825c2f-4dae-e786-1645-dd10caec3c79.png)

New Appをクリック

---

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/22110/c747c0c6-4b69-e1c7-ad83-75889e8c5402.png)
上の画像で黒塗りになってるClient ID と Token をメモっておく。

Discord側の設定はこれだけでOK。REDIRECT URI(S)は設定しなくても大丈夫。

## コーディング & 実装
コーディングといいつつ、今回はポストするまでが目標なので、discordrbのサンプルをそのまま使う。
最初はechoだけでもいいと思ったけど、それだとあまりにも味気ないから、投稿されたRubyのコードをそのまま eval するサンプルを使った。

```ruby:bot.rb
require 'discordrb'
bot = Discordrb::Commands::CommandBot.new token: 'あなたのトークンを入れてね', client_id: 000000000000000000, prefix: '!'

bot.command(:eval, help_available: false) do |event, *code|
  begin
    eval code.join(' ')
  rescue
    'An error occurred '
  end
end
```

これを適当なファイル名で保存して、

```
ruby bot.rb
```

すれば実行開始。
上手く行けば以下みたいな表記が出るはず。

```
Using WSCS version: 0.3.0
libsodium not available! You can continue to use discordrb as normal but voice support won't work.
        Read https://github.com/meew0/discordrb/wiki/Installing-libsodium for more details.
[INFO : websocket @ 2017-02-28 02:26:10.165] Discord using gateway protocol version: 6, requested: 6
```

※なんか利用不可って言われてるけど気にしない。

常に動作させたい場合はコマンドの末尾に ```&``` をつけてやってバックグラウンド実行するといいかも。

```
ruby bot.rb &
```

## おしゃべりする
あとはDiscordでBotに話しかけるだけ！
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/22110/5465218f-7e5e-985b-2f99-b9fe216957eb.png)







ちなみに、ここですげー躓いたんだけど、Discordの場合、Botにコマンドを実行させるときは prefixが必要らしく、Botに対していくら

```
eval 1+2
```

ってやっても効かなくて、ちゃんと ! をつけてやらないとダメみたい（prefixは変更できる）。

```
!eval 1+2
```

それと、上記の画像はDMだけど、任意のチャンネルでBotにコマンドを打つときも ```@Chika !eval 1+1``` ってやる必要はないみたい。
これだと、同じコマンドを持ったBotが複数いる場合どうなるんだろう・・・このへんの仕様はまだ調べてない。

# 次の目標
とりあえずポストできることがわかったので、次回はもう少し実用的なBotにしたい。