← Dokumentation  /  Entwicklerhandbuch

Erstelle ein Plugin

Die vollständige SDK-Referenz für Plugin-Entwickler — Sandboxed Python, als ZIP-Datei versendet, über den Marketplace verteilt.

These docs are publicly viewable. To publish a plugin you'll need a free YourBot account: sign in to access the Dev Portal.
SDK v0.8.4

Plugins sind isolierte Python-Prozesse. Schreibe einen Handler, deklariere deine Fähigkeiten, lade ein Zip hoch — wir führen es in einem abgesicherten Docker-Container aus und übertragen Discord-Events per JSON-RPC.

Referenz — ctx Attribute

AttributTyp
ctx.server_idstr — Discord-Server (Guild)-ID
ctx.plugin_idstr — die ID deines Plugins
ctx.versionstr — installierter Versionsstring
ctx.capabilitiesset[str] — vom Nutzer genehmigte Berechtigungen
ctx.discordDiscord-REST-Oberfläche
ctx.interactionInteraktionsantwort-Oberfläche
ctx.kvServer-spezifischer KV-Speicher
ctx.sqlSandbox-SQL (Berechtigung)
ctx.ephemeralRedis-gestützte Zähler / Cooldowns / Flags
ctx.httpAusgehendes HTTP über Proxy
ctx.wsPersistent WebSocket connections via the platform broker (capability)
ctx.secretsEncrypted secret storage (capability)
ctx.metricsZeitreihenmesswerte
ctx.request_idstr — correlation ID for the current interaction ("" outside one)
ctx.log(message, *, level, tags, **extra)Strukturiertes Plugin-Log
ctx.has_capability(name)bool — Berechtigungsprüfung

ctx.discord

MethodeBerechtigung
send_message(*, channel_id, content="", embeds=None, components=None, files=None) Handler gibt zurück {"message_id", "channel_id"}discord:send_message
edit_message(*, channel_id, message_id, content=None, embeds=None, components=None) — None leaves components unchanged, [] clears themdiscord:edit_message
delete_message(*, channel_id, message_id)discord:delete_message
bulk_delete_messages(*, channel_id, message_ids)discord:delete_message
add_reaction(*, channel_id, message_id, emoji)discord:add_reaction
pin_message(*, channel_id, message_id)discord:send_message
unpin_message(*, channel_id, message_id)discord:send_message
get_messages(*, channel_id, limit=50, before=None, after=None)discord:read
iter_messages(*, channel_id, batch_size=50, before=None, after=None) v0.6.1 — generator that pages through full channel history (newest→oldest, or oldest→newest with after=)discord:read
get_guild()discord:read
get_channel(*, channel_id)discord:read
list_channels()discord:read
get_member(*, user_id)discord:read
list_members(*, role_id=None, limit=100, after=None)discord:read
search_members(query, *, limit=25)discord:read
list_roles()discord:read
create_channel(*, name, channel_type=0, category_id=None, topic=None, user_limit=None)discord:manage_channels
edit_channel(*, channel_id, name=None, topic=None, user_limit=None)discord:manage_channels
delete_channel(*, channel_id)discord:manage_channels
set_channel_permissions(*, channel_id, target_id, allow="0", deny="0", target_type=0)discord:manage_channels
delete_channel_permission(*, channel_id, target_id)discord:manage_channels
create_thread(*, channel_id, name, thread_type=11, auto_archive_duration=1440)discord:manage_channels
edit_thread(*, thread_id, archived=None, locked=None, name=None, auto_archive_duration=None)discord:manage_channels
timeout_member(*, user_id, duration_seconds, reason="")discord:moderate_members
set_nickname(*, user_id, nickname=None)discord:moderate_members
kick_member(*, user_id, reason="")discord:kick_members
ban_member(*, user_id, reason="", delete_message_seconds=0)discord:ban_members
unban_member(*, user_id)discord:ban_members
add_role(*, user_id, role_id, reason="")discord:manage_roles
remove_role(*, user_id, role_id, reason="")discord:manage_roles
add_role_bulk / remove_role_bulk / timeout_bulk / kick_bulk(entspricht Einzelaktions-Berechtigung)
create_webhook(*, channel_id, name)discord:manage_webhooks
execute_webhook(*, webhook_id, webhook_token, content="", embeds=None, username=None, avatar_url=None)discord:manage_webhooks
delete_webhook(*, webhook_id)discord:manage_webhooks

