good progress :3

This commit is contained in:
2025-01-05 03:51:02 +01:00
parent 07aa025ba0
commit 94d2fc40e6
12 changed files with 243 additions and 54 deletions

View File

@@ -0,0 +1,5 @@
import config from "config";
import { EmbedBuilder } from "discord.js";
export const dmWelcomeContent = `hey! ich bin avocadi von [avocadi-study](<https://discord.gg/kkryyeXu3S>)!\n\num auf den rest des servers zugreifen zu koennen, musst du dich noch vorstellen (unter <#${config.discord.channelIdIntroduction}>)!\n\n---\nname und alter:\npronomen:\nklasse/studiengang/beruf:\nhobby:\nueber mich:\n---\n\nsobald wir deine nachricht ueberprueft haben, bekommst du die rolle **lernende:r** :)`;
export const dmAcceptedContent = `huhu! du wurdest als lernende:r akzeptiert :3\nsag gerne hallo: <#${config.discord.channelIdOffTopic}> <:avocadi_cute:1321893797138923602>`;

View File

@@ -0,0 +1,55 @@
import config from "config";
import client from "lib/client";
import { getRandomInt } from "lib/utils";
import { dmWelcomeContent, dmAcceptedContent } from "./dm.components.ts";
import {
Client,
EmbedBuilder,
type Message,
type CacheType,
type GuildMember,
type Interaction,
type OmitPartialGroupDMChannel,
} from "discord.js";
export class DmService {
async handleInteraction(interaction: Interaction<CacheType>) {
// todo ?
}
async welcomePrivate(member: GuildMember) {
console.log("welcome private");
try {
await client.users.send(member, dmWelcomeContent);
} catch (error) {
console.error("error while sending a welcome msg:", error);
}
}
async welcomePrivateTest() {
console.log("test welcome private");
try {
await client.users.send(config.discord.myId, dmWelcomeContent);
} catch (error) {
console.error("error while sending a welcome msg:", error);
}
}
async forward(message: OmitPartialGroupDMChannel<Message<boolean>>) {
console.log("forward message");
const context = `<@${message.author.id}> hat geschrieben: " ${message.content} "`;
console.log(context);
client.users.send(config.discord.myId, context);
}
async acceptDm(member: GuildMember) {
console.log("acceept dm");
try {
await client.users.send(member, dmAcceptedContent);
} catch (error) {
console.error("error while sending a accept msg:", error);
}
}
}

View File

