Lint: Enabling 'strictNullChecks'

This commit is contained in:
David Teller 2021-07-22 08:38:44 +02:00
parent 2a77509f9e
commit 2e22154870
11 changed files with 43 additions and 35 deletions

View File

@ -26,7 +26,7 @@ const levelToFn = {
[LogLevel.ERROR.toString()]: LogService.error, [LogLevel.ERROR.toString()]: LogService.error,
}; };
export async function logMessage(level: LogLevel, module: string, message: string | any, additionalRoomIds: string[] | string = null, isRecursive = false) { export async function logMessage(level: LogLevel, module: string, message: string | any, additionalRoomIds: string[] | string | null = null, isRecursive = false) {
if (!additionalRoomIds) additionalRoomIds = []; if (!additionalRoomIds) additionalRoomIds = [];
if (!Array.isArray(additionalRoomIds)) additionalRoomIds = [additionalRoomIds]; if (!Array.isArray(additionalRoomIds)) additionalRoomIds = [additionalRoomIds];

View File

@ -153,7 +153,7 @@ export class Mjolnir {
await logMessage(LogLevel.DEBUG, "Mjolnir@startup", "Loading protected rooms..."); await logMessage(LogLevel.DEBUG, "Mjolnir@startup", "Loading protected rooms...");
await this.resyncJoinedRooms(false); await this.resyncJoinedRooms(false);
try { try {
const data = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE); const data: Object|null = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
if (data && data['rooms']) { if (data && data['rooms']) {
for (const roomId of data['rooms']) { for (const roomId of data['rooms']) {
this.protectedRooms[roomId] = Permalinks.forRoom(roomId); this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
@ -252,7 +252,7 @@ export class Mjolnir {
private async getEnabledProtections() { private async getEnabledProtections() {
let enabled: string[] = []; let enabled: string[] = [];
try { try {
const protections = await this.client.getAccountData(ENABLED_PROTECTIONS_EVENT_TYPE); const protections: Object|null = await this.client.getAccountData(ENABLED_PROTECTIONS_EVENT_TYPE);
if (protections && protections['enabled']) { if (protections && protections['enabled']) {
for (const protection of protections['enabled']) { for (const protection of protections['enabled']) {
enabled.push(protection); enabled.push(protection);
@ -296,7 +296,7 @@ export class Mjolnir {
await this.client.setAccountData(ENABLED_PROTECTIONS_EVENT_TYPE, {enabled: existing}); await this.client.setAccountData(ENABLED_PROTECTIONS_EVENT_TYPE, {enabled: existing});
} }
public async watchList(roomRef: string): Promise<BanList> { public async watchList(roomRef: string): Promise<BanList|null> {
const joinedRooms = await this.client.getJoinedRooms(); const joinedRooms = await this.client.getJoinedRooms();
const permalink = Permalinks.parseUrl(roomRef); const permalink = Permalinks.parseUrl(roomRef);
if (!permalink.roomIdOrAlias) return null; if (!permalink.roomIdOrAlias) return null;
@ -321,12 +321,12 @@ export class Mjolnir {
return list; return list;
} }
public async unwatchList(roomRef: string): Promise<BanList> { public async unwatchList(roomRef: string): Promise<BanList|null> {
const permalink = Permalinks.parseUrl(roomRef); const permalink = Permalinks.parseUrl(roomRef);
if (!permalink.roomIdOrAlias) return null; if (!permalink.roomIdOrAlias) return null;
const roomId = await this.client.resolveRoom(permalink.roomIdOrAlias); const roomId = await this.client.resolveRoom(permalink.roomIdOrAlias);
const list = this.banLists.find(b => b.roomId === roomId); const list = this.banLists.find(b => b.roomId === roomId) || null;
if (list) this.banLists.splice(this.banLists.indexOf(list), 1); if (list) this.banLists.splice(this.banLists.indexOf(list), 1);
await this.client.setAccountData(WATCHED_LISTS_EVENT_TYPE, { await this.client.setAccountData(WATCHED_LISTS_EVENT_TYPE, {
@ -347,7 +347,7 @@ export class Mjolnir {
this.applyUnprotectedRooms(); this.applyUnprotectedRooms();
try { try {
const accountData = await this.client.getAccountData(WARN_UNPROTECTED_ROOM_EVENT_PREFIX + roomId); const accountData: Object|null = await this.client.getAccountData(WARN_UNPROTECTED_ROOM_EVENT_PREFIX + roomId);
if (accountData && accountData['warned']) return; // already warned if (accountData && accountData['warned']) return; // already warned
} catch (e) { } catch (e) {
// Ignore - probably haven't warned about it yet // Ignore - probably haven't warned about it yet
@ -595,7 +595,7 @@ export class Mjolnir {
} }
} }
private async printActionResult(errors: RoomUpdateError[], title: string = null, logAnyways = false) { private async printActionResult(errors: RoomUpdateError[], title: string|null = null, logAnyways = false) {
if (errors.length <= 0) return false; if (errors.length <= 0) return false;
if (!logAnyways) { if (!logAnyways) {

View File

@ -53,7 +53,10 @@ export async function execImportCommand(roomId: string, event: any, mjolnir: Mjo
reason: reason, reason: reason,
}; };
const stateKey = `rule:${ruleContent.entity}`; const stateKey = `rule:${ruleContent.entity}`;
await mjolnir.client.sendStateEvent(list.roomId, ruleTypeToStable(RULE_USER), stateKey, ruleContent); let stableRule = ruleTypeToStable(RULE_USER);
if (stableRule) {
await mjolnir.client.sendStateEvent(list.roomId, stableRule, stateKey, ruleContent);
}
importedRules++; importedRules++;
} }
} else if (stateEvent['type'] === 'm.room.server_acl' && stateEvent['state_key'] === '') { } else if (stateEvent['type'] === 'm.room.server_acl' && stateEvent['state_key'] === '') {
@ -71,7 +74,10 @@ export async function execImportCommand(roomId: string, event: any, mjolnir: Mjo
reason: reason, reason: reason,
}; };
const stateKey = `rule:${ruleContent.entity}`; const stateKey = `rule:${ruleContent.entity}`;
await mjolnir.client.sendStateEvent(list.roomId, ruleTypeToStable(RULE_SERVER), stateKey, ruleContent); let stableRule = ruleTypeToStable(RULE_SERVER);
if (stableRule) {
await mjolnir.client.sendStateEvent(list.roomId, stableRule, stateKey, ruleContent);
}
importedRules++; importedRules++;
} }
} }

View File

@ -21,8 +21,8 @@ import { Permalinks } from "matrix-bot-sdk";
// !mjolnir redact <user ID> [room alias] [limit] // !mjolnir redact <user ID> [room alias] [limit]
export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) { export async function execRedactCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
const userId = parts[2]; const userId = parts[2];
let roomAlias = null; let roomAlias: string|null = null;
let limit = Number.parseInt(parts.length > 3 ? parts[3] : null, 10); // default to NaN for later let limit = Number.parseInt(parts.length > 3 ? parts[3] : "", 10); // default to NaN for later
if (parts.length > 3 && isNaN(limit)) { if (parts.length > 3 && isNaN(limit)) {
roomAlias = await mjolnir.client.resolveRoom(parts[3]); roomAlias = await mjolnir.client.resolveRoom(parts[3]);
if (parts.length > 4) { if (parts.length > 4) {

View File

@ -23,17 +23,17 @@ import { logMessage } from "../LogProxy";
import { DEFAULT_LIST_EVENT_TYPE } from "./SetDefaultBanListCommand"; import { DEFAULT_LIST_EVENT_TYPE } from "./SetDefaultBanListCommand";
interface Arguments { interface Arguments {
list: BanList; list: BanList | null;
entity: string; entity: string;
ruleType: string; ruleType: string | null;
reason: string; reason: string;
} }
// Exported for tests // Exported for tests
export async function parseArguments(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]): Promise<Arguments> { export async function parseArguments(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]): Promise<Arguments|null> {
let defaultShortcode = null; let defaultShortcode = null;
try { try {
const data = await mjolnir.client.getAccountData(DEFAULT_LIST_EVENT_TYPE); const data: Object = await mjolnir.client.getAccountData(DEFAULT_LIST_EVENT_TYPE);
defaultShortcode = data['shortcode']; defaultShortcode = data['shortcode'];
} catch (e) { } catch (e) {
LogService.warn("UnbanBanCommand", "Non-fatal error getting default ban list"); LogService.warn("UnbanBanCommand", "Non-fatal error getting default ban list");
@ -43,9 +43,9 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
} }
let argumentIndex = 2; let argumentIndex = 2;
let ruleType = null; let ruleType: string | null = null;
let entity = null; let entity: string | null = null;
let list = null; let list: BanList | null = null;
let force = false; let force = false;
while (argumentIndex < 7 && argumentIndex < parts.length) { while (argumentIndex < 7 && argumentIndex < parts.length) {
const arg = parts[argumentIndex++]; const arg = parts[argumentIndex++];
@ -62,7 +62,7 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
else if (!ruleType) ruleType = RULE_SERVER; else if (!ruleType) ruleType = RULE_SERVER;
} else if (!list) { } else if (!list) {
const foundList = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === arg.toLowerCase()); const foundList = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === arg.toLowerCase());
if (foundList) { if (foundList !== undefined) {
list = foundList; list = foundList;
} }
} }
@ -88,10 +88,10 @@ export async function parseArguments(roomId: string, event: any, mjolnir: Mjolni
} }
if (!list) { if (!list) {
list = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === defaultShortcode); list = mjolnir.lists.find(b => b.listShortcode.toLowerCase() === defaultShortcode) || null;
} }
let replyMessage = null; let replyMessage: string | null = null;
if (!list) replyMessage = "No ban list matching that shortcode was found"; if (!list) replyMessage = "No ban list matching that shortcode was found";
else if (!ruleType) replyMessage = "Please specify the type as either 'user', 'room', or 'server'"; else if (!ruleType) replyMessage = "Please specify the type as either 'user', 'room', or 'server'";
else if (!entity) replyMessage = "No entity found"; else if (!entity) replyMessage = "No entity found";
@ -128,7 +128,7 @@ export async function execBanCommand(roomId: string, event: any, mjolnir: Mjolni
}; };
const stateKey = `rule:${bits.entity}`; const stateKey = `rule:${bits.entity}`;
await mjolnir.client.sendStateEvent(bits.list.roomId, bits.ruleType, stateKey, ruleContent); await mjolnir.client.sendStateEvent(bits.list!.roomId, bits.ruleType!, stateKey, ruleContent);
await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅'); await mjolnir.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '✅');
} }
@ -140,14 +140,14 @@ export async function execUnbanCommand(roomId: string, event: any, mjolnir: Mjol
const ruleContent = {}; // empty == clear/unban const ruleContent = {}; // empty == clear/unban
const stateKey = `rule:${bits.entity}`; const stateKey = `rule:${bits.entity}`;
await mjolnir.client.sendStateEvent(bits.list.roomId, bits.ruleType, stateKey, ruleContent); await mjolnir.client.sendStateEvent(bits.list!.roomId, bits.ruleType!, stateKey, ruleContent);
if (USER_RULE_TYPES.includes(bits.ruleType) && bits.reason === 'true') { if (USER_RULE_TYPES.includes(bits.ruleType!) && bits.reason === 'true') {
const rule = new MatrixGlob(bits.entity); const rule = new MatrixGlob(bits.entity);
await logMessage(LogLevel.INFO, "UnbanBanCommand", "Unbanning users that match glob: " + bits.entity); await logMessage(LogLevel.INFO, "UnbanBanCommand", "Unbanning users that match glob: " + bits.entity);
let unbannedSomeone = false; let unbannedSomeone = false;
for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) { for (const protectedRoomId of Object.keys(mjolnir.protectedRooms)) {
const members = await mjolnir.client.getRoomMembers(protectedRoomId, null, ['ban'], null); const members = await mjolnir.client.getRoomMembers(protectedRoomId, undefined, ['ban'], undefined);
await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Found ${members.length} banned user(s)`); await logMessage(LogLevel.DEBUG, "UnbanBanCommand", `Found ${members.length} banned user(s)`);
for (const member of members) { for (const member of members) {
const victim = member.membershipFor; const victim = member.membershipFor;

View File

@ -66,7 +66,7 @@ interface IConfig {
* here as much as possible. * here as much as possible.
*/ */
RUNTIME: { RUNTIME: {
client: MatrixClient; client?: MatrixClient;
}; };
} }
@ -116,7 +116,6 @@ const defaultConfig: IConfig = {
// Needed to make the interface happy. // Needed to make the interface happy.
RUNTIME: { RUNTIME: {
client: null,
}, },
}; };

View File

@ -32,7 +32,7 @@ import { MembershipEvent } from "matrix-bot-sdk/lib/models/events/MembershipEven
import * as htmlEscape from "escape-html"; import * as htmlEscape from "escape-html";
import { Healthz } from "./health/healthz"; import { Healthz } from "./health/healthz";
config.RUNTIME = {client: null}; config.RUNTIME = {};
LogService.setLogger(new RichConsoleLogger()); LogService.setLogger(new RichConsoleLogger());
LogService.setLevel(LogLevel.fromString(config.logLevel, LogLevel.DEBUG)); LogService.setLevel(LogLevel.fromString(config.logLevel, LogLevel.DEBUG));

View File

@ -28,7 +28,7 @@ export const ALL_RULE_TYPES = [...USER_RULE_TYPES, ...ROOM_RULE_TYPES, ...SERVER
export const SHORTCODE_EVENT_TYPE = "org.matrix.mjolnir.shortcode"; export const SHORTCODE_EVENT_TYPE = "org.matrix.mjolnir.shortcode";
export function ruleTypeToStable(rule: string, unstable = true): string { export function ruleTypeToStable(rule: string, unstable = true): string|null {
if (USER_RULE_TYPES.includes(rule)) return unstable ? USER_RULE_TYPES[USER_RULE_TYPES.length - 1] : RULE_USER; if (USER_RULE_TYPES.includes(rule)) return unstable ? USER_RULE_TYPES[USER_RULE_TYPES.length - 1] : RULE_USER;
if (ROOM_RULE_TYPES.includes(rule)) return unstable ? ROOM_RULE_TYPES[ROOM_RULE_TYPES.length - 1] : RULE_ROOM; if (ROOM_RULE_TYPES.includes(rule)) return unstable ? ROOM_RULE_TYPES[ROOM_RULE_TYPES.length - 1] : RULE_ROOM;
if (SERVER_RULE_TYPES.includes(rule)) return unstable ? SERVER_RULE_TYPES[SERVER_RULE_TYPES.length - 1] : RULE_SERVER; if (SERVER_RULE_TYPES.includes(rule)) return unstable ? SERVER_RULE_TYPES[SERVER_RULE_TYPES.length - 1] : RULE_SERVER;
@ -37,7 +37,7 @@ export function ruleTypeToStable(rule: string, unstable = true): string {
export default class BanList { export default class BanList {
private rules: ListRule[] = []; private rules: ListRule[] = [];
private shortcode: string = null; private shortcode: string|null = null;
constructor(public readonly roomId: string, public readonly roomRef, private client: MatrixClient) { constructor(public readonly roomId: string, public readonly roomRef, private client: MatrixClient) {
} }
@ -85,7 +85,7 @@ export default class BanList {
continue; continue;
} }
let kind: string = null; let kind: string|null = null;
if (USER_RULE_TYPES.includes(event['type'])) { if (USER_RULE_TYPES.includes(event['type'])) {
kind = RULE_USER; kind = RULE_USER;
} else if (ROOM_RULE_TYPES.includes(event['type'])) { } else if (ROOM_RULE_TYPES.includes(event['type'])) {

View File

@ -19,7 +19,7 @@ import { MatrixGlob } from "matrix-bot-sdk";
export const RECOMMENDATION_BAN = "m.ban"; export const RECOMMENDATION_BAN = "m.ban";
export const RECOMMENDATION_BAN_TYPES = [RECOMMENDATION_BAN, "org.matrix.mjolnir.ban"]; export const RECOMMENDATION_BAN_TYPES = [RECOMMENDATION_BAN, "org.matrix.mjolnir.ban"];
export function recommendationToStable(recommendation: string, unstable = true): string { export function recommendationToStable(recommendation: string, unstable = true): string|null {
if (RECOMMENDATION_BAN_TYPES.includes(recommendation)) return unstable ? RECOMMENDATION_BAN_TYPES[RECOMMENDATION_BAN_TYPES.length - 1] : RECOMMENDATION_BAN; if (RECOMMENDATION_BAN_TYPES.includes(recommendation)) return unstable ? RECOMMENDATION_BAN_TYPES[RECOMMENDATION_BAN_TYPES.length - 1] : RECOMMENDATION_BAN;
return null; return null;
} }

View File

@ -150,7 +150,7 @@ export async function getMessagesByUserIn(client: MatrixClient, sender: string,
let token = timeline['prev_batch'] || response['next_batch']; let token = timeline['prev_batch'] || response['next_batch'];
let bfMessages = {chunk: syncedMessages, end: token}; let bfMessages = {chunk: syncedMessages, end: token};
do { do {
const messages = []; const messages: any[] = [];
for (const event of (bfMessages['chunk'] || [])) { for (const event of (bfMessages['chunk'] || [])) {
if (processed >= limit) return; // we're done even if we don't want to be if (processed >= limit) return; // we're done even if we don't want to be
processed++; processed++;
@ -199,7 +199,9 @@ export async function replaceRoomIdsWithPills(client: MatrixClient, text: string
} }
const regexRoomId = new RegExp(escapeRegex(roomId), "g"); const regexRoomId = new RegExp(escapeRegex(roomId), "g");
content.body = content.body.replace(regexRoomId, alias); content.body = content.body.replace(regexRoomId, alias);
content.formatted_body = content.formatted_body.replace(regexRoomId, `<a href="${Permalinks.forRoom(alias, viaServers)}">${alias}</a>`); if (content.formatted_body) {
content.formatted_body = content.formatted_body.replace(regexRoomId, `<a href="${Permalinks.forRoom(alias, viaServers)}">${alias}</a>`);
}
} }
return content; return content;

View File

@ -9,6 +9,7 @@
"target": "es2015", "target": "es2015",
"noImplicitAny": false, "noImplicitAny": false,
"sourceMap": true, "sourceMap": true,
"strictNullChecks": true,
"outDir": "./lib", "outDir": "./lib",
"types": [ "types": [
"node", "node",