DiscordのメッセージをLINEに共有するbotを作る


#はじめに
 結構前からDiscordを使ってチャットやボイスなどを使って会話しながらゲームしたり、情報を共有や打ち合わせしたり、スタンプ押したりなどTwitterと同じかそれ以上くらい使っています。半年くらい前から、Discordはいれてないが、LINEは入ってる。Discordいれてるけど、LINEしか見ない。などといった人たちが多くなって、いちいちDiscordとLINE両方にメッセージを送信するのが面倒だったので、DiscordのメッセージをLINEにも送るbotを作ることにしました。

あと、LINEbotやDiscordbotを作ったことがない。Rubyを書いたことがない人でも簡単に作れました。

最終的なコードは[こちら](#最終的なコード)

# やったこと
動作確認とか色々テストしながらやってきたので、最終的にはやらなくても良い箇所が存在します。

- LINEbotを作成しオウム返しbotの作成
- 送りたいuserIdまたはgroupIdの確認
- プッシュメッセージを送る
- Discordbotの作成
- コマンドを入力したらLINEに転送するようにした



# LINEbotの作成
最終的にはbotを作るだけでよい。Webhookとかこれからやる作業を省いてもできますが、初めてbotを作る人は一通りやっておいた方が良いです

## オウム返しbotの作成　
- [Heroku+Ruby+SinatraでReplyにオウム返しするLineBotを作った](https://qiita.com/fullmated/items/81d1a49ed3d49eda2285)を参考にしてオウム返しbotを作成します。

- ただし、Gemfileは以下のように記述すること



```shell
$ vi Gemfile
```
```shell:Gemfile
source "https://rubygems.org"
gem 'sinatra'
gem 'line-bot-api'
gem 'discordrb'
```
- インストール

```shell
$ bundle install --path=vendor/bundle
```

- Herokuに環境変数を設定

```shell
$ heroku config:set LINE_CHANNEL_SECRET=<Channel Secret> 
$ heroku config:set LINE_CHANNEL_SECRET=<アクセストークン> 
```

- リプライイベントの時にも、userId, groupId, roomIdのjsonが含まれているので、メッセージの転送先に合わせて控えておいてください。 ```p event['source']```で取得できます。

## メッセージを送信する
メッセージのプッシュにかなり時間がかかってしまいました。SDKを使ってもうまくメッセージが送信されませんでしたので、直接APIを叩いてプッシュすることにしました。

[LINEのAPIリファレンス](https://developers.line.biz/ja/reference/messaging-api/)を参考にして、Rubyに書き変えてリクエストを投げました。

以下のように入力すると指定したユーザIDに　"Hello, world"　とメッセージがプッシュされたので、これを元にしてRubyで書き変えることにしました

```shell
curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "to": "ユーザID",
    "messages":[
        {
            "type":"text",
            "text":"Hello, world"
        }
    ]
}'
```

以下がRubyに変換したコードです

```ruby
  
require 'line/bot'
require 'net/http'
require 'uri'
require 'json'


uri = URI.parse("https://api.line.me/v2/bot/message/push")

request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request["Authorization"] = "Bearer アクセストークン"
request.body = JSON.dump({
  "to" => "ユーザIDもしくはグループID",
  "messages" => [
    {
      "type" => "text",
      "text" => "Hello, world"
    }
  ]
})

req_options = {
  use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(request)
end
```

これで、プッシュメッセージを送ることができます。


ここまででプッシュメッセージを送れていれば、config.ruは必要ないので、削除して良いです。

# Discordbotの作成
Discordのbotには コマンド + message を送ると、LINEに message を送るプログラムを書きます。

- [Discord Developer](https://discordapp.com/developers)にアクセスし、botを作成する
- OAuth2で「bot」を選択すると下にURLが出るので、コピペしてサーバにbotを追加
    - https://discordapp.com/api/oauth2/authorize?client_id=('cilent_id')&permissions=0&scope=bot>  ← こんな感じ

## コード
今回書いたコードを大まかに分けて説明します

```ruby
bot = Discordrb::Commands::CommandBot.new token: 'token', client_id: 'ClientId', prefix: "!"

bot.command :line do |event|
  bot_message = event.message.content
  bot_message.slice!(0,6)
  event.respond "#{bot_message}"
end
```
- コマンドを使えるbotを生成( Discordrb::Bot.new token: 'token'でも可能)
- bot.commandでコマンドを作成
- event.message.contentは「!line 」も含んでしまいますので、sliceで最初から６文字目までをカット
- event.respondはなくてもよいが、ただの動作確認です。(オウム返し)


```ruby
def push_line(message)

  uri = URI.parse("https://api.line.me/v2/bot/message/push")

  request = Net::HTTP::Post.new(uri)
  request.content_type = "application/json"
  request["Authorization"] = "Bearer AccessToken"
  request.body = JSON.dump({
    "to" => "userIdもしくはgroupId",
    "messages" => [
      {
        "type" => "text",
        "text" => message
      }
    ]
  })

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(request)
  end
end
```

 push_lineでは「!line」と入力したらコマンド以降のメッセージをLINEに送信します。一回、shellでpostして成功したものをそのままRubyに変換しました。



最後にProcfileを以下の通りに変更

```:Procfile
bundle exec ruby app.rb
```
- 「!line + message」を入力すると「message」がLINEに送信されていれば完成です。

最後にデプロイしてあげれば、いつでもDiscordとLINEにメッセージを共有することができます。成功すると、以下のような動作になります。

<img width="348" alt="スクリーンショット 2019-05-15 10.08.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/71fb97fd-0724-4f24-4e84-9fb4eddbaef8.png">


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351883/afa9bc6f-98e0-88b5-de5e-1a92257dee57.png)


# 最終的なコード

```shell:Gemfile
source "https://rubygems.org"

gem 'sinatra'
gem 'line-bot-api'
gem 'discordrb'
```

```ruby:app.rb
require 'line/bot'
require 'discordrb'
require 'net/http'
require 'uri'
require 'json'

bot = Discordrb::Commands::CommandBot.new token: 'token', client_id: 'ClientId', prefix: "!"

def client
  @client ||= Line::Bot::Client.new { |config|
    config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
    config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
  }
end

bot.command :line do |event|
  bot_message = event.message.content
  bot_message.slice!(0,6)
  event.respond "#{bot_message}"
  push_line(bot_message)
end

def push_line(message)

  uri = URI.parse("https://api.line.me/v2/bot/message/push")

  request = Net::HTTP::Post.new(uri)
  request.content_type = "application/json"
  request["Authorization"] = "Bearer AccessToken"
  request.body = JSON.dump({
    "to" => "userIdもしくはgroupId",
    "messages" => [
      {
        "type" => "text",
        "text" => message
      }
    ]
  })

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(request)
  end
end

bot.run
```

```:Procfile
bundle exec ruby app.rb
```

# おわりに

今回はDiscordにコマンド＋メッセージを送ると、LINEにメッセージを転送するbotたちを作りました。Rubyで書いたが、ドキュメントやリファレンスを見ると、Pythonやjavascriptの方がわかりやすいなと感じました。(Rubyが初めてでPuthonとjavascriptは書いたことがあるというのもありますが)
無駄な部分がいくつか残ってますが、当初の目的である「DiscordとLINEにメッセージを送りたい」というのは達成できました。discordbotのコマンドは結構簡単に作れたので、これからも機能を追加していこうと思います。

あと、bot名は適当です

2019.5.16追記

肝心の誰が発信したかが不明だったので、以下のコードに編集

```ruby
def add_message(str1, str2)
  return str1 + str2
end

post(add_message(event.user.name, bot_message))
```