Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,11 @@ OmegaBot is online
│ │ │ └── changelog.ts
│ │ ├── faq
│ │ │ ├── subcommands
│ │ │ │ ├── _shared.ts
│ │ │ │ ├── add.ts
│ │ │ │ ├── get.ts
│ │ │ │ ├── list.ts
│ │ │ │ └── remove.ts
│ │ │ ├── faq.ts
│ │ │ ├── services.ts
│ │ │ ├── store.ts
│ │ │ └── types.ts
│ │ │ └── faq.ts
│ │ ├── fun
│ │ │ ├── subcommands
│ │ │ │ ├── chucknorris.ts
Expand Down Expand Up @@ -214,6 +210,7 @@ OmegaBot is online
│ │ │ ├── fetchChannelMessages.ts
│ │ │ └── interactionHandler.ts
│ │ ├── faq
│ │ │ ├── _shared.ts
│ │ │ ├── faqService.ts
│ │ │ ├── permissions.ts
│ │ │ ├── services.test.ts
Expand Down
6 changes: 0 additions & 6 deletions src/commands/faq/services.ts

This file was deleted.

104 changes: 0 additions & 104 deletions src/commands/faq/store.ts

This file was deleted.

6 changes: 5 additions & 1 deletion src/commands/faq/subcommands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import type { ChatInputCommandInteraction } from "discord.js";
import { logger } from "../../../utils/logger.js";
import { create } from "../../../services/faq/services.js";

import { guardFaqAction, parseTags, handleFaqSubcommandError } from "./_shared.js";
import {
guardFaqAction,
parseTags,
handleFaqSubcommandError,
} from "../../../services/faq/_shared.js";

export async function run(interaction: ChatInputCommandInteraction): Promise<void> {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/faq/subcommands/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
readRequiredKey,
formatFaqEntry,
handleFaqSubcommandError,
} from "./_shared.js";
} from "../../../services/faq/_shared.js";

export async function run(interaction: ChatInputCommandInteraction): Promise<void> {
try {
Expand Down
6 changes: 5 additions & 1 deletion src/commands/faq/subcommands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import type { ChatInputCommandInteraction } from "discord.js";
import { getAll } from "../../../services/faq/services.js";
import { guardFaqAction, formatFaqList, handleFaqSubcommandError } from "./_shared.js";
import {
guardFaqAction,
formatFaqList,
handleFaqSubcommandError,
} from "../../../services/faq/_shared.js";

export async function run(interaction: ChatInputCommandInteraction): Promise<void> {
try {
Expand Down
6 changes: 5 additions & 1 deletion src/commands/faq/subcommands/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType } from "dis

import { logger } from "../../../utils/logger.js";
import { getByKey, remove } from "../../../services/faq/services.js";
import { guardFaqAction, readRequiredKey, handleFaqSubcommandError } from "./_shared.js";
import {
guardFaqAction,
readRequiredKey,
handleFaqSubcommandError,
} from "../../../services/faq/_shared.js";

export async function run(interaction: ChatInputCommandInteraction): Promise<void> {
try {
Expand Down
37 changes: 0 additions & 37 deletions src/commands/faq/types.ts

This file was deleted.

56 changes: 46 additions & 10 deletions src/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ type SummaryMode = "local" | "llm";
* Application ID required for slash command registration.
*
* - DISCORD_GUILD_ID
* Guild where development commands are registered.
* OPTIONAL: Guild where development commands are registered.
* If not set, commands should be registered globally instead.
*
* ------------------------------------------------------------------
* Optional (feature flags / enhancements)
Expand All @@ -70,10 +71,7 @@ type SummaryMode = "local" | "llm";
*
* - GITHUB_TOKEN
* Personal Access Token used for authenticated GitHub REST calls.
* Required for:
* - Issue lookup
* - PR lookup
* - PR announcements
* Required only when GitHub-backed features are enabled.
*
* - GITHUB_OWNER
* Default repository owner for polling PRs (optional).
Expand All @@ -88,11 +86,12 @@ type SummaryMode = "local" | "llm";
* Polling interval for PR announcements.
* Defaults to 60 seconds if not provided.
*
* All GitHub announcement fields are optional so the bot can run
* without polling enabled.
* All GitHub-related fields are OPTIONAL so the bot can run
* without any GitHub configuration or tokens.
*/
const summaryMode = (process.env.SUMMARY_MODE ?? "local") as SummaryMode;

// Fail fast ONLY when LLM summaries are explicitly enabled
if (summaryMode === "llm" && !process.env.OPENAI_API_KEY) {
throw new Error("OPENAI_API_KEY is required when SUMMARY_MODE=llm");
}
Expand All @@ -104,7 +103,13 @@ export const env = {

token: requireEnv("DISCORD_TOKEN"),
appId: requireEnv("DISCORD_APP_ID"),
guildId: requireEnv("DISCORD_GUILD_ID"),

/**
* Optional:
* Used for faster slash-command iteration during development.
* If unset, you can register commands globally instead.
*/
guildId: process.env.DISCORD_GUILD_ID ?? null,

/* ---------------------------------------------------------------- */
/* Summaries */
Expand All @@ -120,16 +125,47 @@ export const env = {
/* GitHub */
/* ---------------------------------------------------------------- */

// Auth token for GitHub REST API
// Auth token for GitHub REST API (optional)
githubToken: process.env.GITHUB_TOKEN ?? null,

// Default repo configuration for PR polling (optional)
githubOwner: process.env.GITHUB_OWNER ?? null,
githubRepo: process.env.GITHUB_REPO ?? null,

// Where PR announcements should be posted
// Where PR announcements should be posted (optional)
githubAnnounceChannelId: process.env.GITHUB_ANNOUNCE_CHANNEL_ID ?? null,

// Polling interval (ms). Defaults to 60s.
githubPollIntervalMs: envInt("GITHUB_POLL_INTERVAL_MS", 60_000),

/**
* Feature gate:
*
* GitHub announcement polling is enabled ONLY when all required
* configuration is present. This prevents the bot from attempting
* GitHub API calls (or requiring tokens) at startup.
*/
githubAnnouncementsEnabled:
Boolean(process.env.GITHUB_TOKEN) &&
Boolean(process.env.GITHUB_OWNER) &&
Boolean(process.env.GITHUB_REPO) &&
Boolean(process.env.GITHUB_ANNOUNCE_CHANNEL_ID),

/**
* Helper for GitHub-only code paths.
*
* Call this ONLY inside GitHub feature implementations
* (commands, pollers, handlers).
*
* This ensures:
* - The bot can start without GitHub config
* - GitHub features fail loudly and clearly when misconfigured
*/
requireGithubToken(): string {
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error("GITHUB_TOKEN is required for this GitHub feature");
}
return token;
},
};
Loading