Skip to content

Commit 3fa1a43

Browse files
committed
Use Ban/Unban command as an example.
1 parent cddfe58 commit 3fa1a43

File tree

1 file changed

+53
-49
lines changed

1 file changed

+53
-49
lines changed

src/commands/UnbanBanCommand.ts

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,17 @@ limitations under the License.
1616

1717
import { Mjolnir } from "../Mjolnir";
1818
import PolicyList from "../models/PolicyList";
19-
import { extractRequestError, LogLevel, LogService, MatrixGlob, RichReply } from "matrix-bot-sdk";
19+
import { extractRequestError, LogLevel, LogService, MatrixGlob } from "matrix-bot-sdk";
2020
import { RULE_ROOM, RULE_SERVER, RULE_USER, USER_RULE_TYPES } from "../models/ListRule";
2121
import { DEFAULT_LIST_EVENT_TYPE } from "./SetDefaultBanListCommand";
2222
import { defineApplicationCommand } from "./ApplicationCommand";
2323
import { defineMatrixInterfaceCommand } from "./MatrixInterfaceCommand";
24+
import { ValidationError, ValidationResult } from "./Validation";
2425

25-
interface Arguments {
26-
list: PolicyList | null;
27-
entity: string;
28-
ruleType: string | null;
29-
reason: string;
30-
}
26+
type Arguments = Parameters<(mjolnir: Mjolnir, list: PolicyList, ruleType: string, entity: string, reason: string) => void>;
3127

3228
// Exported for tests
33-
export async function parseArguments(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]): Promise<Arguments | null> {
29+
export async function parseArguments(mjolnir: Mjolnir, roomId: string, event: any, parts: string[]): Promise<ValidationResult<Arguments, ValidationError>> {
3430
let defaultShortcode: string | null = null;
3531
try {
3632
const data: { shortcode: string } = await mjolnir.client.getAccountData(DEFAULT_LIST_EVENT_TYPE);
@@ -42,10 +38,19 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
4238
// Assume no default.
4339
}
4440

41+
const findList = (mjolnir: Mjolnir, shortcode: string): ValidationResult<PolicyList, ValidationError> => {
42+
const foundList = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === shortcode.toLowerCase());
43+
if (foundList !== undefined) {
44+
return ValidationResult.Ok(foundList);
45+
} else {
46+
return ValidationResult.Err(ValidationError.makeValidationError('shortcode not found', `A list with the shourtcode ${shortcode} could not be found.`));
47+
}
48+
}
49+
4550
let argumentIndex = 2;
4651
let ruleType: string | null = null;
4752
let entity: string | null = null;
48-
let list: PolicyList | null = null;
53+
let list: ValidationResult<PolicyList, ValidationError>|null = null;
4954
let force = false;
5055
while (argumentIndex < 7 && argumentIndex < parts.length) {
5156
const arg = parts[argumentIndex++];
@@ -61,10 +66,7 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
6166
else if (arg.startsWith("!") && !ruleType) ruleType = RULE_ROOM;
6267
else if (!ruleType) ruleType = RULE_SERVER;
6368
} else if (!list) {
64-
const foundList = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === arg.toLowerCase());
65-
if (foundList !== undefined) {
66-
list = foundList;
67-
}
69+
list = findList(mjolnir, arg.toLocaleLowerCase());
6870
}
6971

7072
if (entity) break;
@@ -88,47 +90,55 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
8890
}
8991

9092
if (!list) {
91-
list = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === defaultShortcode) || null;
92-
}
93-
94-
let replyMessage: string | null = null;
95-
if (!list) replyMessage = "No ban list matching that shortcode was found";
96-
else if (!ruleType) replyMessage = "Please specify the type as either 'user', 'room', or 'server'";
97-
else if (!entity) replyMessage = "No entity found";
98-
99-
if (mjolnir.config.commands.confirmWildcardBan && /[*?]/.test(entity) && !force) {
100-
replyMessage = "Wildcard bans require an additional `--force` argument to confirm";
93+
if (defaultShortcode) {
94+
list = await findList(mjolnir, defaultShortcode);
95+
if (list.isErr()) {
96+
return ValidationResult.Err(ValidationError.makeValidationError(
97+
"shortcode not found",
98+
`A shortcode was not provided for this command, and a list couldn't be found with the default shortcode ${defaultShortcode}`))
99+
}
100+
} else {
101+
// FIXME: should be turned into a utility function to find the default list.
102+
// and in general, why is there a default shortcode instead of a default list?
103+
return ValidationResult.Err(ValidationError.makeValidationError(
104+
"no default shortcode",
105+
`A shortcode was not provided for this command, and a default shortcode was not set either.`
106+
))
107+
}
101108
}
102109

