{"id":49305157,"url":"https://github.com/jayanaxhf/hydride","last_synced_at":"2026-04-26T09:03:12.749Z","repository":{"id":352635464,"uuid":"1215924439","full_name":"JayanAXHF/Hydride","owner":"JayanAXHF","description":"A moderation bot for the Plushy's Playground Investigation Server","archived":false,"fork":false,"pushed_at":"2026-04-20T12:51:00.000Z","size":42,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T14:48:05.790Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JayanAXHF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-20T11:45:09.000Z","updated_at":"2026-04-20T12:51:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JayanAXHF/Hydride","commit_stats":null,"previous_names":["jayanaxhf/hydride"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/JayanAXHF/Hydride","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JayanAXHF%2FHydride","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JayanAXHF%2FHydride/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JayanAXHF%2FHydride/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JayanAXHF%2FHydride/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JayanAXHF","download_url":"https://codeload.github.com/JayanAXHF/Hydride/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JayanAXHF%2FHydride/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32291343,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T08:29:33.829Z","status":"ssl_error","status_checked_at":"2026-04-26T08:29:18.366Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-26T09:03:09.458Z","updated_at":"2026-04-26T09:03:12.734Z","avatar_url":"https://github.com/JayanAXHF.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Moderation Bot\n\nA Discord moderation bot written in Rust with `poise`, `serenity`, and `sqlx`.\n\nIt supports both prefix commands and slash commands, stores moderation cases in SQLite, and sends audit-style moderation logs to a configured channel.\n\n## Features\n\n- Warn, timeout, kick, ban, and unban members\n- Purge recent messages from a channel\n- Persist moderation cases in SQLite\n- View a single case or recent cases for a user\n- Per-guild moderation settings stored in the database\n- Configurable moderator roles in addition to Discord permissions\n- Automatic database migrations on startup\n- Slash command registration either globally or to development guilds only\n\n## Tech Stack\n\n- Rust 2024\n- `poise` / `serenity` for Discord bot framework and API access\n- `tokio` for async runtime\n- `sqlx` with SQLite for persistence\n- `tracing` for logging\n\n## Configuration\n\nThe bot reads configuration from `config.toml` by default.\n\nYou can override the config path with:\n\n```bash\nMODBOT_CONFIG=/path/to/config.toml cargo run\n```\n\nUse `config.example.toml` as a starting point:\n\n```toml\n[discord]\ntoken = \"DISCORD_BOT_TOKEN\"\nprefix = \"!\"\nowner_ids = []\ndev_guild_ids = [123456789012345678]\nregister_globally = false\n\n[database]\nurl = \"sqlite://moderation_bot.db\"\n\n[logging]\nfilter = \"info,serenity=warn,sqlx=warn\"\n\n[moderation]\ndefault_log_channel_id = 123456789012345678\nrequire_reason = true\nephemeral_slash_responses = true\nmax_case_results = 10\n```\n\n### Config Fields\n\n`[discord]`\n\n- `token`: Bot token\n- `prefix`: Prefix for text commands\n- `owner_ids`: Optional Discord user IDs treated as bot owners by `poise`\n- `dev_guild_ids`: Guild IDs used for slash command registration when `register_globally = false`\n- `register_globally`: Register application commands globally instead of per dev guild\n\n`[database]`\n\n- `url`: SQLite connection string\n\n`[logging]`\n\n- `filter`: `tracing_subscriber` env filter string\n\n`[moderation]`\n\n- `default_log_channel_id`: Default moderation log channel used if a guild-specific value is not set\n- `require_reason`: Require a reason for moderation commands\n- `ephemeral_slash_responses`: Send slash command confirmations ephemerally\n- `max_case_results`: Maximum number of cases returned by the `cases` command\n\n## Running\n\n1. Copy `config.example.toml` to `config.toml`.\n2. Fill in your Discord bot token and guild/channel IDs.\n3. Run the bot:\n\n```bash\ncargo run\n```\n\nOn startup, the bot:\n\n- loads the bootstrap config\n- initializes tracing\n- connects to SQLite\n- runs database migrations from `migrations/`\n- registers slash commands\n- starts the Discord gateway client\n\n## Required Discord Intents\n\nThe bot enables these gateway intents:\n\n- non-privileged intents\n- `MESSAGE_CONTENT`\n- `GUILD_MEMBERS`\n- `GUILD_MESSAGES`\n- `GUILD_MODERATION`\n\nMake sure the matching privileged intents are enabled in the Discord developer portal if your bot needs them.\n\n## Commands\n\nAll commands are available as both prefix commands and slash commands unless noted otherwise.\n\n### Meta\n\n- `ping`\n- `help [command]`\n\n### Moderation\n\n- `warn \u003cuser\u003e [reason]`\n- `timeout \u003cuser\u003e \u003cduration\u003e [reason]`\n- `kick \u003cuser\u003e [reason]`\n- `ban \u003cuser\u003e [reason]`\n- `unban \u003cuser\u003e [reason]`\n- `purge [user] \u003ccount\u003e [reason]`\n\nDuration format for `timeout` supports `s`, `m`, `h`, and `d`, for example `30m`, `4h`, or `7d`.\n\n### Cases\n\n- `case \u003ccase_id\u003e`\n- `cases \u003cuser\u003e [limit]`\n\n### Configuration\n\n- `config view`\n- `config set_log_channel \u003cchannel\u003e`\n- `config clear_log_channel`\n- `config set_require_reason \u003ctrue|false\u003e`\n- `config set_ephemeral \u003ctrue|false\u003e`\n- `config add_mod_role \u003crole\u003e`\n- `config remove_mod_role \u003crole\u003e`\n\n## Permissions Model\n\nModeration commands check both Discord permissions and guild-specific moderator roles.\n\n- Guild owners are always allowed\n- Administrators are allowed\n- Users with the required Discord permission are allowed\n- Users with a configured moderator role are allowed\n\nThe bot also checks role hierarchy before acting on a target member.\n\n## Data Model\n\nThe SQLite schema includes:\n\n- `guild_settings`: per-guild moderation settings\n- `guild_mod_roles`: extra roles allowed to moderate\n- `moderation_cases`: stored moderation actions\n- `case_notes`: note records attached to cases\n\nEach moderation action creates a case record. If audit log delivery succeeds, the audit message channel and message IDs are stored with the case.\n\n## Audit Logging\n\nModeration actions are posted as embeds to the configured moderation log channel. Embeds include:\n\n- action type\n- moderator\n- target\n- creation time\n- reason\n- optional duration / expiry\n- optional details\n\n## Current Limitations\n\n- `notes_enabled` and `appeals_enabled` are stored in guild settings but do not have full user-facing flows yet.\n- `case_notes` support exists in the database and code, but there is no public command wired in for adding notes.\n- `purge` with a specific target user is not complete yet; the filtered fetch helper still ends in `todo!()`.\n\n## Development\n\nUseful commands:\n\n```bash\ncargo fmt\ncargo check\ncargo run\n```\n\nFor local development, keep `register_globally = false` and set `discord.dev_guild_ids` so slash commands update quickly in a test server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjayanaxhf%2Fhydride","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjayanaxhf%2Fhydride","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjayanaxhf%2Fhydride/lists"}