---
title: Liora
---

Liora (hereinafter the "Application") is a Discord bot that provides a "highlight words" notification system for Discord servers. The Application monitors messages in Discord servers and sends direct messages (DMs) to users when specific words or phrases they've configured are mentioned, bringing IRC-style highlight/ping functionality to Discord.

## 1. User Documentation

This section is for those interacting with a live instance of the Application.

### 1.1. Getting Started

To use Liora in your Discord server, you'll need to:

1. **Add the bot to your server**: Visit the [invite link](https://discord.com/oauth2/authorize?client_id=1391492296222179459)
2. **Subscribe to premium**: A server administrator must purchase a server subscription from the Discord store, unless your server is whitelisted
3. **Enable DMs**: Ensure you have direct messages enabled from server members to receive notifications

### 1.2. Available Commands

The Application provides the following slash commands:

#### `/about`
Displays information about Liora, including what it does and how to get help.

#### `/add <word>`
Adds a word or phrase to your highlight list for the current server.
- **Parameters**:
  - `word` (required): The word or phrase to monitor
- **Limitations**: Maximum of 10 highlights per user per server
- **Behaviour**: Case-insensitive matching

**Example**: `/add typescript` will notify you whenever someone mentions "TypeScript", "typescript", or "TYPESCRIPT"

#### `/remove <word>`
Removes a word or phrase from your highlight list for the current server.
- **Parameters**:
  - `word` (required): The word or phrase to remove from monitoring

**Example**: `/remove typescript`

#### `/list`
Displays all your configured highlight words for the current server.

#### `/dm`
Tests whether the bot can send you direct messages. Use this command if you're not receiving notifications to verify your DM settings are correct.

### 1.3. Notification Format

When a message contains one of your highlight words, you'll receive a DM containing:

- Which word(s) were matched
- The server name where the message was sent
- The display name of the user who sent the message
- A direct link to the original message
- Action buttons:
  - **Jump to Message**: Opens the message in Discord
  - **Discord Server**: Links to the support server
  - **Discord Community**: Links to the Discord community

### 1.4. Important Notes

- You will **not** receive notifications for messages you send yourself
- Highlight matching is **case-insensitive** (e.g., "discord" matches "Discord", "DISCORD", etc.)
- Highlights are **server-specific** - each server has its own separate list
- The bot requires the ability to send you DMs - check your privacy settings if notifications aren't working

### 1.5. Support and Feedback

If you need assistance or want to report a bug:

- **Discord Server**: [chat.nhcarrigan.com](https://chat.nhcarrigan.com)
- **Email**: contact@nhcarrigan.com
- **Discord Forum**: Post in the #bug-reports or #feature-requests forum channels on our Discord community

### 1.6. Subscription Information

The Application uses Discord's premium subscription system. Server administrators can purchase a subscription to enable the bot for all members. Two servers are currently whitelisted for free access (Naomi's server and FreeCodeCamp).

**Premium SKU ID**: 1396962587471515769

## 2. Technical Documentation

This section is for those interested in running their own instance of the Application.

### 2.1. System Requirements

- **Node.js**: v22 or higher
- **Package Manager**: pnpm 10.13.1 or higher
- **Database**: MongoDB instance
- **Discord**: Bot token from Discord Developer Portal
- **1Password CLI** (optional): For secure environment variable management

### 2.2. Technology Stack

#### Core Technologies
- **Runtime**: Node.js v22
- **Language**: TypeScript 5.8.3
- **Package Manager**: pnpm 10.13.1

#### Main Dependencies
- **discord.js** (v14.21.0): Discord API interaction and bot framework
- **@prisma/client** (v6.12.0): Database ORM for MongoDB
- **fastify** (v5.4.0): Lightweight HTTP server for health monitoring
- **@nhcarrigan/discord-analytics** (v0.0.6): Analytics tracking
- **@nhcarrigan/logger** (v1.1.1): Logging utility

#### Development Tools
- **ESLint** (v9.31.0): Code linting with @nhcarrigan/eslint-config
- **Prisma** (v6.12.0): Database schema management
- **TypeScript**: Type safety and compilation

### 2.3. Architecture Overview

The Application follows an event-driven architecture:

```
src/
├── index.ts                  # Application entry point
├── commands/                 # Slash command handlers
│   ├── about.ts
│   ├── add.ts
│   ├── remove.ts
│   ├── list.ts
│   └── dm.ts
├── events/                   # Discord event handlers
│   ├── interactionCreate.ts # Command routing
│   └── messageCreate.ts     # Message monitoring (core logic)
├── interfaces/               # TypeScript type definitions
│   ├── liora.ts             # Main bot interface
│   └── command.ts           # Command type definition
├── utils/                    # Utility functions
│   ├── checkEntitlement.ts  # Subscription validation
│   ├── errorHandler.ts      # Error logging with UUIDs
│   └── logger.ts            # Logger configuration
├── modules/                  # Business logic
│   └── sendUnentitledResponse.ts
├── config/                   # Configuration
│   └── entitlements.ts      # Whitelisted guild IDs
└── server/                   # HTTP server
    └── serve.ts              # Health monitoring endpoint
```

#### Key Components

**Entry Point** (`src/index.ts`):
- Initializes Prisma database client
- Creates Discord bot with required intents (Guilds, GuildMessages, MessageContent)
- Sets up event listeners
- Starts analytics cron job
- Launches Fastify web server on port 5022

**Message Processing** (`src/events/messageCreate.ts`):
- Validates guild entitlement/subscription
- Queries database for all highlights in the server
- Performs case-insensitive matching against message content
- Sends DM notifications with formatted components
- Logs metrics for analytics

**Command Handlers**:
All commands use Discord's Components V2 API with ContainerBuilder and TextDisplayBuilder for rich formatting.

### 2.4. Database Schema

The Application uses MongoDB with Prisma ORM:

```prisma
model Highlights {
  id        String   @id @default(auto()) @map("_id") @db.ObjectId
  serverId  String   # Discord guild ID
  userId    String   # Discord user ID
  words     String[] # Array of highlight words

  @@unique([serverId, userId])
  @@index([serverId])
}
```

- Each user can have one document per server
- The unique constraint ensures no duplicate user-server combinations
- The server ID is indexed for efficient queries when processing messages

### 2.5. Installation and Setup

#### Step 1: Clone the Repository

```bash
git clone https://git.nhcarrigan.com/NHCarrigan/liora.git
cd liora
```

#### Step 2: Install Dependencies

```bash
pnpm install
```

#### Step 3: Configure Environment Variables

Create a `prod.env` file with the following variables:

```sh
DISCORD_TOKEN=your_discord_bot_token
MONGO_URI=your_mongodb_connection_string
LOG_TOKEN=your_logging_service_token
```

**Discord Bot Setup**:
1. Visit [Discord Developer Portal](https://discord.com/developers/applications)
2. Create a new application
3. Navigate to the "Bot" section and create a bot
4. Enable these Privileged Gateway Intents:
   - Server Members Intent (GUILDS)
   - Message Content Intent (MESSAGE_CONTENT)
5. Copy the bot token to your environment file

**MongoDB Setup**:
- Provide a MongoDB connection URI in the format: `mongodb://user:password@host:port/database`
- Alternatively, use MongoDB Atlas for a cloud-hosted solution

#### Step 4: Generate Prisma Client

```bash
pnpm run build
```

This command runs `prisma generate && tsc`, which:
- Generates the Prisma client from the schema
- Compiles TypeScript to the `./prod` directory

#### Step 5: Register Discord Commands

Use the `commandJson.js` file to register slash commands with Discord:

```bash
node commandJson.js
```

Then use the output to register commands via Discord's API or developer portal.

#### Step 6: Start the Application

**With 1Password CLI**:
```bash
pnpm run start
```

**Without 1Password CLI**:
```bash
node ./prod/index.js
```

The Application will:
- Connect to MongoDB
- Log in to Discord
- Start the web server on port 5022
- Begin monitoring messages

### 2.6. Development Workflow

#### Linting

```bash
pnpm run lint
```

Uses ESLint with @nhcarrigan/eslint-config.

#### Building

```bash
pnpm run build
```

Generates Prisma client and compiles TypeScript.

#### Running Tests

```bash
pnpm test
```

Currently returns a placeholder. Test implementation is pending.

### 2.7. Continuous Integration

The repository includes a Gitea Actions workflow (`.gitea/workflows/ci.yml`) that:
- Runs on push and pull requests to the main branch
- Executes linting with ESLint
- Verifies TypeScript compilation
- Runs tests

### 2.8. Configuration

#### Whitelisted Guilds

Two Discord servers have free access without subscriptions, configured in `src/config/entitlements.ts`. To modify:

1. Edit `src/config/entitlements.ts`
2. Add guild IDs to the whitelist array
3. Rebuild the application

#### Subscription SKU

The premium subscription SKU is defined in `src/utils/checkEntitlement.ts`. To use your own subscription:

1. Create a subscription in Discord's Developer Portal
2. Update the SKU ID in the entitlement check logic
3. Rebuild the application

### 2.9. Deployment

#### Web Server

The Application includes a Fastify web server that:
- Listens on port 5022
- Serves a landing page at `/`
- Provides information about the bot
- Includes an "Add to Discord" button
- Useful for health checks and monitoring

#### Production Deployment Checklist

1. Ensure all environment variables are configured
2. Build the application with `pnpm run build`
3. Set up process management (PM2, systemd, Docker, etc.)
4. Configure reverse proxy if exposing the web server
5. Set up MongoDB backups
6. Monitor logs via the configured logging service
7. Register Discord commands before starting the bot

#### Health Monitoring

The web server on port 5022 can be used for health checks. A simple GET request to `/` will return the landing page HTML if the service is running.

### 2.10. Analytics

The Application integrates with a custom analytics service (@nhcarrigan/discord-analytics):

- **Tracked Metrics**:
  - `highlight_triggered`: Logged when a highlight word is matched
  - Gateway events (connection, ready, etc.)
- **Metadata**: Includes server ID, user ID, and matched words
- **Authentication**: Requires LOG_TOKEN environment variable

### 2.11. API Endpoints

The Fastify web server exposes:

- `GET /`: Landing page with bot information and "Add to Discord" link

### 2.12. Security Considerations

- **Message Content Intent**: The bot requires access to read all message content in subscribed guilds. This is a privileged intent and should be handled responsibly.
- **Environment Variables**: Use secure methods to manage secrets (1Password CLI, environment variable management services, etc.)
- **DM Privacy**: The bot only sends DMs when highlights are triggered; it does not store message content
- **Entitlement Validation**: All commands and message processing verify subscription status to prevent unauthorised usage

### 2.13. Troubleshooting

#### Bot Not Responding to Commands
- Verify the bot has appropriate permissions in the server
- Check that commands are registered with Discord's API
- Ensure the bot is online and connected

#### DMs Not Being Sent
- Verify users have DMs enabled from server members
- Check that the bot has permission to send DMs
- Use the `/dm` command to test DM functionality

#### Database Connection Issues
- Verify MongoDB connection string format
- Ensure MongoDB instance is accessible from the application
- Check Prisma client is generated (`pnpm run build`)

#### Analytics Not Working
- Verify LOG_TOKEN is correctly configured
- Check analytics service is reachable
- Review application logs for errors

## 3. Legal Documentation

This section is for expansions to our legal policies specific to the Application.

### 3.1. License

This software is licensed under [Naomi's Public Licence](https://docs.nhcarrigan.com/#/license).

Copyright held by Naomi Carrigan.

### 3.2. Data Collection and Privacy

The Application collects and stores the following data:

- **Discord User IDs**: To identify which users should receive notifications
- **Discord Server IDs**: To associate highlights with specific servers
- **Highlight Words**: The words/phrases users choose to monitor
- **Analytics Metrics**: Anonymous usage statistics (highlight triggers, command usage)

**Data Usage**:
- User data is used solely to provide the highlight notification functionality
- Analytics data is used to improve the Application
- No message content is stored permanently
- Data is stored in a MongoDB database

**Data Retention**:
- Highlight data is retained until manually removed by users via the `/remove` command
- Users can view all their stored data via the `/list` command

**Third-Party Services**:
- Discord API: Required for bot functionality
- MongoDB: Database hosting
- Custom Analytics Service: Usage metrics tracking

### 3.3. Terms of Service

By using the Application, you agree to:

- Use the Application in accordance with Discord's Terms of Service
- Not abuse the highlight system to spam or harass other users
- Accept that the service is provided "as is" without warranties
- Understand that subscription fees are non-refundable per Discord's policies

### 3.4. Acceptable Use

Users must not:

- Use the Application to harass or spam other users
- Attempt to circumvent subscription requirements
- Exploit bugs or vulnerabilities in the Application
- Use the Application for any illegal purposes

### 3.5. Subscription Terms

- Subscriptions are managed through Discord's subscription system
- Pricing and billing are handled by Discord
- Subscriptions are server-specific (per-guild)
- Two servers are currently whitelisted for free access
- Subscription status is validated before processing commands and notifications

### 3.6. Liability

The Application maintainers are not liable for:

- Missed notifications due to Discord API issues or user configuration
- Data loss due to database failures or user error
- Service interruptions or downtime
- Actions taken by users based on notifications received

### 3.7. Contact for Legal Inquiries

For legal questions or concerns:

- **Email**: contact@nhcarrigan.com
- **Discord**: [chat.nhcarrigan.com](https://chat.nhcarrigan.com)

## 4. Contributing Documentation

This section is for documentation related to contributing to the Application's codebase.

### 4.1. Contributing Guidelines

Our comprehensive contributing guidelines can be found at: [https://docs.nhcarrigan.com/#/contributing](https://docs.nhcarrigan.com/#/contributing)

### 4.2. Code of Conduct

Before interacting with our community, please review our Code of Conduct: [https://docs.nhcarrigan.com/#/coc](https://docs.nhcarrigan.com/#/coc)

### 4.3. How to Contribute

#### Reporting Bugs

If you encounter a bug:

1. Post in the #bug-reports forum channel on our Discord community
2. Include in your post:
   - Clear description of the bug
   - Steps to reproduce
   - Expected vs. actual behaviour
   - Environment details (Node.js version, OS, etc.)
   - Error logs or screenshots if applicable

#### Suggesting Features

For feature requests:

1. Post in the #feature-requests forum channel on our Discord community
2. Describe the feature and its use case
3. Explain why it would benefit users
4. Be open to discussion and feedback

#### Submitting Pull Requests

To contribute code:

1. **Fork the repository** on Gitea or GitHub
2. **Create a feature branch**: `git checkout -b feature/your-feature-name`
3. **Make your changes**:
   - Follow the existing code style
   - Add comments for complex logic
   - Update documentation if needed
4. **Test your changes**:
   - Ensure the application builds: `pnpm run build`
   - Run linting: `pnpm run lint`
   - Test functionality locally
5. **Commit your changes**:
   - Use clear, descriptive commit messages
   - Reference related issues if applicable
6. **Push to your fork**: `git push origin feature/your-feature-name`
7. **Open a Pull Request**:
   - Describe what changes were made and why
   - Link to related issues
   - Wait for review and address feedback

### 4.4. Development Setup

Follow the steps in Section 2.5 (Installation and Setup) to set up your development environment.

**Additional Development Tips**:

- Use TypeScript strict mode for type safety
- Follow the ESLint configuration for consistent code style
- Test commands in a development Discord server before submitting
- Use meaningful variable and function names
- Add JSDoc comments for public functions and interfaces

### 4.5. Code Style Guidelines

The Application uses:

- **@nhcarrigan/eslint-config**: ESLint configuration for consistent style
- **@nhcarrigan/typescript-config**: TypeScript configuration
- **Prettier-compatible formatting**: Enforced via ESLint

Key conventions:

- **File naming**: camelCase for TypeScript files
- **Function naming**: camelCase for functions, PascalCase for classes/interfaces
- **Indentation**: 2 spaces
- **Quotes**: Double quotes for strings
- **Semicolons**: Required
- **Max line length**: Enforced by ESLint (exceptions allowed for long strings)

### 4.6. Project Structure Guidelines

When adding new features:

- **Commands**: Add to `src/commands/` directory
- **Events**: Add to `src/events/` directory
- **Utilities**: Add to `src/utils/` directory
- **Business Logic**: Add to `src/modules/` directory
- **Type Definitions**: Add to `src/interfaces/` directory

### 4.7. Testing Guidelines

Currently, the Application does not have automated tests. Contributions to add testing infrastructure are welcome!

**Manual Testing Checklist**:

- Test all commands in a Discord server
- Verify highlight matching works correctly
- Test edge cases (max highlights, special characters, etc.)
- Verify DM notifications are sent properly
- Test subscription validation
- Check error handling

### 4.8. Documentation Contributions

Documentation improvements are highly valued! You can contribute by:

- Fixing typos or unclear explanations
- Adding examples or use cases
- Improving setup instructions
- Translating documentation (if applicable)
- Adding diagrams or visual aids

### 4.9. Community Involvement

Join our community:

- **Discord Server**: [chat.nhcarrigan.com](https://chat.nhcarrigan.com) - Ask questions, discuss features
- **Discord Community**: [chat.nhcarrigan.com](https://chat.nhcarrigan.com) - Long-form discussions and support
- **Discord Forum**: Post in the #bug-reports or #feature-requests forum channels for bugs and feature requests

### 4.10. Recognition

Contributors will be recognised in:

- Git commit history
- Release notes for significant contributions
- The community Discord server

### 4.11. Getting Help

If you need help while contributing:

- Ask in the Discord server (#development or #support channels)
- Post in the relevant Discord forum channel (#bug-reports or #feature-requests)
- Email: contact@nhcarrigan.com

### 4.12. Release Process

The Application follows semantic versioning (SemVer):

- **Major versions** (X.0.0): Breaking changes
- **Minor versions** (0.X.0): New features, backward compatible
- **Patch versions** (0.0.X): Bug fixes, backward compatible

**Current Version**: v1.0.0

Releases are managed by the maintainers. Contributors should focus on feature branches and pull requests rather than version bumping.

---

**Additional Resources**:

- **Live Bot**: [Add to Discord](https://discord.com/oauth2/authorize?client_id=1391492296222179459)
- **Source Code**: [Gitea Repository](https://git.nhcarrigan.com/NHCarrigan/liora)
- **Documentation Hub**: [docs.nhcarrigan.com](https://docs.nhcarrigan.com)
- **Support Server**: [chat.nhcarrigan.com](https://chat.nhcarrigan.com)
- **Contact Email**: contact@nhcarrigan.com
