Two ways to run daily work. The wall-clock way: declare the task in your manifest's "cron" array and handle it with @plugin.cron (Build: Cron schedules). The zero-manifest way shown here: piggyback on message traffic and gate with a once-per-day flag — the recap posts with the first message after 09:00 UTC, so quiet servers skip it for free. Recipes 13 and 14 reuse this pattern.
from datetime import datetime, timezone
@plugin.on_event("message_create")
def count(ctx: Context, event: dict):
if event.get("author_bot"):
return
ctx.metrics.record("messages")
_maybe_recap(ctx, event["channel_id"])
def _maybe_recap(ctx: Context, fallback_channel: str):
now = datetime.now(timezone.utc)
if now.hour < 9:
return
if not ctx.ephemeral.dedup(f"recap:{now:%Y-%m-%d}", ttl_seconds=86400):
return # already posted today
channel_id = ctx.kv.get("recap_channel_id") or fallback_channel
total = int(ctx.metrics.total("messages", period="24h"))
ctx.discord.send_message(channel_id=str(channel_id),
content=f"Good morning! {total} messages in the last 24 hours.")