作った理由
私ね、スマホのDiscord時間制限かかってるんですよ
LINEはかかってないし両方APIが公開されているから頑張ったら連携ソフト作れるんじゃね?って思って作ることにしました
必要ものとかもろもろ
今回使った言語はRubyです
なんとね、Disocrdrbって
bot.run true
って書くだけでbotのもろもろの処理バックグラウンドで実行してくれるんですよ
サーバーを併用するときにこれくそ便利なんです
なんか最近Rubyオワコンとか言われてますがこの機能めちゃくそ便利なんでぜひやってみてください!!
あとは今回使うSinatra鯖を公開するためのngrokですね
これもくそ便利です
ぜひ使ってみてください
そんで今回使ったモジュール君たち
gem install discordrb
gem install line-bot-api
gem install sinatra
この3つですね
圧倒的少量で済むんですからめちゃくそ楽です
仕組み
まぁやってることはProxyみたいなもんです
Discordrb
まず、Discordのほうから説明していきます
Discordrbでbotをログインさせます
ここから全部バックグラウンドでの処理です
ボットが参加しているサーバーのメッセージ受信イベントを検知したらLINEのAPIにリクエスト飛ばして度のサーバーのどのチャンネルでどのユーザーがどんなメッセージを送信したかを転送します
Sinatra(LINEのWebhookサーバー側)
LINEにメッセージを送信したらこのSinatraの鯖にも同じリクエストが来るんでメッセージ内容を取得、そんでDiscordの指定チャンネルにメッセージを送信するといった感じです
コード
require 'sinatra'
require 'rack/protection'
require 'discordrb'
require './src/internal/config'
require './src/internal/client/line'
require './src/internal/client/discord'
# Config関係class作成
ConfigPath = 'config.json'
ServerConfig = Config::Server.new(config_file: ConfigPath) # ConfigのServer項目を読み取るオブジェクトを作成
DiscordConfig = Config::Discord.new(config_file: ConfigPath) # ConfigのDiscord項目を読み取るオブジェクトを作成
LineConfig = Config::Line.new(config_file: ConfigPath) # ConfigのLine項目を読み取るオブジェクトを作成
# Config読み込み
server_config = ServerConfig.load # server関連の設定取得
discord_config = DiscordConfig.load # discord関連のtokenなどを取得
line_config = LineConfig.load # line関連のtokenなど取得
# SinatraServerの設定
# 以下は自家用サーバーで実行するとき
set :bind, server_config['host'].to_s # hostを設定
set :port, server_config['port'].to_i # 何番PORTでサーバーを開くか設定
# 以下はRenderでデプロイする場合
# set :port, ENV['PORT'] || 4567
set :environment, :production
set :protection, :except => [:host_authorization] # サーバーのhost制限を解除 セキュリティ的に非推奨
# その他の変数設定
set_mode = false # チャンネルの送信モードか取得
send_mode = true # LINEのAPI使用制限節約のため、取得したメッセージをLINEに送るかモード選択
fetch_mode = false # サーバー情報取得モードか判別用
# LineBotの作成
line_client = LineBot::Client.new(
access_token: line_config['access_token'],
channel_secret: line_config['channel_secret'],
send_user_id: line_config['send_user_id']
)
# DiscordBotの作成
bot = Discordrb::Bot.new(
client_id: discord_config['client_id'],
token: discord_config['token'],
)
discord_client = DiscordBot::Client.new(
client: bot
)
bot.message do |event| # メッセージを受け取った時
unless send_mode
return nil
end
message_server = event.server # メッセージ送信元のサーバーを取得
message_channel = event.channel # メッセージ送信元のチャンネルを取得
message_author = event.author # メッセージ送信者を取得
message_content = event.content # メッセージの内容を取得
if message_author.bot_account? # メッセージ送信者がbotならそのままスルー
puts "pass"
return nil
end
line_send_content = discord_config['template']['message'].to_s
replace_words = { # 置き換え文字一覧 ここから変数の追加、削除が可能
"{guild_name}" => message_server.name,
"{guild_id}" => message_server.id,
"{channel_name}" => message_channel.name,
"{channel_id}" => message_channel.id,
"{author_name}" => message_author.name,
"{author_display_name}" => message_author.display_name,
"{author_id}" => message_author.id,
"{content}" => message_content,
}
replace_words.each do |id, value|
line_send_content = line_send_content.sub(id, value.to_s)
end
res = line_client.send line_send_content # LINEに送信
puts res.body
end
# サーバー指定のための変数など
discord_place = discord_config['template']
# SinatraServerの処理書き込み
post '/' do # LINEからメッセージを受信したら
params = JSON.parse request.body.read
event = params['events'][0]
puts event
unless event['message']['type'] == 'message'
return nil
end
message = event['message']['text'].to_s
if set_mode
argv = message.split(" ") # 書式が`<server_id> <channel_id>`のはずなので、サーバーとチャンネルで分ける
discord_place['guild'] = argv[0].to_i
discord_place['channel'] = argv[1].to_i
line_client.reply(event, "サーバーを変更しました\n詳しくは!infoコマンドで確認してください")
set_mode = false
return
end
if fetch_mode
guild_id = message.to_i
guild_data = discord_client.get_guild(guild_id)
content = "Name: #{guild_data['name']}\nId: #{guild_data['id']}\nChannels\n"
guild_data['channels'].each do |channel_id, channel|
content += "Name: #{channel['name']}\nType: #{channel['type']}\nId: #{channel_id}\n\n"
end
line_client.reply(event, content)
fetch_mode = false
return
end
commands = %w[!ready !info !set !list !fetch !catch] # コマンドと認識する単語を追加 ここからコマンドの追加&削除可能
if commands.include? message # メッセージがコマンドと認識されたら
case message
when '!ready' then # ログインしているか送信
content = 'Login!'
when '!info' then # 現在のサーバー、チャンネル情報などを送信
guild = bot.server(discord_place['guild'].to_i)
channel = bot.channel(discord_place['channel'].to_i, guild)
content = "GuildInfo\nGuildName: #{guild.name}\nGuildId: #{guild.id}\nChannelName: #{channel.name}\nChannelId: #{channel.id}"
when '!set' then # サーバ、チャンネルを設定するモードに移行
set_mode = true
content = "サーバー指定モードへ移行します\n<サーバーID> <チャンネルID>\n上記のように送信してください"
when '!list' then # サーバーの情報を取得
content = "参加しているサーバーリスト\n"
bot.servers.each do |server_id, server|
content += "#{server.name}\nID: #{server.id}\n\n"
end
when '!fetch' then
fetch_mode = true
content = "サーバー取得モードに移行します\nサーバーIDだけ送信してください"
when '!catch' then
send_mode = !send_mode
content = "メッセージ取得モードを#{send_mode.to_s}に設定しました\n" +
if send_mode
"メッセージを送信します"
else
"LINE Message API使用制限節約のため、メッセージの送信を控えます"
end
end
line_client.send content
return
end
discord_client.send_message(
discord_place['guild'].to_i,
discord_place['channel'].to_i,
message
)
end
bot.run true
こんなコードですね
完璧なコード(internal内のコードも含むやつ)は販売してるので公開しません!
でもこれさえあれば誰でも作れると思います
まぁこんなくそコードでも何人か買ってくれてるのでね
作るのめんどくさい!とか思う人はぜひご購入ください
TwitterのDMやDiscord(@tanahiro2010)のDMから受け付けます
値段は1500円!
読んでくれてありがとうって話
最後まで読んでいただき、ありがとうございました!
僕に依頼してくれたり売ってるプログラム購入してくれたりすると励みになります!
Qiitaではあんまり活動してないけどまぁ読んでくれる人が何人かいたら次の記事も出ると思うのでぜひ高評価(あるのかは知らん)おねがいします!
ではまた次の記事で!