A hobby project Discord bot built around Anki and YouTube. It watches YouTube channels for new uploads and streams, manages Anki flashcard sessions through Discord, and ties it all together with a shared config file and a couple of services that talk to each other.
Nothing fancy. It works for what I need it to do.
holoBot/
└── services/
├── anki-api/ # Python HTTP server that wraps Anki's internals
└── discord-bot/ # Java Discord bot powered by JDAThe two services are designed to run alongside each other. The Discord bot talks to the Anki API over HTTP to handle flashcard stuff. The YouTube side runs independently and just polls the YouTube Data API on a schedule.
- You run
anki-api— it starts a small HTTP server sitting in front of your local Anki collection. - You run
discord-bot— it connects to Discord, loads your config, and registers slash commands. - People use slash commands in Discord to study their Anki cards, browse decks, check stats, etc.
- The bot also polls YouTube channels you've configured and posts to Discord when there's new content.
Both services share a single config.yml. By default they both look for it at:
Active/holoBot/config/config.ymlYou can override the path in the individual service configs if you want to put it somewhere else.
Here's what a full config looks like:
version: 1.0
secrets:
discord_api_key: "your-discord-bot-token"
youtube_api_key: "your-youtube-data-api-key"
aa_api_key: "optional-anki-api-bearer-token"
global:
logLevel: INFO
timezone: UTC
files:
dataBase: "Active/holoBot/data/discord-bot/data.json"
logs: "Active/holoBot/logs/discord-bot.log"
config: "Active/holoBot/config/config.yml"
discord_bot:
channels:
- channelId: "UCxxxxxxxxxxxxxxxx" # YouTube channel ID to watch
checkQue: true
checkCooldown: 60
discordRoleId: "123456789012345678" # Role to ping on new content
discordChannelId: "123456789012345678" # Discord channel to post to
settings:
channelCooldownMinutes: 30
saveLimit: 50
options:
checkIntervalSeconds: 300
mediaChannelId: "123456789012345678"
premierChannelId: "123456789012345678"
streamChannelId: "123456789012345678"
modChannelId: "123456789012345678"
adminPingId: "123456789012345678"
anki_api:
options:
apiPollInterval: 25
apiVersion: 1
webBindAddress: "127.0.0.1"
webBindPort: 8211Python. Wraps Anki's collection internals and exposes them over HTTP. The Discord bot calls this to do anything Anki-related.
See services/anki-api/README.md for setup and usage.
Java, built with Gradle. Connects to Discord via JDA, registers slash commands, handles interactions, polls YouTube, and calls anki-api as needed.
See services/discord-bot/README.md for setup and usage.
You'll need:
- A Discord bot token (create one at discord.com/developers)
- A YouTube Data API v3 key (from Google Cloud Console)
- Anki installed locally with the
ankiPython package available - Java 21 for the Discord bot
- Python 3.9+ for the Anki API
- Copy the config template above, fill in your secrets, and save it somewhere.
- Start
anki-apifirst so the Discord bot can reach it on startup. - Start
discord-bot, point it at the same config file. - Invite the bot to your server and test a slash command.
That's the gist of it. Check the individual service READMEs for the specifics.
holoBot/
├── README.md
└── services/
├── anki-api/
│ ├── README.md
│ ├── pyproject.toml
│ ├── poetry.lock
│ ├── src/
│ │ └── anki-api/
│ │ ├── __init__.py # core API logic
│ │ ├── __main__.py # entry point
│ │ ├── edit.py # collection manager
│ │ ├── util.py # settings, helpers
│ │ └── web.py # HTTP server
│ └── tests/
└── discord-bot/
├── README.md
├── settings.gradle.kts
├── gradlew
└── app/
└── src/main/java/dev/m3v/
├── Main.java
├── Log.java
├── StartupChecks.java
├── Services.java
├── api/ # Anki API HTTP client
├── data/ # config, data, file I/O, models
├── discord/ # bot client, commands, UI framework
└── youtube/ # YouTube API clientHobby project. Use it however you want, just don't blame me if it breaks your Anki collection.