Skip to content

Commit 93aa164

Browse files
committed
initial commit for counting game
added COUNTING_CHANNEL_ID requirement to vars.json users must work together to count as high as possible coins will be awarded based on the highest number counted to
1 parent 41a2dab commit 93aa164

File tree

1 file changed

+84
-3
lines changed

1 file changed

+84
-3
lines changed

src/events/messageCreate.ts

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,28 @@ import { PDFDocument } from 'pdf-lib';
1414
import { Logger } from 'winston';
1515
import { applyBonusByUserId } from '../components/coin';
1616
import { vars } from '../config';
17-
import { sendKickEmbed } from '../utils/embeds';
17+
import { sendKickEmbed, DEFAULT_EMBED_COLOUR } from '../utils/embeds';
1818
import { convertPdfToPic } from '../utils/pdfToPic';
1919
import { openDB } from '../components/db';
2020
import { spawnSync } from 'child_process';
21+
import { User } from 'discord.js';
22+
import { getCoinEmoji } from '../components/emojis';
2123

2224
const ANNOUNCEMENTS_CHANNEL_ID: string = vars.ANNOUNCEMENTS_CHANNEL_ID;
2325
const RESUME_CHANNEL_ID: string = vars.RESUME_CHANNEL_ID;
26+
const COUNTING_CHANNEL_ID: string = vars.COUNTING_CHANNEL_ID;
2427
const IRC_USER_ID: string = vars.IRC_USER_ID;
2528
const PDF_FILE_PATH = 'tmp/resume.pdf';
2629
const HEIC_FILE_PATH = 'tmp/img.heic';
2730
const CONVERTED_IMG_PATH = 'tmp/img.jpg';
2831

32+
// Variables and constants associated with the counting game
33+
const coinsPerMessage: number = 0.1; // Number of coins awarded = coinsPerMessage * highest counting number * messages sent by user
34+
const countingAuthorDelay: number = 1; // The minimum number of users that must count for someone to go again
35+
const previousCountingAuthors: Array<User> = [];
36+
const authorMessageCounts: Map<User, number> = new Map();
37+
let currentCountingNumber: number = 1;
38+
2939
/*
3040
* If honeypot is to exist again, then add HONEYPOT_CHANNEL_ID to the config
3141
* and add a check for a message's channel ID being equal to HONEYPOT_CHANNEL_ID
@@ -93,13 +103,12 @@ const convertResumePdfsIntoImages = async (
93103
message: Message,
94104
): Promise<Message<boolean> | undefined> => {
95105
const attachment = message.attachments.first();
96-
const hasAttachment = attachment;
97106
const isPDF = attachment && attachment.contentType === 'application/pdf';
98107
const isImage =
99108
attachment && attachment.contentType && attachment.contentType.startsWith('image');
100109

101110
// If no resume pdf is provided, nuke message and DM user about why their message got nuked
102-
if (!(hasAttachment && (isPDF || isImage))) {
111+
if (!(attachment && (isPDF || isImage))) {
103112
const user = message.author.id;
104113
const channel = message.channelId;
105114

@@ -200,6 +209,74 @@ const convertResumePdfsIntoImages = async (
200209
}
201210
};
202211

212+
const countingGameLogic = async (
213+
client: Client,
214+
message: Message,
215+
): Promise<Message<boolean> | undefined> => {
216+
217+
// Check to see if game should end
218+
let reasonForFailure = '';
219+
if (isNaN(Number(message.content))) { // Message was not a number
220+
reasonForFailure = `"${message.content}" is not a number!`;
221+
}
222+
else if (previousCountingAuthors.find((author) => author === message.author)) { // Author is still on cooldown
223+
reasonForFailure = `<@${message.author.id}> counted too recently!`;
224+
}
225+
else if (Number(message.content) != currentCountingNumber) { // Wrong number was sent
226+
reasonForFailure = `${message.content} is not the next number! The next number was ${currentCountingNumber}.`;
227+
}
228+
229+
if (reasonForFailure) {
230+
return endCountingGame(client, message, reasonForFailure);
231+
}
232+
233+
// If checks passed, continue the game
234+
currentCountingNumber++;
235+
message.react('✅');
236+
previousCountingAuthors.unshift(message.author); // Add current author to list of authors on cooldown
237+
while (previousCountingAuthors.length > countingAuthorDelay) {
238+
previousCountingAuthors.pop(); // Remove last author from cooldown
239+
}
240+
const currentAuthorCount: number | undefined = authorMessageCounts.get(message.author);
241+
authorMessageCounts.set(message.author, currentAuthorCount ? currentAuthorCount + 1 : 1);
242+
243+
return;
244+
}
245+
246+
const endCountingGame = async (
247+
client: Client,
248+
message: Message,
249+
reasonForFailure: string
250+
): Promise<Message<boolean> | undefined> => {
251+
const sortedAuthorMessageCounts: Array<[User, number]> = Array.from(authorMessageCounts).sort((a, b) => b[1] - a[1]); // Turns map into descending sorted array
252+
const coinsAwarded: Array<string> = ['**Coins awarded:**'];
253+
sortedAuthorMessageCounts.forEach((pair) => {
254+
pair[1] *= coinsPerMessage * currentCountingNumber; // Changes number of messages sent to number of coins awarded
255+
coinsAwarded.push(`<@${pair[0].id}> - ${pair[1]} ${getCoinEmoji()}`);
256+
});
257+
258+
// ** REMEMBER TO ACTUALLY AWARD COINS
259+
260+
const endGameEmbed = new EmbedBuilder()
261+
.setColor(DEFAULT_EMBED_COLOUR)
262+
.setTitle('Counting Game Over')
263+
.setDescription(coinsAwarded.join('\n'));
264+
endGameEmbed.addFields([
265+
{
266+
name: 'Reason for Game Over',
267+
value: reasonForFailure,
268+
},
269+
]);
270+
271+
currentCountingNumber = 1;
272+
message.react('❌');
273+
previousCountingAuthors.length = 0;
274+
authorMessageCounts.clear();
275+
276+
return await message.channel?.send({embeds: [endGameEmbed]});
277+
};
278+
279+
203280
export const initMessageCreate = async (
204281
client: Client,
205282
logger: Logger,
@@ -219,6 +296,10 @@ export const initMessageCreate = async (
219296
await convertResumePdfsIntoImages(client, message);
220297
}
221298

299+
if (message.channelId === COUNTING_CHANNEL_ID) {
300+
await countingGameLogic(client, message);
301+
}
302+
222303
// Ignore DMs; include announcements, thread, and regular text channels
223304
if (message.channel.type !== ChannelType.DM) {
224305
await applyBonusByUserId(message.author.id);

0 commit comments

Comments
 (0)