botiti

Discord servers become more fun with custom bots. While there are plenty of feature-rich bots available, building your own allows for inside jokes, personalized commands, and exactly the functionality your group wants.

BOTiti is a custom Discord bot I built for friends, featuring Youtube video playback, Reddit integration, custom commands, and automated responses to make our server more entertaining.

Screenshot of BOTiti in action on Discord

the appeal of custom bots

Public Discord bots are powerful, but they're generic. They don't know your server's culture, inside jokes, or specific needs. A custom bot can respond to running gags, target specific users with automated responses, and integrate exactly the content sources you care about.

BOTiti was designed around our group's sense of humor - responding to specific people, fetching memes from particular subreddits, and running commands we actually wanted.

main features

The bot responds to commands prefixed with !:

  • YouTube playback - Play audio from YouTube links in voice channels - useful for playing musics to the group when playing
  • Reddit integration - Fetch and post images from specific subreddits
  • Custom command system - Command dictionary loaded at runtime
  • User-specific responses - Automated reactions to particular server members
  • Command discovery - List all available commands

Everything is intentionally simple and focused on entertainment rather than server management.

technical implementation

Built with Python and discord.py:

  • discord.py for Discord API interaction
  • PRAW for Reddit content fetching
  • pickle for persisting command configurations

The bot maintains state through a command dictionary that can be updated without redeploying, making it easy to add new functionality on the fly.

command system

Commands are stored in a dictionary mapping command names to Python functions:

commands = {
    'play': ['play_youtube_video', '(message, video_name)'],
    'skip': ['skip_current_video', '(message)'],
    'queue': ['show_video_queue', '(message)'],
    'repeat': ['toggle_repeat_mode', '(message)'],
    'reddit': ['get_imgs_from_reddit', '(message, subreddit)'],
    'commands': ['say_command_list', '(message, commands)']
}

This design allows for flexible command creation - each entry specifies the function to call and its arguments. While using eval() isn't the most secure pattern, the bot only executes predefined commands from this dictionary.

reddit integration

One of BOTiti's signature features is pulling content from Reddit and posting it in Discord. The bot:

  1. Takes a subreddit or search term from the command
  2. Fetches a post using PRAW
  3. Checks if the channel allows NSFW content
  4. Posts the image as a Discord embed

This brings relevant memes and content directly into conversations without leaving Discord.

personality

The isBlacklisted function checks every message for specific users and responds with an inside joke. It's silly, but these personalized touches make the bot feel like part of the community rather than a tool.

deployment

The bot ran continuously on a Heroku server, connecting to Discord's gateway and listening for events. The !stop command allows for graceful shutdown for testing purposes, though the bot typically runs for weeks without intervention.

lessons learned

Building a Discord bot taught me:

  • Event-driven architecture - Discord bots are reactive by nature
  • API rate limits - Be mindful of Discord's and Reddit's request limits, the bot had rate limiting logic for this
  • Error handling matters - Bare except clauses hide bugs; specific exception handling is better
  • Community features create engagement - People used the bot constantly because it was tailored to them

reflection

BOTiti isn't sophisticated or feature-complete, but it didn't need to be. It served its purpose: making our Discord server more entertaining and personalized.

While I've since worked with more advanced bot frameworks, this project remains a fun reminder that the best tools are the ones designed for specific communities with specific needs.