edit_message, delete_message and bulk_delete_messages only operate on messages your plugin sent — attempts on other messages are rejected, and a bulk call fails closed on the whole batch if any ID isn't plugin-owned.

ctx.ws

Requires proxy:websocket. Connections are named; the platform's broker holds the socket. Full guide on the Storage & I/O tab.

MethodeVerwenden
ensure(name, url, *, secret_auth=None, auth=None, subscribe=None, binary=False)Idempotently open (or confirm) the named connection. Returns {"conn_id", "name", "state"}. subscribe frames are re-sent after every reconnect.
send(name, data)One frame: str sends text, bytes sends binary.
close(name)Hang up the named connection.
allow_host(host) / revoke_host(host)Authorize a WebSocket destination a server admin supplies at setup time; must be called from a slash handler run by that admin.

ctx.interaction

All four methods require the interaction:respond capability (auto-added when your manifest declares slash_commands).

MethodeVerwenden
respond(*, content="", embeds=None, components=None, ephemeral=False, allowed_mentions=None, update_message=False)Erste Antwort (innerhalb von 3s nach Empfang der Interaktion). allowed_mentions spiegelt das Discord-API-Feld wider — z.B. unterdrückt {"parse": []} alle Pings.
defer(*, ephemeral=False)"Ich arbeite daran" — gibt dir bis zu 15 Minuten für eine Folgeantwort
followup(*, content="", embeds=None, components=None, ephemeral=False, allowed_mentions=None)Reply after a defer (or send additional messages). Returns {"message_id", "channel_id"} so you can edit the message later.
send_modal(*, title, custom_id, fields=None)Ein Modal öffnen — als ERSTE Antwort verwenden, nicht nach einem Defer

ctx.kv / ctx.sql / ctx.ephemeral / ctx.http / ctx.metrics

Full method signatures live on the Storage & I/O tab: KV, SQL, Ephemeral, HTTP (including secret-backed Authorization injection via secret_auth=), Metrics.

Plugin-Dekoratoren

DekoratorHandler-Signatur
@plugin.on_ready(ctx) — per (worker, server) before that server's first event in pool mode; once per boot locally
@plugin.on_event(event_type)(ctx, event)
@plugin.on_slash_command(name)(ctx, event)
@plugin.on_component(custom_id=None, *, prefix=None)(ctx, event) — exactly one of exact custom_id or prefix match
@plugin.on_modal_submit(custom_id)(ctx, event)
@plugin.on_ws_message(name)(ctx, frame) — {"name", "conn_id", "data", "binary"}, binary data base64. "prefix:*" wildcard matches by prefix; exact names win
@plugin.on_ws_open(name)(ctx)
@plugin.on_ws_close(name)(ctx, info) — {"reason", "will_reconnect"}
@plugin.on_dashboard(method_name)(ctx, params) → dict
@plugin.schedule(seconds)(ctx) — local yourbot dev only; does not run in pool mode (marketplace plugins), see Pool mode
@plugin.cron(spec)(ctx) — 5-field UTC cron string. Runs in production when declared in the manifest "cron" array (5-minute floor, 5 entries max); see Cron schedules
@plugin.on_install / on_enable / on_disable / on_uninstall(ctx) — advisory signals, delivered best-effort when a worker is live, with a tenant-scoped ctx that keeps your approved capabilities. Required init still belongs in on_ready

Ereignis-Payload-Referenz

Typed payload shapes for all 16 events live in yourbot_sdk.events (MessageCreate, MemberJoin, …). Defaults produced by yourbot_sdk.testing.make_event:

make_event("message_create", content="hi")
# {message_id, channel_id, guild_id, author_id, author_username, author_bot,
#  content, timestamp}

make_event("interaction_create", command_name="ban", custom_id="")
# {interaction_id, interaction_type, guild_id, channel_id, user_id,
#  command_name, custom_id, modal_values}

make_event("reaction_add", emoji="🎉")
# {message_id, channel_id, user_id, emoji, guild_id}

WebSocket handlers receive their own shapes (not events): on_ws_message gets {"name", "conn_id", "data", "binary"} (binary data base64, frames per connection arrive in order) and on_ws_close gets {"reason", "will_reconnect"}.

Ausnahmen-Referenz

Siehe die vollständige Tabelle unter Fehlerbehandlung.

Berechtigung

