summaryrefslogtreecommitdiff
path: root/packages/gateway/src/commands/timeout.ts
blob: d43d6bd6194933782002afcafc49638af91a4845 (plain) (blame)
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
116
117
118
119
120
import { Message } from "discord.js";
import { CENTRAL_GUILD_ID, ROLEPLAY_GUILD_ID } from "../constants";
import { logUnexpectedDiscordAPIError, replyWithCleanup } from "../utilities";

const parseDuration = (duration: string): number | null => {
  const match = duration.match(/^(\d+)([smhd])$/);

  if (!match) return null;

  const value = parseInt(match[1]);
  const unit = match[2];

  switch (unit) {
    case "s":
      return value * 1000;
    case "m":
      return value * 60 * 1000;
    case "h":
      return value * 60 * 60 * 1000;
    case "d":
      return value * 24 * 60 * 60 * 1000;
    default:
      return null;
  }
};

const getUserId = (input: string): string | null => {
  const mentionMatch = input.match(/^<@(\d+)>$/);

  if (mentionMatch) return mentionMatch[1];

  const userIdMatch = input.match(/^\d+$/);

  if (userIdMatch) return input;

  return null;
};

const getGuild = (client: any, serverId: string) => {
  if (serverId === "central" || serverId === CENTRAL_GUILD_ID)
    return client.guilds.cache.get(CENTRAL_GUILD_ID);

  if (serverId === "roleplay" || serverId === ROLEPLAY_GUILD_ID)
    return client.guilds.cache.get(ROLEPLAY_GUILD_ID);

  return null;
};

export const handleTimeoutCommand = async (message: Message) => {
  if (message.author.bot) return;

  if (message.content.toLowerCase().startsWith("uma!timeout")) {
    const application = await message.client.application?.fetch();
    const ownerId = application?.owner?.id;

    if (message.author.id !== ownerId) return;

    const parameters = message.content.split(" ").slice(1);

    if (parameters.length < 3) {
      await replyWithCleanup(
        message,
        "❌ Usage: `uma!timeout <server_id|central|roleplay> <user_id|@mention> <duration> [reason]`\n\n**Examples:**\n- `uma!timeout central @user 1h Being toxic`\n- `uma!timeout roleplay 1234567890123456789 6h`\n- `uma!timeout 1406422617724026901 @user 1d Spam`\n\n**Duration format:** Use suffix: `s` (seconds), `m` (minutes), `h` (hours), `d` (days)",
      );

      return;
    }

    const [serverInput, userInput, durationInput, ...reasonParts] = parameters;
    const reason = reasonParts.join(" ") || undefined;
    const durationMs = parseDuration(durationInput);

    if (!durationMs) {
      await replyWithCleanup(
        message,
        "❌ Invalid duration format. Use: `<number><s|m|h|d>`\nExamples: `1m`, `6h`, `1d`",
      );

      return;
    }

    const guild = getGuild(message.client, serverInput);

    if (!guild) {
      await replyWithCleanup(
        message,
        "❌ Invalid server. Use `central`, `roleplay`, or a guild ID.",
      );

      return;
    }

    const userId = getUserId(userInput);

    if (!userId) {
      await replyWithCleanup(
        message,
        "❌ Invalid user. Use a user ID or mention: `<@userId>`",
      );

      return;
    }

    try {
      const member = await guild.members.fetch(userId);

      await member.timeout(durationMs, reason);
      await replyWithCleanup(
        message,
        `✅ Successfully timed out ${member.user.tag} in ${guild.name} for ${durationInput}${reason ? ` - ${reason}` : ""}`,
      );
    } catch (error) {
      logUnexpectedDiscordAPIError(error);
      await replyWithCleanup(
        message,
        `❌ Failed to timeout user. ${error instanceof Error ? error.message : "Unknown error"}`,
      );
    }
  }
};