Custom Commands docsCustom CommandsDocs

Search docs

Find a page, function or guide

HomeSupportDashboard

Getting started

  • Introduction
  • Your first command
  • How a command runs
  • Variables in replies
  • Text commands
  • Events
  • Using Slushy

Guides

  • Welcome messages
  • Role menus
  • Auto moderation
  • Social alerts
  • Moderation commands
  • Levels and XP
  • Economy and coins
  • Ticket system
  • Giveaways
  • Poll
  • Button game
  • Reminders

Concepts

  • Buttons and menus
  • Forms
  • Saving data
  • Permissions and cooldowns
  • Limits and premium
  • Common mistakes

API reference

  • Response
  • Messages
  • Embeds
  • Members and roles
  • Channels
  • Storage
  • Checks
  • Views
  • Components
  • Modals
  • Interactions
  • Paginators
  • Web and files
  • Scheduling
  • Server events and polls
  • Time
  • Waiting
  • Utilities
  • Objects
  • Event variables

Examples

  • /8ball
  • /coinflip
  • /avatar
  • /serverinfo
  • /rank
  • /remind

Guides

View .md

Giveaways

Start a giveaway with a Join button, then pick a random winner with one command.

You will build a giveaway system:

PartJob
/giveawayPosts the giveaway with a Join button
Giveaway join eventSaves each member who clicks Join
/gendPicks a random winner and announces it

Works on every plan. One giveaway runs at a time.

What you need#

  • About 10 minutes.
  • A channel for giveaways.

Entries are saved in a Mongo database called giveaway, one row per member. A member who clicks twice still has one entry. See Saving data.

1. /giveaway#

Open Create → Slash Command.

FieldValue
Command Namegiveaway
DescriptionStart a giveaway

Add a Text argument named prize, Required on.

Open the permissions part of the form. In Discord permissions, pick Manage Server. Under Behavior, turn on Only the user sees the reply.

Pre-hook:

python
# Start fresh: remove entries from the last giveaway.
entries = SlashMongo("giveaway")
await entries.delete_many({})
update_server_var("giveaway_prize", prize)

join = ComponentBuilder()
join.add_button("Join", style="success", emoji="🎉", custom_id="giveaway_join")

send_message(
    channel,
    message=Message(
        title=f"🎉 Giveaway: {prize}",
        description="Press **Join** to enter. Good luck!",
        color="#E91E63",
    ),
    components=join,
)

set_content("Giveaway started. Run /gend to pick the winner.")

update_server_var saves the prize name, so /gend can show it later.

2. The Join button#

Open Create → Event.

FieldValue
NameGiveaway join
TypeButton Click / Select Menu Change
Custom idsgiveaway_join

Code:

python
defer_response(ephemeral=True)

entries = SlashMongo("giveaway")
await entries.update_one(
    {"_id": str(user.id)},
    {"$setOnInsert": {"joined": int(unix_timestamp)}},
    upsert=True,
)
total = await entries.count()

respond_interaction(interaction, f"You are in! {total} entries so far.")
  • The member's ID is the row's _id, so a second click finds the same row. No double entries.
  • $setOnInsert only writes when the row is new.
  • count() counts every entry.

3. /gend#

Make another slash command named gend, description Pick the giveaway winner. Give it Manage Server too, and turn on Only the user sees the reply.

Pre-hook:

python
entries = SlashMongo("giveaway")
picked = await entries.aggregate([{"$sample": {"size": 1}}])
if not picked:
    set_error("Nobody has joined yet.")

winner = picked[0]["_id"]
prize = server_var("giveaway_prize", "the prize")

send_message(channel, f"🎉 Congratulations <@{winner}>! You won **{prize}**!")
await entries.delete_many({})

set_content("Winner picked.")

$sample picks one random row. The database does the picking, so it stays fast with thousands of entries.

4. Test it#

  1. Run /giveaway with prize Nitro.
  2. Press Join. It says "You are in! 1 entries so far."
  3. Press Join again. Still 1 entry.
  4. Run /gend. You win.

Errors from your code show in Logs → Error Logs on the dashboard.

Ideas#

  • Reroll. Remove the delete_many line from /gend. Entries then stay until the next /giveaway, so running /gend again picks a new winner.
  • Only members with a role can join. In the event, check has_role(user, "Member") before saving. When it is False, answer with respond_interaction and skip the save.
  • End on its own. schedule can run a built-in action later, but it cannot run your own code. A Clock event with schedule_clock can. See Scheduling.
  • Show the count on the message. Edit the giveaway message with edit_message after each join. See Messages.
PreviousTicket systemNext Poll

On this page

  • What you need
  • 1. /giveaway
  • 2. The Join button
  • 3. /gend
  • 4. Test it
  • Ideas
Custom CommandsCustom Commands

The #1 Custom Commands Discord bot — build commands, events and databases with zero boilerplate.

Join the support server

Product

  • Overview
  • Why us?
  • Premium
  • Template shop

Features

  • AI Agent
  • Reaction roles
  • Welcome messages
  • Embed builder
  • Social alerts
  • Custom bot

Resources

  • Docs
  • Blog
  • Support
  • Dashboard

Company

  • Privacy
  • Terms
  • Contact
contact@ccbot.app

2 Frederick Street, London, WC1X 0ND

Payments secured by Stripe

© WEiRDSOFT LTD. All rights reserved.

Custom Commands