Skip to main content

Serverless Discord interactions framework for AWS Lambda

Project description

cordless

A serverless Discord interactions framework for AWS Lambda.

Build Discord bots without running a server — just functions deployed to Lambda. Discord sends HTTP interactions to your endpoint; you return a JSON response. No WebSockets, no gateway, no persistent runtime.

Discord → API Gateway → Lambda → cordless → your handlers → response

install

pip install cordless

quickstart

import os
from cordless import Cordless

bot = Cordless(public_key=os.environ["DISCORD_PUBLIC_KEY"])

@bot.command("ping", description="Replies with pong")
async def ping(ctx):
    await ctx.send("pong")

def handler(event, context):
    return bot.handle(event)

Deploy as lambda_function.py and point Discord's Interactions Endpoint URL at your function's URL (via API Gateway or a Lambda function URL).


request verification

Every request from Discord is signed with Ed25519. Pass your application's public key (from the Developer Portal → General Information) to Cordless() and every incoming request is verified automatically — invalid signatures return 401 before your code runs.

bot = Cordless(public_key=os.environ["DISCORD_PUBLIC_KEY"])

Omitting public_key skips verification. Fine for local testing, never do it in production. PING interactions (sent when you first configure your endpoint) are answered automatically.


commands

@bot.command("hello", description="Says hello")
async def hello(ctx):
    await ctx.send("Hello!")

Commands with options:

@bot.command(
    "echo",
    description="Repeats text back to you",
    options=[
        {"name": "text", "description": "Text to repeat", "type": 3, "required": True},
    ],
)
async def echo(ctx):
    await ctx.send(ctx.options["text"])

Options land on ctx.options as a plain {name: value} dict.

buttons

@bot.button("confirm")
async def confirm(ctx):
    await ctx.edit(f"Confirmed (button: {ctx.custom_id})")

ephemeral replies

@bot.command("secret", description="Only you can see this")
async def secret(ctx):
    await ctx.send("just for you", ephemeral=True)

registering commands

@bot.command(...) wires up local dispatch — Discord also needs to know your commands exist. Use the CLI after deploying:

export DISCORD_BOT_TOKEN=...

cordless register app:bot                        # global — up to 1 hour to propagate
cordless register app:bot --guild-id 123456789   # single guild, instant

Pass MODULE:ATTRIBUTE pointing at your Cordless() instance.

No bot user? Authenticate with client credentials instead:

export DISCORD_CLIENT_ID=...
export DISCORD_CLIENT_SECRET=...
cordless register app:bot

Or call it from code:

bot.sync_commands(bot_token=os.environ["DISCORD_BOT_TOKEN"])
bot.sync_commands(client_id=..., client_secret=..., guild_id="123456789")

deploying the layer

cordless has no compiled dependencies. Package it as a Lambda layer and attach it to your function in one step:

cordless upload --function my-discord-bot
cordless upload --function my-discord-bot --region eu-west-1

Uses the AWS CLI under the hood — your existing credentials, profile, and region config all apply.


context reference

Attributes

ctx.options Command options as {name: value}
ctx.custom_id Custom ID of the button that was clicked
ctx.user User who triggered the interaction
ctx.guild_id Guild ID, or None in DMs
ctx.channel_id Channel ID
ctx.interaction_id Interaction ID
ctx.token Interaction token
ctx.interaction Raw interaction payload

Methods

await ctx.send(msg, *, ephemeral=False) Reply with a message
await ctx.edit(msg) Edit the original message (button handlers)
await ctx.defer() Acknowledge within 3 s, respond later

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cordless-0.5.0.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cordless-0.5.0-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file cordless-0.5.0.tar.gz.

File metadata

  • Download URL: cordless-0.5.0.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cordless-0.5.0.tar.gz
Algorithm Hash digest
SHA256 9da93c2b16630e60c653905876cc641dfe77060c392837131b2f84f522320e1f
MD5 d03f58a7f5e3d9aa9d9510fc8baa2622
BLAKE2b-256 f9e9d87423074d3d215e3414f17424bedbeba7e3bcea84e3b73a14363905f132

See more details on using hashes here.

File details

Details for the file cordless-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: cordless-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cordless-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91d9cc3d7933bab20c62a2be671edbd75fe3235cd59b85957a634834b4b6a6cd
MD5 567ef3e9db8a7ba10ab88e3ab6ad78f7
BLAKE2b-256 c3e8c77dbe0513bc5a4dc275de85d4391ef94df6d86742d3676cdb59bf4ea959

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page