とあるDiscord.pyを使って色々試してた昼下がりのこと、
Discordのサーバーでこんなことを言ってる人が居た。
「おしゃべりくん欲しい!!」
おしゃべりくんとは、一時期よく見た喋り相手が居ないぼっちに優しいDiscord上のTalkBotのことなわけだが....
そういえば、A3RTとかいう無料で使えるAPIがあったな。
よし、作ろう。
一応注意事項。
これを書いてる人はPython初心者勢なので至らぬところがあるかもしれません。そのときはやさしくお願いします....
あと、Qiita初投稿です。よろしくおねがいします。ねこです。
環境
環境についてはQiitaに落ちている記事のようなBotと比べるとかなりアウトローなのでこれを参考にされる方は自分の環境に合わせてください。
- discord.py 1.3.0
- Python 3.7.2
- Herokuで複数のBotを回すためイベントループを共有させたりしてます。
- Bot Commands Framework及びCogを使っています。
やりたいこと
特定のチャンネルで喋ったら無条件に反応し
→それにA3RTのTalkAPIで返す。
じゃあやってこー。
##A3RTのAPIKEY発行
TalkAPIのページからメール送信したりで簡単にAPIKEY発行できます。後で使います。
##Botの中身書いてこー。
run.pyをこんな感じで。
import discord
from discord.ext import commands
import asyncio
import os
import sys
import traceback
loop = asyncio.get_event_loop()
airlinia_token = os.environ['AIRLINIA_DISCORD_TOKEN'] # 環境変数~~。
technetium_token = os.environ['TECHNETIUM_DISCORD_TOKEN']
class DISCORDBOT(commands.Bot):
# コンストラクタ。
def __init__(self, command_prefix, cogs, **options):
# スーパークラスのコンストラクタに値を渡して実行。
super().__init__(command_prefix, **options)
# cogフォルダにある.pyファイルを読み込む。
for cog in os.listdir(f'./{cogs}'):
if cog.endswith('.py'):
try:
self.load_extension(f'{cogs}.{cog[:-3]}')
except Exception:
traceback.print_exc()
async def on_ready(self): # 準備完了時に呼び出す。
print(f"""ログインしました。
------\nBotのアカウントの概要\nユーザー名:{self.user.name}\nユーザーID:{self.user.id}
------\nDiscord.pyのバージョン\n{discord.__version__}
------\nPythonのバージョン\n{sys.version}
――――――――――――――――――――――――――――――""")
await self.change_presence(activity=discord.Game(name=f'{self.command_prefix}¦{self.user.name} - by.amazakura0804'))
if __name__ == '__main__':
airlinia = DISCORDBOT(command_prefix='al!', cogs='airlinia_cogs', loop=loop)
airlinia_task = loop.create_task(airlinia.start(airlinia_token))
technetium = DISCORDBOT(command_prefix='te!', cogs='technetium_cogs', loop=loop)
technetium_task = loop.create_task(technetium.start(technetium_token))
loop.run_until_complete(technetium_task)
loop.run_until_complete(airlinia_task)
loop.close()
discord.pyのBot Commands Frameworkを用いたBot開発など参考にしながら。
TOKENについては環境変数にしています。ここらへんも環境によって変えてください。
別に2つ以上動かさないよー。って方はこんな感じで十分だと思います。
import discord
from discord.ext import commands
import asyncio
import os
import sys
import traceback
token = os.environ['DISCORD_TOKEN']
class HogeBot(commands.Bot):
# コンストラクタ。
def __init__(self, command_prefix, cogs, **options):
# スーパークラスのコンストラクタに値を渡して実行。
super().__init__(command_prefix, **options)
# cogフォルダにある.pyファイルを読み込む。
for cog in os.listdir(f'./{cogs}'):
if cog.endswith('.py'):
try:
self.load_extension(f'{cogs}.{cog[:-3]}')
except Exception:
traceback.print_exc()
async def on_ready(self): # 準備完了時に呼び出す。
print(f"""ログインしました。
------\nBotのアカウントの概要\nユーザー名:{self.user.name}\nユーザーID:{self.user.id}
------\nDiscord.pyのバージョン\n{discord.__version__}
------\nPythonのバージョン\n{sys.version}
――――――――――――――――――――――――――――――""")
await self.change_presence(activity=discord.Game(name=f'{self.command_prefix}¦{self.user.name} - by.amazakura0804'))
if __name__ == '__main__':
hogebot = HogeBot(command_prefix='!', cogs='hogebot_cogs')
hogebot.run(token) # Botのトークン
##Talk.py
import discord
from discord.ext import commands
import asyncio
import os
import pya3rt
class Talk_Bot(commands.Cog):
def __init__(self, airlinia):
self.bot = airlinia #botを受け取る。
@commands.Cog.listener()
async def on_message(self, message):
if message.author.bot: # ボットのメッセージをハネる
return
if message.channel.id == TALK_CHANNEL_ID: # 適宜喋らせたいCHANNELIDに置き換え。
client = pya3rt.TalkClient(os.environ['TALK_API_KEY']) # ここも環境変数なので以下略。
content = client.talk(message.content)['results'][0]['reply']
await message.channel.send(content) # 返信メッセージを送信
def setup(airlinia):
airlinia.add_cog(Talk_Bot(airlinia))
はい。A3RT半端ない。A3RTのAPIKEYは環境変数に当てはめるか直接ぶち込むかしてみてください。
たったこれだけのコードで...
やったー。神。
リクルートさんありがとうございます。
#最後に
A3RT含めた様々なAPIを利用することでかなりできることに幅が広がるなと。
他にもいろいろ面白そうなのがあるので活用してみたい。