commit e502583b90f1a0c89ee41688a236112d54b55dce
parent 41cdf09e9d6592ec0da710b6ee0c39613090332c
Author: Bruno <b-coimbra@hotmail.com>
Date: Wed, 25 Mar 2020 16:00:03 -0300
added cron and hangman commands
Diffstat:
4 files changed, 330 insertions(+), 1 deletion(-)
diff --git a/lib/commands/cron.ts b/lib/commands/cron.ts
@@ -0,0 +1,133 @@
+interface Schedule {
+ hours?: string;
+ minutes?: string;
+ dayOfMonth?: string;
+ month?: string;
+ dayOfWeek?: string;
+}
+
+interface Command {
+ name: string,
+ args?: string[]
+};
+
+interface Cron {
+ job: number,
+ schedule?: Schedule,
+ command?: Command
+};
+
+const RESPONSES = {
+ help: {
+ rm: '.cron rm #[job-index]',
+ command: ':warning: There is no command to execute the cron job on.',
+ schedule: ':warning: There is no schedule to execute the command on.'
+ },
+ added: 'New cron job has been added', // TODO
+ empty: ":warning: There are no cron jobs being executed."
+};
+
+const MATCHERS = {
+ hour_mins:
+ /^(((0|1)[0-9])|2[0-3]):[0-5][0-9]\s?(pm|am)?$/i,
+ day_of_month:
+ /(?:\b)(([1-9]|0[1-9]|[1-2][0-9]|3[0-1])(st|nd|rd|th)?)(?:\b|\/)/i,
+ weekdays: 'mon tue wed thu fri sat sun'.split(' '),
+ prefix: (prefix: string) => new RegExp(`^${prefix}`),
+ ordinals: /st|nd|rd|th/,
+ greenwich: /pm|am/
+};
+
+export default (home_scope: HomeScope) => {
+ const { message, args, CONFIG } = home_scope;
+
+ // let command = `20:32pm 26th 7 fri ${prefix}echo poopoo`;
+ let crons: Cron[] = CONFIG.cron_jobs;
+
+ const matches = (value: string, regex: RegExp): string | undefined =>
+ (value.match(regex) || {})?.input;
+
+ const rm = (job: number) =>
+ delete crons[crons.map(cron => cron.job).indexOf(job)];
+
+ // TODO
+ const list = () => {
+ if (crons.length == 0)
+ return message.answer(RESPONSES.empty);
+
+ crons.each(cron => message.answer("Can't list jobs yet..."));
+ }
+
+ const parse = (args: string[]): Cron => {
+ let cron: Cron = {
+ job: crons.slice(-1)[0]?.job + 1 || 0
+ };
+
+ args.some((argument, i) => {
+ switch (argument) {
+ case (matches(argument, MATCHERS.prefix(CONFIG.commands.prefix))):
+ cron.command = {
+ name: argument,
+ args: args.slice(i + 1)
+ };
+ break;
+ case (matches(argument, MATCHERS.hour_mins)):
+ const [hour, min] = argument.split(':');
+
+ cron.schedule = {
+ hours: hour,
+ minutes: min.split(MATCHERS.greenwich)[0]
+ };
+ break;
+ case (matches(argument, MATCHERS.day_of_month)):
+ const date =
+ matches(argument, MATCHERS.ordinals) == undefined
+ ? { month: argument }
+ : { dayOfMonth: argument.split(MATCHERS.ordinals)[0] };
+
+ cron.schedule = {
+ ...cron.schedule,
+ ...date
+ };
+ break;
+ }
+
+ argument = argument.toLowerCase();
+
+ if (MATCHERS.weekdays.includes(argument)) {
+ cron.schedule = {
+ ...cron.schedule,
+ dayOfWeek: (
+ MATCHERS.weekdays.indexOf(argument) + 1
+ ).toString()
+ };
+ }
+ });
+
+ return cron;
+ };
+
+ let options = args.join(' ').split(' ');
+
+ if (options[0] === 'ls')
+ list();
+ else if (options[0] === 'rm') {
+ let job: number = Number(options[1]);
+
+ (isNaN(job))
+ ? message.answer(RESPONSES.help.rm)
+ : rm(job);
+ }
+ else {
+ const cron: Cron = parse(options);
+
+ if (!cron?.command)
+ message.answer(RESPONSES.help.command);
+ else if (!cron?.schedule)
+ message.answer(RESPONSES.help.schedule)
+ else {
+ crons.push(parse(options));
+ message.answer(RESPONSES.added);
+ }
+ }
+};
diff --git a/lib/commands/hangman.ts b/lib/commands/hangman.ts
@@ -0,0 +1,195 @@
+import { Message, User } from 'discord.js';
+import { FORMATS } from '../extensions';
+
+namespace Types {
+ type ScoreStats = {
+ missed: number,
+ scored: number
+ };
+
+ export type Mask = '_' | '.' | '-' | ':';
+
+ export interface Score {
+ [id: string]: ScoreStats
+ };
+
+ export interface Guess {
+ id: string,
+ answer: string,
+ attempt?: string
+ };
+
+ export interface Config {
+ attempt_limit: number,
+ mask: Mask;
+ };
+
+ export interface Messages {
+ help: string,
+ lose: string,
+ miss: string,
+ in_progress: string,
+ win: (id: string) => string,
+ start: (word: string) => string,
+ guess: (attempt: string) => string,
+ result: (missed: number,
+ scored: number) => string;
+ };
+
+ export enum Status {
+ Started,
+ InProgress
+ }
+}
+
+declare global {
+ interface Array<T> {
+ result(): string;
+ pick(): string;
+ }
+
+ interface String {
+ mask_with(mask: Types.Mask): string[];
+ }
+}
+
+Array.prototype.result = function () {
+ return this.join('');
+};
+
+Array.prototype.pick = function (): string {
+ return this[Math.floor(Math.random() * this.length)];
+}
+
+String.prototype.mask_with = function (mask: Types.Mask = '_') {
+ return [...(mask.repeat(this.length))];
+};
+
+const WORDS: string[] = [
+ "hello",
+ "world"
+];
+
+let GAME_STATUS: Types.Status;
+
+let scores: Types.Score = {
+ "29138138129139128": {
+ missed: 0,
+ scored: 0
+ }
+}
+
+const CONFIG: Types.Config = {
+ attempt_limit: 10,
+ mask: '_'
+}
+
+const MESSAGES: Types.Messages = {
+ help: "To start a new hangman game"
+ + ".hangman new\n".format(FORMATS.block)
+ + "Make a guess: "
+ + ".hangman [@letter]\n".format(FORMATS.block)
+ + "Guess the full word: "
+ + ".hangman [@word]".format(FORMATS.block),
+ in_progress: "A hangman game is already in progress!",
+ lose: "You reached the number of attempts. You lose!",
+ miss: "You missed :(",
+ start: (word) =>
+ `The word is ${word.length} letters long.\n` +
+ `Make a guess!`,
+ win: (id) =>
+ `Congrats ${id}, you won the game!`,
+ guess: (attempt) =>
+ `You guessed: ${attempt}`,
+ result: (missed, scored) =>
+ `Missed: ${missed}\n` +
+ `Scored: ${scored}`,
+};
+
+// export default (home_scope: HomeScope) => {
+// const { message, args } = home_scope;
+
+ // if (args.length === 0 || args[0] === 'help')
+ // message.channel.send(MESSAGES.help);
+
+const args = ['new'];
+
+const start = (w: string) => {
+ console.log(MESSAGES.start(w));
+ GAME_STATUS = Types.Status.Started;
+};
+
+const answer = WORDS.pick();
+
+const [id, attempts, output]: [string, number, string[]] = [
+ // message.author,
+ "494924924924999",
+ CONFIG.attempt_limit,
+ answer.mask_with(CONFIG.mask)
+];
+
+const score = (id: string) =>
+ scores[id].scored++;
+
+const miss = (id: string) =>
+ scores[id].missed++;
+
+const guessed = (attempt: string) =>
+ MESSAGES.guess(attempt);
+
+const hasWon = () =>
+ !output.includes(CONFIG.mask);
+
+const lose = () =>
+ console.log(MESSAGES.lose);
+ // message.channel.send(MESSAGES.lose);
+
+const win = (id: string) => {
+ score(id);
+ const { missed, scored } = scores[id];
+ MESSAGES.win(id);
+ MESSAGES.result(missed, scored);
+};
+
+const guess = ({ id, answer, attempt }: Types.Guess) => {
+ if (GAME_STATUS != (Types.Status.Started | Types.Status.InProgress)) {
+ console.log(MESSAGES.in_progress);
+ return;
+ }
+
+ guessed(attempt);
+
+ if (attempt.length === answer.length)
+ (attempt === answer) ? win(id) : miss(id);
+
+ if (answer.indexOf(attempt) != -1) {
+ miss(id);
+
+ return (scores[id].missed >= attempts)
+ ? lose()
+ : output.result();
+ }
+
+ [...answer]
+ .each((letter: string, i: number) => {
+ if (letter === attempt)
+ output[i] = attempt.toUpperCase();
+
+ if (typeof (output[i]) === 'undefined')
+ output[i] = CONFIG.mask;
+ });
+
+ score(id);
+ return output.result();
+};
+
+if (args[0] === 'new')
+ start(answer);
+else {
+ guess({ id, answer, attempt: args[0] });
+
+ if (hasWon())
+ win(id);
+}
+
+// };
diff --git a/lib/default.ts b/lib/default.ts
@@ -11,7 +11,7 @@ const DEFAULT_GUILD_CONFIG : Types.Config = {
weather_locations: {
'541761315887120399': 'Moscow'
},
-
+ cron_jobs: [],
commands: {
prefix: '!',
max_history: 40,
diff --git a/lib/extensions.ts b/lib/extensions.ts
@@ -25,6 +25,7 @@ declare global {
main_channel: string,
system_channel: string,
pp_sizes: { [key: string]: number }
+ cron_jobs: any[],
weather_locations: { [key: string]: string },
commands: {
prefix: string,