Ask — a focused Discord application that provides quick answers, web searches, and image generation via a single /ask command or by mentioning the bot in chat. This repository contains the bot implementation, localization files, and deployment helpers (systemd / Docker). The project is based on the @eliware/discord foundations and is ready to adapt to your server.
- Overview
- Features
- Quick Start
- Usage
- Configuration
- Deployment
- Database & Telemetry
- Localization
- Development & Testing
- Support
- License
- Links
Ask is a concise assistant for Discord that supports:
- Short answers, summaries, and rewrites
- Quick web searches to surface sources
- Simple image generation (via the bot's image tool)
- Context-aware replies by including recent channel messages
- Usage tracking and optional persistence of generated images
The bot is intentionally concise: the system prompt instructs responses to be succinct and to not identify as "ChatGPT" or "OpenAI".
- Single
/askcommand with natural language input - Message fallback: mention the bot, DM it, or reply to a bot message to invoke /ask
- Automatic inclusion of recent message history (up to 100 messages) for context
- Image generation support (returns images as attachments or URLs)
- Rate limiting (per-user, per-channel, per-guild) enforced via the usage DB
- Usage and response metadata stored to a
usagetable; generated images saved tousage_imageswhen enabled - Locales support for multi-language replies (see locales/)
- Ready-to-run with systemd or Docker
- Testable with Jest
-
Clone the repo and install dependencies:
git clone https://github.com/eliware/ask.git cd ask npm install -
Copy and edit environment variables:
cp .env.example .env # edit .env and add your Discord token, DB credentials, OpenAI/API keys, etc. -
Start locally:
npm start # or node ask.mjs
Use the slash command for structured usage:
- Examples:
- /ask explain recursion in simple terms
- /ask summarize the last 3 messages
- /ask draft a 3-item meeting agenda about onboarding
- /ask generate a simple red circle on a white background --image
The handler will:
- Defer the reply (typing indicator) while contacting the backend
- Include recent channel history when available
- Return text and attach generated images (files or URLs)
- Split long replies into multiple messages when needed
The bot also listens for messages and will create a lightweight mock interaction when:
- The bot is mentioned in a server message
- The message is a reply to a message previously sent by the bot
- The bot receives a DM
Behavior:
- Strips the mention and uses the remaining text as the prompt (falls back to "Hello!" if empty)
- Replies in-channel (or DMs user if response is ephemeral)
- Uses blockquote formatting per-line for message-originated replies
- Respects Discord message length limits (chunks to 2000 characters)
All runtime configuration is via .env. Copy .env.example to .env and provide required values:
- DISCORD_TOKEN / DISCORD_CLIENT_ID / DISCORD_PUBLIC_KEY (Discord app credentials)
- DATABASE_URL or DB connection details (optional, required for usage tracking & image persistence)
- OPENAI_KEY or other model API credentials (if using external LLM/image tools)
- LOG_LEVEL, NODE_ENV, and other standard variables
See .env.example for the complete list.
Start with npm start or node ask.mjs. Ensure your .env is populated.
A sample ask.service (included) facilitates running the app as a systemd service:
-
Copy
ask.serviceto/usr/lib/systemd/system/ask.serviceand adjust paths/user. -
Reload and start:
sudo systemctl daemon-reload sudo systemctl enable ask sudo systemctl start ask sudo systemctl status ask
Build and run:
docker build -t ask .
docker run --env-file .env askThis bot optionally integrates with a MySQL/MariaDB database to record usage, enforce rate limits, and persist generated images. If you do not need persistence, you can run the bot without a configured DB (image persistence, rate-limits, and usage analytics will be disabled).
Key points:
- The app records a pre-call row in a
usagetable and updates it after the LLM response. - Generated images (when present) may be stored in
usage_imagesas binary BLOBs with JSON metadata. - Schema dump for the database is included at
/opt/ask/schema.sqlin this repository (or generated by the maintainer).
The code expects the following tables (see /opt/ask/schema.sql for the exact CREATE statements):
usage— records queries and responses plus metadatausage_images— stores image blobs and metadata with a FK tousage
You can consult /opt/ask/schema.sql for the complete table definitions and character-set options.
Example commands to create the ask database and a dedicated ask user with restricted privileges (run as a MySQL root user):
-- run in mysql shell as root
CREATE DATABASE IF NOT EXISTS `ask` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'ask'@'%' IDENTIFIED BY 'your_strong_password_here';
GRANT SELECT, INSERT, UPDATE, DELETE ON `ask`.* TO 'ask'@'%';
-- Optional: grant LOCK TABLES and SHOW VIEW if you plan to run full dumps or use views
GRANT LOCK TABLES, SHOW VIEW ON `ask`.* TO 'ask'@'%';
FLUSH PRIVILEGES;After creating the DB and user, apply the schema (from the repo) as root or a user with CREATE privileges:
mysql -u root -p ask < /opt/ask/schema.sql
# or, if you have the schema locally
mysql -u root -p ask < schema.sqlNotes:
- The code performs INSERT/UPDATE via prepared statements; ensure the DB user has INSERT and UPDATE rights.
- If you will allow the bot to write image BLOBs, ensure your MySQL instance has appropriate max_allowed_packet and disk capacity.
Backup (schema + data) with mysqldump:
# full dump (schema + data)
mysqldump -u root -p ask > ask_full_dump.sql
# schema only
mysqldump --no-data -u root ask > ask_schema.sqlRestore:
# restore schema/data
mysql -u root -p ask < ask_full_dump.sqlPermissions for dumps:
- For logical backups, mysqldump needs SELECT on all tables. LOCK TABLES is required for consistent dumps unless you use --single-transaction.
If using a MySQL container, set the corresponding env vars in .env (MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE). Example docker-compose service snippet:
services:
mysql:
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: example_root_pw
MYSQL_DATABASE: ask
MYSQL_USER: ask
MYSQL_PASSWORD: ask_pw
volumes:
- mysql-data:/var/lib/mysql
ask:
build: .
env_file: .env
depends_on:
- mysqlWhen running in containers, use docker exec to run mysqldump inside the DB container if network access is restricted.
Responses and help text are localized via JSON files under locales/. The default English help (locales/en-US.json) contains the bot's quick-help text and install link.
Add or edit locale files to localize command names, descriptions, and bot responses.
-
Tests are run with Jest:
npm test -
Command handlers live in
commands/(e.g.,commands/ask.mjs). -
Event handlers live in
events/(e.g.,events/messageCreate.mjs). -
The ask handler expects an interaction-like object and supports both real interactions and the lightweight mock created by the messageCreate handler.
Tips:
- The code attempts to import
@eliware/discordsplit helpers when available for message chunking; this is optional. - Typing indicator is kept alive with an interval while processing message-originated requests — ensure that any custom handlers clear this interval on completion to avoid stray timers.
For help or discussion, join the community:


