mirror of
https://git.sr.ht/~emerson/reflectionircd
synced 2025-08-05 16:59:10 +00:00
create channel sync system to ensure everything is correct
This commit is contained in:
parent
f8f082e4c8
commit
d701496130
4 changed files with 78 additions and 13 deletions
|
@ -1,15 +1,21 @@
|
|||
import axios from "axios";
|
||||
import { IRCUser } from "./IRCUser.js";
|
||||
import { MatrixUser } from "./MatrixUser.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 eventIDsSeen: Set<string>;
|
||||
public historyVisibility: string
|
||||
public guestAccess: string
|
||||
public joinRules: string
|
||||
constructor(public roomId: string, initialMatrixUser: MatrixUser) {
|
||||
private syncLocks: Set<string>
|
||||
private initialSyncID: NodeJS.Timeout;
|
||||
constructor(public roomId: string, initialMatrixUser: MatrixUser, private ircUser: IRCUser) {
|
||||
this.name = roomId;
|
||||
this.matrixUsers = new Map();
|
||||
this.matrixUsers.set(initialMatrixUser.nick, initialMatrixUser);
|
||||
|
@ -19,6 +25,58 @@ export class Channel {
|
|||
this.historyVisibility = "";
|
||||
this.guestAccess = "";
|
||||
this.joinRules = "";
|
||||
this.syncLocks = new Set();
|
||||
this.doInitialSync();
|
||||
this.initialSyncID = setInterval(this.checkChannelSync.bind(this), 2000);
|
||||
}
|
||||
|
||||
doInitialSync() {
|
||||
this.syncLocks.add("m.room.canonical_alias");
|
||||
axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/event/m.room.canonical_alias?access_token=${this.ircUser.accessToken}`).then(response => {
|
||||
const canonical_alias = response.data["content"]?.["alias"];
|
||||
if (canonical_alias) {
|
||||
this.name = canonical_alias;
|
||||
}
|
||||
this.syncLocks.delete("m.room.canonical_alias")
|
||||
}).catch(e => {
|
||||
this.syncLocks.delete("m.room.canonical_alias")
|
||||
})
|
||||
this.syncLocks.add("m.room.topic");
|
||||
axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/event/m.room.topic?access_token=${this.ircUser.accessToken}`).then(response => {
|
||||
const topicText = response.data["content"]?.["topic"];
|
||||
if (!topicText)
|
||||
return;
|
||||
const topicSetter = this.ircUser.getOrCreateMatrixUser(response.data["sender"]);
|
||||
const topicTS: string = response.data["origin_server_ts"].toString();
|
||||
this.topic.set("text", topicText);
|
||||
this.topic.set("timestamp", topicTS.substring(0,10))
|
||||
this.topic.set('setter', topicSetter.nick);
|
||||
this.syncLocks.delete("m.room.topic")
|
||||
}).catch(e => {
|
||||
this.syncLocks.delete("m.room.topic")
|
||||
})
|
||||
this.syncLocks.add("m.room.members");
|
||||
axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/joined_members?access_token=${this.ircUser.accessToken}`).then(response => {
|
||||
const allMembers = response.data["joined"];
|
||||
for (const member of Object.keys(allMembers)) {
|
||||
const nextMatrixUser = this.ircUser.getOrCreateMatrixUser(member);
|
||||
this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser);
|
||||
}
|
||||
this.syncLocks.delete("m.room.members")
|
||||
}).catch(e => {
|
||||
this.syncLocks.delete("m.room.members")
|
||||
})
|
||||
}
|
||||
|
||||
checkChannelSync() {
|
||||
if (this.syncLocks.size === 0) {
|
||||
if (this.matrixUsers.size === 2 && this.name === this.roomId) {
|
||||
const otherUser = [...this.matrixUsers.values()].filter(m => m.nick !== this.ircUser.nick);
|
||||
this.name = `&${otherUser[0].mxid.substring(1)}`
|
||||
}
|
||||
this.ircUser.finishChannelSync(this);
|
||||
clearInterval(this.initialSyncID);
|
||||
}
|
||||
}
|
||||
|
||||
getNickPowerLevelMapping(nick: string): string {
|
||||
|
|
|
@ -198,24 +198,15 @@ export class Client {
|
|||
if (this.user === null)
|
||||
return;
|
||||
if (rooms['join']) {
|
||||
const joinedRooms: Set<Channel> = new Set();
|
||||
for (const roomId of Object.keys(rooms.join)) {
|
||||
const targetChannel = this.user.getOrCreateIRCChannel(roomId);
|
||||
joinedRooms.add(targetChannel);
|
||||
//@ts-ignore
|
||||
rooms.join[roomId].state.events.forEach((nextEvent: any) => this.user.routeMatrixEvent(nextEvent, targetChannel));
|
||||
}
|
||||
joinedRooms.forEach(c => {
|
||||
if (this.user !== null) {
|
||||
this.user.channels.set(c.name, c);
|
||||
this.user.roomIdToChannel.set(c.roomId, c);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.user === null)
|
||||
return;
|
||||
this.user.nextBatch = data.next_batch;
|
||||
this.sendMessage(this.server.name, 'NOTICE', [this.user.nick, 'You are now synced to the network!']);
|
||||
this.user.addClient(this);
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
|
|
|
@ -8,6 +8,7 @@ export class IRCUser {
|
|||
private clients: Set<Client>
|
||||
public channels: Map<string, Channel>
|
||||
public roomIdToChannel: Map<string, Channel>
|
||||
private syncLocks: Set<Channel>
|
||||
public matrixUsers: Map<string, MatrixUser>
|
||||
public nickToMatrixUser: Map<string, MatrixUser>
|
||||
public nick: string
|
||||
|
@ -18,6 +19,7 @@ export class IRCUser {
|
|||
public ourMatrixUser: MatrixUser
|
||||
public txnIdStore: Map<string, Client>
|
||||
public nextBatch: string
|
||||
private initialSync: boolean
|
||||
private isSyncing: boolean
|
||||
private currentSyncTime: number
|
||||
private syncIntervalID: NodeJS.Timeout;
|
||||
|
@ -25,6 +27,7 @@ export class IRCUser {
|
|||
this.clients = new Set();
|
||||
this.channels = new Map();
|
||||
this.roomIdToChannel = new Map();
|
||||
this.syncLocks = new Set();
|
||||
this.matrixUsers = new Map();
|
||||
this.nickToMatrixUser = new Map();
|
||||
const mxidSplit = mxid.split(':')
|
||||
|
@ -38,6 +41,7 @@ export class IRCUser {
|
|||
this.nickToMatrixUser.set(this.nick, this.ourMatrixUser);
|
||||
this.txnIdStore = new Map();
|
||||
this.nextBatch = "";
|
||||
this.initialSync = false;
|
||||
this.isSyncing = false;
|
||||
this.currentSyncTime = 0;
|
||||
this.syncIntervalID = setInterval(this.doSync.bind(this), 2000);
|
||||
|
@ -69,7 +73,8 @@ export class IRCUser {
|
|||
if (maybeChannel)
|
||||
return maybeChannel;
|
||||
|
||||
const newChannel = new Channel(roomId, this.ourMatrixUser);
|
||||
const newChannel = new Channel(roomId, this.ourMatrixUser, this);
|
||||
this.syncLocks.add(newChannel);
|
||||
this.roomIdToChannel.set(roomId, newChannel);
|
||||
this.channels.set(roomId, newChannel);
|
||||
return newChannel;
|
||||
|
@ -79,6 +84,17 @@ export class IRCUser {
|
|||
return this.nextBatch !== "";
|
||||
}
|
||||
|
||||
finishChannelSync(targetChannel: Channel) {
|
||||
this.syncLocks.delete(targetChannel);
|
||||
this.channels.set(targetChannel.name, targetChannel);
|
||||
this.roomIdToChannel.set(targetChannel.roomId, targetChannel);
|
||||
this.clients.forEach(c => this.joinNewIRCClient(c, targetChannel));
|
||||
if (this.initialSync === false && this.syncLocks.size === 0) {
|
||||
this.initialSync = true;
|
||||
this.sendToAll(this.server.name, 'NOTICE', [this.nick, 'You are now synced to the network!']);
|
||||
}
|
||||
}
|
||||
|
||||
getVerification() {
|
||||
return axios.get(`https://${this.homeserver}/_matrix/client/v3/account/whoami?access_token=${this.accessToken}`, {
|
||||
validateStatus: function (status) {
|
||||
|
@ -107,7 +123,7 @@ export class IRCUser {
|
|||
|
||||
addClient(client: Client) {
|
||||
this.clients.add(client);
|
||||
if (this.nextBatch !== "") {
|
||||
if (this.initialSync) {
|
||||
for (const channel of this.channels.values()) {
|
||||
this.joinNewIRCClient(client, channel);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ export class MatrixUser {
|
|||
public channels: Set<Channel>
|
||||
constructor(public mxid: string, public nick: string) {
|
||||
const mxidSplit = this.mxid.split(':')
|
||||
this.ident = mxidSplit[0].substr(1);
|
||||
this.ident = mxidSplit[0].substring(1);
|
||||
this.hostname = mxidSplit[1];
|
||||
this.realname = this.mxid;
|
||||
this.accountName = this.mxid.slice(1);
|
||||
|
|
Loading…
Add table
Reference in a new issue