103-
if (replyMessage) {
104-
const reply = RichReply.createFor(roomId, event, replyMessage, replyMessage);
105-
reply["msgtype"] = "m.notice";
106-
await mjolnir.client.sendMessage(roomId, reply);
107-
return null;
110+
if (list.isErr()) {
111+
return ValidationResult.Err(list.err);
112+
} else if (!ruleType) {
113+
return ValidationResult.Err(
114+
ValidationError.makeValidationError('uknown rule type', "Please specify the type as either 'user', 'room', or 'server'")
115+
);
116+
} else if (!entity) {
117+
return ValidationResult.Err(
118+
ValidationError.makeValidationError('no entity', "No entity was able to be parsed from this command")
119+
);
120+
} else if (mjolnir.config.commands.confirmWildcardBan && /[*?]/.test(entity) && !force) {
121+
return ValidationResult.Err(
122+
ValidationError.makeValidationError("wildcard required", "Wildcard bans require an additional `--force` argument to confirm")
123+
);
108124
}
109125

110-
return {
111-
list,
112-
entity,
126+
return ValidationResult.Ok([
127+
mjolnir,
128+
list.ok,
113129
ruleType,
114-
reason: parts.splice(argumentIndex).join(" ").trim(),
115-
};
130+
entity,
131+
parts.splice(argumentIndex).join(" ").trim(),
132+
]);
116133
}
117134

118-
const BAN_COMMAND = defineApplicationCommand([], async (list: PolicyList, ruleType: string, entity: string, reason: string): Promise<void> => {
135+
const BAN_COMMAND = defineApplicationCommand([], async (mjonlir: Mjolnir, list: PolicyList, ruleType: string, entity: string, reason: string): Promise<void> => {
119136
await list.banEntity(ruleType, entity, reason);
120137
});
121138

122139
// !mjolnir ban <shortcode> <user|server|room> <glob> [reason] [--force]
123140
defineMatrixInterfaceCommand(["ban"],
124-
async function (mjolnir: Mjolnir, roomId: string, event: any, parts: string[]): Promise<[PolicyList, string, string, string]> {
125-
const bits = await parseArguments(roomId, event, mjolnir, parts);
126-
if (bits === null) {
127-
// FIXME
128-
throw new Error("Couldn't parse arguments FIXME - parser needs to be rewritten to reject nulls");
129-
}
130-
return [bits.list!, bits.ruleType!, bits.entity!, bits.reason!];
131-
},
141+
parseArguments,
132142
BAN_COMMAND,
133143
async function (mjolnir: Mjolnir, commandRoomId: string, event: any, result: void) {
134144
await mjolnir.client.unstableApis.addReactionToEvent(commandRoomId, event['event_id'], '✅');
@@ -180,13 +190,7 @@ const UNBAN_COMMAND = defineApplicationCommand([], async (mjolnir: Mjolnir, list
180190

181191
// !mjolnir unban <shortcode> <user|server|room> <glob> [apply:t/f]
182192
defineMatrixInterfaceCommand(["unban"],
183-
async function (mjolnir: Mjolnir, roomId: string, event: any, parts: string[]): Promise<[Mjolnir, PolicyList, string, string, string]> {
184-
const bits = await parseArguments(roomId, event, mjolnir, parts);
185-
if (bits === null) {
186-
throw new Error("Couldn't parse arguments FIXME");
187-
}
188-
return [mjolnir, bits.list!, bits.ruleType!, bits.entity!, bits.reason!];
189-
},
193+
parseArguments,
190194
UNBAN_COMMAND,
191195
async function (mjolnir: Mjolnir, commandRoomId: string, event: any, result: void) {
192196
await mjolnir.client.unstableApis.addReactionToEvent(commandRoomId, event['event_id'], '✅');

0 commit comments

Comments
 (0)