diff --git a/drizzle/0001_dusty_wolverine.sql b/drizzle/0001_dusty_wolverine.sql new file mode 100644 index 0000000..9ba08b8 --- /dev/null +++ b/drizzle/0001_dusty_wolverine.sql @@ -0,0 +1,2 @@ +ALTER TABLE `users_table` ADD `join_streak` integer;--> statement-breakpoint +ALTER TABLE `users_table` ADD `last_joined_at` integer; \ No newline at end of file diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..e9f5e55 --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,79 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "e9592066-1da0-41af-9e25-e2672ebe256f", + "prevId": "ddb7170b-7f66-4e3c-ab64-9069e760e09a", + "tables": { + "users_table": { + "name": "users_table", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "discord_id": { + "name": "discord_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_streak": { + "name": "join_streak", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_joined_at": { + "name": "last_joined_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "took_medication_today": { + "name": "took_medication_today", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": { + "users_table_discord_id_unique": { + "name": "users_table_discord_id_unique", + "columns": [ + "discord_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 3c45250..1a11730 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1735431085265, "tag": "0000_needy_nightshade", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1736688734822, + "tag": "0001_dusty_wolverine", + "breakpoints": true } ] } \ No newline at end of file diff --git a/mydb.sqlite b/mydb.sqlite index e69de29..c1bdba7 100644 Binary files a/mydb.sqlite and b/mydb.sqlite differ diff --git a/src/actions/embed/embed.components.ts b/src/actions/customMessage/customMessage.components.ts similarity index 100% rename from src/actions/embed/embed.components.ts rename to src/actions/customMessage/customMessage.components.ts diff --git a/src/actions/customMessage/customMessage.service.ts b/src/actions/customMessage/customMessage.service.ts new file mode 100644 index 0000000..f0821b0 --- /dev/null +++ b/src/actions/customMessage/customMessage.service.ts @@ -0,0 +1,133 @@ +import config from "config"; +import client from "lib/client"; +import { getRandomInt } from "lib/utils"; +import { customContent, createEmbed } from "./customMessage.components.ts"; +import { + Client, + EmbedBuilder, + type Message, + type CacheType, + type GuildMember, + type Interaction, + type OmitPartialGroupDMChannel, + type ChatInputCommandInteraction, + ChannelType, +} from "discord.js"; +import { type CommandsType, Commands } from "commands/index.ts"; +import { time } from "drizzle-orm/mysql-core"; + +export class CustomMessageService { + async handleInteraction(interaction: Interaction) { + if (interaction.isChatInputCommand()) { + await this.handleChatInputCommand(interaction); + return; + } + } + + async handleChatInputCommand( + interaction: ChatInputCommandInteraction, + ) { + console.log("accept"); + const commandName = interaction.commandName as CommandsType; + switch (commandName) { + case Commands.Enum.embed: + await this.customEmbed(interaction); + return; + case Commands.Enum.message: + await this.customMessage(interaction); + return; + default: + break; + } + } + + async checkPermission(interaction: ChatInputCommandInteraction) { + const userIdCommand = interaction.user.id; + if (userIdCommand !== config.discord.myId) { + await interaction.reply({ + content: "you have no permission for that command", + ephemeral: true, + }); + return false; + } + return true; + } + + // check if command done in server + async checkIfServer(interaction: ChatInputCommandInteraction) { + const guild = interaction.guild; + if (!guild) { + await interaction.reply({ + content: "command can only be used on a server", + ephemeral: true, + }); + return false; + } + return true; + } + + async customEmbed(interaction: ChatInputCommandInteraction) { + const title = interaction.options.getString("title") || " "; + const description = interaction.options.getString("description") || " "; + const timestamp = interaction.options.getBoolean("timestamp") || false; + // return the value + console.log(title, description, timestamp); + + // permission check + // permission check + if (await this.checkPermission(interaction) && await this.checkIfServer(interaction)) + try { + const channels = client.channels; + const channel = channels.cache.get(interaction.channelId); + + if (channel?.isTextBased() && channel?.isSendable()) { + await channel.send({ + embeds: [createEmbed(title, description, timestamp)], + }); + } + await interaction.reply({ + content: "successfully created embed", + ephemeral: true, + }); + } catch (error) { + console.error("error while creating embed:", error); + await interaction.reply({ + content: + "error while creating embed", + ephemeral: true, + }); + } + } + + async customMessage(interaction: ChatInputCommandInteraction) { + const input: string = interaction.options.getString("input") || ""; + const result = input.replaceAll(";", "\n"); + + // return the value + console.log(input); + + // permission check && server check + if (await this.checkPermission(interaction) && await this.checkIfServer(interaction)) + try { + const channels = client.channels; + const channel = channels.cache.get(interaction.channelId); + + if (channel?.isTextBased() && channel?.isSendable()) { + await channel.send({ + content: result, + }); + } + await interaction.reply({ + content: "successfully created message", + ephemeral: true, + }); + } catch (error) { + console.error("error while creating message:", error); + await interaction.reply({ + content: + "error while creating message", + ephemeral: true, + }); + } + } +} diff --git a/src/actions/embed/embed.service.ts b/src/actions/embed/embed.service.ts deleted file mode 100644 index 850d8ac..0000000 --- a/src/actions/embed/embed.service.ts +++ /dev/null @@ -1,88 +0,0 @@ -import config from "config"; -import client from "lib/client"; -import { getRandomInt } from "lib/utils"; -import { customContent, createEmbed } from "./embed.components.ts"; -import { - Client, - EmbedBuilder, - type Message, - type CacheType, - type GuildMember, - type Interaction, - type OmitPartialGroupDMChannel, - type ChatInputCommandInteraction, -} from "discord.js"; -import { type CommandsType, Commands } from "commands/index.ts"; -import { time } from "drizzle-orm/mysql-core"; - -export class EmbedService { - async handleInteraction(interaction: Interaction) { - if (interaction.isChatInputCommand()) { - await this.handleChatInputCommand(interaction); - return; - } - } - - async handleChatInputCommand( - interaction: ChatInputCommandInteraction, - ) { - console.log("accept"); - const commandName = interaction.commandName as CommandsType; - switch (commandName) { - case Commands.Enum.embed: - await this.customEmbed(interaction); - return; - default: - break; - } - } - async customEmbed(interaction: ChatInputCommandInteraction) { - const title = interaction.options.getString("title") || " "; - const description = interaction.options.getString("description") || " "; - const timestamp = interaction.options.getBoolean("timestamp") || false; - // return the value - console.log(title, description, timestamp); - - // permission check - const userIdCommand = interaction.user.id; - if (userIdCommand !== config.discord.myId) { - await interaction.reply({ - content: "you have no permission for that command", - ephemeral: true, - }); - return; - } - try { - // get user id from mentioning - const guild = interaction.guild; - if (!guild) { - await interaction.reply({ - content: "command can only be used on a server", - ephemeral: true, - }); - return; - } - - - const channels = client.channels; - const channel = channels.cache.get(interaction.channelId); - - if (channel?.isTextBased() && channel?.isSendable()) { - await channel.send({ - embeds: [createEmbed(title, description, timestamp)], - }); - } - await interaction.reply({ - content: "done", - ephemeral: true, - }); - } catch (error) { - console.error("Fehler beim Hinzufügen der Rolle:", error); - await interaction.reply({ - content: - "Es gab einen Fehler beim Hinzufügen der Rolle. Stelle sicher, dass du einen gültigen User erwähnt hast.", - ephemeral: true, - }); - } - } -} diff --git a/src/commands/index.ts b/src/commands/index.ts index 8831245..8aa11df 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,7 +1,7 @@ import { SlashCommandBuilder, userMention } from "discord.js"; import { z } from "zod"; -export const Commands = z.enum(["giessen", "medikamente", "hilfe", "accept", "welcome", "embed"]); +export const Commands = z.enum(["giessen", "medikamente", "hilfe", "accept", "welcome", "embed", "message"]); export const CommandsMeta: Record, { description: string }> = { giessen: { @@ -21,6 +21,9 @@ export const CommandsMeta: Record, { description: stri }, embed: { description: "admin use only" + }, + message: { + description: "admin use only" } } @@ -66,6 +69,13 @@ export default function getCommands() { option.setName('timestamp') .setDescription('timestamp bool') .setRequired(false)), + new SlashCommandBuilder() + .setName(Commands.Enum.message) + .setDescription(CommandsMeta.message.description) + .addStringOption(option => + option.setName('input') + .setDescription('input for bot') + .setRequired(true)), ].map((command) => command.toJSON()); diff --git a/src/controllers/discord.controller.ts b/src/controllers/discord.controller.ts index f2e89f3..9b01397 100644 --- a/src/controllers/discord.controller.ts +++ b/src/controllers/discord.controller.ts @@ -20,7 +20,7 @@ import { HelpService } from "actions/help/help.service"; import { GreetingService } from "actions/greeting/greeting.service"; import { ActivityService } from "actions/activity/activity.service"; import { DmService } from "actions/dm/dm.service"; -import { EmbedService } from "actions/embed/embed.service"; +import { CustomMessageService } from "actions/customMessage/customMessage.service"; export default class DiscordController extends EventEmitter { private discordService!: DiscordService; @@ -30,7 +30,7 @@ export default class DiscordController extends EventEmitter { helpService: HelpService; activityService: ActivityService; dmService: DmService; - embedService: EmbedService; + customMessageService: CustomMessageService; constructor() { super(); @@ -41,7 +41,7 @@ export default class DiscordController extends EventEmitter { this.helpService = new HelpService(); this.activityService = new ActivityService(); this.dmService = new DmService(); - this.embedService = new EmbedService(); + this.customMessageService = new CustomMessageService(); // log when running client.once("ready", async () => { await this.setActivity(); @@ -128,7 +128,10 @@ export default class DiscordController extends EventEmitter { await this.greetingService.handleInteraction(interaction); return; case Commands.Enum.embed: - await this.embedService.handleInteraction(interaction); + await this.customMessageService.handleInteraction(interaction); + return; + case Commands.Enum.message: + await this.customMessageService.handleInteraction(interaction); return; default: break; diff --git a/src/db/schema.ts b/src/db/schema.ts index 23930b3..1a63496 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,8 +1,12 @@ -import { int, sqliteTable, text } from "drizzle-orm/sqlite-core"; +import { TimestampStyles } from "discord.js"; +import { timestamp } from "drizzle-orm/mysql-core"; +import { integer, int, sqliteTable, text } from "drizzle-orm/sqlite-core"; export const usersTable = sqliteTable("users_table", { - id: int().primaryKey({ autoIncrement: true }), + id: integer().primaryKey({ autoIncrement: true }), name: text().notNull(), - discord_id: int().notNull().unique(), - took_medication_today: int().notNull().default(0), + discord_id: integer().notNull().unique(), + join_streak: integer(), + last_joined_at: integer({ mode: "timestamp" }), + took_medication_today: integer().notNull().default(0), });