Compare commits

..

2 Commits

Author SHA1 Message Date
Moritz Riese
90341b277c Merge branch 'main' of git.unom.io:moriese/avocadi-bot 2024-12-28 20:09:57 +01:00
Moritz Riese
03d36358bf wip medication and db (sqlite) 2024-12-28 20:09:43 +01:00
19 changed files with 191 additions and 46 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -6,7 +6,8 @@
"dev": "bun --watch src/index.ts" "dev": "bun --watch src/index.ts"
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "latest" "@types/bun": "^1.1.14",
"drizzle-kit": "^0.30.1"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5.0.0" "typescript": "^5.0.0"
@ -15,6 +16,8 @@
"@discordjs/rest": "^2.4.0", "@discordjs/rest": "^2.4.0",
"cron": "^3.3.1", "cron": "^3.3.1",
"discord.js": "^14.16.3", "discord.js": "^14.16.3",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.38.3",
"zod": "^3.24.1" "zod": "^3.24.1"
} }
} }

1
process.env Normal file
View File

@ -0,0 +1 @@
DB_FILE_NAME=mydb.sqlite

View File

@ -0,0 +1,2 @@
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*"];

View File

@ -1,17 +1,9 @@
import config from "config"; import config from "config";
import client from "lib/client"; import client from "lib/client";
import { getRandomInt } from "lib/utils"; import { getRandomInt } from "lib/utils";
import { greetContent, sleepContent } from "./greeting.components.ts";
export class GreetingService { export class GreetingService {
private greetContent = ["HALLOOOO"] as const;
private sleepContent = ["zzzzZZ..", "*schnarch*"] as const;
getContent(asleep: boolean) {
if (asleep) {
return this.sleepContent[getRandomInt(0, this.sleepContent.length - 1)];
}
return this.greetContent[getRandomInt(0, this.greetContent.length - 1)];
}
async greet() { async greet() {
const channels = client.channels; const channels = client.channels;
@ -19,7 +11,7 @@ export class GreetingService {
const channel = channels.cache.get(config.discord.channelId); const channel = channels.cache.get(config.discord.channelId);
if (channel?.isTextBased && channel?.isSendable()) { if (channel?.isTextBased && channel?.isSendable()) {
await channel.send({ content: "HALLOOOO" }); await channel.send({ content: this.getContent(false) });
} }
} }
@ -32,4 +24,11 @@ export class GreetingService {
await channel.send({ content: this.getContent(true) }); await channel.send({ content: this.getContent(true) });
} }
} }
getContent(asleep: boolean) {
if (asleep) {
return sleepContent[getRandomInt(0, sleepContent.length - 1)];
}
return greetContent[getRandomInt(0, greetContent.length - 1)];
}
} }

View File

@ -0,0 +1,26 @@
import { CronJob } from "cron";
import { GreetingService } from "actions/greeting/greeting.service";
const greetingService = new GreetingService();
new CronJob(
"0 30 6 * * *", // cronTime
async () => {
console.log("good morning");
await greetingService.greet();
}, // onTick
null, // onComplete
true, // start
"Europe/Berlin", // timeZone
);
new CronJob(
"0 30 22 * * *",
async () => {
console.log("good night");
await greetingService.sleep();
},
null,
true,
"Europe/Berlin",
);

View File

@ -0,0 +1,10 @@
import { ButtonBuilder, ButtonStyle } from "discord.js";
export const yesButton = new ButtonBuilder()
.setCustomId("yesMedication")
.setLabel("ja")
.setStyle(ButtonStyle.Primary);
export const noButton = new ButtonBuilder()
.setCustomId("noMedication")
.setLabel("noch nicht")
.setStyle(ButtonStyle.Secondary);

View File

@ -0,0 +1,94 @@
import { CronJob } from "cron";
import { getRandomInt } from "lib/utils";
import config from "config";
import client from "lib/client";
import {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
type CacheType,
type Interaction,
} from "discord.js";
import { yesButton, noButton } from "./medication.components";
export class MedicationService {
medication: string;
tookMedication: boolean;
constructor() {
this.medication = "";
this.tookMedication = false;
}
async askMedication() {
const channels = client.channels;
const channel = channels.cache.get(config.discord.channelId);
// funkt noch nicht, beides
const row = new ActionRowBuilder().addComponents(yesButton);
row.addComponents(noButton);
if (channel?.isTextBased &&
channel?.isSendable() &&
this.tookMedication == false) {
await channel.send({ content: "hast du schon deine medis genommen? :)", components: [row as any] });
}
}
getMedication() {
throw new Error("Method not implemented.");
}
setMedication() {
const reply = this.getReply();
console.log("medication");
// this.medication = input von user:in hier rein;
return {
reply,
}
}
getReply() {
return "medication reminder";
}
async handleInteraction(interaction: Interaction<CacheType>) {
const result = this.setMedication();
const yesButton = new ButtonBuilder()
.setCustomId("yesMedication")
.setLabel("ja")
.setStyle(ButtonStyle.Primary);
const noButton = new ButtonBuilder()
.setCustomId("noMedication")
.setLabel("noch nicht")
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder().addComponents(yesButton);
row.addComponents(noButton);
if (interaction.isChatInputCommand()) {
await interaction.reply({
content: result.reply,
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
components: [row as any],
});
} else if (interaction.isButton()) {
console.log("button interaction");
if (interaction.customId == "yesMedication") {
interaction.reply({
content: "das hast du toll gemacht <3 mach weiter so :3",
});
} else if (interaction.customId == "noMedication") {
interaction.reply({
content: "das passiert mal... aber versuch sie heute noch zu nehmen, oki? :)",
});
}
}
}
}

