import { MatrixUser } from "./MatrixUser.js"; import { IRCServer } from "./Server.js"; export class Channel { public name: string // public matrixUsers: Map // public powerLevels: Map public topic: Map; public channelModes: Map; public eventIDsSeen: Set; public historyVisibility: string public guestAccess: string public joinRules: string public roomVersion: number public roomType: string private syncLocks: Set 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; } }