Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.
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
16 changes: 12 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "template",
"name": "gitcord",
"version": "1.0.0",
"description": "A quick and easy to use template for TypeScript like projects ✏️",
"author": "ijsKoud <github@ijskoud.dev>",
"description": "🪝Custom GitHub embeds for Discord",
"author": "Daan Klarenbeek <github@ijskoud.dev>",
"license": "MIT",
"type": "module",
"main": "dist/index.js",
Expand Down Expand Up @@ -37,5 +37,13 @@
"engines": {
"node": ">= v18.16.0"
},
"packageManager": "yarn@3.5.0"
"packageManager": "yarn@3.5.0",
"dependencies": {
"@snowcrystals/icicle": "^1.0.3",
"@snowcrystals/iglo": "^1.2.1",
"colorette": "2.0.19",
"discord.js": "^14.9.0",
"dotenv": "^16.0.3",
"zod": "^3.21.4"
}
}
15 changes: 15 additions & 0 deletions src/bot/listeners/ReadyListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ApplyOptions, EventListener, type EventListenerOptions } from "@snowcrystals/iglo";
import { bold } from "colorette";
import { ActivityType } from "discord.js";

@ApplyOptions<EventListenerOptions>({ name: "ready", once: true })
export default class extends EventListener {
public override run() {
if (!this.client.isReady()) return;

const username = bold(this.client.user.tag);
this.client.logger.info(`${username} is up and running!`);

this.client.user.setPresence({ activities: [{ name: "GitHub webhooks", type: ActivityType.Listening }] });
}
}
10 changes: 9 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
console.log("Hello World!");
import { config } from "dotenv";
config();

import parse from "./lib/env.js";
parse();

import GitCordClient from "./lib/GitCordClient.js";
const client = new GitCordClient();
client.start();
17 changes: 17 additions & 0 deletions src/lib/GitCordClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IgloClient } from "@snowcrystals/iglo";
import { BOT_COMMANDS_DIR, BOT_INTERACTIONS_DIR, BOT_LISTENER_DIR } from "./constants.js";

export default class GitCordClient extends IgloClient {
public constructor() {
super({
client: { intents: ["GuildWebhooks", "Guilds"], allowedMentions: { repliedUser: true, roles: [], users: [] } },
paths: { commands: BOT_COMMANDS_DIR, events: BOT_LISTENER_DIR, interactions: BOT_INTERACTIONS_DIR },
logger: { defaultFormat: { infix: "[BOT]" } }
});
}

/** Starts the Discord bot and its processes */
public start() {
void this.run(process.env.DISCORD_BOT_TOKEN);
}
}
10 changes: 10 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));

// === Discord bot directory constants ===
export const BASE_BOT_DIR = join(__dirname, "..", "bot");
export const BOT_COMMANDS_DIR = join(BASE_BOT_DIR, "commands");
export const BOT_LISTENER_DIR = join(BASE_BOT_DIR, "listeners");
export const BOT_INTERACTIONS_DIR = join(BASE_BOT_DIR, "interactions");
40 changes: 40 additions & 0 deletions src/lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ZodError, z } from "zod";
import { Logger } from "@snowcrystals/icicle";
import { bold } from "colorette";

const logger = new Logger();
// List of environment variables which are used by this application
const envSchema = z.object({
DISCORD_BOT_TOKEN: z.string().nonempty()
});

/** Parses process.env to check if all required environment variables are present and valid */
export default function parse() {
try {
envSchema.parse(process.env);
} catch (err) {
if (!(err instanceof ZodError<typeof envSchema>)) {
console.error(err);
process.exit(1);
}

// Filter out missing ones
const missing = err.issues.filter((issue) => issue.message === "Required").map((issue) => bold(issue.path[0]));
logger.fatal(`The following environment variables are missing: ${missing}`);

const failedTest = err.issues.filter((issue) => issue.message !== "Required");
for (const failedItem of failedTest) {
// Environment variable
const path = failedItem.path[0];
logger.fatal(`[${path}]: Failed the test with reason: ${failedItem.message}`);
}

process.exit(1);
}
}

declare global {
namespace NodeJS {
interface ProcessEnv extends z.infer<typeof envSchema> {}
}
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "@sapphire/ts-config/extra-strict-without-decorators",
"extends": "@sapphire/ts-config/extra-strict",
"compilerOptions": {
"outDir": "./dist",
"noUnusedParameters": false,
Expand Down
Loading