Added Drizzle ORM for Database Connection and Basic Member Command

This commit is contained in:
Ahmad 2024-11-23 15:14:21 -05:00
parent f1e6e05345
commit 9030fbcdcb
No known key found for this signature in database
GPG key ID: 8FD8A93530D182BF
11 changed files with 1955 additions and 154 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
target/
node_modules/
drizzle/
config.json
.vscode
.yarn

View file

@ -1,5 +1,6 @@
{
"token": "DISCORD_BOT_API_KEY",
"clientId": "DISCORD_BOT_ID",
"guildId": "DISCORD_SERVER_ID"
"guildId": "DISCORD_SERVER_ID",
"dbConnectionString": "POSTGRESQL_CONNECTION_STRING"
}

14
drizzle.config.ts Normal file
View file

@ -0,0 +1,14 @@
import fs from "node:fs";
import { defineConfig } from 'drizzle-kit';
const config = JSON.parse(fs.readFileSync("./config.json", "utf8"));
const { dbConnectionString } = config;
export default defineConfig({
out: './drizzle',
schema: './src/db/schema.ts',
dialect: 'postgresql',
dbCredentials: {
url: dbConnectionString,
},
});

View file

@ -99,7 +99,7 @@ export default [
"no-var": "error",
"object-curly-spacing": ["error", "always"],
"prefer-const": "error",
quotes: ["error", "single"],
quotes: ["warning", "single"],
semi: ["error", "always"],
"space-before-blocks": "error",

View file

@ -14,17 +14,21 @@
},
"dependencies": {
"discord.js": "^14.16.3",
"mongoose": "^8.8.2"
"drizzle-orm": "^0.36.4",
"pg": "^8.13.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.15.0",
"@types/node": "^22.9.1",
"@types/pg": "^8.11.10",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"drizzle-kit": "^0.28.1",
"eslint": "^9.15.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.2",
"typescript": "^5.7.2"
},
"packageManager": "yarn@4.5.1"
"packageManager": "yarn@4.5.2"
}

24
src/commands/members.ts Normal file
View file

@ -0,0 +1,24 @@
import { SlashCommandBuilder, CommandInteraction, EmbedBuilder } from "discord.js";
import { getAllMembers } from "../util/db.js";
interface Command {
data: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">;
execute: (interaction: CommandInteraction) => Promise<void>;
}
const command: Command = {
data: new SlashCommandBuilder()
.setName("members")
.setDescription("Lists all non-bot members of the server"),
execute: async (interaction) => {
const members = await getAllMembers();
const memberList = members.map(m => `**${m.discordUsername}** (${m.discordId})`).join("\n");
const membersEmbed = new EmbedBuilder()
.setTitle("Members")
.setDescription(memberList)
.setColor(0x0099ff);
await interaction.reply({ embeds: [membersEmbed] });
},
};
export default command;

7
src/db/schema.ts Normal file
View file

@ -0,0 +1,7 @@
import { integer, pgTable, varchar } from "drizzle-orm/pg-core";
export const memberTable = pgTable("members", {
id: integer().primaryKey().generatedAlwaysAsIdentity(),
discordId: varchar("discord_id").notNull().unique(),
discordUsername: varchar("discord_username").notNull(),
});

View file

@ -1,12 +1,16 @@
import fs from "node:fs";
import path from "node:path";
import { Client, Collection, Events, GatewayIntentBits } from "discord.js";
import { deployCommands } from "./util/deployCommand.js";
import { getAllMembers, setMembers } from "./util/db.js";
const config = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
const { token } = config;
const config = JSON.parse(fs.readFileSync("./config.json", "utf8"));
const { token, guildId } = config;
const client: any = new Client({ intents: [GatewayIntentBits.Guilds] });
const client: any = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
});
client.commands = new Collection();
try {
@ -44,7 +48,13 @@ try {
console.log(`Error while registering commands: ${error}`);
}
client.once(Events.ClientReady, (c: any) => {
client.once(Events.ClientReady, async (c: any) => {
const guild = await client.guilds.fetch(guildId);
const members = await guild.members.fetch();
const nonBotMembers = members.filter((member: any) => !member.user.bot);
await setMembers(nonBotMembers);
console.log(`Ready! Logged in as ${c.user.tag}`);
});

40
src/util/db.ts Normal file
View file

@ -0,0 +1,40 @@
import fs from "node:fs";
import pkg from "pg";
import { drizzle } from "drizzle-orm/node-postgres";
import { memberTable } from "../db/schema.js";
import { eq } from "drizzle-orm";
const { Pool } = pkg;
const config = JSON.parse(fs.readFileSync("./config.json", "utf8"));
const { dbConnectionString, guildId } = config;
const dbPool = new Pool({
connectionString: dbConnectionString,
ssl: true,
});
const db = drizzle({ client: dbPool });
export async function getAllMembers() {
return await db.select().from(memberTable);
}
export async function setMembers(nonBotMembers: any) {
nonBotMembers.forEach(async (member: any) => {
const memberExists = await db
.select()
.from(memberTable)
.where(eq(memberTable.discordId, member.user.id));
if (memberExists.length > 0) {
await db
.update(memberTable)
.set({ discordUsername: member.user.username })
.where(eq(memberTable.discordId, member.user.id));
} else {
const members: typeof memberTable.$inferInsert = {
discordId: member.user.id,
discordUsername: member.user.username,
};
await db.insert(memberTable).values(members);
}
});
}

View file

@ -105,5 +105,8 @@
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
},
"include": [
"src/**/*"
]
}

1987
yarn.lock

File diff suppressed because it is too large Load diff