Reactions Module
The Reactions Module (@zumito-team/reactions-module) provides a /reaction command that sends animated GIF reactions with customizable categories (kiss, angry, happy, etc.) and multi-language message templates. It includes a complete admin panel for managing categories and images.
Installation
Section titled “Installation”npm install @zumito-team/reactions-moduleAdd to your zumito.config.ts:
bundles: ['@zumito-team/reactions-module']What it provides
Section titled “What it provides”Reaction command
Section titled “Reaction command”The /reaction slash command with arguments:
| Argument | Type | Required | Description |
|---|---|---|---|
category | string | Yes | Reaction category (kiss, angry, happy, etc.). |
member | user | No | Target user. If omitted, the reaction is self-directed. |
When executed:
- Looks up the category (merging defaults with database overrides).
- Resolves the locale from guild settings.
- Selects a random image from the category.
- Renders the template with
%user%and%user2%placeholders. - Sends a Discord embed with the image, author info, and formatted message.
Default categories
Section titled “Default categories”Three categories come pre-configured:
| Category | Order | Templates (EN) |
|---|---|---|
kiss | 1 | %user% kissed %user2% / %user% wants to kiss themselves |
angry | 2 | %user% got angry with %user2% / %user% is angry |
happy | 3 | %user% got happy with %user2% / %user% is happy |
Each category has a default GIF image from cdn.nekotina.com.
ReactionService
Section titled “ReactionService”Accessible via the service container:
const reactions = ServiceContainer.getService('ReactionService');| Method | Description |
|---|---|
listCategories() | List all categories with merged defaults and overrides. |
getCategory(key) | Get a single category by key. |
upsertCategory(input) | Create or update a category. |
deleteCategory(key) | Delete a category from the database. |
addImage(categoryKey, imageInput) | Add an image to a category. |
updateImage(categoryKey, imageUrl, updates) | Update an image’s source or description. |
removeImage(categoryKey, imageUrl) | Remove an image by URL. |
getImagesForCategory(key) | Get all images for a category. |
getRandomImage(key) | Get a random image from a category. |
Admin panel routes
Section titled “Admin panel routes”| Method | Path | Description |
|---|---|---|
GET | /admin/reactions | Category list with CRUD forms. |
POST | /admin/reactions/category | Create/update a category. |
POST | /admin/reactions/category/:key/delete | Delete a category. |
GET | /admin/reactions/images | Images management page. |
POST | /admin/reactions/category/:key/images | Add image to category. |
POST | /admin/reactions/category/:key/images/update | Update image source/description. |
POST | /admin/reactions/category/:key/images/delete | Delete an image. |
Configuration
Section titled “Configuration”All category data is stored in the reaction_categories database collection. Categories can be managed entirely through the admin panel.
Category schema
Section titled “Category schema”| Field | Type | Description |
|---|---|---|
key | string | Unique category identifier (lowercase, trimmed). |
order | number | Display order. |
images | ReactionImage[] | Array of { source: string, description?: string } objects. |
translations | TranslationMap | Record<string, { mentionTemplate: string, simpleTemplate: string }> for each locale. |
Templates
Section titled “Templates”Templates are locale-aware and support two variants:
mentionTemplate— Used when a target user is specified (%user%= author,%user2%= target).simpleTemplate— Used for self-reactions (%user%= author).
Extending
Section titled “Extending”Adding custom categories programmatically
Section titled “Adding custom categories programmatically”const reactions = ServiceContainer.getService('ReactionService');
await reactions.upsertCategory({ key: 'highfive', order: 4, translations: { en: { mentionTemplate: '%user% high-fived %user2%!', simpleTemplate: '%user% wants a high-five!' }, es: { mentionTemplate: '%user% chocó los cinco con %user2%!', simpleTemplate: '%user% quiere chocar los cinco!' } }, images: [ { source: 'https://example.com/highfive1.gif', description: 'Epic high five' }, { source: 'https://example.com/highfive2.gif', description: 'Slow motion high five' } ]});Consuming ReactionService in other modules
Section titled “Consuming ReactionService in other modules”class MyModule extends Module { requirements = { services: ['ReactionService'] };
async getRandomKissGif(): Promise<string> { const reactions = ServiceContainer.getService('ReactionService'); const image = await reactions.getRandomImage('kiss'); return image?.source; }}Adding more locales
Section titled “Adding more locales”The translation system supports any locale key. Simply add translations for a new locale:
await reactions.upsertCategory({ key: 'kiss', translations: { fr: { mentionTemplate: '%user% a embrassé %user2%!', simpleTemplate: '%user% veut un bisou!' } }});Dependencies
Section titled “Dependencies”@zumito-team/admin-module— ForNavigationService,AdminAuthService, andAdminViewService.ejs— Template rendering.zumito-framework
Related modules
Section titled “Related modules”- Admin Module — Provides the admin panel where reactions are managed.