Everything you can put in capabilities_required, with the badge customers see on the install consent screen. ctx.metrics, ctx.ephemeral and ctx.log need no capability.

BerechtigungAbzeichenWas es freischaltet
storage:kvSicherServer-spezifischer KV-Speicher
discord:send_messageSichersend_message, pin_message, unpin_message
discord:edit_messageSicheredit_message
discord:add_reactionSicheradd_reaction
interaction:respondSicherSlash-Command- und Komponenten-Verarbeitung
discord:readStarboardNachrichtenverlauf, Mitglieder, Kanäle und Rollen lesen
discord:delete_messageStarboarddelete_message, bulk_delete_messages
discord:manage_webhooksStarboardcreate_webhook, execute_webhook, delete_webhook
storage:secretsStarboardErstellt ctx.secrets.* + secret-backed auth on ctx.http/ctx.ws
storage:sql ÜberprüftStarboardAbgeschirmtes SQL-Schema
proxy:httpStarboardAusgehend ctx.http.* — von dir deklariert
events:message_contentGefährlichMessage text and author detail in events — without it events arrive meta-only (IDs and timestamps). Privacy-sensitive; request it only if you parse what people type
discord:manage_channelsGefährlichKanäle & Threads erstellen/bearbeiten/löschen, Berechtigungen setzen
discord:moderate_membersGefährlichtimeout_member, timeout_bulk, set_nickname
discord:kick_membersGefährlichkick_member, kick_bulk
discord:ban_membersGefährlichban_member, unban_member
discord:manage_rolesGefährlichadd_role, remove_role, bulk variants (admin roles blocked)
proxy:websocket ÜberprüftGefährlichVersionsverlauf ctx.ws.* — exact host required (or admin-approved via allow_host)

Dangerous-tier calls are logged at WARNING level. Capability narrative (auto-detection at upload, consent flow, CapabilityError semantics) lives on the Production tab.

Discord-Befehle

These names belong to YourBot's built-in plugins and are refused at upload (yourbot validate checks them locally):

announce   appeal     ban          beacon     case        giveaway   group
group-admin  group-alerts  help    history    kick        leaderboard
lockdown   maid-bug-report  music  note       poll        purge
quarantine quests     raidmode     report     slowmode    stats
temp-role  ticket     tickets      timeout    unban       unlockdown
unquarantine  untimeout  warn      welcome    yourbot

Grandfathering: if your plugin published a command before its name joined this list, you keep publishing it and on each server it registers under the alias /yourpluginid-name instead. Your handlers need no changes; events still arrive under the manifest name, and your command sync status shows the alias.

Limits and quotas

Every enforced number in one place. Each row links to the section that explains it.

BereitLimit
Seite25 MB zipped, 100 MB uncompressed, 500 files, 10 MB per file
KV-Speicher50,000 keys per (server, plugin), 500,000 per plugin globally; 64 KB values, 512-byte keys; get_many 50 / set_many 25 / list 1000 keys / list_values 100 entries per call
Secret64-char keys, 4096-char values
SQL1000 rows per query (hard cap), one statement per call, 100 tables, 10,000,000 rows per (plugin, server), DDL 20/hour
— ephemer256-char keys, 24 h max TTL (silently clamped); writes cost 0.1 outbound action
HTTP500 KB request, 200 KB response, 8 s timeout, 30 requests/min
WebSockets6 connects/min, 4 MB/min traffic shared across both directions
Symbol5-minute minimum interval, 5 entries per manifest, UTC minute resolution
Metriken1,000,000 stored points per (server, plugin), 10 tags per record, 128-char tag values, 90-day query window; names 1–64 chars
Protokolle4000-char messages, 10 tags, 20 extra kwargs at 500 chars each
Verfügbarkeit50 events/s, 60 outbound actions/min; 64 MB / 0.25 vCPU per worker (24 MB / 0.1 in pool mode); 64 PIDs; 16 MB /tmp
Dashboard8 s widget RPC timeout, 600 bridge calls/min
Aktionen3 s to first response; defer() buys 15 minutes

SDK-Changelog

v0.8.4

  • Added production cron delivery: @plugin.cron tasks declared in the manifest "cron" array now fire in pool mode with a tenant-scoped ctx (Cron schedules). yourbot validate checks specs (5-minute floor, 5 entries) and warns when a decorated task has no manifest entry.
  • Hinzugefügt Lifecycle-Dekoratoren: on_install, on_enable, on_disable, on_uninstall.

