From e861006e6178d048cc4e6c5cf525ae2ede5c35d6 Mon Sep 17 00:00:00 2001 From: Benedikt Magnus <magnus@magnuscraft.de> Date: Sun, 14 Nov 2021 21:29:45 +0100 Subject: [PATCH] Added "distribute wichtel profiles" command. --- locale/de-DE.commands.json | 7 ++ locale/de-DE.texts.json | 2 + scripts/utility/localisation.ts | 3 + scripts/wichtelbot/database/database.ts | 46 +++++++++ .../database/relationshipWithMembers.ts | 7 ++ .../wichtelbot/endpoint/definitions/state.ts | 1 + .../wichtelbot/message/handlingDefinition.ts | 4 + .../message/handlingTools/handlingUtils.ts | 93 +++++++++++++++++++ .../message/modules/informationModule.ts | 90 +----------------- .../message/modules/moderationModule.ts | 25 ++++- 10 files changed, 189 insertions(+), 89 deletions(-) create mode 100644 scripts/wichtelbot/database/relationshipWithMembers.ts create mode 100644 scripts/wichtelbot/message/handlingTools/handlingUtils.ts diff --git a/locale/de-DE.commands.json b/locale/de-DE.commands.json index 796b2cf..5ccc362 100644 --- a/locale/de-DE.commands.json +++ b/locale/de-DE.commands.json @@ -92,6 +92,13 @@ "maybe": { "commands": ["vielleicht", "vllt", "eventuell", "evtl"] }, + "moddingDistributeWichtelProfiles": + { + "commands": [ + "SteckbriefeVerteilen" + ], + "info": "Verteilt die Steckbriefe der Wichtelkinder an alle Wichtelpaten." + }, "moddingEndRegistration": { "commands": [ diff --git a/locale/de-DE.texts.json b/locale/de-DE.texts.json index 396088e..8cf1332 100644 --- a/locale/de-DE.texts.json +++ b/locale/de-DE.texts.json @@ -39,6 +39,7 @@ "oldInformation": "Dies findet sich aktuell dazu in meiner Datenbank:\n>>> {var.informationValue}", "moderationNeedHelp": "<@&{var.moderationRoleId}> Der Wichtel {contact.nickname} ({contact.tag}) bittet um Hilfe.", "moderationRegistrationEnded": "Registrierungsphase beendet. \nAnzahl Wartender: {var.waitingMemberCount}", + "moderationProfilesDistributed": "Alle {var.profileCount} Steckbriefe wurden verteilt.", "moderationStatus": "**Status des Wichtelns {var.currentEventName}**\nAktuelle Phase: {var.eventPhaseString}\n\nAnzahl Teilnehmer: {var.contactCount}\nDavon vollständig registriert: {var.waitingMemberCount}\n\nBewichtelungsarten:\nAls Wichtelpate: {var.analogueGiverCount} mal analog, {var.digitalGiverCount} mal digital, {var.allGiverCount} mal beides\nAls Wichtelkind: {var.analogueTakerCount} mal analog, {var.digitalTakerCount} mal digital, {var.allTakerCount} mal beides\n\nPakete: {var.parcelSentCount} versendet, {var.parcelReceivedCount} erhalten", "moderationStatusEventPhase": "{var.currentEventPhase}", "moderationStatusEventPhaseWithNextPhase": "{var.currentEventPhase} ({var.nextEventPhase} startet am {date.day}.{date.month}.{date.year} um {date.hour}:{date.minute} Uhr)", @@ -58,5 +59,6 @@ "sentComponentText": "Klicken! Du sollst klicken!", "sternenrose": "Vielen Dank, Sterni! :)", "thankYouResponse": "Bitte!", + "wichtelProfileDistribution": "Hallo {contact.nickname},\ndie Auslosung ist vorüber!\nHier ist der Steckbrief deines Wichtelkindes:", "yourAreWelcomeRespone": "🙂" } diff --git a/scripts/utility/localisation.ts b/scripts/utility/localisation.ts index f72d176..97d4d5f 100644 --- a/scripts/utility/localisation.ts +++ b/scripts/utility/localisation.ts @@ -27,6 +27,7 @@ interface Commands informationBothAnalogueAndDigital: CommandInfo; informationDigital: CommandInfo; maybe: CommandInfo; + moddingDistributeWichtelProfiles: CommandInfo; moddingEndRegistration: CommandInfo; moddingRunAssignment: CommandInfo; // TODO: Rename "modding" commands to "moderation". moddingStatus: CommandInfo; @@ -81,6 +82,7 @@ interface Texts oldInformation: TokenString; moderationNeedHelp: TokenString; // TODO: This includes a Discord specific mention which is not portable to other implementations. moderationRegistrationEnded: TokenString; + moderationProfilesDistributed: TokenString; moderationStatus: TokenString; moderationStatusEventPhase: TokenString; moderationStatusEventPhaseWithNextPhase: TokenString; @@ -100,6 +102,7 @@ interface Texts sentComponentText: TokenString; sternenrose: TokenString; thankYouResponse: TokenString; + wichtelProfileDistribution: TokenString; yourAreWelcomeRespone: TokenString; } diff --git a/scripts/wichtelbot/database/database.ts b/scripts/wichtelbot/database/database.ts index 15a0bfb..ba090a4 100644 --- a/scripts/wichtelbot/database/database.ts +++ b/scripts/wichtelbot/database/database.ts @@ -9,6 +9,7 @@ import { GiftTypeStatistics } from './giftTypeStatistics'; import { InformationData } from '../classes/information'; import Member from '../classes/member'; import { ParcelStatistics } from './parcelStatistics'; +import { RelationshipWithMembers } from './relationshipWithMembers'; import { State } from '../endpoint/definitions'; import Utils from '../../utility/utils'; import Sqlite = require('better-sqlite3'); @@ -569,6 +570,51 @@ export default class Database return relationships; } + public getRelationshipsWithMembers (): RelationshipWithMembers[] + { + const statement = this.mainDatabase.prepare( + `SELECT + giverContact.*, giverInformation.*, takerContact.*, takerInformation.* + FROM + relationship + LEFT JOIN + contact AS giverContact + ON giverContact.id = relationship.giverId + LEFT JOIN + information AS giverInformation + ON giverInformation.contactId = giverContact.id + LEFT JOIN + contact AS takerContact + ON takerContact.id = relationship.takerId + LEFT JOIN + information AS takerInformation + ON takerInformation.contactId = takerContact.id` + ); + + statement.expand(true); + + const resultData = statement.all() as { + giverContact: ContactData, + giverInformation: InformationData, + takerContact: ContactData, + takerInformation: InformationData + }[]; + + const relationshipsWithMembers: RelationshipWithMembers[] = []; + + for (const result of resultData) + { + const relationshipWithMembers: RelationshipWithMembers = { + giver: new Member(result.giverContact, result.giverInformation), + taker: new Member(result.takerContact, result.takerInformation), + }; + + relationshipsWithMembers.push(relationshipWithMembers); + } + + return relationshipsWithMembers; + } + public saveRelationships (relationships: RelationshipData[]): void { const statement = this.mainDatabase.prepare( diff --git a/scripts/wichtelbot/database/relationshipWithMembers.ts b/scripts/wichtelbot/database/relationshipWithMembers.ts new file mode 100644 index 0000000..e924a13 --- /dev/null +++ b/scripts/wichtelbot/database/relationshipWithMembers.ts @@ -0,0 +1,7 @@ +import Member from "../classes/member"; + +export interface RelationshipWithMembers +{ + giver: Member; + taker: Member; +} diff --git a/scripts/wichtelbot/endpoint/definitions/state.ts b/scripts/wichtelbot/endpoint/definitions/state.ts index 8bf10af..e65a0e1 100644 --- a/scripts/wichtelbot/endpoint/definitions/state.ts +++ b/scripts/wichtelbot/endpoint/definitions/state.ts @@ -23,6 +23,7 @@ enum State /** While assignment is running; cannot change information. */ Assignment = 'assignment', // As wichtel: + Wichteling = 'wichteling', MessageToGiftGiver = 'messageToGiftGiver', MessageToGiftTaker = 'messageToGiftTaker', ParcelSendConsignmentNumber = 'sendParcelConsignmentNumber', diff --git a/scripts/wichtelbot/message/handlingDefinition.ts b/scripts/wichtelbot/message/handlingDefinition.ts index 5fd8953..f8009ee 100644 --- a/scripts/wichtelbot/message/handlingDefinition.ts +++ b/scripts/wichtelbot/message/handlingDefinition.ts @@ -497,6 +497,10 @@ export default class HandlingDefinition ]; public moderatorCommands: CommandDefinition[] = [ + { + commandInfo: Localisation.commands.moddingDistributeWichtelProfiles, + handlerFunction: async (message: Message): Promise<void> => this.moderationModule.distributeWichtelProfiles(message) + }, { commandInfo: Localisation.commands.moddingEndRegistration, // TODO: Remove with cron feature that does this automatically. handlerFunction: async (message: Message): Promise<void> => this.moderationModule.endRegistration(message) diff --git a/scripts/wichtelbot/message/handlingTools/handlingUtils.ts b/scripts/wichtelbot/message/handlingTools/handlingUtils.ts new file mode 100644 index 0000000..2460c1d --- /dev/null +++ b/scripts/wichtelbot/message/handlingTools/handlingUtils.ts @@ -0,0 +1,93 @@ +import { Visualisation, VisualisationType } from "../../endpoint/definitions"; +import GiftType from "../../types/giftType"; +import Localisation from "../../../utility/localisation"; +import Member from "../../classes/member"; + +export abstract class HandlingUtils +{ + public static getProfileVisualisations (member: Member): Visualisation[] + { + const visualisations: Visualisation[] = [ + { + headline: Localisation.texts.profileName.process(member), + text: member.name, + type: VisualisationType.Compact + }, + { + headline: Localisation.texts.profileGiftType.process(member), + text: Localisation.translateGiftType(member.information.giftTypeAsTaker), + type: VisualisationType.Compact + } + ]; + + const sendAnalogue = member.information.giftTypeAsTaker == GiftType.Analogue || member.information.giftTypeAsTaker == GiftType.All; + const sendDigital = member.information.giftTypeAsGiver == GiftType.Digital || member.information.giftTypeAsGiver == GiftType.All; + + if (sendAnalogue) + { + visualisations.push( + { + headline: Localisation.texts.profileCounty.process(member), + text: Localisation.translateCountry(member.information.country), + type: VisualisationType.Compact + } + ); + + visualisations.push( + { + headline: Localisation.texts.profileAddress.process(member), + text: member.information.address, + type: VisualisationType.Compact + } + ); + } + + if (sendDigital) + { + visualisations.push( + { + headline: Localisation.texts.profileDigitalAddress.process(member), + text: member.information.digitalAddress, + type: VisualisationType.Compact + } + ); + } + + visualisations.push( + { + headline: Localisation.texts.profileWishlist.process(member), + text: member.information.wishList, + type: VisualisationType.Normal + } + ); + + if (sendAnalogue) + { + visualisations.push( + { + headline: Localisation.texts.profileAllergies.process(member), + text: member.information.allergies, + type: VisualisationType.Normal + } + ); + } + + visualisations.push( + { + headline: Localisation.texts.profileExclusion.process(member), + text: member.information.giftExclusion, + type: VisualisationType.Normal + } + ); + + visualisations.push( + { + headline: Localisation.texts.profileFreeText.process(member), + text: member.information.freeText, + type: VisualisationType.Normal + } + ); + + return visualisations; + } +} diff --git a/scripts/wichtelbot/message/modules/informationModule.ts b/scripts/wichtelbot/message/modules/informationModule.ts index 6f5ac22..73770c1 100644 --- a/scripts/wichtelbot/message/modules/informationModule.ts +++ b/scripts/wichtelbot/message/modules/informationModule.ts @@ -1,8 +1,8 @@ -import { Visualisation, VisualisationType } from "../../endpoint/definitions"; import Config from "../../../utility/config"; import ContactType from "../../types/contactType"; import Database from "../../database/database"; import GiftType from "../../types/giftType"; +import { HandlingUtils } from "../handlingTools/handlingUtils"; import { KeyValuePairList } from "../../../utility/keyValuePair"; import Localisation from "../../../utility/localisation"; import Member from "../../classes/member"; @@ -313,93 +313,7 @@ export default class InformationModule // Send an overview of all information gathered in the form of the own profile: const profileOverviewText = Localisation.texts.registrationProfileOverview.process(member); - const profileVisualisations = this.getProfileVisualisations(member); + const profileVisualisations = HandlingUtils.getProfileVisualisations(member); await message.reply(profileOverviewText, profileVisualisations); } - - public getProfileVisualisations (member: Member): Visualisation[] - { - const visualisations: Visualisation[] = [ - { - headline: Localisation.texts.profileName.process(member), - text: member.name, - type: VisualisationType.Compact - }, - { - headline: Localisation.texts.profileGiftType.process(member), - text: Localisation.translateGiftType(member.information.giftTypeAsTaker), - type: VisualisationType.Compact - } - ]; - - const sendAnalogue = member.information.giftTypeAsTaker == GiftType.Analogue || member.information.giftTypeAsTaker == GiftType.All; - const sendDigital = member.information.giftTypeAsGiver == GiftType.Digital || member.information.giftTypeAsGiver == GiftType.All; - - if (sendAnalogue) - { - visualisations.push( - { - headline: Localisation.texts.profileCounty.process(member), - text: Localisation.translateCountry(member.information.country), - type: VisualisationType.Compact - } - ); - - visualisations.push( - { - headline: Localisation.texts.profileAddress.process(member), - text: member.information.address, - type: VisualisationType.Compact - } - ); - } - - if (sendDigital) - { - visualisations.push( - { - headline: Localisation.texts.profileDigitalAddress.process(member), - text: member.information.digitalAddress, - type: VisualisationType.Compact - } - ); - } - - visualisations.push( - { - headline: Localisation.texts.profileWishlist.process(member), - text: member.information.wishList, - type: VisualisationType.Normal - } - ); - - if (sendAnalogue) - { - visualisations.push( - { - headline: Localisation.texts.profileAllergies.process(member), - text: member.information.allergies, - type: VisualisationType.Normal - } - ); - } - - visualisations.push( - { - headline: Localisation.texts.profileExclusion.process(member), - text: member.information.giftExclusion, - type: VisualisationType.Normal - } - ); - - visualisations.push( - { - headline: Localisation.texts.profileFreeText.process(member), - text: member.information.freeText, - type: VisualisationType.Normal - } - ); - - return visualisations; - } } diff --git a/scripts/wichtelbot/message/modules/moderationModule.ts b/scripts/wichtelbot/message/modules/moderationModule.ts index a0a6300..8a9fa0d 100644 --- a/scripts/wichtelbot/message/modules/moderationModule.ts +++ b/scripts/wichtelbot/message/modules/moderationModule.ts @@ -1,8 +1,9 @@ +import { Message, State } from "../../endpoint/definitions"; import Config from "../../../utility/config"; import Database from "../../database/database"; +import { HandlingUtils } from "../handlingTools/handlingUtils"; import { KeyValuePairList } from "../../../utility/keyValuePair"; import Localisation from "../../../utility/localisation"; -import { Message, State } from "../../endpoint/definitions"; import Utils from "../../../utility/utils"; import WichtelEventPhase from "../../../utility/wichtelEvent"; @@ -111,4 +112,26 @@ export class ModerationModule await message.reply(answer); } + + public async distributeWichtelProfiles (message: Message): Promise<void> + { + const relationships = this.database.getRelationshipsWithMembers(); + + for (const relationship of relationships) + { + const profileOverviewText = Localisation.texts.wichtelProfileDistribution.process(relationship.giver); + const profileVisualisations = HandlingUtils.getProfileVisualisations(relationship.taker); + + await message.reply(profileOverviewText, profileVisualisations); + + relationship.giver.state = State.Wichteling; + // NOTE: We can use "updateContacts" instead of "updateMembers" because we changed the state, which is only part of the contact: + this.database.updateContact(relationship.giver); + } + + const parameters = new KeyValuePairList('profileCount', `${relationships.length}`); + const answer = Localisation.texts.moderationProfilesDistributed.process(message.author, parameters); + + await message.reply(answer); + } } -- GitLab