|
1 | 1 | [discord-shield]: https://img.shields.io/discord/1407300551686885418?color=5865F2&logo=discord&logoColor=white |
| 2 | + |
2 | 3 | [discord-invite]: https://discord.gg/9Bzma6SwtW |
3 | 4 |
|
4 | 5 | <div align="center"> |
|
10 | 11 | [ ![discord-shield][] ][discord-invite] |
11 | 12 |
|
12 | 13 | --- |
13 | | -A Discord modmail bot written in Rust that allows staff to manage support tickets via channels, with features like message editing, internationalization, structured error handling, and more. |
14 | | -The bot can operate in single-server or dual-server modes, supports SQLite for data storage, and offers a range of commands for staff to interact with users efficiently. |
15 | | - |
16 | | ---- |
17 | | -## ⚠️ Warning ⚠️ |
18 | | -This is my first major project in Rust; while I have solid experience in C and other languages, I'm learning Rust as I go — feedback and PRs are welcome. |
19 | | - |
20 | | -Project documentation is currently being written. |
21 | | - |
22 | | ---- |
23 | | -## Feature Summary (Currently Implemented) |
24 | | -- Open support ticket / staff⇄user thread (`!new_thread` or optional manual creation if enabled) |
25 | | -- **Single-server** or **dual-server (community + staff)** mode |
26 | | -- SQLite storage (threads, messages, staff alerts, blocked users) |
27 | | -- Incremental per-thread message numbering |
28 | | -- Staff replies → user DM + mirrored in thread channel |
29 | | -- Anonymous replies (`!anonreply` / `!ar`) |
30 | | -- Retroactive message editing (staff) with propagation & internal audit note (`!edit` / `!e`) |
31 | | -- Message deletion + renumbering (`!delete`) |
32 | | -- Controlled thread closing (`!close`) + forced orphan cleanup (`!force_close`) |
33 | | -- Scheduled closing with cancel and silent modes (see Thread Closing) |
34 | | -- Thread category moving with fuzzy matching (`!move` / `!mv`) |
35 | | -- Add/remove staff participants to a ticket (`!add_staff`, `!remove_staff`) |
36 | | -- Staff alert subscription with ping on next user activity (mentions + auto-clear on use) |
37 | | -- User/server membership awareness (e.g., user left server / not in community → system notice) |
38 | | -- Asynchronous recovery of missing messages (`!recover`) |
39 | | -- Typing proxy (user ↔ staff) configurable |
40 | | -- Configurable system messages (welcome / close) |
41 | | -- Configurable embed colors (user / staff / system) in hex |
42 | | -- Fine‑grained success/failure notification toggles |
43 | | -- Internationalization (multi-language + per-user preferences) – English & French shipped |
44 | | -- Structured error system (categorization, codes, TTL, auto-delete, translation) |
45 | | -- Error & language test commands (`!test_errors`, `!test_language`, `!test_all_errors`) |
46 | | -- In‑memory per-thread locks (basic race mitigation) |
47 | | -- Attachment download & relay |
48 | | -- Dynamic configuration validation (logs, features, Discord guild access) |
| 14 | +A Discord modmail bot written in Rust that allows staff to manage support tickets via channels, with features like |
| 15 | +message editing, internationalization, structured error handling, and more. |
| 16 | +The bot can operate in single-server or dual-server modes, supports SQLite for data storage, and offers a range of |
| 17 | +commands for staff to interact with users efficiently. |
49 | 18 |
|
50 | 19 | --- |
51 | | -## Architecture |
52 | | -- `main.rs`: Initialization (DB, config, Serenity client, handlers, guild validation) |
53 | | -- `config.rs`: Load + structural validation + dependency injection (pool, error handler) |
54 | | -- `handlers/`: Discord event listeners (messages, reactions, members, interactions, moderation, ready, typing proxy) |
55 | | -- `commands/`: Prefix command logic (manual parsing) |
56 | | -- `db/` & `db/operations/`: SQLx abstraction (SQLite) – threads, messages, features, alerts |
57 | | -- `modules/`: Functional logic (message recovery, thread helpers) |
58 | | -- `utils/`: Utility helpers (conversion, message builder, content extraction, time, locks) |
59 | | -- `i18n/`: Dictionary system + multi-language resolution + fallback |
60 | | -- `errors/`: Strongly typed errors, dictionary mapping → localized embeds |
61 | | -- `features/`: Optional / experimental modules (e.g. poll) |
62 | | - |
63 | | -### Staff → User Reply Flow |
64 | | -1. Staff types `!reply` inside a thread channel |
65 | | -2. Parse content & attachments |
66 | | -3. Allocate message number (approx. atomic) → increment `next_message_number` |
67 | | -4. Send staff embed to thread + DM user |
68 | | -5. Persist in DB (`thread_messages`) with Discord IDs |
69 | | -6. Optional success notification |
70 | | - |
71 | | -### Thread Closing |
72 | | -- `!close`: Final DM (if user still guild member), mark closed & delete channel |
73 | | -- Scheduled closing with delay and optional silent mode (no user DM) |
74 | | -- `!close cancel`: Cancel a scheduled closing (prevents pending closure) |
75 | | -- `!force_close`: Delete orphaned channel OR residual untracked inbox channel |
76 | | - |
77 | | -### Message Editing |
78 | | -- `!edit <num> <new text>`: Validate rights (author/staff), fetch IDs, edit thread + DM messages, update DB |
79 | | -- System message (audit) indicates change with deep link to edited message |
80 | | - |
81 | | ---- |
82 | | -## Configuration (config.toml) |
83 | | -Minimal example (adjust real IDs): |
84 | | -```toml |
85 | | -[bot] |
86 | | -token = "YOUR_TOKEN" |
87 | | -status = "DM FOR SUPPORT" |
88 | | -welcome_message = "We received your message! A staff member will reply soon." |
89 | | -close_message = "Thanks for contacting support! Your ticket is now closed." |
90 | | -typing_proxy_from_user = true |
91 | | -typing_proxy_from_staff = true |
92 | | -enable_logs = true |
93 | | -enable_features = true |
94 | | -logs_channel_id = 1404359738566133899 |
95 | | -features_channel_id = 1406940454859309076 |
96 | | - |
97 | | -[bot.mode] |
98 | | -type = "dual" |
99 | | -community_guild_id = 1209667980506892590 |
100 | | -staff_guild_id = 711880297245311856 |
101 | | - |
102 | | -[command] |
103 | | -prefix = "!" |
104 | | - |
105 | | -[thread] |
106 | | -inbox_category_id = 1376460196847505960 |
107 | | -embedded_message = true |
108 | | -user_message_color = "3d54ff" |
109 | | -staff_message_color = "ff3126" |
110 | | -system_message_color = "00ff00" |
111 | | -block_quote = true |
112 | | -time_to_close_thread = 5 |
113 | | -create_ticket_by_create_channel = true |
114 | | - |
115 | | -[notifications] |
116 | | -show_success_on_edit = false |
117 | | -show_partial_success_on_edit = true |
118 | | -show_failure_on_edit = true |
119 | | -show_success_on_reply = false |
120 | | -show_success_on_delete = false |
121 | | - |
122 | | -[logs] |
123 | | -show_log_on_edit = true |
124 | | - |
125 | | -[language] |
126 | | -default_language = "en" |
127 | | -auto_detect = true |
128 | | -fallback_language = "en" |
129 | | -supported_languages = ["en", "fr", "es", "de"] |
130 | 20 |
|
131 | | -[error_handling] |
132 | | -show_detailed_errors = false |
133 | | -log_errors = true |
134 | | -send_error_embeds = true |
135 | | -auto_delete_error_messages = true |
136 | | -error_message_ttl = 30 |
137 | | -``` |
138 | | - |
139 | | ---- |
140 | | -## Commands (Prefix configurable – default `!`) |
141 | | -General format: `!command [arguments]` |
142 | | - |
143 | | -| Command | Alias | Description | Example | |
144 | | -|----------------------------------|-------|-----------------------------------------------------------------------------------------------------------------|----------------------------------| |
145 | | -| new_thread <user_id \| @mention> | nt | Create a thread for a user | `!new_thread 123456789012345678` | |
146 | | -| reply <text> | r | Reply (staff visible + DM) | `!reply Hello` | |
147 | | -| anonreply <text> | ar | Anonymous reply | `!ar Thanks for reporting` | |
148 | | -| edit <num> <new> | e | Edit message number N | `!edit 5 Correction` | |
149 | | -| delete <num> | — | Delete message N + renumber | `!delete 7` | |
150 | | -| add_staff <@user> | — | Add a staff member to the current ticket | `!add_staff @Moderator` | |
151 | | -| remove_staff <@user> | — | Remove a staff member from the current ticket | `!remove_staff @Moderator` | |
152 | | -| id [@user] | — | Show the numeric ID of a user (defaults to author if omitted) | `!id @User` | |
153 | | -| move <category> | mv | Move thread to category (fuzzy) | `!move Resolved` | |
154 | | -| alert [cancel] | — | Set (or cancel) personal alert | `!alert` / `!alert cancel` | |
155 | | -| recover | — | Start async missing message recovery | `!recover` | |
156 | | -| close | — | Close current thread (DM user if still present) | `!close` | |
157 | | -| close cancel | — | Cancel a scheduled closing | `!close cancel` | |
158 | | -| force_close | — | Force delete orphan / leftover channel | `!force_close` | |
159 | | -| test_errors <type> | — | Emit test error (db, discord, command, validation, message, thread, permission, user, channel, number, success) | `!test_errors db` | |
160 | | -| test_language <code> | — | Set user language + trigger test error | `!test_language fr` | |
161 | | -| test_all_errors | — | Sequential demo of various errors | `!test_all_errors` | |
162 | | - |
163 | | -Notes: |
164 | | -- `move` uses Levenshtein matching (~50% distance threshold) on category names. |
165 | | - |
166 | | ---- |
167 | | -## Internationalization (i18n) |
168 | | -- Default + fallback language from config. |
169 | | -- Per-user preference via `!test_language <code>` (test command; a dedicated command could replace it later). |
170 | | -- Key namespaces: (reply.*, delete.*, new_thread.*, move.*, permission.*, success.*, close.*, alert.*, server.*, user.*, etc.). |
171 | | -- Missing translation → fallback language. |
172 | | - |
173 | | -### Adding a Language |
174 | | -1. Create file in `src/i18n/language/<code>.rs` |
175 | | -2. Implement dictionary similar to `en.rs` |
176 | | -3. Add code to `supported_languages` + enum mapping |
177 | | - |
178 | | ---- |
179 | | -## Install & Run |
180 | | -### Prerequisites |
181 | | -- Rust (2024 edition toolchain) – see `rust-toolchain.toml` |
182 | | -- SQLite library (SQLx manages access) |
183 | | -- Create application + bot in [Discord Developer Portal] |
184 | | - |
185 | | -### Steps |
186 | | -```bash |
187 | | -git clone https://github.com/Akinator31/rustmail.git |
188 | | -cd rustmail |
189 | | -cp config.example.toml config.toml |
190 | | -cargo run --release |
191 | | -``` |
| 21 | +## ⚠️ Warning ⚠️ |
192 | 22 |
|
193 | | -### Critical Variables |
194 | | -- Keep `bot.token` secret (do not commit). |
195 | | -- Enable required privileged intents (MESSAGE CONTENT, GUILD MEMBERS, PRESENCES) in the developer portal. |
| 23 | +This is my first major project in Rust; while I have solid experience in C and other languages, I'm learning Rust as I |
| 24 | +go — feedback and PRs are welcome. |
196 | 25 |
|
197 | | ---- |
198 | | -## Roadmap |
199 | | -Not yet determined. See GitHub Project. |
200 | | - |
201 | | ---- |
202 | | -## Message Conventions |
203 | | -- Staff → `staff_message_color` |
204 | | -- User → `user_message_color` |
205 | | -- System / success / errors → `system_message_color` (or derivative) |
206 | | -- `block_quote = true` applies quoted styling depending on builder implementation |
| 26 | +Project documentation is currently being written. |
207 | 27 |
|
208 | 28 | --- |
209 | | -## Maintenance |
210 | | -- Backups: copy `db/db.sqlite` |
211 | | -- New migration → restart binary (sqlx applies at startup via `init_database()`) |
212 | | -- Logs: currently stdout/stderr (improve later) |
213 | 29 |
|
214 | | ---- |
215 | | -## License |
216 | | -MIT. See LICENSE file. |
| 30 | +## Getting Started |
217 | 31 |
|
218 | | ---- |
219 | | -## Contributions |
220 | | -Alpha phase: open descriptive issues (bugs, UX). PRs accepted after discussion. |
| 32 | +- 🛠️ [Setting up the bot](https://github.com/Rustmail/rustmail/tree/main/docs/setup.md) |
| 33 | +- 📦 [Commands](https://github.com/Rustmail/rustmail/tree/main/docs/commands.md) |
221 | 34 |
|
222 | 35 | --- |
223 | | -## Final Disclaimer |
224 | | -Project is in **alpha**. APIs, structures, schemas and behaviors may change without backward compatibility. Do not use in critical environments or with sensitive data. Make frequent backups. |
225 | 36 |
|
226 | | ---- |
| 37 | +## Support |
227 | 38 |
|
228 | | -Made with Rust 🦀 – contributions welcome. |
| 39 | +If you need help, join the [Discord server][discord-invite] and ask for assistance in the #support channel. |
0 commit comments