@@ -5,7 +5,7 @@ export class GreetingService {
async greet() { async greet() {
const channels = client.channels; const channels = client.channels;
const channel = channels.cache.get(config.discord.channelId); const channel = channels.cache.get(config.discord.channelIdBot);
if (channel?.isTextBased && channel?.isSendable()) { if (channel?.isTextBased && channel?.isSendable()) {
await channel.send({ content: "HALLOOOO" }); await channel.send({ content: "HALLOOOO" });

View File

@@ -1,5 +1,26 @@
import config from "config"; import config from "config";
import { EmbedBuilder } from "discord.js";
export const greetContent = ["HALLOOOO", "guten morgen! ich hoffe es geht euch gut <3"]; export const greetContent = ["HALLOOOO", "guten morgen! ich hoffe es geht euch gut <3"];
export const sleepContent = ["gute nacht! ich muss jetzt schlafen gehen :c", "zzzzZZ..", "*schnarch*"]; export const sleepContent = ["gute nacht! ich muss jetzt schlafen gehen :c", "zzzzZZ..", "*schnarch*"];
export const customContent = `hey <@&${config.discord.mentionStudy}>! meine [eigene website](https://avocadi.unom.io) ist endlich on :3\ngebe mir gerne rueckmeldung unter <#${config.discord.channelIdFeedback}>! <3`; export const customContent = `hey <@&${config.discord.roleStudy}>! meine [eigene website](https://avocadi.unom.io) ist endlich on :3\ngebe mir gerne rueckmeldung unter <#${config.discord.channelIdFeedback}>! <3`;
export const dmWelcomeContent = `hey! ich bin avocadi von [avocadi-study](<https://discord.gg/kkryyeXu3S>)!\n\num auf den rest des servers zugreifen zu koennen, musst du dich noch vorstellen (unter <#${config.discord.channelIdIntroduction}>)!\n\n---\nname und alter:\npronomen:\nklasse/studiengang/beruf:\nhobby:\nueber mich:\n---\n\nsobald wir deine nachricht ueberprueft haben, bekommst du die rolle **lernende:r** :)`;
export const dmAcceptedContent = `huhu! du wurdest als lernende:r akzeptiert :3\nsag gerne hallo: <#${config.discord.channelIdOffTopic}> <:avocadi_cute:1321893797138923602>`;
export function createEmbed() {
// ({ embeds: [exampleEmbed] })
console.log("createEmbed()");
const exampleEmbed = new EmbedBuilder()
.setColor(0x004400)
.setAuthor({
name: "avocadi - neuigkeiten",
iconURL:
"https://media.discordapp.net/attachments/1321933410188656693/1323447010380222474/mo_Avocadi_Avatar_Closeup_2.png?ex=67748b93&is=67733a13&hm=f48efb3523bca5f50e79144c7b41a127c94670e693e3da3dc2e6ffe62ad8a769&=&format=webp&quality=lossless&width=1524&height=1524",
url: "https://avocadi.unom.io",
})
.setDescription(customContent)
.setTimestamp();
//.setFooter({ text: 'Some footer text here', iconURL: 'https://i.imgur.com/AfFp7pu.png' });
return exampleEmbed;
}

View File

@@ -5,68 +5,126 @@ import {
customContent, customContent,
greetContent, greetContent,
sleepContent, sleepContent,
createEmbed,
} from "./greeting.components.ts"; } from "./greeting.components.ts";
import { Client, EmbedBuilder, type GuildMember } from "discord.js"; import {
type ChatInputCommandInteraction,
Client,
EmbedBuilder,
type CacheType,
type GuildMember,
type Interaction,
} from "discord.js";
import { DmService } from "actions/dm/dm.service.ts";
export class GreetingService { export class GreetingService {
async customMessage() { dmService: DmService;
constructor() {
this.dmService = new DmService();
}
async handleInteraction(
interaction: Interaction<CacheType>
) {
console.log("accept");
if (interaction.isChatInputCommand()) {
await this.acceptUser(interaction);
}
}
async custom() {
console.log("custom message"); console.log("custom message");
const channels = client.channels; client.users.send(config.discord.myId, "hat funktioniert :)");
const channel = channels.cache.get(config.discord.channelIdBot);
if (channel?.isTextBased && channel?.isSendable()) {
await channel.send({ embeds: [this.createEmbed()] });
}
}
createEmbed() {
// ({ embeds: [exampleEmbed] })
console.log("createEmbed()");
const exampleEmbed = new EmbedBuilder()
.setColor(0x004400)
.setAuthor({
name: "avocadi - neuigkeiten",
iconURL:
"https://media.discordapp.net/attachments/1321933410188656693/1323447010380222474/mo_Avocadi_Avatar_Closeup_2.png?ex=67748b93&is=67733a13&hm=f48efb3523bca5f50e79144c7b41a127c94670e693e3da3dc2e6ffe62ad8a769&=&format=webp&quality=lossless&width=1524&height=1524",
url: "https://avocadi.unom.io",
})
.setDescription(customContent)
.setTimestamp();
//.setFooter({ text: 'Some footer text here', iconURL: 'https://i.imgur.com/AfFp7pu.png' });
return exampleEmbed;
} }
async welcome(member: GuildMember) { async welcome(member: GuildMember) {
const welcomeMessages = [ console.log("welcome msg");
const welcomeContents = [
`willkommen auf dem server, ${member}! 💕`, `willkommen auf dem server, ${member}! 💕`,
`hey ${member}! schoen, dass du hier bist! 😊`, `hey ${member}! schoen, dass du hier bist! 😊`,
`hi ${member}, willkommen! viel spass hier! 💖`, `hi ${member}, willkommen! viel spass hier! 💖`,
`willkommen, ${member}! schoen, dass du da bist! 🥳`, `willkommen, ${member}! schoen, dass du da bist! 🥳`,
`moin ${member}! viel spass im server! c:`, `moin ${member}! viel spass im server! c:`,
`hey ${member}! herzlich willkommen! fühl dich wie zu hause! 🏡`, `hey ${member}, herzlich willkommen! fuehl dich wie zu hause! <3`,
`hi ${member}! cool, dass du da bist! 👏`, `hi ${member}! cool, dass du da bist! 👏`,
`willkommen, ${member}! wir freuen uns, dass du hier bist! 💕`, `willkommen, ${member}! wir freuen uns, dass du hier bist! 💕`,
`hey ${member}! schoen, dass du bei uns bist! :3`, `hey ${member}! schoen, dass du bei uns bist! :3`,
`willkommen auf dem server, ${member}! viel spass hier! ✨` `willkommen auf dem server, ${member}! viel spass hier! ✨`,
]; ];
const randomMessage = `${welcomeMessages[Math.floor(Math.random() * welcomeMessages.length)]} bitte stelle dich kurz in <#${config.discord.channelIdIntro}> vor. sobald wir deine nachricht gelesen haben, vergeben wir dir die rolle *lernende:r*, damit du alle kanaele nutzen kannst viel spass und bis bald! :) `; const welcomeContent =
welcomeContents[Math.floor(Math.random() * welcomeContents.length)];
try { try {
console.log("welcome msg");
const channels = client.channels; const channels = client.channels;
const channel = channels.cache.get( const channel = channels.cache.get(config.discord.channelIdWelcome);
config.discord.channelIdWelcome,
);
if (channel?.isTextBased() && channel?.isSendable()) { if (channel?.isTextBased() && channel?.isSendable()) {
await channel.send(randomMessage); await channel.send(welcomeContent);
} }
} catch (error) { } catch (error) {
console.error("error while senden a welcome msg:", error); console.error("error while sending a welcome msg:", error);
}
}
async acceptUser(
interaction: ChatInputCommandInteraction<CacheType>
) {
console.log("accept user");
// get the string option
const input = interaction.options.getString("input") || "";
// return the value
//console.log(input);
// 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 userId = input.replace(/[<@!>]/g, "");
console.log(userId.toString());
const guild = interaction.guild;
if (!guild) {
await interaction.reply({
content: "command can only be used on a server",
ephemeral: true,
});
return;
}
const username = (await guild.members.fetch(userId)).user.username;
console.log(username);
// get member from id
const member = await guild.members.fetch(userId);
const role = config.discord.roleStudy;
await member.roles.add(role);
await interaction.reply({
content: `die rolle *lernende:r* wurde erfolgreich an ${member.user.username} vergeben`,
ephemeral: true,
});
this.dmService.acceptDm(member);
} 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,
});
} }
} }

View File

@@ -29,7 +29,7 @@ export class MedicationService {
async askMedication() { async askMedication() {
const channels = client.channels; const channels = client.channels;
const channel = channels.cache.get(config.discord.channelId); const channel = channels.cache.get(config.discord.channelIdBot);
// funkt noch nicht, beides // funkt noch nicht, beides
@@ -50,7 +50,7 @@ export class MedicationService {
} }
getMedication() { getMedication() {
throw new Error("Method not implemented."); // todo
} }
setMedication() { setMedication() {
@@ -104,7 +104,7 @@ export class MedicationService {
const tookMedication = interaction.customId === "yesMedication"; const tookMedication = interaction.customId === "yesMedication";
interaction.reply({ await interaction.reply({
content: tookMedication content: tookMedication
? "das hast du toll gemacht <3 mach weiter so :3" ? "das hast du toll gemacht <3 mach weiter so :3"
: "das passiert mal... aber versuch sie heute noch zu nehmen, oki? :)", : "das passiert mal... aber versuch sie heute noch zu nehmen, oki? :)",
@@ -134,8 +134,7 @@ export class MedicationService {
}); });
} }
/** /**, um die Benutzerdaten in die Datenbank zu schreiben.
* Methode, um die Benutzerdaten in die Datenbank zu schreiben.
* @param discordId unique user id * @param discordId unique user id
* @param name name how the user wants to get called by avocadi * @param name name how the user wants to get called by avocadi
* @param tookMedication if user took medication * @param tookMedication if user took medication
@@ -155,9 +154,9 @@ export class MedicationService {
took_medication_today: Number(tookMedication), took_medication_today: Number(tookMedication),
}); */ }); */
console.log(`Benutzer mit ID ${id} wurde in der Datenbank gespeichert.`); console.log(`user with id ${id} saved`);
} catch (error) { } catch (error) {
console.error("Fehler beim Speichern in der Datenbank:", error); console.error("error while saving in db:", error);
} }
} }
@@ -192,11 +191,11 @@ export class MedicationService {
console.log(`ID für Discord-ID ${discordId} gefunden: ${result[0].id}`); console.log(`ID für Discord-ID ${discordId} gefunden: ${result[0].id}`);
return result[0].id; return result[0].id;
} }
console.log(`Keine ID für Discord-ID ${discordId} gefunden.`); console.log(`no id for discordId ${discordId} found`);
return null; return null;
} catch (error) { } catch (error) {
console.error( console.error(
`Fehler beim Abrufen der ID für Discord-ID ${discordId}:`, `error while calling id for discordId ${discordId}:`,
error, error,
); );
return null; return null;
@@ -213,7 +212,7 @@ export class MedicationService {
} }
console.log( console.log(
`found no entry for discordID ${discordId}. creating new entry.`, `found no entry for discordID ${discordId}. creating new entry`,
); );
const result = await db const result = await db

