Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Discord LLM Announcement Summarizer

A Discord bot that watches game-announcement channels across several servers, summarizes each new announcement with a local LLM via any OpenAI-compatible API (defaults to LM Studio on localhost:1234), and delivers the result to your DM. The same DM is also a normal LLM chat.

  • Summaries preserve game name, version, release date and maintenance windows, with times converted to your timezone (default Europe/Paris).
  • Reads image attachments with the vision model and extracts text from PDF attachments, so announcements posted as screenshots or PDFs still get summarized; the source image is re-attached to the forwarded DM summary.
  • Each reply carries a small-text performance footer: TTFT | Prefill | Decode | Context (measured by streaming internally; only the completed reply is ever sent).
  • Chat in DMs, or in-server: a button spins up a private per-user channel that remembers the last 5 exchanges (10 messages).
  • One inference at a time (serial queue) — no GPU thrash, order preserved.
  • /models lists the server's models and shows the selected one; /models <name> tells the server which model to use (sent as the model field on every request).
  • Graceful handling of a down/slow LLM (offline, timeout, empty-response, unknown-model).

Requirements

  • Node.js 18+ (developed on 26).
  • An OpenAI-compatible LLM server with at least one model available — local LM Studio (default, http://localhost:1234/v1; app → Developer → Start Server, or lms server start) or a cloud one like OpenRouter (https://openrouter.ai/api/v1). Works with any /v1/chat/completions server.
  • A Discord application/bot you can invite to the announcement servers.

Setup

1. Install

npm install

2. Discord application

  1. Create an app at https://discord.com/developers/applications.
  2. Bot tab → Reset Token → copy into DISCORD_TOKEN.
  3. Bot tab → enable the MESSAGE CONTENT INTENT (privileged — required to read announcements).
  4. General Information → copy the Application ID into DISCORD_CLIENT_ID.
  5. OAuth2 → URL Generator → scopes bot + applications.commands; bot permissions: View Channels, Send Messages, Read Message History, and Manage Channels (the last only needed for server chat). Invite the bot to each server.
  6. In Discord, enable Settings → Advanced → Developer Mode, then right-click each announcement channelCopy ID, and right-click each recipientCopy ID. (The bot can only DM a user who shares a server with it and allows DMs.)

3. Configure

cp .env.example .env                 # fill DISCORD_TOKEN, DISCORD_CLIENT_ID
cp config.example.json config.json   # fill recipients + channel→game map

config.json:

Field Meaning
summaryRecipients User IDs (array) that receive announcement summaries.
chatUsers User IDs (array) allowed to chat with the bot in DMs — independent of summaries.
announcementChannels Map of channelId → game name (any number of channels).
serverChat.createChannelId Channel ID hosting the "Start a chat" button. Empty = server chat off.
serverChat.categoryName Category the bot creates/uses for per-user chat channels (default Bot Chats).
llm.model Model id the server should use (see /models). Empty = first available.
llm.allowedModels / llm.excludedModels OpenRouter only: when llm.model is openrouter/auto, restrict which models the auto-router may pick (arrays; wildcards like anthropic/* allowed).
llm.temperature, llm.maxTokens Generation settings.
llm.timeoutSeconds Per-generation timeout (also covers model load on first use).
timezone IANA zone for time conversion (default Europe/Paris).

summaryRecipients and chatUsers are independent — a user can receive summaries without chat access, or have chat access without receiving summaries. An older single-user ownerUserId still works (it applies to both lists).

Set OPENAI_BASE_URL in .env only if your server isn't at the default http://localhost:1234/v1 (e.g. http://192.168.1.10:1234/v1). Set OPENAI_API_KEY only if the server requires one (LM Studio doesn't).

Using OpenRouter: set OPENAI_BASE_URL=https://openrouter.ai/api/v1, OPENAI_API_KEY to your OpenRouter key, and llm.model to a model id like openai/gpt-4o or anthropic/claude-3.5-sonnet (with 400+ models, don't leave it blank — the "first available" default is arbitrary). Optionally set OPENROUTER_APP_URL / OPENROUTER_APP_NAME for attribution. /models still lists and switches models, capped for readability. To let OpenRouter auto-pick among a shortlist, set llm.model to openrouter/auto and put the candidates in llm.allowedModels (e.g. ["anthropic/*", "openai/gpt-4o"]) — make sure they're models your account can actually use, or the auto-router returns a 404.

4. Register the slash command (once, optional)

npm run register

Global commands can take up to an hour to appear the first time. You don't have to wait — typing /models (or /models <name>) directly in the DM works immediately.

5. Run

npm start

How it works

  • A message in a mapped announcement channel → summarized → DM'd to every summaryRecipients user.
  • A DM from a chatUsers user → answered as chat (each reply goes only to its sender; other users' DMs are ignored).
  • Server chat: in the create-channel, anyone clicks Start a chat → the bot makes a private channel (that user + the bot only) under the Bot Chats category. Messages there are answered with memory of the last 5 exchanges; a fresh channel is made on each click.
  • Everything else (other channels, bot messages, edits) → ignored.

Notes

  • Time conversion is done by the model (per the system prompt); there's no separate date parser.
  • /models <name> matches by exact id or substring (e.g. gemmagoogle/gemma-4-e2b).
  • Attachments: images are read by the vision model (and re-attached to the DM summary); PDFs have their text layer extracted (scanned/image-only PDFs yield no text — no image-OCR fallback). Vision input plus reasoning can eat a lot of tokens, so if image summaries come back empty, raise llm.maxTokens. Up to 5 images per message, ≤20 MB each; other file types become a name+URL note.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages