diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..239240e --- /dev/null +++ b/index.d.ts @@ -0,0 +1,23 @@ +export const version: string; + +export * from './types/Base'; + +export * from './types/2048'; +export * from './types/Connect4'; +export * from './types/FastType'; +export * from './types/FindEmoji'; +export * from './types/Fishy'; +export * from './types/Flood'; +export * from './types/GuessThePokemon'; +export * from './types/Hangman'; +export * from './types/MatchPairs'; +export * from './types/Minesweeper'; +export * from './types/RockPaperScissors'; +export * from './types/Slots'; +export * from './types/Snake'; +export * from './types/TicTacToe'; +export * from './types/Trivia'; +export * from './types/Wordle'; +export * from './types/WouldYouRather'; + +export * from './types/Emojify'; diff --git a/package.json b/package.json index 6e0c96b..cb9c8c8 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "4.2.0", "description": "Discord Gamecord is a powerful npm package with a collection of minigames for your discord bot", "main": "index.js", + "types": "index.d.ts", "scripts": { "test": "cd test && node ." }, @@ -30,4 +31,5 @@ "directories": { "src": "src" } -} \ No newline at end of file +} + diff --git a/types/2048.d.ts b/types/2048.d.ts new file mode 100644 index 0000000..8f65eb8 --- /dev/null +++ b/types/2048.d.ts @@ -0,0 +1,54 @@ +import { + AttachmentBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType, Position } from './Base'; + +export interface TwoZeroFourEightConstructorOptions + extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + emojis?: { + up?: string; + down?: string; + left?: string; + right?: string; + }; + timeoutTime?: number; + buttonStyle?: ButtonStyle; +} + +export class TwoZeroFourEight extends EventEmitter { + options: DeepRequired>; + message: MessageType; + gameBoard: string[]; + mergedPos: Position[]; + length: number; + score: number; + + on(eventName: 'gameOver', listener: (result: { result: 'win' | 'lose'; player: User; score: number }) => void): this; + once(...args: Parameters): this; + + constructor(options: TwoZeroFourEightConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + getBoardImage(): Promise; // There is literally no reason to make this asynchronous + startGame(): Promise; + placeRandomTile(): void; + handleButtons(msg: Message): void; + gameOver(msg: Message): Promise; + isGameOver(): boolean; + shiftVertical(dir: 'up' | 'down'): boolean; + shiftHorizontal(dir: 'left' | 'right'): boolean; + isInsideBlock(pos: Position): boolean; + shift(pos: Position, dir: 'up' | 'down' | 'left' | 'right'): boolean; +} diff --git a/types/Approve.d.ts b/types/Approve.d.ts new file mode 100644 index 0000000..9b8d228 --- /dev/null +++ b/types/Approve.d.ts @@ -0,0 +1,31 @@ +import { Message, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { DeepRequired, MessageType } from './Base'; + +export interface ApproveConstructorOptions { + embed?: { + requestTitle?: string; + requestColor?: string; + rejectTitle?: string; + rejectColor?: string; + }; + buttons?: { + accept?: string; + reject?: string; + }; + reqTimeoutTime?: number; + mentionUser?: boolean; + requestMessage?: string; + rejectMessage?: string; + reqTimeoutMessage?: string; +} + +export class Approve extends EventEmitter { + options: DeepRequired; + message: MessageType; + opponent: User; + + constructor(options: ApproveConstructorOptions); + approve(): Promise; + formatTurnMessage(options: Options, contentMsg: keyof Options): string; +} diff --git a/types/Base.d.ts b/types/Base.d.ts new file mode 100644 index 0000000..1a5e250 --- /dev/null +++ b/types/Base.d.ts @@ -0,0 +1,21 @@ +import { ChatInputCommandInteraction, Message } from 'discord.js'; + +// Helper type +export type DeepRequired = T extends object ? { [K in keyof T]-?: DeepRequired } : T; +export type Tuple = N extends N ? (number extends N ? T[] : _TupleOf) : never; +type _TupleOf = R['length'] extends N ? R : _TupleOf; + +export type ButtonStyle = 'PRIMARY' | 'SECONDARY' | 'SUCCESS' | 'DANGER'; + +export interface Position { + x: number; + y: number; +} + +export type MessageType = IsSlashGame extends true ? ChatInputCommandInteraction : Message; + +export interface BaseConstructorOptions { + isSlashGame?: IsSlashGame; + message: MessageType; + playerOnlyMessage: string | false; // Wouldn't string | null be more natural? +} diff --git a/types/Connect4.d.ts b/types/Connect4.d.ts new file mode 100644 index 0000000..bcdde64 --- /dev/null +++ b/types/Connect4.d.ts @@ -0,0 +1,54 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { Approve, ApproveConstructorOptions } from './Approve'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface Connect4ConstructorOptions extends BaseConstructorOptions { + opponent: User; + embed?: { + title?: string; + statusTitle?: string; + color?: string; + }; + emojis?: { + board?: string; + player1?: string; + player2?: string; + }; + timeoutTime?: number; + buttonStyle?: ButtonStyle; + turnMessage?: string; + winMessage?: string; + tieMessage?: string; + timeoutMessage?: string; + requestMessage?: string; + rejectMessage?: string; +} + +export class Connect4 extends Approve { + options: DeepRequired>; + message: MessageType; + opponent: User; + player1Turn: boolean; + gameBoard: string[]; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'tie' | 'timeout'; player: User; opponent: User }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: ApproveConstructorOptions & Connect4ConstructorOptions); + + getBoardContent(): string; + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + connect4Game(msg: Message): Promise; + handleButtons(msg: Message): void; + gameOver(msg: Message, result: 'win' | 'tie' | 'timeout'): Promise; + getPlayerEmoji(): string; + getTurnMessage(msg?: string): string; + isBoardFull(): boolean; + foundCheck(blockX: number, blockY: number): boolean; +} diff --git a/types/Emojify.d.ts b/types/Emojify.d.ts new file mode 100644 index 0000000..4ca4676 --- /dev/null +++ b/types/Emojify.d.ts @@ -0,0 +1,26 @@ +type CharsKeys = + | '0' + | '1' + | '2' + | '3' + | '4' + | '5' + | '6' + | '7' + | '8' + | '9' + | '#' + | '*' + | '?' + | '!' + | '+' + | '-' + | '×' + | '$' + | '/' + | ' '; + +export const Emojify: { + (content: string): string; + chars: Record; +}; diff --git a/types/FastType.d.ts b/types/FastType.d.ts new file mode 100644 index 0000000..50330ce --- /dev/null +++ b/types/FastType.d.ts @@ -0,0 +1,36 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface FastTypeConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + description?: string; + }; + sentense?: string; + timeoutTime?: number; + winMessage?: string; + loseMessage?: string; +} + +export class FastType extends EventEmitter { + options: DeepRequired>; + message: MessageType; + timeTaken: number | null; + wpm: number; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; timeTaken: number; wpm: number }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: FastTypeConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message, result: boolean): Promise; +} diff --git a/types/FindEmoji.d.ts b/types/FindEmoji.d.ts new file mode 100644 index 0000000..b79bbfc --- /dev/null +++ b/types/FindEmoji.d.ts @@ -0,0 +1,55 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface FindEmojiConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + description?: string; + findDescription?: string; + }; + timeoutTime?: number; + hideEmojiTime?: number; + buttonStyle?: ButtonStyle; + emojis?: string[]; + winMessage?: string; + loseMessage?: string; + timeoutMessage?: string; +} + +export class FindEmoji extends EventEmitter { + options: DeepRequired>; + message: MessageType; + emojis: string[]; + selected: string | null; + emoji: string | null; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'lose' | 'timeout'; + player: User; + selectedEmoji: string | null; + correctEmoji: string | null; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: FindEmojiConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message, result: boolean): Promise; + getComponents(showEmoji: boolean): ActionRowBuilder[]; +} diff --git a/types/Fishy.d.ts b/types/Fishy.d.ts new file mode 100644 index 0000000..de8d35c --- /dev/null +++ b/types/Fishy.d.ts @@ -0,0 +1,55 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, Snowflake, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface Fish { + emoji: string; + price: number; +} + +export type Fishes = Record<'junk' | 'common' | 'uncommon' | 'rare', Fish>; + +// XXX: Someone suggest a better name, this name has a lot of ambiguity +export interface Player { + id: Snowflake; + balance: number; + fishes: object; +} + +export interface FishyConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + player?: Partial; + fishes?: Partial; + fishyRodPrice?: number; + catchMessage?: string; + sellMessage?: string; + noBalanceMessage?: string; + invalidTypeMessage?: string; + invalidAmountMessage?: string; + noItemMesaage?: string; +} + +export class Fishy extends EventEmitter { + options: DeepRequired>; + message: MessageType; + player: Player; + fishes: Fishes; + + on( + eventName: 'catchFish' | 'sellFish', + listener: (fishy: { player: User; fishType: keyof Fishes; fish: Fish }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: FishyConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + catchFish(): Promise; + sellFish(type: string, amount: number): Promise; + fishyInventory(): Promise; +} diff --git a/types/Flood.d.ts b/types/Flood.d.ts new file mode 100644 index 0000000..41c7474 --- /dev/null +++ b/types/Flood.d.ts @@ -0,0 +1,47 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface FloodConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + difficulty?: number; + timeoutTime?: number; + buttonStyle?: ButtonStyle; + winMessage?: string; + loseMessage?: string; + emojis?: string[]; +} + +export class Flood extends EventEmitter { + options: DeepRequired>; + message: MessageType; + length: number; + gameBoard: string[]; + maxTurns: number; + turns: number; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'lose'; + player: User; + turns: number; + maxTurns: number; + boardColor: string; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: FloodConstructorOptions); + + getBoardContent(): string; + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message, result: boolean): Promise; + updateGame(selected: string, msg: Message): Promise; +} diff --git a/types/GuessThePokemon.d.ts b/types/GuessThePokemon.d.ts new file mode 100644 index 0000000..95a8d5a --- /dev/null +++ b/types/GuessThePokemon.d.ts @@ -0,0 +1,46 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface Pokemon { + name: string; + id: number; + types: string[]; + abilities: string[]; + height: number; + width: number; + answerImage: string; + questionImage: string; +} + +export interface GuessThePokemonConstructorOptions + extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + timeoutTime?: number; + winMessage?: string; + loseMessage?: string; + errMessage?: string; +} + +export class GuessThePokemon extends EventEmitter { + options: DeepRequired>; + message: MessageType; + pokemon: Pokemon; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; pokemon: Pokemon }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: GuessThePokemonConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message, result: boolean): Promise; +} diff --git a/types/Hangman.d.ts b/types/Hangman.d.ts new file mode 100644 index 0000000..ca20393 --- /dev/null +++ b/types/Hangman.d.ts @@ -0,0 +1,65 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +// I am bad at naming +export interface HangmanBody { + hat?: string; + head?: string; + shirt?: string; + pants?: string; + boots?: string; +} + +export interface HangmanConstructorOptions extends BaseConstructorOptions { + embed?: { title?: string; color?: string }; + hangman?: HangmanBody; + customWord?: string | null; + timeoutTime?: number; + theme?: string; + winMessage?: string; + loseMessage?: string; +} + +export class Hangman extends EventEmitter { + options: DeepRequired>; + message: MessageType; + hangman: HangmanBody; + word: string | null; + buttonPage: number; + guessed: string[]; + damage: number; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'lose'; + player: User; + word: string | null; + damage: number; + guessed: string[]; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: HangmanConstructorOptions); + + getBoardContent(): string; + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + handleButtons(msg: Message): void; + gameOver(msg: Message, result: boolean): Promise; + foundWord(): boolean; + getWordEmojis(): string; + getComponent(page: number): ActionRowBuilder; +} diff --git a/types/MatchPairs.d.ts b/types/MatchPairs.d.ts new file mode 100644 index 0000000..89d707c --- /dev/null +++ b/types/MatchPairs.d.ts @@ -0,0 +1,47 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType, Position } from './Base'; + +export interface MatchPairsConstructorOptions extends BaseConstructorOptions { + embed?: { title?: string; color?: string; description?: string }; + timeoutTime?: number; + emojis?: string[]; + winMessage?: string; + loseMessage?: string; +} + +export class MatchPairs extends EventEmitter { + options: DeepRequired>; + message: MessageType; + emojis: string[]; + remainingPairs: number; + components: ActionRowBuilder; + selected: (Position & { id: number }) | null; + tilesTurned: number; + length: number; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; tilesTurned: number; remainingPairs: number }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: MatchPairsConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + getPairEmoji(emoji: string): (Position & { id: number })[]; + getComponent(): ActionRowBuilder; + gameOver(msg: Message, result: boolean): Promise; + handleButtons(msg: Message): Promise; +} diff --git a/types/Minesweeper.d.ts b/types/Minesweeper.d.ts new file mode 100644 index 0000000..10aae63 --- /dev/null +++ b/types/Minesweeper.d.ts @@ -0,0 +1,56 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface MinesweeperConstructorOptions + extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + description?: string; + }; + emojis?: { + flag?: string; + mine?: string; + }; + mines?: number; + timeoutTime?: number; + winMessage?: string; + loseMessage?: string; +} + +export class Minesweeper extends EventEmitter { + options: DeepRequired>; + message: MessageType; + emojis: { flag: string; mine: string }; + gameBoard: (number | boolean)[]; + length: number; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; blocksTurned: number }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: MinesweeperConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + handleButtons(msg: Message): void; + gameOver(msg: Message, result: boolean): Promise; + plantMines(): void; + getMinesAround(x: number, y: number): number; + showFirstBlock(): void; + foundAllMines(): boolean; + getComponents(showMines: boolean, found: boolean): ActionRowBuilder[]; +} diff --git a/types/RockPaperScissors.d.ts b/types/RockPaperScissors.d.ts new file mode 100644 index 0000000..7c300c7 --- /dev/null +++ b/types/RockPaperScissors.d.ts @@ -0,0 +1,62 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { Approve, ApproveConstructorOptions } from './Approve'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface RockPaperScisdorsConstructorOptions + extends BaseConstructorOptions { + opponent: User; + embed?: { + title?: string; + color?: string; + description?: string; + }; + buttons: { + rock?: string; + paper?: string; + scissors?: string; + }; + emojis?: { + rock?: string; + paper?: string; + scissors?: string; + }; + timeoutTime?: number; + buttonStyle?: ButtonStyle; + pickMessage?: string; + winMessage?: string; + tieMessage?: string; + timeoutMessage?: string; + requestMessage?: string; + rejectMessage?: string; +} + +export class RockPaperScissors extends Approve { + options: DeepRequired>; + message: MessageType; + opponent: User; + playerPick: string | null; + opponentPick: string | null; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'tie' | 'timeout'; + player: User; + opponent: User; + playerPick: string | null; + opponentPick: string | null; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: ApproveConstructorOptions & RockPaperScisdorsConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + RPSGame(msg: Message): Promise; + getResult(): 'win' | 'tie' | 'timeout'; + player1Won(): boolean; + gameOver(msg: Message, result: 'win' | 'tie' | 'timeout'): Promise; +} diff --git a/types/Slots.d.ts b/types/Slots.d.ts new file mode 100644 index 0000000..f3a7aea --- /dev/null +++ b/types/Slots.d.ts @@ -0,0 +1,39 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface SlotsConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + slots: string[]; +} + +export class Slots extends EventEmitter { + options: DeepRequired>; + message: MessageType; + slot1: number; + slot2: number; + slot3: number; + slots: string[]; + result: null; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; slots: [string, string, string] }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: SlotsConstructorOptions); + + getBoardContent(showResult: boolean): string; + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message): Promise; + slotMachine(): void; + hasWon(): boolean; + wrap(s: number, add: boolean): string; +} diff --git a/types/Snake.d.ts b/types/Snake.d.ts new file mode 100644 index 0000000..c56444d --- /dev/null +++ b/types/Snake.d.ts @@ -0,0 +1,55 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType, Position } from './Base'; + +export interface SnakeConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + overTitle?: string; + }; + snake?: { + head?: string; + body?: string; + tail?: string; + skull?: string; + }; + emojis?: { + board?: string; + food?: string; + + up?: string; + down?: string; + left?: string; + right?: string; + }; + foods?: string[]; + stopButton?: string; + timeoutTime?: number; +} + +export class Snake extends EventEmitter { + options: DeepRequired>; + message: MessageType; + snake: Position[]; + apple: Position; + snakeLength: number; + gameBoard: string[]; + score: number; + + on(eventName: 'gameOver', listener: (result: { result: 'win' | 'lose'; player: User; score: number }) => void): this; + once(...args: Parameters): this; + + constructor(options: SnakeConstructorOptions); + + getBoardContent(isSkull: boolean): string; + isSnake(pos: Position): Position | false; // I think this should be boolean type in the src + updateFoodLoc(): void; + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + updateGame(msg: Message): Promise; + gameOver(msg: Message): Promise; + handleButtons(msg: Message): void; +} diff --git a/types/TicTacToe.d.ts b/types/TicTacToe.d.ts new file mode 100644 index 0000000..4124a38 --- /dev/null +++ b/types/TicTacToe.d.ts @@ -0,0 +1,73 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { Approve, ApproveConstructorOptions } from './Approve'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType, Tuple } from './Base'; + +export type TicTacToeGameCellState = 0 | 1 | 2; + +export interface TicTacToeConstructorOptions extends BaseConstructorOptions { + opponent: User; + embed?: { + title?: string; + statusTitle?: string; + overTitle?: string; + color?: string; + }; + emojis?: { + xButton?: string; + oButton?: string; + blankButton?: string; + }; + timeoutTime?: number; + xButtonStyle?: ButtonStyle; + oButtonStyle?: ButtonStyle; + turnMessage?: string; + winMessage?: string; + tieMessage?: string; + timeoutMessage?: string; + requestMessage?: string; + rejectMessage?: string; +} + +export class TicTacToe extends Approve { + options: DeepRequired>; + message: MessageType; + opponent: User; + gameBoard: Tuple<9, TicTacToeGameCellState>; + player1Turn: boolean; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'tie' | 'timeout'; + player: User; + opponent: User; + gameBoard: TicTacToe['gameBoard']; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: ApproveConstructorOptions & TicTacToeConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + TicTacToeGame(msg: Message): Promise; + handleButtons(msg: Message): void; + gameOver(msg: Message, result: 'win' | 'tie' | 'timeout'): Promise; + isGameOver(): boolean; + hasWonGame(player: 1 | 2): boolean; + getPlayerEmoji(): string; + getTurnMessage(msg?: string): string; + // The functiom argument name 'btn' should be changed to 'state' or something like this + getButton(btn: TicTacToeGameCellState): { emoji: string; style: ButtonStyle }; + getComponents(): ActionRowBuilder[]; +} diff --git a/types/Trivia.d.ts b/types/Trivia.d.ts new file mode 100644 index 0000000..63405db --- /dev/null +++ b/types/Trivia.d.ts @@ -0,0 +1,64 @@ +import { + ActionRowBuilder, + ButtonBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface TriviaConstructorOptions extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + description?: string; + }; + mode?: 'single' | 'multiple'; + timeoutTime?: number; + buttonStyle?: ButtonStyle; + trueButtonStyle?: ButtonStyle; + falseButtonStyle?: ButtonStyle; + difficulty: 'easy' | 'medium' | 'hard'; + winMessage?: string; + loseMessage?: string; + errMessage?: string; +} + +export class Trivia extends EventEmitter { + options: DeepRequired>; + message: MessageType; + selected: string | number | null; + trivia: + | {} + | { + question: string; + difficulty: string; + category: string; + answer: string; + options: string[]; + }; + + on( + eventName: 'gameOver', + listener: (result: { + result: 'win' | 'lose'; + player: User; + question: Trivia['trivia']; + selected: string | number | null; + }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: TriviaConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + startGame(): Promise; + gameOver(msg: Message, result: boolean): Promise; + getComponents(gameOver: boolean): [ActionRowBuilder]; + getTriviaQuestion(): Promise; +} diff --git a/types/Wordle.d.ts b/types/Wordle.d.ts new file mode 100644 index 0000000..84697c3 --- /dev/null +++ b/types/Wordle.d.ts @@ -0,0 +1,40 @@ +import { + AttachmentBuilder, + InteractionEditReplyOptions, + Message, + MessageEditOptions, + MessagePayload, + User, +} from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, DeepRequired, MessageType } from './Base'; + +export interface WordleConstructorOptions extends BaseConstructorOptions { + embed?: { title?: string; color?: string }; + customWord?: string | null; + timeoutTime?: number; + winMessage?: string; + loseMessage?: string; +} + +export class Wordle extends EventEmitter { + options: DeepRequired>; + message: MessageType; + word: string | null; + guessed: string[]; + + on( + eventName: 'gameOver', + listener: (result: { result: 'win' | 'lose'; player: User; word: string | null; guessed: string[] }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: WordleConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + getBoardImage(): Promise; // There is no reason to make this asynchronous + startGame(): Promise; + gameOver(msg: Message): Promise; +} diff --git a/types/WouldYouRather.d.ts b/types/WouldYouRather.d.ts new file mode 100644 index 0000000..fb870e8 --- /dev/null +++ b/types/WouldYouRather.d.ts @@ -0,0 +1,47 @@ +import { InteractionEditReplyOptions, Message, MessageEditOptions, MessagePayload, User } from 'discord.js'; +import { EventEmitter } from 'node:events'; +import { BaseConstructorOptions, ButtonStyle, DeepRequired, MessageType } from './Base'; + +export interface WouldYouRatherConstructorOptions + extends BaseConstructorOptions { + embed?: { + title?: string; + color?: string; + }; + buttons?: { + option1?: string; + option2?: string; + }; + errMessage?: string; + buttonStyle?: ButtonStyle; +} + +export interface WouldYouRatherData { + title: string; + author: string; + option1: string; + option2: string; + option1_votes: string; + option2_votes: string; +} + +export class WouldYouRather extends EventEmitter { + options: DeepRequired>; + message: MessageType; + data: WouldYouRatherData | {} | null; + + on( + eventName: 'gameOver', + listener: (result: { result: 'finish'; player: User; question: WouldYouRatherData; selected: string }) => void + ): this; + once(...args: Parameters): this; + + constructor(options: WouldYouRatherConstructorOptions); + + sendMessage( + content: string | MessagePayload | (IsSlashGame extends true ? InteractionEditReplyOptions : MessageEditOptions) + ): Promise; + getWyrQuestion(): Promise; + startGame(): Promise; + gameOver(msg: Message, result: '1' | '2'): Promise; +}