From 9951089da5a288a78356a6b8aaccbdcbe49f0164 Mon Sep 17 00:00:00 2001 From: PM Date: Mon, 28 Dec 2020 09:18:52 -0600 Subject: [PATCH 1/3] comment information --- src/typings.ts | 59 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/typings.ts b/src/typings.ts index 734d910..e1b3f72 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -39,39 +39,40 @@ export interface ExtMessage extends Discord.Message { guesses?: number; } -export interface guildObject { - guildID?: string; - count?: number; - increment?: number; - countChannel?: string; - commandChannel?: string; - failRole?: string; - lastUpdatedID?: string; - lastMessageID?: string; - chatAllowed?: boolean; - leaderboardEligible?: 0 | 1; - numberOfCounts?: number; - totalCount?: number; - recordNumber?: number; - numberOfErrors?: number; - pogNumStat?: number; +export interface guildObject {// the information object assigned to every active guild + guildID?: string;// identifying snowflake + count?: number;// current count (the last number in the counting channel) + increment?: number;// what the count should be increasing by + countChannel?: string;// identifying snowflake of the channel the count takes place in + commandChannel?: string;// identifying snowflake of the only channel commands can be executed in, if enabled + failRole?: string;// identifying snowflake of the role given to players when they fail the count + lastUpdatedID?: string;// identifying snowflake of the last user to count + lastMessageID?: string;// identifying snowflake of the message containing the last count + chatAllowed?: boolean;// setting for whether non-numeric messages should be allowed in the counting channel + leaderboardEligible?: 0 | 1;// status of whether the guild is stil eligible to appear on the leaderboard + numberOfCounts?: number;// the total number of counts committed in the guild + totalCount?: number;// numberOfCounts * increment (the current increment is added to this figure every count) + recordNumber?: number;// the highest number reached in the guild + numberOfErrors?: number;// the total number of counting errors made in the guild + pogNumStat?: number;// the number of times the number 69 was reached + players?: Array;// individual player data for the guild, not global info + saves?: number;// the number of saves the guild currently has (max 3) + lastSaved?: Date;// the timestamp of the last time a save was used on the count + deletedMessageReminder?: boolean;// whether or not the message warning that the previous count was deleted was already sent for the turn + courtesyChances?: 0 | 1 | 2;// the number of chances remaining for the players to guess the number if the situation arises + autoMute?: boolean;// whether the auto-mute on fail feature is enabled, IN BETA + recordHolder?: string; + recordRole?: string;// for the achievement role handed out when the record is broken //paused?: boolean; - players?: Array; - saves?: number; - lastSaved?: Date; - //checkMarks?: boolean; - deletedMessageReminder?: boolean; - courtesyChances?: 0 | 1 | 2; //foulMessage?: boolean; - //redemptionChances?: 0 | 1 | 2; - autoMute?: boolean; + //checkMarks?: boolean; } -export interface GuildPlayer { - id: string; - errors: number; - totalCounts: number; - highestNumber: number; +export interface GuildPlayer {// used for player data in a guildObject + id: string;// the identifying snowflake + errors: number;// the number of errors in total made by the player + totalCounts: number;// the total number of counts made by the player + highestNumber: number;// the highest number the player reached //mutedUntil?: Date; } From de9a58749631ef2026c9713c76aee932ada78e6c Mon Sep 17 00:00:00 2001 From: PM Date: Mon, 28 Dec 2020 09:19:55 -0600 Subject: [PATCH 2/3] more comment --- src/typings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typings.ts b/src/typings.ts index e1b3f72..8e382eb 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -61,8 +61,8 @@ export interface guildObject {// the information object assigned to every active deletedMessageReminder?: boolean;// whether or not the message warning that the previous count was deleted was already sent for the turn courtesyChances?: 0 | 1 | 2;// the number of chances remaining for the players to guess the number if the situation arises autoMute?: boolean;// whether the auto-mute on fail feature is enabled, IN BETA - recordHolder?: string; recordRole?: string;// for the achievement role handed out when the record is broken + recordHolder?: string;// identifying snowflake of the user who made the last highest count, MAY SWITCH TO ARRAY OF USERS //paused?: boolean; //foulMessage?: boolean; //checkMarks?: boolean; From 9a4d0e2c064da75238cb0a7529ce00ed4fb2192f Mon Sep 17 00:00:00 2001 From: PM Date: Mon, 28 Dec 2020 10:08:37 -0600 Subject: [PATCH 3/3] really basic record role This is not complete yet and does not yet meet Codec's FR. --- src/commands/recordrole.ts | 55 +++++++++++++++++++++++++++++++++++++ src/utils/counthandler.ts | 46 ++++++++++++++++++++++++++----- src/utils/dbm.ts | 56 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 src/commands/recordrole.ts diff --git a/src/commands/recordrole.ts b/src/commands/recordrole.ts new file mode 100644 index 0000000..628d637 --- /dev/null +++ b/src/commands/recordrole.ts @@ -0,0 +1,55 @@ +import xlg from '../xlogger'; +import { sendError } from "../utils/messages"; +import checkAccess from '../utils/checkaccess'; +import { CommandClient, ExtMessage } from '../typings'; +import { TextChannel } from 'discord.js'; +import { stringToRole } from "../utils/parsers"; + +module.exports = { + name: "recordrole", + aliases: ["rr"], + usage: "<#role | none>", + args: true, + specialArgs: 1, + description: "set the role given to record breakers", + async execute(client: CommandClient, message: ExtMessage, args: string[]) { + try { + // check for perms + if (!(await checkAccess(message))) return; + if (!message.guild) return; + + const a = args.join(" "); + if (a === "none") { + await client.database?.setRecordRole(message.guild.id, "");// set the recordrole to "" to mean "none" (resetting) + message.channel.send({ + embed: { + color: process.env.NAVY_COLOR, + description: `The Fail Role has been reset.` + } + }); + return; + } + + const target = stringToRole(message.guild, a);// getting role from args + if (!target || typeof target === "string") { + if (!(message.channel instanceof TextChannel)) return false; + sendError(message.channel, "A valid role is required", true); + return false; + } + + await client.database?.setRecordRole(message.guild.id, target.id);// set the id of the recordrole for the guild in the db + message.channel.send({ + embed: { + color: process.env.NAVY_COLOR, + description: `The Record Role has been set to ${target}.\nPeople deemed new record breakers will receive this role, it will be removed from old record breakers.` + } + }); + return; + } catch (error) { + xlg.error(error); + if (!(message.channel instanceof TextChannel)) return; + sendError(message.channel); + return false; + } + } +} \ No newline at end of file diff --git a/src/utils/counthandler.ts b/src/utils/counthandler.ts index 51435d3..e92a22a 100644 --- a/src/utils/counthandler.ts +++ b/src/utils/counthandler.ts @@ -37,10 +37,34 @@ export = async (client: CommandClient, message: ExtMessage): Promise => const incre = increment.increment || 1; //if (parseInt(message.content, 10) !== parseInt((rmsgs.array())[1].content, 10) + 1) { if (parseInt(message.content, 10) !== cc + incre) { - if (!await handleFoul(client, message, "wrong number")) xlg.log("failed to handle foul: number"); + if (!await handleFoul(client, message, "wrong number", parseInt(message.content, 10) - (cc + incre))) xlg.log("failed to handle foul: number"); return true; } - + + // record role handling + const recordRoleID = await client.database?.getRecordRole(message.guild?.id || ""); + if (recordRoleID && recordRoleID.length > 0) {// will check if a role needs to be given to the user who failed the count + const s = await client.database.getStats(message.guild.id); + if (s && s.recordNumber) { + if (cc + incre > s.recordNumber) { + const recordRole = message.guild?.roles.cache.get(recordRoleID); + if (recordRole) { + message.member?.roles.add(recordRole).catch(xlg.error); + const rhid = await client.database.getRecordHolder(message.guild.id); + if (rhid && rhid !== message.author.id) { + const rh = message.guild.members.cache.get(rhid); + if (rh/* && rh.roles.cache.has(recordRoleID)*/) { + rh.roles.remove(recordRole); + } + } + await client.database.setRecordHolder(message.guild.id, message.author.id); + } else { + await client.database?.setRecordRole(message.guild?.id || "", ""); + } + } + } + } + await client.database?.setLastUpdater(message.guild.id, message.author.id);// mark the sender as the last counter await client.database?.updateCount(message.guild.id, cc + incre, message.id); await client.database?.setDelReminderShown(message.guild.id, false);// resets the status to no for whether the reminder for being delete-tricked had been sent @@ -62,7 +86,7 @@ export = async (client: CommandClient, message: ExtMessage): Promise => } } -async function handleFoul(client: CommandClient, message: ExtMessage, reason?: string): Promise { +async function handleFoul(client: CommandClient, message: ExtMessage, reason?: string, offBy?: number): Promise { if (!client || !message) return false; if (!reason) reason = "Foul"; @@ -139,10 +163,11 @@ async function handleFoul(client: CommandClient, message: ExtMessage, reason?: s await client.database?.updateCount(message.guild?.id || "", 0);// reset the count await client.database?.incrementErrorCount(message.guild?.id || "");// adds to the total count of errors for the guild await client.database?.setDelReminderShown(message.guild?.id || "", false);// resets the status to no for whether the reminder for being delete-tricked had been sent + await client.database?.incrementGuildPlayerStats(message.guild?.id || "", message.author.id, true); if (message.guesses !== 2) { await client.database?.setCourtesyChances(message.guild?.id || "", 2);// resets the chances given for the players to guess the number if they get it wrong under circums. } - await client.database?.incrementGuildPlayerStats(message.guild?.id || "", message.author.id, true); + // fail role handling const failroleid = await client.database?.getFailRole(message.guild?.id || ""); if (failroleid && failroleid.length > 0) {// will check if a role needs to be given to the user who failed the count @@ -154,7 +179,7 @@ async function handleFoul(client: CommandClient, message: ExtMessage, reason?: s } } // auto mute handling - await handleMute(client, message); + await handleMute(client, message, offBy); const increment = await client.database?.getIncrement(message.guild?.id); if (!increment) return false; @@ -172,14 +197,21 @@ async function handleFoul(client: CommandClient, message: ExtMessage, reason?: s return true; } -async function handleMute(client: CommandClient, message: ExtMessage): Promise { +async function handleMute(client: CommandClient, message: ExtMessage, offBy?: number): Promise { if (!message.guild || message.channel.type !== "text" || !message.member) return; const ams = await client.database?.getAutoMuteSetting(message.guild?.id); if (!ams) return; + message.channel.updateOverwrite(message.member, { "SEND_MESSAGES": false }, `muting ${message.author.tag} for failing the count`); - const aimDate = moment(new Date()).add(parseInt(process.env.DEF_MUTE_LENGTH || "10"), "m").toDate(); + + let muteLength = parseInt(process.env.DEF_MUTE_LENGTH || "10"); + if (offBy && Math.abs(offBy) > 5) { + muteLength = (Math.abs(offBy) + 5) * 2; + } + const aimDate = moment(new Date()).add(muteLength, "m").toDate(); + client.database?.setMemberMute(message.guild?.id, message.author.id, aimDate) } diff --git a/src/utils/dbm.ts b/src/utils/dbm.ts index 1149a5d..5557dac 100644 --- a/src/utils/dbm.ts +++ b/src/utils/dbm.ts @@ -99,7 +99,9 @@ export class Database { pogNumStat: 0, players: [], courtesyChances: 2, - autoMute: false + autoMute: false, + recordRole: "", + recordHolder: "" } private userDefaults: PlayerData = { userID: "", @@ -295,6 +297,28 @@ export class Database { if (!result || !result.autoMute) return false; return true; } + + async getRecordRole(guildID: string | undefined): Promise { + if (!guildID || !this.db) return false; + await this.maybeSetDefaults(guildID); + const GuildData = this.db.collection("GuildData"); + const result = await GuildData.findOne({ "guildID": guildID }) || this.guildDefaults; + if (result.recordRole) { + return result.recordRole; + } + return ""; + } + + async getRecordHolder(guildID: string | undefined): Promise { + if (!guildID || !this.db) return false; + await this.maybeSetDefaults(guildID); + const GuildData = this.db.collection("GuildData"); + const result = await GuildData.findOne({ "guildID": guildID }) || this.guildDefaults; + if (result.recordHolder) { + return result.recordHolder; + } + return ""; + } /*┏━━━━━━━━━┓ ┃ SETTERS ┃ @@ -571,6 +595,32 @@ export class Database { }); } + async setRecordRole(guildID: string, role: string): Promise { + if (!this.db) return; + await this.maybeSetDefaults(guildID); + const GuildData = this.db.collection("GuildData"); + await GuildData.updateOne({ + "guildID": guildID, + }, { + $set: { "recordRole": role } + }, { + upsert: true + }); + } + + async setRecordHolder(guildID: string, id: string): Promise { + if (!this.db) return; + await this.maybeSetDefaults(guildID); + const GuildData = this.db.collection("GuildData"); + await GuildData.updateOne({ + "guildID": guildID, + }, { + $set: { "recordHolder": id } + }, { + upsert: true + }); + } + /*┏━━━━━━━━━━┓ ┃ DEFAULTS ┃ ┗━━━━━━━━━━┛*/ @@ -598,7 +648,9 @@ export class Database { lastMessageID: "", totalCount: 0, failRole: "", - autoMute: false + autoMute: false, + recordRole: "", + recordHolder: "" } const guild = await GuildData.findOne({ "guildID": guildID }) || guildDefaults; if (isNaN(guild.count)) guild.count = 0;