A lightweight, personal “swipe” style matching mini‑game for Discord servers. Users opt into a pool with a short bio. When someone starts a round, they get shown profiles one‑by‑one with Yes / Skip buttons, then can reveal mutual matches.
- Opt‑in pool:
join/leave - Profiles: per‑user bio stored in JSON
- Personal sessions: only the session owner can press buttons
- Mutual matching: results show only reciprocal “yes” pairs
- Safety-ish: strips ANSI/control characters from user bios before embedding
- Python 3.10+ recommended
discord.py2.x (uses interactions/buttons)- Discord Developer Portal intents:
- Server Members Intent (this module uses
guild.get_member) - Message Content Intent (if your bot uses prefix commands like
!pm)
- Server Members Intent (this module uses
Install deps:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtCopy .env.example to .env and set:
DISCORD_TOKEN
If your main bot already loads env vars, you’re done. If it doesn’t, add
python-dotenv loading in your entrypoint:
from dotenv import load_dotenv
load_dotenv()In config.py:
PERFECT_MATCH_CHANNEL_ID = <channel_id>
This is the only channel where start is allowed. (Ending a session can be done anywhere.)
In config.py:
JOIN_TIMER(seconds, currently unused in provided code)SWIPE_TIMER(seconds per profile)
- Join Phase
- Builds the target list: opted-in participants who also have a profile and are in the guild.
- Swipe Phase
- Shows each target with Yes / Skip buttons.
- Records responses in
responses.jsonas{viewer_id, target_id, choice}. - Buttons are guarded so only the session owner can click.
- Supports cancellation via an in-memory
asyncio.Event.
- Results Phase
- Sends a Reveal Results button.
- Owner gets an ephemeral list of mutual matches.
This module registers a command group:
!perfect_match(aliases:!pm,!perfect_march)!pm start
Starts a personal session and auto‑joins the caller to the pool.!pm end
Cancels the caller’s current session (if active).!pm bio <text>
Sets/updates your bio.!pm profile [@user]
Shows your bio (or the mentioned user’s bio).!pm join
Opt into the pool.!pm leave
Opt out of the pool.
Because commands.py uses:
from bot import get_bot…your main project needs to expose that function and return a discord.ext.commands.Bot
(or compatible subclass).
Also, message sending goes through:
from pets.helper import send_as_petIf your bot doesn’t have that, replace send_as_pet(...) with channel.send(...)
or your own helper.
A typical integration pattern:
- Ensure your bot imports/loads this module on startup.
- Make sure
setup_perfect_match_commands(bot)is called if your framework expects it (right now it’s a no‑op and commands are registered at import time via@bot.group).
MIT. See LICENSE.