Adds some more polish
This commit is contained in:
parent
b3d0b3a90c
commit
11bd836ec3
18 changed files with 272 additions and 29 deletions
|
|
@ -6,6 +6,10 @@ on:
|
||||||
- release-*
|
- release-*
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILD_TARGET: DOCKER
|
||||||
|
BUILD_LABEL: release
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: node-20
|
runs-on: node-20
|
||||||
|
|
@ -31,5 +35,5 @@ jobs:
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
tags: neintonine/pnp-scheduler:release
|
tags: neintonine/pnp-scheduler:${{ env.BUILD_LABEL }}
|
||||||
context: .
|
context: .
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
|
if (!process.env.BUILD_TARGET) {
|
||||||
|
process.env.BUILD_TARGET = "LOCAL";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.env.BUILD_LABEL) {
|
||||||
|
process.env.BUILD_LABEL = "development";
|
||||||
|
}
|
||||||
|
|
||||||
|
import "./create-build-file.mjs";
|
||||||
import context from './context.mjs';
|
import context from './context.mjs';
|
||||||
|
|
||||||
await context.rebuild();
|
await context.rebuild();
|
||||||
await context.dispose();
|
await context.dispose();
|
||||||
|
|
||||||
|
|
|
||||||
12
build/create-build-file.mjs
Normal file
12
build/create-build-file.mjs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import * as os from "node:os";
|
||||||
|
import * as child_process from "node:child_process";
|
||||||
|
import {json} from "node:stream/consumers";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
|
||||||
|
const buildContext = {
|
||||||
|
target: process.env.BUILD_TARGET ?? 'LOCAL',
|
||||||
|
commitHash: child_process.execSync("git rev-parse HEAD").toString(),
|
||||||
|
label: process.env.BUILD_LABEL ?? 'development',
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync("./dist/deploy.json", JSON.stringify(buildContext))
|
||||||
|
|
@ -15,7 +15,7 @@ export type RuntimeGroupConfiguration = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChannelRuntimeGroupConfiguration = {
|
export type ChannelRuntimeGroupConfiguration = {
|
||||||
newPlaydates: ChannelId,
|
notifications: ChannelId,
|
||||||
playdateReminders: ChannelId
|
playdateReminders: ChannelId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ export class GroupConfigurationProvider implements ConfigurationProvider<
|
||||||
return new ConfigurationTransformer(
|
return new ConfigurationTransformer(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
path: ['channels', 'newPlaydates'],
|
path: ['channels', 'notifications'],
|
||||||
type: TransformerType.Channel,
|
type: TransformerType.Channel,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import {Repository} from "./Repository";
|
||||||
import {GroupModel} from "../Models/GroupModel";
|
import {GroupModel} from "../Models/GroupModel";
|
||||||
import Groups, {DBGroup} from "../tables/Groups";
|
import Groups, {DBGroup} from "../tables/Groups";
|
||||||
import {DatabaseConnection} from "../DatabaseConnection";
|
import {DatabaseConnection} from "../DatabaseConnection";
|
||||||
import {GuildMember, UserFlagsBitField} from "discord.js";
|
import {GuildMember} from "discord.js";
|
||||||
import {Nullable} from "../../types/Nullable";
|
import {Nullable} from "../../types/Nullable";
|
||||||
import {PlaydateRepository} from "./PlaydateRepository";
|
import {PlaydateRepository} from "./PlaydateRepository";
|
||||||
import {Container} from "../../Container/Container";
|
import {Container} from "../../Container/Container";
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,12 @@ export class Repository<ModelType extends Model, IntermediateModelType = unknown
|
||||||
return result.changes > 0;
|
return result.changes > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getById(id: number): Nullable<ModelType> {
|
public getById(id: number|bigint): Nullable<ModelType> {
|
||||||
const sql = `SELECT * FROM ${this.schema.name} WHERE id = ? LIMIT 1`;
|
const sql = `SELECT * FROM ${this.schema.name} WHERE id = ? LIMIT 1`;
|
||||||
return this.convertToModelType(this.database.fetch<number, IntermediateModelType>(sql, id));
|
return this.convertToModelType(this.database.fetch<number, IntermediateModelType>(sql, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete(id: number) {
|
public delete(id: number|bigint) {
|
||||||
const sql = `DELETE FROM ${this.schema.name} WHERE id = ?`;
|
const sql = `DELETE FROM ${this.schema.name} WHERE id = ?`;
|
||||||
return this.database.execute(sql, id);
|
return this.database.execute(sql, id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
60
source/Discord/Commands/Bot.ts
Normal file
60
source/Discord/Commands/Bot.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import {CacheType, ChatInputCommandInteraction, hyperlink, PermissionFlagsBits, SlashCommandBuilder} from "discord.js";
|
||||||
|
import {ChatInteractionCommand, Command} from "./Command";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import {UserError} from "../UserError";
|
||||||
|
import {ifError} from "node:assert";
|
||||||
|
import {BuildContextGetter} from "../../Utilities/BuildContext";
|
||||||
|
import {EmbedLibrary} from "../EmbedLibrary";
|
||||||
|
|
||||||
|
export class BotCommand implements Command, ChatInteractionCommand {
|
||||||
|
definition(): SlashCommandBuilder {
|
||||||
|
return new SlashCommandBuilder()
|
||||||
|
.setName("bot")
|
||||||
|
.setDescription("Offers some information about the bot")
|
||||||
|
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
|
||||||
|
.addSubcommand(command => command
|
||||||
|
.setName("build")
|
||||||
|
.setDescription("Displays some information about the build the bot is running on.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(interaction: ChatInputCommandInteraction<CacheType>): Promise<void> {
|
||||||
|
switch (interaction.options.getSubcommand()) {
|
||||||
|
case "build":
|
||||||
|
this.displayBuildInfos(interaction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayBuildInfos(interaction: ChatInputCommandInteraction<CacheType>) {
|
||||||
|
const buildContext = new BuildContextGetter().getContext();
|
||||||
|
if (!buildContext) {
|
||||||
|
throw new UserError("Can't find required deploy information", "Using a valid docker image or (when running on a dev build) running `npm run build` once.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = EmbedLibrary.base("Current Build")
|
||||||
|
.setFields(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: "Build Target",
|
||||||
|
value: buildContext.target,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Build Label",
|
||||||
|
value: buildContext.label,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Latest Commit",
|
||||||
|
value: hyperlink(buildContext.commitHash, buildContext.commitLink)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
interaction.reply({
|
||||||
|
embeds: [embed]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,14 @@ import {PlaydatesCommand} from "./Playdates";
|
||||||
import {RESTPostAPIChatInputApplicationCommandsJSONBody} from "discord.js";
|
import {RESTPostAPIChatInputApplicationCommandsJSONBody} from "discord.js";
|
||||||
import {Nullable} from "../../types/Nullable";
|
import {Nullable} from "../../types/Nullable";
|
||||||
import {ServerCommand} from "./Server";
|
import {ServerCommand} from "./Server";
|
||||||
|
import {BotCommand} from "./Bot";
|
||||||
|
|
||||||
const commands: Set<Command> = new Set<Command>([
|
const commands: Set<Command> = new Set<Command>([
|
||||||
new HelloWorldCommand(),
|
new HelloWorldCommand(),
|
||||||
new GroupCommand(),
|
new GroupCommand(),
|
||||||
new PlaydatesCommand(),
|
new PlaydatesCommand(),
|
||||||
new ServerCommand()
|
new ServerCommand(),
|
||||||
|
new BotCommand()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default class Commands {
|
export default class Commands {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ import {ServerConfigurationProvider} from "../../Configuration/Server/ServerConf
|
||||||
import {ServerConfigurationRepository} from "../../Database/Repositories/ServerConfigurationRepository";
|
import {ServerConfigurationRepository} from "../../Database/Repositories/ServerConfigurationRepository";
|
||||||
import {PermissionError} from "../PermissionError";
|
import {PermissionError} from "../PermissionError";
|
||||||
import {EmbedLibrary, EmbedType} from "../EmbedLibrary";
|
import {EmbedLibrary, EmbedType} from "../EmbedLibrary";
|
||||||
|
import {EventHandler} from "../../Events/EventHandler";
|
||||||
|
import {ElementChangedEvent} from "../../Events/EventClasses/ElementChangedEvent";
|
||||||
|
import GroupConfiguration from "../../Database/tables/GroupConfiguration";
|
||||||
|
import Groups from "../../Database/tables/Groups";
|
||||||
|
|
||||||
export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand {
|
export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand {
|
||||||
private static GOODBYE_MESSAGES: string[] = [
|
private static GOODBYE_MESSAGES: string[] = [
|
||||||
|
|
@ -50,7 +54,7 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
|
||||||
definition(): SlashCommandBuilder {
|
definition(): SlashCommandBuilder {
|
||||||
// @ts-expect-error Slash command expects more than needed.
|
// @ts-expect-error Slash command expects more than needed.
|
||||||
return new SlashCommandBuilder()
|
return new SlashCommandBuilder()
|
||||||
.setName('groups')
|
.setName('group')
|
||||||
.setDescription(`Manages groups`)
|
.setDescription(`Manages groups`)
|
||||||
.addSubcommand(create =>
|
.addSubcommand(create =>
|
||||||
create.setName("create")
|
create.setName("create")
|
||||||
|
|
@ -289,9 +293,9 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
|
||||||
type: MenuItemType.Collection,
|
type: MenuItemType.Collection,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
traversalKey: "newPlaydates",
|
traversalKey: "notifications",
|
||||||
label: "New Playdates",
|
label: "Notifications",
|
||||||
description: "Sets the channel, where the group gets notified, when new Playdates are set.",
|
description: "Sets the channel, where the group gets notified, when things are happening, such as a new playdate is created.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
traversalKey: "playdateReminders",
|
traversalKey: "playdateReminders",
|
||||||
|
|
@ -369,6 +373,17 @@ export class GroupCommand implements Command, ChatInteractionCommand, Autocomple
|
||||||
group.leader.memberid = newLeader.id
|
group.leader.memberid = newLeader.id
|
||||||
repo.update(group);
|
repo.update(group);
|
||||||
|
|
||||||
|
Container.get<EventHandler>(EventHandler.name)
|
||||||
|
.dispatch(new ElementChangedEvent<GroupModel>(
|
||||||
|
Groups.name,
|
||||||
|
{
|
||||||
|
id: group.id,
|
||||||
|
leader: {
|
||||||
|
memberid: newLeader.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: [
|
embeds: [
|
||||||
EmbedLibrary.base(
|
EmbedLibrary.base(
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
||||||
definition(): SlashCommandBuilder {
|
definition(): SlashCommandBuilder {
|
||||||
// @ts-expect-error Command builder is improperly marked as incomplete.
|
// @ts-expect-error Command builder is improperly marked as incomplete.
|
||||||
return new SlashCommandBuilder()
|
return new SlashCommandBuilder()
|
||||||
.setName("playdates")
|
.setName("playdate")
|
||||||
.setDescription("Manage your playdates")
|
.setDescription("Manage your playdates")
|
||||||
.addSubcommand((subcommand) => subcommand
|
.addSubcommand((subcommand) => subcommand
|
||||||
.setName("create")
|
.setName("create")
|
||||||
|
|
@ -153,7 +153,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
||||||
|
|
||||||
playdateRepo.create(playdate);
|
playdateRepo.create(playdate);
|
||||||
|
|
||||||
const embed = EmbedLibrary.playdate(
|
const embed = EmbedLibrary.withGroup(
|
||||||
group,
|
group,
|
||||||
"Created a play-date.",
|
"Created a play-date.",
|
||||||
":white_check_mark: Your playdate has been created! You and your group get notified, when its time.",
|
":white_check_mark: Your playdate has been created! You and your group get notified, when its time.",
|
||||||
|
|
@ -198,7 +198,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
||||||
private async list(interaction: ChatInputCommandInteraction, group: GroupModel) {
|
private async list(interaction: ChatInputCommandInteraction, group: GroupModel) {
|
||||||
const playdates = Container.get<PlaydateRepository>(PlaydateRepository.name).findFromGroup(group);
|
const playdates = Container.get<PlaydateRepository>(PlaydateRepository.name).findFromGroup(group);
|
||||||
|
|
||||||
const embed = EmbedLibrary.playdate(
|
const embed = EmbedLibrary.withGroup(
|
||||||
group,
|
group,
|
||||||
"Created a play-date.",
|
"Created a play-date.",
|
||||||
null,
|
null,
|
||||||
|
|
@ -242,7 +242,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
||||||
|
|
||||||
repo.delete(playdateId);
|
repo.delete(playdateId);
|
||||||
|
|
||||||
const embed = EmbedLibrary.playdate(
|
const embed = EmbedLibrary.withGroup(
|
||||||
group,
|
group,
|
||||||
"Playdate deleted",
|
"Playdate deleted",
|
||||||
`:x: Deleted ${time(selected.from_time, 'F')} - ${time(selected.to_time, 'F')}`,
|
`:x: Deleted ${time(selected.from_time, 'F')} - ${time(selected.to_time, 'F')}`,
|
||||||
|
|
@ -296,7 +296,7 @@ export class PlaydatesCommand implements Command, AutocompleteCommand, ChatInter
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const embed = EmbedLibrary.playdate(
|
const embed = EmbedLibrary.withGroup(
|
||||||
group,
|
group,
|
||||||
"Imported play-dates",
|
"Imported play-dates",
|
||||||
`:white_check_mark: Your ${playdates.length} playdates has been created! You and your group get notified, when its time.`,
|
`:white_check_mark: Your ${playdates.length} playdates has been created! You and your group get notified, when its time.`,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export class EmbedLibrary {
|
||||||
return embed
|
return embed
|
||||||
}
|
}
|
||||||
|
|
||||||
public static playdate(
|
public static withGroup(
|
||||||
group: GroupModel,
|
group: GroupModel,
|
||||||
title: string,
|
title: string,
|
||||||
description: string|null = null,
|
description: string|null = null,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ export class UserError extends Error {
|
||||||
public readonly tryInstead: string | null = null
|
public readonly tryInstead: string | null = null
|
||||||
) {
|
) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEmbed(e: UserError): EmbedBuilder {
|
public getEmbed(e: UserError): EmbedBuilder {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import {PlaydateModel} from "../Database/Models/PlaydateModel";
|
||||||
import {TimedEvent} from "./EventHandler.types";
|
import {TimedEvent} from "./EventHandler.types";
|
||||||
import {CleanupEvent} from "./Handlers/CleanupEvent";
|
import {CleanupEvent} from "./Handlers/CleanupEvent";
|
||||||
import {Logger} from "log4js";
|
import {Logger} from "log4js";
|
||||||
|
import {ElementChangedEvent} from "./EventClasses/ElementChangedEvent";
|
||||||
|
import {GroupModel} from "../Database/Models/GroupModel";
|
||||||
|
import {sendLeaderChangeNotificationEventHandler} from "./Handlers/LeaderChanged";
|
||||||
|
|
||||||
export class DefaultEvents {
|
export class DefaultEvents {
|
||||||
public static setupTimed() {
|
public static setupTimed() {
|
||||||
|
|
@ -29,5 +32,9 @@ export class DefaultEvents {
|
||||||
method: sendCreatedNotificationEventHandler,
|
method: sendCreatedNotificationEventHandler,
|
||||||
persistent: true
|
persistent: true
|
||||||
});
|
});
|
||||||
|
eventHandler.addHandler<ElementChangedEvent<GroupModel>>(ElementChangedEvent.name, {
|
||||||
|
method: sendLeaderChangeNotificationEventHandler,
|
||||||
|
persistent: true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
source/Events/EventClasses/ElementChangedEvent.ts
Normal file
13
source/Events/EventClasses/ElementChangedEvent.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import {Model} from "../../Database/Models/Model";
|
||||||
|
import {EventType, NormalEvent} from "../EventHandler.types";
|
||||||
|
import {DeepPartial} from "../../types/Partial";
|
||||||
|
|
||||||
|
export class ElementChangedEvent<T extends Model = Model> implements NormalEvent {
|
||||||
|
constructor(
|
||||||
|
public readonly tableName: string,
|
||||||
|
public readonly changes: DeepPartial<T> & Model,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
type: EventType.Normal = EventType.Normal;
|
||||||
|
}
|
||||||
81
source/Events/Handlers/LeaderChanged.ts
Normal file
81
source/Events/Handlers/LeaderChanged.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
import {ElementChangedEvent} from "../EventClasses/ElementChangedEvent";
|
||||||
|
import {GroupModel} from "../../Database/Models/GroupModel";
|
||||||
|
import Groups from "../../Database/tables/Groups";
|
||||||
|
import {Container} from "../../Container/Container";
|
||||||
|
import {GroupRepository} from "../../Database/Repositories/GroupRepository";
|
||||||
|
import {ConfigurationHandler} from "../../Configuration/ConfigurationHandler";
|
||||||
|
import {GroupConfigurationModel} from "../../Database/Models/GroupConfigurationModel";
|
||||||
|
import {
|
||||||
|
GroupConfigurationProvider,
|
||||||
|
RuntimeGroupConfiguration
|
||||||
|
} from "../../Configuration/Groups/GroupConfigurationProvider";
|
||||||
|
import {GroupConfigurationRepository} from "../../Database/Repositories/GroupConfigurationRepository";
|
||||||
|
import {DiscordClient} from "../../Discord/DiscordClient";
|
||||||
|
import {EmbedLibrary} from "../../Discord/EmbedLibrary";
|
||||||
|
import {roleMention, userMention} from "discord.js";
|
||||||
|
import * as util from "node:util";
|
||||||
|
import {ArrayUtils} from "../../Utilities/ArrayUtils";
|
||||||
|
|
||||||
|
const CHANGED_LINES = [
|
||||||
|
"Look who now manages your group, its %s. He will do a fantastic job!",
|
||||||
|
"Oh the 14th god changed... again, now its %s",
|
||||||
|
"This group was given to %s",
|
||||||
|
"This world was given over to %s, lets hope you survive the next adventure :smiling_imp:"
|
||||||
|
]
|
||||||
|
|
||||||
|
export async function sendLeaderChangeNotificationEventHandler(event: ElementChangedEvent<GroupModel>) {
|
||||||
|
if (event.tableName !== Groups.name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.changes.leader?.memberid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const group = Container.get<GroupRepository>(GroupRepository.name).getById(event.changes.id);
|
||||||
|
if (!group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupConfig = new ConfigurationHandler<GroupConfigurationModel, RuntimeGroupConfiguration>(
|
||||||
|
new GroupConfigurationProvider(
|
||||||
|
Container.get<GroupConfigurationRepository>(GroupConfigurationRepository.name),
|
||||||
|
group
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const targetChannel = groupConfig.getConfigurationByPath('channels.notifications').value;
|
||||||
|
if (!targetChannel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const channel = await Container.get<DiscordClient>(DiscordClient.name).Client.channels.fetch(<string>targetChannel)
|
||||||
|
if (!channel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channel.isTextBased()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channel.isSendable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = EmbedLibrary.withGroup(
|
||||||
|
group,
|
||||||
|
"You have a new leader",
|
||||||
|
util.format(ArrayUtils.chooseRandom(CHANGED_LINES), userMention(group.leader.memberid))
|
||||||
|
)
|
||||||
|
|
||||||
|
channel.send({
|
||||||
|
content: roleMention(group.role.roleid),
|
||||||
|
embeds: [
|
||||||
|
embed
|
||||||
|
],
|
||||||
|
allowedMentions: {
|
||||||
|
roles: [group.role.roleid]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {ElementCreatedEvent} from "../EventClasses/ElementCreatedEvent";
|
import {ElementCreatedEvent} from "../EventClasses/ElementCreatedEvent";
|
||||||
import {PlaydateModel} from "../../Database/Models/PlaydateModel";
|
import {PlaydateModel} from "../../Database/Models/PlaydateModel";
|
||||||
import PlaydateTableConfiguration from "../../Database/tables/Playdate";
|
import PlaydateTableConfiguration from "../../Database/tables/Playdate";
|
||||||
import {EmbedBuilder, roleMention, time} from "discord.js";
|
import {EmbedBuilder, roleMention, time, userMention} from "discord.js";
|
||||||
import {ArrayUtils} from "../../Utilities/ArrayUtils";
|
import {ArrayUtils} from "../../Utilities/ArrayUtils";
|
||||||
import {Container} from "../../Container/Container";
|
import {Container} from "../../Container/Container";
|
||||||
import {GroupConfigurationRepository} from "../../Database/Repositories/GroupConfigurationRepository";
|
import {GroupConfigurationRepository} from "../../Database/Repositories/GroupConfigurationRepository";
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
GroupConfigurationProvider,
|
GroupConfigurationProvider,
|
||||||
RuntimeGroupConfiguration
|
RuntimeGroupConfiguration
|
||||||
} from "../../Configuration/Groups/GroupConfigurationProvider";
|
} from "../../Configuration/Groups/GroupConfigurationProvider";
|
||||||
|
import {EmbedLibrary} from "../../Discord/EmbedLibrary";
|
||||||
|
|
||||||
const NEW_PLAYDATE_MESSAGES = [
|
const NEW_PLAYDATE_MESSAGES = [
|
||||||
'A new playdate was added. Lets hope, your GM has not planned to kill you. >:]',
|
'A new playdate was added. Lets hope, your GM has not planned to kill you. >:]',
|
||||||
|
|
@ -37,7 +38,7 @@ export async function sendCreatedNotificationEventHandler(event: ElementCreatedE
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const targetChannel = groupConfig.getConfigurationByPath('channels.newPlaydates').value;
|
const targetChannel = groupConfig.getConfigurationByPath('channels.notifications').value;
|
||||||
if (!targetChannel) {
|
if (!targetChannel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -55,17 +56,14 @@ export async function sendCreatedNotificationEventHandler(event: ElementCreatedE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = EmbedLibrary.withGroup(
|
||||||
.setTitle("New Playdate added")
|
playdate.group,
|
||||||
.setDescription(
|
"New Playdate added",
|
||||||
ArrayUtils.chooseRandom(NEW_PLAYDATE_MESSAGES)
|
ArrayUtils.chooseRandom(NEW_PLAYDATE_MESSAGES)
|
||||||
)
|
)
|
||||||
.addFields({
|
.addFields({
|
||||||
name: "Playdate:",
|
name: "Playdate:",
|
||||||
value: `${time(playdate.from_time, "F")} - ${time(playdate.to_time, 'F')}`,
|
value: `${time(playdate.from_time, "F")} - ${time(playdate.to_time, 'F')}`,
|
||||||
})
|
|
||||||
.setFooter({
|
|
||||||
text: `Group: ${playdate.group.name}`
|
|
||||||
});
|
});
|
||||||
|
|
||||||
channel.send({
|
channel.send({
|
||||||
|
|
|
||||||
39
source/Utilities/BuildContext.ts
Normal file
39
source/Utilities/BuildContext.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import {Nullable} from "../types/Nullable";
|
||||||
|
import {DataManager} from "discord.js";
|
||||||
|
import * as util from "node:util";
|
||||||
|
|
||||||
|
export type BuildContext = {
|
||||||
|
target: string,
|
||||||
|
commitHash: string,
|
||||||
|
commitLink: string,
|
||||||
|
label: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BuildContextGetter {
|
||||||
|
private static EXPECTED_PATHS = [
|
||||||
|
"./deploy.json",
|
||||||
|
"./dist/deploy.json"
|
||||||
|
];
|
||||||
|
private static GIT_PATH = "https://git.iedsoftworks.com/neintonine/pnp-scheduler/commit/%s";
|
||||||
|
|
||||||
|
getContext(): Nullable<BuildContext> {
|
||||||
|
const path = this.findValidPath();
|
||||||
|
if (!path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonData = fs.readFileSync(path).toString();
|
||||||
|
const data = JSON.parse(jsonData);
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
commitLink: util.format(BuildContextGetter.GIT_PATH, data.commitHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private findValidPath(): Nullable<string> {
|
||||||
|
return BuildContextGetter.EXPECTED_PATHS.find((path) => {
|
||||||
|
return fs.existsSync(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
3
source/types/Partial.ts
Normal file
3
source/types/Partial.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export type DeepPartial<T> = T extends object ? {
|
||||||
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
|
} : T;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue