-
Notifications
You must be signed in to change notification settings - Fork 34
/
GameCommand.ts
115 lines (107 loc) 路 3.89 KB
/
GameCommand.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import CommandInteractionMessagingTunnel from '@bot/messaging/CommandInteractionMessagingTunnel';
import MessagingTunnel from '@bot/messaging/MessagingTunnel';
import TextMessagingTunnel from '@bot/messaging/TextMessagingTunnel';
import GameStateManager from '@bot/state/GameStateManager';
import CommandConfig from '@config/CommandConfig';
import localize from '@i18n/localize';
import { GuildMember, Interaction, Message } from 'discord.js';
/**
* Command to start a duel with someone else.
*
* @author Utarwyn
* @since 2.0.0
*/
export default class GameCommand {
/**
* Global game manager of the module.
* @private
*/
private readonly manager: GameStateManager;
/**
* Configuration of the game command.
* @private
*/
private readonly config: CommandConfig;
/**
* Constructs the command to start a game.
*
* @param manager game state manager
*/
constructor(manager: GameStateManager) {
this.manager = manager;
this.config = manager.bot.configuration;
}
/**
* Handles an incoming message.
*
* @param message discord.js message instance
* @param noTrigger true to bypass trigger checks
* @deprecated use chat command interaction instead
*/
public async handleMessage(message: Message, noTrigger = false): Promise<void> {
if (
message.member &&
!message.author.bot &&
message.channel.isTextBased() &&
(noTrigger ||
(this.config.textCommand && message.content.startsWith(this.config.textCommand)))
) {
const tunnel = new TextMessagingTunnel(message);
const invited = message.mentions.members?.first();
return this.handleInvitation(tunnel, message.member, invited);
}
}
/**
* Handles an incoming interaction.
*
* @param interaction discord.js interaction instance
* @param noTrigger true to bypass trigger checks
*/
public async handleInteraction(interaction: Interaction, noTrigger = false): Promise<void> {
if (
interaction?.isChatInputCommand() &&
interaction.inCachedGuild() &&
interaction.channel?.isTextBased() &&
(noTrigger || interaction.commandName === this.config.command)
) {
// Retrieve the inviter and create an interaction tunnel
const tunnel = new CommandInteractionMessagingTunnel(interaction);
// Retrieve invited user from options if provided
const member = await interaction.member.fetch();
const mentionned =
interaction.options.getMember(this.config.commandOptionName ?? 'opponent') ??
undefined;
return this.handleInvitation(tunnel, member, mentionned);
}
}
/**
* Handles an invitation by starting a game
* or requesting a duel between two members.
*
* @param tunnel game messaging tunnel
* @param inviter discord.js inviter member instance
* @param invited discord.js invited member instance, can be undefined to play against AI
*/
private async handleInvitation(
tunnel: MessagingTunnel,
inviter: GuildMember,
invited?: GuildMember
): Promise<void> {
if (invited) {
if (!invited.user.bot) {
if (
inviter.user.id !== invited.user.id &&
invited.permissionsIn(tunnel.channel).has('ViewChannel')
) {
await this.manager.requestDuel(tunnel, invited);
} else {
await tunnel.replyWith({ content: localize.__('duel.unknown-user') }, true);
}
} else {
await tunnel.replyWith({ content: localize.__('duel.no-bot') }, true);
}
} else {
await this.manager.createGame(tunnel);
}
}
}