View File

@@ -52,7 +52,7 @@ export class WaterMeService {
async isThirsty() { async isThirsty() {
const channels = client.channels; const channels = client.channels;
const channel = channels.cache.get(config.discord.channelId); const channel = channels.cache.get(config.discord.channelIdBot);
if ( if (
channel?.isTextBased && channel?.isTextBased &&

View File

@@ -1,7 +1,7 @@
import { SlashCommandBuilder, userMention } from "discord.js"; import { SlashCommandBuilder, userMention } from "discord.js";
import { z } from "zod"; import { z } from "zod";
export const Commands = z.enum(["giessen", "medikamente", "hilfe"]); export const Commands = z.enum(["giessen", "medikamente", "hilfe", "accept"]);
export const CommandsMeta: Record<z.output<typeof Commands>, { description: string }> = { export const CommandsMeta: Record<z.output<typeof Commands>, { description: string }> = {
giessen: { giessen: {
@@ -13,6 +13,9 @@ export const CommandsMeta: Record<z.output<typeof Commands>, { description: stri
hilfe: { hilfe: {
description: "ich schreibe dir auf, was du alles mit mir machen kannst :)" description: "ich schreibe dir auf, was du alles mit mir machen kannst :)"
}, },
accept: {
description: "admin use only"
}
} }
export type CommandsType = z.output<typeof Commands>; export type CommandsType = z.output<typeof Commands>;
@@ -28,6 +31,13 @@ export default function getCommands() {
new SlashCommandBuilder() new SlashCommandBuilder()
.setName(Commands.Enum.hilfe) .setName(Commands.Enum.hilfe)
.setDescription(CommandsMeta.hilfe.description), .setDescription(CommandsMeta.hilfe.description),
new SlashCommandBuilder()
.setName(Commands.Enum.accept)
.setDescription(CommandsMeta.accept.description)
.addStringOption(option =>
option.setName('input')
.setDescription('input for bot')
.setRequired(true)),
].map((command) => command.toJSON()); ].map((command) => command.toJSON());
return commands; return commands;

View File

@@ -5,14 +5,20 @@ export default {
channelIdBot: process.env.DISCORD_CHANNEL_ID_BOT || "", channelIdBot: process.env.DISCORD_CHANNEL_ID_BOT || "",
// avocadi // avocadi
serverID: process.env.DISCORD_SERVER_ID || "",
channelIdNews: process.env.DISCORD_CHANNEL_ID_NEWS || "", channelIdNews: process.env.DISCORD_CHANNEL_ID_NEWS || "",
channelIdFeedback: process.env.DISCORD_CHANNEL_ID_FEEDBACK || "", channelIdFeedback: process.env.DISCORD_CHANNEL_ID_FEEDBACK || "",
channelIdIntro: process.env.DISCORD_CHANNEL_ID_INTRO || "", channelIdIntroduction: process.env.DISCORD_CHANNEL_ID_INTRODUCTION || "",
channelIdWelcome: process.env.DISCORD_CHANNEL_ID_WELCOME || "", channelIdWelcome: process.env.DISCORD_CHANNEL_ID_WELCOME || "",
mentionStudy: process.env.PEOPLE || "", channelIdOffTopic: process.env.DISCORD_CHANNEL_ID_OFF_TOPIC || "",
roleStudy: process.env.PEOPLE || "",
// other // other
applicationId: process.env.DISCORD_APPLICATION_ID || "", applicationId: process.env.DISCORD_APPLICATION_ID || "",
token: process.env.DISCORD_TOKEN || "", token: process.env.DISCORD_TOKEN || "",
botId: process.env.BOT_ID || "",
myId: process.env.MY_ID || "",
enricoId: process.env.ENRICO_ID || "",
}, },
}; };

View File

@@ -1,6 +1,8 @@
import { Commands, type CommandsType } from "commands"; import { Commands, type CommandsType } from "commands";
import { import {
ChannelType,
Client, Client,
Events,
IntentsBitField, IntentsBitField,
type ButtonInteraction, type ButtonInteraction,
type CacheType, type CacheType,
@@ -18,6 +20,7 @@ import { HelpService } from "actions/help/help.service";
import { custom } from "zod"; import { custom } from "zod";
import { GreetingService } from "actions/greeting/greeting.service"; import { GreetingService } from "actions/greeting/greeting.service";
import { ActivityService } from "actions/activity/activity.service"; import { ActivityService } from "actions/activity/activity.service";
import { DmService } from "actions/dm/dm.service";
export default class DiscordController extends EventEmitter { export default class DiscordController extends EventEmitter {
private discordService!: DiscordService; private discordService!: DiscordService;
@@ -26,6 +29,7 @@ export default class DiscordController extends EventEmitter {
medicationService: MedicationService; medicationService: MedicationService;
helpService: HelpService; helpService: HelpService;
activityService: ActivityService; activityService: ActivityService;
dmService: DmService;
constructor() { constructor() {
super(); super();
@@ -35,17 +39,29 @@ export default class DiscordController extends EventEmitter {
this.medicationService = new MedicationService(); this.medicationService = new MedicationService();
this.helpService = new HelpService(); this.helpService = new HelpService();
this.activityService = new ActivityService(); this.activityService = new ActivityService();
this.dmService = new DmService();
// log when running // log when running
client.once("ready", async () => { client.once("ready", async () => {
this.setActivity(); await this.setActivity();
this.greetingService.customMessage(); console.log("ready");
}); });
// listen for interactions // listen for interactions
client.on("interactionCreate", this.handleInteraction.bind(this)); client.on("interactionCreate", this.handleInteraction.bind(this));
client.on("messageCreate", async (message) => {
console.log(message.id)
if (message.channel.type === ChannelType.DM
&& message.author.id !== config.discord.botId
) {
console.log("got msg");
this.dmService.forward(message);
}
});
client.on("guildMemberAdd", async (member) => { client.on("guildMemberAdd", async (member) => {
console.log("client on guildMemberAdd");
await this.greetingService.welcome(member); await this.greetingService.welcome(member);
await this.dmService.welcomePrivate(member);
}); });
} }
@@ -105,6 +121,9 @@ export default class DiscordController extends EventEmitter {
case Commands.Enum.hilfe: case Commands.Enum.hilfe:
await this.helpService.handleInteraction(interaction); await this.helpService.handleInteraction(interaction);
return; return;
case Commands.Enum.accept:
await this.greetingService.handleInteraction(interaction);
return;
default: default:
break; break;
} }

View File

@@ -1,3 +1,4 @@
import { drizzle } from "drizzle-orm/bun-sqlite"; import { drizzle } from "drizzle-orm/bun-sqlite";
// biome-ignore lint/style/noNonNullAssertion: <explanation>
export const db = drizzle(process.env.DB_FILE_NAME!); export const db = drizzle(process.env.DB_FILE_NAME!);

View File

@@ -1,7 +1,22 @@
import config from "config"; import config from "config";
import { Client, IntentsBitField } from "discord.js"; import { Client, GatewayIntentBits, Partials, ChannelType, Events, IntentsBitField } from "discord.js";
const client = new Client({ intents: [IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages, IntentsBitField.Flags.GuildMembers] }); const client = new Client({
intents: [IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMembers,
IntentsBitField.Flags.GuildModeration,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.GuildMessageReactions,
IntentsBitField.Flags.GuildMessagePolls,
IntentsBitField.Flags.MessageContent,
IntentsBitField.Flags.DirectMessages,
IntentsBitField.Flags.DirectMessageReactions,
IntentsBitField.Flags.DirectMessageTyping,
IntentsBitField.Flags.DirectMessagePolls,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.MessageContent],
partials: [Partials.Channel, Partials.Message]
});
await client.login(config.discord.token); await client.login(config.discord.token);