Adds initial progress

This commit is contained in:
Michel Fedde 2025-03-28 23:19:54 +01:00
commit a0b668cb90
34 changed files with 2680 additions and 0 deletions

View file

@ -0,0 +1,82 @@
import {Repository} from "./Repository";
import {GroupModel} from "../Models/GroupModel";
import Groups, {DBGroup} from "../Database/tables/Groups";
import {DatabaseConnection} from "../Database/DatabaseConnection";
import {CacheType, CacheTypeReducer, Guild, GuildMember, GuildMemberRoleManager} from "discord.js";
import {Nullable} from "../types/Nullable";
export class GroupRepository extends Repository<GroupModel, DBGroup> {
constructor(
protected readonly database: DatabaseConnection,
) {
super(
database,
Groups
);
}
public findGroupByName(name: string): Nullable<GroupModel> {
const result = this.database.fetch<string, DBGroup>(
`SELECT * FROM groups WHERE name = ? LIMIT 1`,
name
)
if (!result) {
return undefined;
}
return this.convertToModelType(result);
}
public findGroupsByRoles(server: string, roleIds: string[]): GroupModel[] {
const template = roleIds.map(roleId => '?').join(',');
const dbResult = this.database.fetchAll<number[], DBGroup>(`
SELECT * FROM groups WHERE server = ? AND role IN (${template})
`,
server,
...roleIds)
return dbResult.map((result) => this.convertToModelType(result));
}
public findGroupsByMember(member: GuildMember) {
if (!member) {
throw new Error("Can't find member for guild: none given");
}
return this.findGroupsByRoles(member.guild.id, [...member.roles.cache.keys()])
}
protected convertToModelType(intermediateModel: DBGroup | undefined): GroupModel {
if (!intermediateModel) {
throw new Error("No intermediate model provided");
}
return {
id: intermediateModel.id,
name: intermediateModel.name,
leader: {
server: intermediateModel.server,
memberid: intermediateModel.leader
},
role: {
server: intermediateModel.server,
roleid: intermediateModel.role
}
}
}
protected convertToCreateObject(instance: Partial<GroupModel>): object {
return {
name: instance.name ?? '',
server: instance.role?.server ?? null,
leader: instance.leader?.memberid ?? null,
role: instance.role?.roleid ?? null,
}
}
}

View file

@ -0,0 +1,53 @@
import {Repository} from "./Repository";
import {PlaydateModel} from "../Models/PlaydateModel";
import Playdate, {DBPlaydate} from "../Database/tables/Playdate";
import {DatabaseConnection} from "../Database/DatabaseConnection";
import {GroupRepository} from "./GroupRepository";
import {GroupModel} from "../Models/GroupModel";
import {Nullable} from "../types/Nullable";
import playdate from "../Database/tables/Playdate";
export class PlaydateRepository extends Repository<PlaydateModel, DBPlaydate> {
constructor(
protected readonly database: DatabaseConnection,
private readonly groupRepository: GroupRepository,
) {
super(
database,
Playdate
);
}
findFromGroup(group: GroupModel) {
const finds = this.database.fetchAll<number, DBPlaydate>(
`SELECT * FROM ${this.schema.name} WHERE groupid = ? AND time_from > ?`,
group.id,
new Date().getTime()
);
return finds.map((playdate) => this.convertToModelType(playdate, group));
}
protected convertToModelType(intermediateModel: DBPlaydate | undefined, fixedGroup: Nullable<GroupModel> = null): PlaydateModel {
if (!intermediateModel) {
throw new Error("Unable to convert the playdate model");
}
const result: PlaydateModel = {
id: intermediateModel.id,
group: fixedGroup ?? this.groupRepository.getById(intermediateModel.groupid),
from_time: new Date(intermediateModel.time_from),
to_time: new Date(intermediateModel.time_to),
}
return result;
}
protected convertToCreateObject(instance: Partial<PlaydateModel>): object {
return {
groupid: instance.group?.id ?? null,
time_from: instance.from_time?.getTime() ?? 0,
time_to: instance.to_time?.getTime() ?? 0,
}
}
}

View file

@ -0,0 +1,52 @@
import {DatabaseConnection} from "../Database/DatabaseConnection";
import {Model} from "../Models/Model";
import { Nullable } from "../types/Nullable";
import {DatabaseDefinition} from "../Database/DatabaseDefinition";
import {debug} from "node:util";
export class Repository<ModelType extends Model, IntermediateModelType = unknown> {
constructor(
protected readonly database: DatabaseConnection,
public readonly schema: DatabaseDefinition,
) {}
public create(instance: Partial<ModelType>): number|bigint {
const columnNames = this.schema.columns.filter((column) => {
return !column.primaryKey
}).map((column) => {
return column.name;
});
const createObject = this.convertToCreateObject(instance);
const keys = Object.keys(createObject);
const missingColumns = columnNames.filter((columnName) => {
return !keys.includes(columnName);
})
if (missingColumns.length > 0) {
throw new Error("Can't create instance, due to missing column values: " + missingColumns);
}
const sql = `INSERT INTO ${this.schema.name}(${Object.keys(createObject).join(',')})
VALUES (${Object.keys(createObject).map(() => "?").join(',')})`;
const result = this.database.execute(sql, ...Object.values(createObject));
return result.lastInsertRowid;
}
public getById(id: number): Nullable<ModelType> {
const sql = `SELECT * FROM ${this.schema.name} WHERE id = ? LIMIT 1`;
return this.convertToModelType(this.database.fetch<number, IntermediateModelType>(sql, id));
}
public delete(id: number) {
const sql = `DELETE FROM ${this.schema.name} WHERE id = ?`;
return this.database.execute(sql, id);
}
protected convertToModelType(intermediateModel: IntermediateModelType | undefined): ModelType {
return intermediateModel as unknown as ModelType;
}
protected convertToCreateObject(instance: Partial<ModelType>): object {
return instance;
}
}