-
Notifications
You must be signed in to change notification settings - Fork 6
Research and Findings
With the primary aim of executing PPH bot actions via API calls, the following objectives must be addressed in order to resolve the primary goal.
- To Call PPH bot actions manually or independently
- To Perform API calls that requires little refactoring in the code
- To Combine Objective #1 and #2
We have found three possible ways to perform discord actions via API calls.
it mainly uses an HTTP call to perform commands by directly copying the contents of the discord command and replicating it in the API. but the problem is that it is rate limited by 200 calls per day. Sources:
https://discord.com/developers/docs/interactions/application-commands#authorizing-your-application
https://stackoverflow.com/questions/75815526/how-to-invoke-a-discord-bot-command-via-rest-api
2. Using the combination of an API library and discord bot. manually invoking a command through the use of HTTP call.
There are two options of frameworks that we considered.
- Flask
- FastAPI
We will be using FastAPI here mainly due to preferrence being able to use it's concurrency
These are the example
main
from fastapi import FastAPI
import uvicorn
import asyncio
from superbot import ProgPhil
from API.APIcommand import helloCommand
app = FastAPI()
@app.on_event("startup")
async def startup_event():
asyncio.create_task(bot.start('token'))
if __name__ == '__main__':
bot = ProgPhilBot()
app.include_router(helloCommand(bot).router)
uvicorn.run(app, host="localhost", port=8000)
command.py
from discord.ext import commands
import discord
from fastapi import APIRouter
class Basic(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command()
async def hello(self, ctx):
await ctx.send("Hello!")
async def setup(bot):
await bot.add_cog(Basic(bot))
API.py
from fastapi import APIRouter,Request
from superbot import ProgPhil
class helloCommand():
context = None
router = APIRouter(
prefix="/hello",
tags=["commands"],
responses={404: {"description": "Not found"}}
)
#ProgPhil is the bot
def __init__(self,ctx:ProgPhil):
helloCommand.context=ctx
@router.get("/")
async def command_hello():
hello_command = helloCommand.context.get_command('hello')
hello_context = await helloCommand.context.get_context(None)
await helloCommand.context.invoke(hello_command,hello_context)
return {"success":"finally!"}
this method mainly uses bot.invoke to call a command.
The problem with this approach is that the commands all requires a context object. which is impossible to get only using API calls.
It can be easily solved by not using any context-based actions. for example, a message.
async def hello_message():
# Replace these with your actual values
test_guild = bot.get_guild(GUILD_ID)
test_channel = test_guild.get_channel(CHANNEL_ID)
test_message = discord.Message(content="Hello!", author=test_guild.me, channel=test_channel)
await bot.dispatch("message", test_message)
3. Using a webhook, it uses POST requests to send directly to discord. but it may be separate from the bot and not in-line with the bot's purpose.
This is an example code.
import requests
import json
webhook_url = 'YOUR_WEBHOOK_URL'
# Create an embed with an image
embed = {
'title': 'Image Embed',
'image': {'url': 'IMAGE_URL'} # Replace with the actual image URL
}
# Create the payload with the embed
payload = {
'content': 'Here is an image:',
'embeds': [embed]
}
# Send the payload as a POST request to the webhook URL
response = requests.post(webhook_url, data=json.dumps(payload), headers={'Content-Type': 'application/json'})
# Check if the message was sent successfully
if response.status_code == 204:
print('Image sent successfully!')
else:
print('Failed to send image:', response.text)
Source:
https://discord.com/developers/docs/resources/webhook#execute-webhook
https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks