Skip to content

Commit

Permalink
feat: broadcast command
Browse files Browse the repository at this point in the history
Signed-off-by: GitHub <noreply@github.com>
  • Loading branch information
virtual-designer authored Oct 24, 2024
1 parent a9fbb69 commit 65218b0
Showing 1 changed file with 161 additions and 0 deletions.
161 changes: 161 additions & 0 deletions src/main/typescript/commands/system/BroadcastCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* This file is part of SudoBot.
*
* Copyright (C) 2021, 2022, 2023, 2024 OSN Developers.
*
* SudoBot is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SudoBot is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
*/

import { ArgumentSchema } from "@framework/arguments/ArgumentTypes";
import { ErrorType } from "@framework/arguments/InvalidArgumentError";
import RestStringArgument from "@framework/arguments/RestStringArgument";

Check warning on line 22 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L20-L22

Added lines #L20 - L22 were not covered by tests
import type { Buildable, ChatContext } from "@framework/commands/Command";
import { Command } from "@framework/commands/Command";
import { Inject } from "@framework/container/Inject";
import DirectiveParseError from "@framework/directives/DirectiveParseError";
import { fetchChannel, fetchMember } from "@framework/utils/entities";

Check warning on line 27 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L24-L27

Added lines #L24 - L27 were not covered by tests
import DirectiveParsingService from "@main/services/DirectiveParsingService";
import {
APIEmbed,
escapeMarkdown,
GuildMember,
MessageCreateOptions,
MessagePayload
} from "discord.js";

Check warning on line 35 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L35

Added line #L35 was not covered by tests

type BroadcastCommandArgs = {
message: string;
};

@ArgumentSchema.Definition({
names: ["message"],
types: [RestStringArgument],
optional: false,
errorMessages: [
{
[ErrorType.Required]: "You must provide a message to broadcast.",
[ErrorType.InvalidRange]: "The message must be between 1 and 4096 characters long."
}
],
rules: [
{
"range:max": 4096,
"range:min": 1
}
]
})
class BroadcastCommand extends Command {
public override readonly name = "broadcast";
public override readonly description = "Broadcast a message to all servers.";
public override readonly detailedDescription =
"Broadcast a message to all servers. If a server does not have a broadcast channel set, the message will be sent to the server owner via DM.";
public override readonly aliases = ["announce"];
public override readonly usage = ["<...message: RestString>"];
public override readonly systemAdminOnly = true;

Check warning on line 65 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L41-L65

Added lines #L41 - L65 were not covered by tests

@Inject()
protected readonly directiveParsingService!: DirectiveParsingService;

Check warning on line 68 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L67-L68

Added lines #L67 - L68 were not covered by tests

public override build(): Buildable[] {
return [
this.buildChatInput().addStringOption(option =>
option
.setName("message")
.setDescription("The message to broadcast.")
.setRequired(true)
)
];
}

Check warning on line 79 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L70-L79

Added lines #L70 - L79 were not covered by tests

public override async execute(context: ChatContext, args: BroadcastCommandArgs) {
const guilds = this.application.client.guilds.cache.values();
let failed = 0,
success = 0,
fallback = 0,
total = 0;
let options: MessageCreateOptions | MessagePayload | null = null;

Check warning on line 87 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L81-L87

Added lines #L81 - L87 were not covered by tests

try {
const { data, output } = await this.directiveParsingService.parse(args.message);
options = {
files: context.isLegacy()
? context.commandMessage.attachments.map(a => ({
attachment: a.proxyURL,
name: a.name
}))
: [],
content:
output.trim() === ""
? undefined
: output +
"\n-# This message was broadcasted by the system administrators.",
embeds: (data.embeds as APIEmbed[]) ?? [],
allowedMentions: { parse: [], roles: [], users: [] }
};
} catch (error) {
if (error instanceof DirectiveParseError) {
await context.error(error.message.replace("Invalid argument: ", ""));
} else {
await context.error("An error occurred while parsing directives in the message.");
}

Check warning on line 111 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L89-L111

Added lines #L89 - L111 were not covered by tests

return;
}

Check warning on line 114 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L113-L114

Added lines #L113 - L114 were not covered by tests

if (!options) {
this.application.logger.bug(
"BroadcastCommand",
"Options were not set after parsing directives."
);
return;
}

Check warning on line 122 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L116-L122

Added lines #L116 - L122 were not covered by tests

for (const guild of guilds) {
total++;

Check warning on line 125 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L124-L125

Added lines #L124 - L125 were not covered by tests

const target = guild.systemChannelId
? await fetchChannel(guild, guild.systemChannelId)
: await fetchMember(guild, guild.ownerId);

Check warning on line 129 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L127-L129

Added lines #L127 - L129 were not covered by tests

if (!target || !("send" in target)) {
failed++;
continue;
}

Check warning on line 134 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L131-L134

Added lines #L131 - L134 were not covered by tests

try {
await target.send({
...options,
content: options.content
? options.content +
`${target instanceof GuildMember ? ` You are receiving this message because you are the owner of ${escapeMarkdown(guild.name)}.` : ""}`
: undefined
});

Check warning on line 143 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L136-L143

Added lines #L136 - L143 were not covered by tests

if (target instanceof GuildMember) {
fallback++;
}

Check warning on line 147 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L145-L147

Added lines #L145 - L147 were not covered by tests

success++;
} catch (error) {
failed++;
}
}

Check warning on line 153 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L149-L153

Added lines #L149 - L153 were not covered by tests

await context.success(
`Broadcasted the message to **${total}** servers. **${success}** successful, **${failed}** failed, **${fallback}** fallbacks.`
);
}
}

Check warning on line 159 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L155-L159

Added lines #L155 - L159 were not covered by tests

export default BroadcastCommand;

Check warning on line 161 in src/main/typescript/commands/system/BroadcastCommand.ts

View check run for this annotation

Codecov / codecov/patch

src/main/typescript/commands/system/BroadcastCommand.ts#L161

Added line #L161 was not covered by tests

0 comments on commit 65218b0

Please sign in to comment.