Асинхронный REST API внутри Discord.py - PullRequest
0 голосов
/ 23 января 2019

Я ищу способ интеграции REST API внутри моего Discord.py, используя ветвь перезаписи. Я хочу использовать aiohttp для обработки запросов, но я не уверен, какой подход я должен использовать. Цель состоит в том, чтобы, например, сделать запрос GET к API, который бы возвратил список гильдий, в которых находится бот. Или, как другой пример, запрос POST, который попросил бы бот написать данное сообщение в определенный канал. В целом речь идет о том, чтобы дать инструкции боту с веб-страницы.

Я попытался поместить маршрутизатор и бегунок приложения aiohttp в мой класс клиента Discord.py. Веб-сервер действительно работает, я сделал асинхронную функцию для возврата гильдий, в которых находится бот, но похоже, что функция не будет принимать аргумент запроса, который я передаю ей при переходе на http://127.0.0.1/guilds. Это приводит к ошибке missing 1 required positional argument.

import discord
import asyncio
from aiohttp import web

class MyClient(discord.Client):
    async def on_ready(self):
        print('Logged on as {0}!'.format(self.user))

    async def get_guilds(self, request):
        response_obj = self.guilds
        return web.json_response(response_obj,status=200,content_type='application/json')

    app = web.Application()
    app.router.add_get('/guilds', get_guilds)
    web.run_app(app, port=80)

client = MyClient()
client.run(TOKEN)

Кроме того, сервер aiohttp не работает асинхронно. Я ожидаю, что on_ready(self) запустится, но это никогда не произойдет. Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Ну, я нашел способ.

bot.py

from asyncio import gather, get_event_loop
from logging import basicConfig, INFO
from discord.ext.commands import Bot
from aiohttp.web import AppRunner, Application, TCPSite
from sys import argv

from api import routes

basicConfig(level=INFO)

async def run_bot():

    app = Application()
    app.add_routes(routes)

    runner = AppRunner(app)
    await runner.setup()
    site = TCPSite(runner, '0.0.0.0', 8080)
    await site.start()

    bot = Bot(command_prefix="$")
    app['bot'] = bot

    try:
        await bot.start(TOKEN)

    except:
        bot.close(),
        raise

    finally:
        await runner.cleanup()

if __name__ == '__main__':
    loop = get_event_loop()
    loop.run_until_complete(run_bot())

api.py

routes = RouteTableDef()

@routes.get('/guilds')
async def get_guilds(request):
    client = request.app['bot']
    guilds = []
    for guild in client.guilds:
        guilds.append(guild.id)

    response = Handler.success(guilds)
    return json_response(response, status=200, content_type='application/json')
0 голосов
/ 24 января 2019

Я думаю, что ниже должно работать, чтобы запустить две задачи вместе. Это не очень хороший дизайн, и он будет только сложнее. Возможно, вам лучше обслужить, разделив бота и сервер и используя более структурированный способ общения между ними, чем разделение памяти.

import discord
import asyncio
from aiohttp import web

client = discord.Client()

async def on_ready():
    print('Logged on as {0}!'.format(client.user))

async def get_guilds(request):
    response_obj = client.guilds
    return web.json_response(response_obj,status=200,content_type='application/json')


try:
    bot_task = client.loop.create_task(client.start("token"))
    app = web.Application()
    app.router.add_get('/guilds', get_guilds)
    web.run_app(app, port=80)
except:
    client.loop.run_until_complete(client.logout())
...