mirror of
https://git.sr.ht/~emerson/reflectionircd
synced 2025-04-13 09:59:52 +00:00
156 lines
No EOL
6 KiB
TypeScript
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;
|
|
}
|
|
} |