View File

@ -0,0 +1,15 @@
import { CronJob } from "cron";
import { MedicationService } from "actions/medication/medication.service";
const medicationService = new MedicationService();
new CronJob(
"0 0 19 * * *", // cronTime
async () => {
console.log("askMedication()");
await medicationService.askMedication();
}, // onTick
null, // onComplete
true, // start
"Europe/Berlin", // timeZone
);

View File

@ -1,5 +1,5 @@
import { CronJob } from "cron"; import { CronJob } from "cron";
import { WaterMeService } from "services/water-me.service"; import { WaterMeService } from "actions/waterMe/waterMe.service";
const waterMeService = new WaterMeService(); const waterMeService = new WaterMeService();

View File

@ -1,14 +1,18 @@
import { SlashCommandBuilder } from "discord.js"; import { SlashCommandBuilder } from "discord.js";
import { z } from "zod"; import { z } from "zod";
export const Commands = z.enum(["water-me"]); export const Commands = z.enum(["giessen", "medikamente"]);
export type CommandsType = z.output<typeof Commands>; export type CommandsType = z.output<typeof Commands>;
export default function getCommands() { export default function getCommands() {
const commands = [ const commands = [
new SlashCommandBuilder() new SlashCommandBuilder()
.setName(Commands.Enum["water-me"]) .setName(Commands.Enum.giessen)
.setDescription("giess mich mit etwas wasser :3"), .setDescription("giess mich mit etwas wasser :3"),
new SlashCommandBuilder()
.setName(Commands.Enum.medikamente)
.setDescription("ich erinnere dich gerne daran, deine medikamente zu nehmen! :)"),
].map((command) => command.toJSON()); ].map((command) => command.toJSON());
return commands; return commands;

View File

@ -9,17 +9,20 @@ import type {
import client from "lib/client"; import client from "lib/client";
import EventEmitter from "node:events"; import EventEmitter from "node:events";
import DiscordService from "services/discord.service"; import DiscordService from "services/discord.service";
import { WaterMeService } from "services/water-me.service"; import { WaterMeService } from "actions/waterMe/waterMe.service";
import config from "config"; import config from "config";
import { MedicationService } from "actions/medication/medication.service";
export default class DiscordController extends EventEmitter { export default class DiscordController extends EventEmitter {
private discordService!: DiscordService; private discordService!: DiscordService;
waterMeService: WaterMeService; waterMeService: WaterMeService;
medicationService: MedicationService;
constructor() { constructor() {
super(); super();
this.discordService = new DiscordService(); this.discordService = new DiscordService();
this.waterMeService = new WaterMeService(); this.waterMeService = new WaterMeService();
this.medicationService = new MedicationService();
// log when running // log when running
client.once("ready", async () => { client.once("ready", async () => {
console.log("hello :)"); console.log("hello :)");
@ -64,6 +67,9 @@ export default class DiscordController extends EventEmitter {
if (customId === "moreWater") { if (customId === "moreWater") {
await this.waterMeService.handleInteraction(interaction); await this.waterMeService.handleInteraction(interaction);
} }
if (customId.toLowerCase().includes("medication")) {
await this.medicationService.handleInteraction(interaction);
}
} }
async handleChatInputCommand( async handleChatInputCommand(
@ -73,9 +79,12 @@ export default class DiscordController extends EventEmitter {
// add commands // add commands
switch (commandName) { switch (commandName) {
case Commands.Enum["water-me"]: case Commands.Enum.giessen:
await this.waterMeService.handleInteraction(interaction); await this.waterMeService.handleInteraction(interaction);
return; return;
case Commands.Enum.medikamente:
await this.medicationService.handleInteraction(interaction);
return;
default: default:
break; break;
} }

View File

@ -1,8 +1,17 @@
import "tasks/water-me.task"; import "actions/waterMe/waterMe.task";
import "tasks/greeting.task"; import "actions/greeting/greeting.task";
import "tasks/drink.task"; import "actions/medication/medication.task"
import "actions/drink/drink.task";
import DiscordController from "controllers/discord.controller"; import DiscordController from "controllers/discord.controller";
import 'dotenv/config';
import { drizzle } from 'drizzle-orm/bun-sqlite';
import { Database } from 'bun:sqlite';
const sqlite = new Database(process.env.DB_FILE_NAME!);
const db = drizzle({ client: sqlite });
// = main file // = main file
// bootstrap application // bootstrap application

View File

@ -1,27 +0,0 @@
import { CronJob } from "cron";
import { GreetingService } from "services/greeting.service";
const greetingService = new GreetingService();
new CronJob(
"0 */30 7-23 * * *", // cronTime
async () => {
console.log("called greeting");
await greetingService.greet();
}, // onTick
null, // onComplete
true, // start
"Europe/Berlin", // timeZone
);
new CronJob(
"0 */30 0-6 * * *", // cronTime
async () => {
console.log("called greeting");
await greetingService.sleep();
}, // onTick
null, // onComplete
true, // start
"Europe/Berlin", // timeZone
);
// job.start() is optional here because of the fourth parameter set to true.