v0.8.3

  • Added slash-command consistency checks to yourbot validate: declared commands with no matching handler, uppercase decorator names, reserved names and malformed command/option names are caught locally, exactly like the platform does at upload.
  • Hinzugefügt Massen-Discord-Operationen: add_role_bulk, remove_role_bulk, kick_bulk, timeout_bulk.
  • Fixed pool-mode tenant resolution (every RPC now carries the correlation ID of its originating event). Previously documented for 0.7.1, but the code did not ship in that wheel; 0.8.3 ships it.
  • Fixed dashboard handler error logs to name the handler that actually failed.

v0.8.2

  • Added wildcard WebSocket handlers: @plugin.on_ws_message("name:*") (and on_ws_open / on_ws_close) match every connection sharing the prefix; exact-name registrations take precedence.

v0.8.1

  • Added ctx.ws.allow_host(host) / ctx.ws.revoke_host(host) — a server admin authorizes a WebSocket destination at setup time that a static allow-list can't express.

v0.8.0

  • Added ctx.ws — persistent WebSocket connections held by the platform broker (ensure / send / close, on_ws_message / on_ws_open / on_ws_close). Capability: proxy:websocket.
  • Added secret-backed auth injection for ctx.http and ctx.ws: secret_auth="NAME" (or auth={"scheme": ..., "secret": ...}) makes the platform set Authorization from a domain-bound secret your code never sees. Unblocks Bearer-token APIs.
  • Hinzugefügt Lifecycle-Dekoratoren: on_install, on_enable, on_disable, on_uninstall.
  • Added MockContext.ws to the test harness.

v0.7.1

  • Changed ctx.kv.increment(key, amount) to accept amount positionally (was keyword-only).
  • Fixed RateLimitError.retry_after to carry the host's actual retry hint as a float.

v0.7.0

  • Added ctx.interaction.respond(update_message=True) — edit the message a button / select menu is attached to (Discord UPDATE_MESSAGE) instead of sending a new reply. Component interactions only; degrades to a normal reply on older platforms.

v0.6.1

  • Added ctx.discord.iter_messages() — auto-paginating channel history generator.
  • Added machine-readable .code on every SDK exception (CAPABILITY_DENIED, RATE_LIMITED, …).
  • Added typed Discord response shapes (yourbot_sdk.responses) and a PEP 561 py.typed marker, so mypy / pyright / IDEs pick up SDK type hints.
  • Changed MockContext to enforce capabilities by default (gated calls raise CapabilityError like production); several mock-fidelity fixes.
  • Fixed KV quota errors to raise KvQuotaError instead of a generic RateLimitError.

v0.6.0

  • Renamed the SDK from mmo-maid-sdk to yourbot-sdk (pip install yourbot-sdk, from yourbot_sdk import Plugin). Nothing breaks: import mmo_maid_sdk keeps working via a compatibility package and the old PyPI name resolves to the new one.
  • Hinzugefügt Massen-Discord-Operationen: add_role_bulk, remove_role_bulk, kick_bulk, timeout_bulk.

v0.5.1

  • Hinzugefügt: allowed_mentions-Parameter bei ctx.interaction.respond() und ctx.interaction.followup() — steuert, welche Erwähnungen tatsächlich pingen (z.B. unterdrückt {"parse": []} alle Pings).

v0.5.0

  • Hinzugefügt: ctx.metrics-, ctx.sql-, ctx.ephemeral-Sub-APIs.
  • Hinzugefügt mmo_maid_sdk.testing-Modul mit MockContext und make_event.
  • Hinzugefügt Lifecycle-Dekoratoren: on_install, on_enable, on_disable, on_uninstall.
  • Hinzugefügt @plugin.cron(spec) für wanduhrbasierte UTC-Planung (5-Feld-Cron).
  • Hinzugefügt Massen-Discord-Operationen: add_role_bulk, remove_role_bulk, kick_bulk, timeout_bulk.
  • Hinzugefügt typisierte Ausnahmeklassen (10) für handlungsorientierte Fehlerbehandlung.
  • Sicherheit 7 kritische + 1 hohe SDK-/Sandbox-Befunde behoben (Audit, April 2026).

SDK v0.8.4 · Zuletzt aktualisiert Juli 2026 · Zurück zum Entwicklerportal