create channel sync system to ensure everything is correct

This commit is contained in:
emerson 2022-01-24 18:36:20 -05:00
parent f8f082e4c8
commit d701496130
4 changed files with 78 additions and 13 deletions

View file

@ -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 {

View file

@ -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);

View file

@ -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);
}

View file

@ -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);