首页 > 解决方案 > DiscordPy:如何获取 api 的实时更新

问题描述

我一直在寻找几天,并没有找到有关如何通过调用 api 获取实时更新的答案。我希望我的不和谐机器人使用 api 实时更新玩家的分数和统计数据。https://dathost.net/api#/default/post_matches

标签: discorddiscord.py

解决方案


正如其他人所建议的那样,一种方法是启动您的机器人,然后告诉它休眠一段时间(无论您希望检查 API 之间的间隔有多长)。当它醒来时,它会调用你的 API。然后,您需要检查上次轮询 API 之间是否有任何更改,并打印出是否有更改。在此之后,它将重新进入睡眠状态。

这是一个简单的示例,使用他们在 DatHost 上为 python 使用请求提供的代码的 GET 片段。我在这个例子中使用了 SQLAlchemy 来连接数据库,但是你当然可以自由地进行原始 SQL 查询,或者使用不同的 ORM。如果您使用 SQLAlchemy,则需要以类似于您的数据的结构化方式设置表和列。

import requests
import datetime
from sqlalchemy.orm import sessionmaker
from discord.ext.commands import Bot

client = Bot(command_prefix="!")

# Get request snippet from DatHost Python example 
async def call_api():
    response = requests.get(
        "https://dathost.net/api/0.1/game-servers/%s" % server["id"],
        auth=("john@doe.com", "secretPassword"),
    ).json()

    return response

# Example using SQLAlchemy to connect to a local database to store responses
# Since I don't know what data is present in this API response- I'm going to give a simple
#   example- comparing the current whole response to the last saved response- if it's different,
#    it will return true 
def is_response_changed(session, api_response):
    response_changed = False

    # Get the last saved API response
    last_request = session.query(API).order_by(API.id.dec()).first()

    # If we don't have any last request, then our DB is empty- and our data HAS changed!
    if last_request is None:
        response_changed = True

    # Else- we need to check if it's different from our current data
    else:
        # Compare our last data with our current, first will return a result or None
        compare_requests = session.query(API).filter(last_request.data == api_response).first()

        # We did not match our last data, so it HAS changed!
        if compare_requests is None:
            response_changed = True

    return response_changed


# We need to save the new API data to check against next request
def save_new_response(session, api_response):
    # This format will vary depending on how you setup your object in SQLAlchemy
    # This is a simple example assuming you're only storing the raw data and the time it was added
    new_response = API(
        data=api_response,
        date_updated=datetime.datetime.now()
        )

    session.add(new_response)
    session.commit()


# Main bot client loop
client.run(BOT_TOKEN)


# DiscordPY method to initialize bot parameters  
@client.event
async def on_ready():
    # SQLAlchemy initialization 
    DBSession = sessionmaker(bind="apidatabase.db")
    session = DBSession()

    # Anything in this while loop will be executed continually during your main bot loop    
    while not client.is_closed():
        api_response = await call_api()

        if is_response_changed(session, api_response):
            save_new_response(session, api_response)

            # Print out the update to a channel- you'll have to define what channel you want to update
            #   based on its snowflake ID
            await update_channel.send(f"API has updated- here's the new data! {api_response}")

        # Sleeps for 5 minutes- when it wakes up again, it will run the above while loop
        await asyncio.sleep(300)

推荐阅读