私はPython with _discord.py
_を使用しています。ドキュメントここ
サーバーをsubredditにリンクするDiscordサーバー上で実行されているボットを持っています。ユーザーには、上位の提出物の取得、最新の提出物の取得などのさまざまなコマンドがあります。
ボットにいくつかの機能を追加したいのですが、そのうちの1つはキーワード通知機能です。ボットはsubredditでタイトルのキーワードを検索し、そのキーワードのリストにあるかどうかをユーザーに通知する必要があります。私はこれを行う方法を知っています。何度も実行しましたが、Discordボットでそれを行う方法はわかりません。 asynchioや非同期プログラミングの経験はありません。
私がやろうとした方法は機能しますが、それは非常にぎくしゃくしていて間違いなく良くありません。 on message()
関数の先頭にsearch_submissions()
関数の呼び出しを追加するだけで、誰かがサーバーに新しいメッセージを送信するたびに、ボットがReddit送信をスキャンします。サーバーはビジー状態なので、これで比較的問題なく動作しますが、実際には「適切な」方法で実行したいと考えています。
search_submissions()
内に配置せずにon_message()
関数を呼び出す方法がわかりません。
追加コードを編集:
_import discord
TOKEN = "redacted"
client = discord.Client()
@client.event
async def reddit_search():
print("Searching")
@client.event
async def on_message(message):
if message.content.startswith("reddit!hot"):
# Get hot
# Do other things.
@client.event
async def on_ready():
print("Connected to Discord as {}.".format(client.user.name))
client.run(TOKEN)
_
次のようにClient.loop.create_task(search_submissions())
を使用して、ボットイベントループに関数を追加できます。
async def search_submissions():
pass
client = discord.Client()
client.loop.create_task(search_submissions())
client.run(TOKEN)
更新:
関数を継続して動作させたい場合は、関数をwhileループに入れて、間にスリープ状態を設定できます。
async def search_submissions():
while(true):
# do your stuff
await asyncio.sleep(1)
search_submissions()
関数をasyncにしたいので、ボットの他の関数を引き続き呼び出すことができ、ボットは応答性を維持します。これを_def async
_として定義し、aiohttp
を使用して非同期HTTPリクエストをredditに送信します。これにより、リクエストが送信され、イベントループに制御が渡され、結果が出たら制御が戻ります。返信されました。ここで標準のHTTPライブラリを使用すると、結果が返されるまでボット全体がブロックされます。もちろん、これは、タスクが主にI/OバウンドでCPUバウンドが少ない場合にのみ意味があります。
次にsearch_submissions()
でon_message(message)
を呼び出しますが、result = await search_submissions()
を使用してasynchronouslyと呼び出します。 _on_message
_の結果が準備できると、これにより_search_submissions
_の実行が再開されます。
本当に何か他のことをしたい場合同じコンテキストで _search_submissions
_(これはありそうもないことですが)を待つ間に、task = asyncio.create_task(search_submissions())
としてディスパッチします。これにより、タスクがすぐに開始され、同じ関数内で別のことができるようになります。結果が必要な場合は、_result = await task
_にする必要があります。
_async def search_submissions():
async with aiohttp.ClientSession() as session:
async with session.get(some_reddit_url) as response:
return await response.read()
@client.event
async def on_message(message):
if message.content.startswith("reddit!hot"):
result = await search_submissions()
await message.channel.send(result)
_