2025-03-09 19:30:24 +01:00
|
|
|
<div align="center">
|
|
|
|
|
<h1>Pycord REST</h1>
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
[](https://results.pre-commit.ci/latest/github/Paillat-dev/pycord-rest/main)
|
2025-03-07 15:49:17 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
A lightweight wrapper for Discord's HTTP interactions and webhook events using py-cord
|
|
|
|
|
and FastAPI.
|
|
|
|
|
|
2025-03-09 19:30:24 +01:00
|
|
|
</div>
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
## Table of Contents
|
|
|
|
|
|
|
|
|
|
- [Overview](#overview)
|
|
|
|
|
- [Installation](#installation)
|
|
|
|
|
- [Quick Start](#quick-start)
|
|
|
|
|
- [Core Concepts](#core-concepts)
|
|
|
|
|
- [How It Works](#how-it-works)
|
|
|
|
|
- [Discord Application Setup](#discord-application-setup)
|
|
|
|
|
- [Features](#features)
|
|
|
|
|
- [Interaction Handling](#interaction-handling)
|
|
|
|
|
- [Webhook Events](#webhook-events)
|
2025-03-09 19:30:24 +01:00
|
|
|
- [Type Safety](#type-safety)
|
2025-03-09 16:52:18 +01:00
|
|
|
- [Usage Examples](#usage-examples)
|
|
|
|
|
- [Basic Commands](#basic-commands)
|
|
|
|
|
- [Event Handling](#event-handling)
|
|
|
|
|
- [Custom Routes](#custom-routes)
|
|
|
|
|
- [Configuration](#configuration)
|
|
|
|
|
- [Limitations](#limitations)
|
2025-03-09 20:14:40 +01:00
|
|
|
- [Getting Help](#getting-help)
|
2025-03-09 16:52:18 +01:00
|
|
|
- [Development](#development)
|
|
|
|
|
- [Local Testing](#local-testing)
|
|
|
|
|
- [Contributing](#contributing)
|
|
|
|
|
- [License](#license)
|
|
|
|
|
|
|
|
|
|
## Overview
|
|
|
|
|
|
|
|
|
|
Pycord REST enables you to build Discord applications that respond to:
|
|
|
|
|
|
|
|
|
|
- **Interactions** via HTTP endpoints (slash commands, components, modals)
|
|
|
|
|
- **Webhook events** such as application authorization and entitlements
|
|
|
|
|
|
|
|
|
|
Built on:
|
|
|
|
|
|
|
|
|
|
- **FastAPI** - For handling HTTP requests
|
|
|
|
|
- **py-cord** - For Discord command builders and interaction handling
|
2025-03-08 18:28:27 +01:00
|
|
|
- **uvicorn** - ASGI server implementation
|
|
|
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
|
|
|
|
|
```bash
|
2025-03-08 22:00:48 +01:00
|
|
|
pip install pycord-rest-bot --prerelease=allow
|
2025-03-08 18:28:27 +01:00
|
|
|
```
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!NOTE]
|
|
|
|
|
> The package is currently in pre-release.
|
2025-03-08 21:56:50 +01:00
|
|
|
|
2025-03-08 18:28:27 +01:00
|
|
|
## Quick Start
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from pycord_rest import App
|
|
|
|
|
import discord
|
|
|
|
|
|
2025-03-09 09:56:36 +01:00
|
|
|
app = App()
|
2025-03-08 18:28:27 +01:00
|
|
|
|
|
|
|
|
@app.slash_command(name="ping", description="Responds with pong!")
|
|
|
|
|
async def ping(ctx):
|
|
|
|
|
await ctx.respond("Pong!")
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
app.run(
|
|
|
|
|
token="YOUR_BOT_TOKEN",
|
|
|
|
|
public_key="YOUR_PUBLIC_KEY", # From Discord Developer Portal
|
|
|
|
|
uvicorn_options={
|
|
|
|
|
"host": "0.0.0.0",
|
|
|
|
|
"port": 8000
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
## Core Concepts
|
2025-03-09 10:15:06 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### How It Works
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
Pycord REST creates an HTTP server that:
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
1. Listens for Discord interaction requests and webhook events
|
|
|
|
|
2. Verifies request signatures using your application's public key
|
|
|
|
|
3. Routes events to appropriate handlers
|
|
|
|
|
4. Returns responses back to Discord
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
Unlike traditional WebSocket-based Discord bots, HTTP-based applications:
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- Only wake up when receiving interactions or webhook events
|
|
|
|
|
- Don't maintain a persistent connection to Discord's gateway
|
|
|
|
|
- Don't receive most real-time Discord events
|
2025-03-09 10:15:06 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Discord Application Setup
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
1. Create an application on the
|
|
|
|
|
[Discord Developer Portal](https://discord.com/developers/applications)
|
|
|
|
|
2. Copy your public key to verify signatures
|
2025-03-09 20:54:10 +01:00
|
|
|
3. Run the Pycord REST app
|
2025-03-09 16:52:18 +01:00
|
|
|
4. Configure the endpoints:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- **Interactions Endpoint URL** - For slash commands and component interactions
|
|
|
|
|
(`https://example.com`)
|
|
|
|
|
- **Webhook URL** - For receiving application events (e.g.,
|
|
|
|
|
`https://example.com/webhook`)
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!IMPORTANT]
|
|
|
|
|
> Don't forget to run your FastAPI server **before** setting up the application on Discord, or else Discord won't be able to verify the endpoints.
|
|
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
|
|
### Interaction Handling
|
|
|
|
|
|
|
|
|
|
Respond to Discord interactions such as:
|
|
|
|
|
|
|
|
|
|
- **Slash Commands** - Create and respond to application commands
|
|
|
|
|
- **UI Components** - Buttons, select menus, and other interactive elements
|
|
|
|
|
- **Modal Forms** - Pop-up forms for gathering user input
|
|
|
|
|
- **Autocomplete** - Dynamic option suggestions as users type
|
|
|
|
|
|
|
|
|
|
### Webhook Events
|
|
|
|
|
|
|
|
|
|
Handle Discord webhook events such as:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- **Application authorization** - When your app is added to a guild or authorized by a
|
|
|
|
|
user
|
|
|
|
|
- **Entitlement creation** - When a user subscribes to your app's premium features
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 19:30:24 +01:00
|
|
|
### Type Safety
|
|
|
|
|
|
|
|
|
|
Pycord REST is fully type-annotated and type-safe. It uses `basedpyright` for type
|
|
|
|
|
checking.
|
|
|
|
|
|
|
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!NOTE]
|
|
|
|
|
> While Pycord REST itself is fully typed, the underlying py-cord library has limited type annotations, which may affect type checking in some areas.
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
## Usage Examples
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!TIP]
|
|
|
|
|
> For complete examples, check out the [examples directory](/examples).
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Basic Commands
|
|
|
|
|
|
|
|
|
|
Commands use the familiar py-cord syntax:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
@app.slash_command(name="hello", description="Say hello")
|
|
|
|
|
async def hello(ctx, user: discord.Member = None):
|
|
|
|
|
user = user or ctx.author
|
|
|
|
|
await ctx.respond(f"Hello {user.mention}!")
|
|
|
|
|
|
|
|
|
|
@app.slash_command()
|
|
|
|
|
async def button(ctx):
|
|
|
|
|
view = discord.ui.View()
|
|
|
|
|
view.add_item(discord.ui.Button(label="Click me!", custom_id="my_button"))
|
|
|
|
|
await ctx.respond("Press the button!", view=view)
|
|
|
|
|
```
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Event Handling
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
The possible events are:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- `on_application_authorized` - When your app is added to a guild or authorized by a
|
|
|
|
|
user
|
|
|
|
|
- `on_entitlement_create` - When a user subscribes to your app's premium features
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!NOTE]
|
|
|
|
|
> For application installation events, use `on_application_authorized` instead of `on_guild_join`.
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
```python
|
|
|
|
|
@app.listen("on_application_authorized")
|
|
|
|
|
async def on_application_authorized(event: ApplicationAuthorizedEvent):
|
|
|
|
|
# Triggers when app is added to a guild OR when a user authorizes your app
|
|
|
|
|
print(f"Authorization received: Guild={event.guild}, User={event.user}")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Custom Routes
|
|
|
|
|
|
|
|
|
|
Add your own FastAPI routes:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from fastapi import Request
|
|
|
|
|
|
|
|
|
|
@app.router.get("/custom")
|
|
|
|
|
async def custom_endpoint(request: Request):
|
|
|
|
|
return {"message": "This is a custom endpoint"}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Configuration
|
2025-03-08 18:28:27 +01:00
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
app.run(
|
|
|
|
|
token="YOUR_BOT_TOKEN",
|
|
|
|
|
public_key="YOUR_PUBLIC_KEY",
|
|
|
|
|
uvicorn_options={
|
2025-03-08 20:42:14 +01:00
|
|
|
"host": "0.0.0.0", # Listen on all network interfaces
|
|
|
|
|
"port": 8000, # Port to listen on
|
|
|
|
|
"log_level": "info", # Uvicorn logging level
|
2025-03-08 18:28:27 +01:00
|
|
|
},
|
2025-03-09 16:52:18 +01:00
|
|
|
health=True # Enable /health endpoint for monitoring
|
2025-03-08 18:28:27 +01:00
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Integration Options
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
1. **Stand-alone HTTP Interaction Bot** - Commands and components only
|
|
|
|
|
2. **Webhook Event Handler Only** - Process application events alongside a separate
|
|
|
|
|
gateway bot
|
|
|
|
|
3. **Full HTTP Application** - Handle both interactions and webhook events
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
## Limitations
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
Since Pycord REST doesn't use Discord's WebSocket gateway:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- **No Cache** - No local storage of guilds, channels, or users
|
|
|
|
|
- **Limited API Methods** - Functions that rely on cache won't work:
|
|
|
|
|
- `app.get_channel()`, `app.get_guild()`, `app.get_user()`
|
|
|
|
|
- Presence updates
|
|
|
|
|
- Voice support
|
|
|
|
|
- Member tracking
|
|
|
|
|
- **Limited Events** - Only interaction-based and webhook events work
|
2025-03-09 20:14:40 +01:00
|
|
|
|
|
|
|
|
## Getting Help
|
|
|
|
|
|
|
|
|
|
If you encounter issues or have questions about pycord-rest:
|
|
|
|
|
|
|
|
|
|
- **GitHub Issues**:
|
|
|
|
|
[Submit a bug report or feature request](https://github.com/Paillat-dev/pycord-rest/issues)
|
|
|
|
|
- **Discord Support**:
|
|
|
|
|
- For py-cord related questions: Join the
|
|
|
|
|
[Pycord Official Server](https://discord.gg/pycord)
|
|
|
|
|
- For pycord-rest specific help: Join the
|
|
|
|
|
[Pycord Official Server](https://discord.gg/pycord) and mention `@paillat`
|
|
|
|
|
|
|
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!TIP]
|
|
|
|
|
> Before asking for help, check if your question is already answered in the [examples directory](/examples) or existing GitHub issues.
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
## Development
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Local Testing
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
Use tunneling tools to expose your local development server:
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- **ngrok**:
|
2025-03-09 10:15:06 +01:00
|
|
|
|
2025-03-08 20:42:14 +01:00
|
|
|
```bash
|
|
|
|
|
# Install ngrok
|
|
|
|
|
npm install -g ngrok
|
2025-03-09 10:15:06 +01:00
|
|
|
|
2025-03-08 20:42:14 +01:00
|
|
|
# Expose your local server
|
|
|
|
|
ngrok http 8000
|
|
|
|
|
```
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
- **Cloudflare Tunnel** or **localtunnel** - Alternative tunneling options
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
These tools provide temporary URLs for testing without deploying to production.
|
2025-03-08 20:42:14 +01:00
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
### Contributing
|
2025-03-08 18:28:27 +01:00
|
|
|
|
|
|
|
|
1. Fork the repository
|
|
|
|
|
2. Create a feature branch
|
|
|
|
|
3. Make your changes
|
2025-03-09 16:52:18 +01:00
|
|
|
4. Run linter, formatter and type checker: `ruff check .`,`ruff format .`,
|
|
|
|
|
`basedpyright .`
|
2025-03-08 18:28:27 +01:00
|
|
|
5. Submit a pull request
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
**Development Tools**:
|
2025-03-08 18:28:27 +01:00
|
|
|
|
2025-03-09 19:30:24 +01:00
|
|
|
- **uv**: For dependency management
|
2025-03-08 18:28:27 +01:00
|
|
|
- **Ruff**: For linting and formatting
|
|
|
|
|
- **HashiCorp Copywrite**: For managing license headers
|
|
|
|
|
- **basedpyright**: For type checking
|
|
|
|
|
|
2025-03-09 16:52:18 +01:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
|
> [!NOTE]
|
|
|
|
|
> This is an early-stage project and may have unexpected behaviors or bugs. Please report any issues you encounter.
|
2025-03-08 18:28:27 +01:00
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
MIT License - Copyright (c) 2025 Paillat-dev
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-03-09 16:55:06 +01:00
|
|
|
Made with ❤ by Paillat-dev
|