reflectionircd/src/Channel.ts
2023-07-03 16:15:51 +00:00

156 lines
No EOL
6 KiB
TypeScript

import { MatrixUser } from "./MatrixUser.js";
import { IRCServer } from "./Server.js";
export class Channel {
public name: string
// <nick, MatrixUser>
public matrixUsers: Map<string, MatrixUser>
// <nick, PL number>
public powerLevels: Map<string, number>
public topic: Map<string, string>;
public channelModes: Map<string, string>;
public eventIDsSeen: Set<string>;
public historyVisibility: string
public guestAccess: string
public joinRules: string
public roomVersion: number
public roomType: string
private syncLocks: Set<string>
constructor(public roomId: string, private server: IRCServer) {
this.name = roomId;
this.matrixUsers = new Map();
this.powerLevels = new Map();
this.topic = new Map([['text', ''], ['timestamp', '0'], ['setter', 'matrix']]);
this.channelModes = new Map([['n', '']]);
this.eventIDsSeen = new Set();
this.historyVisibility = "";
this.guestAccess = "";
this.joinRules = "";
this.roomVersion = 0;
this.roomType = "";
this.syncLocks = new Set();
this.syncLocks.add('isDM');
this.doInitialSync();
}
isSynced() {
return this.syncLocks.size === 0;
}
addSyncLock(name: string) {
this.syncLocks.add(name);
}
delSyncLock(name: string) {
this.syncLocks.delete(name);
if (this.syncLocks.size === 1) {
if (this.matrixUsers.size === 2 && this.name === this.roomId) {
const otherUser = [...this.matrixUsers.values()].filter(m => m.mxid !== this.server.mxid);
const directRoomsForUser = this.server.directRooms.get(otherUser[0].mxid);
if (directRoomsForUser && directRoomsForUser.includes(this.roomId))
this.name = `&${otherUser[0].mxid.substring(1)}`
}
this.syncLocks.delete('isDM');
this.server.finishChannelSync(this);
}
}
doInitialSync() {
this.addSyncLock("m.room.create");
this.server.apiCall.get(`/rooms/${this.roomId}/state/m.room.create`).then(response => {
this.roomType = response.data?.type || "";
if (this.roomType === "m.space")
this.channelModes.set("S", "");
this.roomVersion = response.data?.room_version || 0;
this.delSyncLock("m.room.create")
}).catch(e => {
const errcode = e.response?.data?.errcode;
if (errcode !== "M_NOT_FOUND")
this.server.doLog(e);
this.delSyncLock("m.room.create")
})
this.addSyncLock("m.room.canonical_alias");
this.server.apiCall.get(`/rooms/${this.roomId}/state/m.room.canonical_alias`).then(response => {
const canonical_alias = response.data["alias"];
if (canonical_alias) {
this.name = canonical_alias;
}
this.delSyncLock("m.room.canonical_alias")
}).catch(e => {
const errcode = e.response?.data?.errcode;
if (errcode !== "M_NOT_FOUND")
this.server.doLog(e);
this.delSyncLock("m.room.canonical_alias")
})
this.addSyncLock("m.room.topic");
this.server.apiCall.get(`/rooms/${this.roomId}/state/m.room.topic`).then(response => {
this.delSyncLock("m.room.topic")
const topicText = response.data["topic"];
if (!topicText || this.topic.get("text") !== "")
return;
this.topic.set("text", topicText.replace(/\r\n|\r|\n/g, " "));
this.topic.set("timestamp", Date.now().toString(10).substring(0, 10));
this.topic.set('setter', "matrix");
}).catch(e => {
const errcode = e.response?.data?.errcode;
if (errcode !== "M_NOT_FOUND")
this.server.doLog(`${this.roomId}: ${e}`);
this.delSyncLock("m.room.topic")
})
this.addSyncLock("m.room.members");
this.server.apiCall.get(`/rooms/${this.roomId}/joined_members`).then(response => {
const allMembers = response.data["joined"];
const allMxids = Object.keys(allMembers);
if (allMxids.length > this.server.config["lazyLoadLimit"]) {
this.channelModes.set('u', '');
} else {
for (const member of allMxids) {
const nextMatrixUser = this.server.getOrCreateMatrixUser(member);
this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser);
}
}
this.delSyncLock("m.room.members")
}).catch(e => {
const errcode = e.response?.data?.errcode;
if (errcode !== "M_NOT_FOUND")
this.server.doLog(e);
this.delSyncLock("m.room.members")
})
this.addSyncLock("m.room.power_levels")
this.server.apiCall.get(`/rooms/${this.roomId}/state/m.room.power_levels`).then(response => {
this.delSyncLock("m.room.power_levels")
const users = response.data["users"];
if (!users)
return;
for (const [mxid, pl] of Object.entries(users)) {
const nextMatrixUser = this.server.getOrCreateMatrixUser(mxid);
this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser);
const numPl = Number(pl);
if (numPl > 0)
this.powerLevels.set(nextMatrixUser.nick, numPl);
}
}).catch(e => {
const errcode = e.response?.data?.errcode;
if (errcode !== "M_NOT_FOUND")
this.server.doLog(e);
this.delSyncLock("m.room.power_levels")
})
}
getNickPowerLevelMapping(nick: string): string {
let opStatus = '';
const pl = this.powerLevels.get(nick) || 0;
if (pl > 99) {
opStatus = '@';
}
else if (pl > 49) {
opStatus = '%';
}
else if (pl > 0) {
opStatus = '+';
}
return opStatus;
}
}