web-dev-qa-db-ja.com

関数をdiscord.pyイベントループに追加するにはどうすればよいですか?

私は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)
_
5
John Yuki

次のように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)
9
Tom Gringauz

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)
_
1
xjcl