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";
|
import { MatrixUser } from "./MatrixUser.js";
|
||||||
|
|
||||||
export class Channel {
|
export class Channel {
|
||||||
public name: string
|
public name: string
|
||||||
|
// <nick, MatrixUser>
|
||||||
public matrixUsers: Map<string, MatrixUser>
|
public matrixUsers: Map<string, MatrixUser>
|
||||||
|
// <nick, PL number>
|
||||||
public powerLevels: Map<string, number>
|
public powerLevels: Map<string, number>
|
||||||
public topic: Map<string, string>;
|
public topic: Map<string, string>;
|
||||||
public eventIDsSeen: Set<string>;
|
public eventIDsSeen: Set<string>;
|
||||||
public historyVisibility: string
|
public historyVisibility: string
|
||||||
public guestAccess: string
|
public guestAccess: string
|
||||||
public joinRules: 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.name = roomId;
|
||||||
this.matrixUsers = new Map();
|
this.matrixUsers = new Map();
|
||||||
this.matrixUsers.set(initialMatrixUser.nick, initialMatrixUser);
|
this.matrixUsers.set(initialMatrixUser.nick, initialMatrixUser);
|
||||||
|
@ -19,6 +25,58 @@ export class Channel {
|
||||||
this.historyVisibility = "";
|
this.historyVisibility = "";
|
||||||
this.guestAccess = "";
|
this.guestAccess = "";
|
||||||
this.joinRules = "";
|
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 {
|
getNickPowerLevelMapping(nick: string): string {
|
||||||
|
|
|
@ -198,24 +198,15 @@ export class Client {
|
||||||
if (this.user === null)
|
if (this.user === null)
|
||||||
return;
|
return;
|
||||||
if (rooms['join']) {
|
if (rooms['join']) {
|
||||||
const joinedRooms: Set<Channel> = new Set();
|
|
||||||
for (const roomId of Object.keys(rooms.join)) {
|
for (const roomId of Object.keys(rooms.join)) {
|
||||||
const targetChannel = this.user.getOrCreateIRCChannel(roomId);
|
const targetChannel = this.user.getOrCreateIRCChannel(roomId);
|
||||||
joinedRooms.add(targetChannel);
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
rooms.join[roomId].state.events.forEach((nextEvent: any) => this.user.routeMatrixEvent(nextEvent, targetChannel));
|
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)
|
if (this.user === null)
|
||||||
return;
|
return;
|
||||||
this.user.nextBatch = data.next_batch;
|
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);
|
this.user.addClient(this);
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
@ -8,6 +8,7 @@ export class IRCUser {
|
||||||
private clients: Set<Client>
|
private clients: Set<Client>
|
||||||
public channels: Map<string, Channel>
|
public channels: Map<string, Channel>
|
||||||
public roomIdToChannel: Map<string, Channel>
|
public roomIdToChannel: Map<string, Channel>
|
||||||
|
private syncLocks: Set<Channel>
|
||||||
public matrixUsers: Map<string, MatrixUser>
|
public matrixUsers: Map<string, MatrixUser>
|
||||||
public nickToMatrixUser: Map<string, MatrixUser>
|
public nickToMatrixUser: Map<string, MatrixUser>
|
||||||
public nick: string
|
public nick: string
|
||||||
|
@ -18,6 +19,7 @@ export class IRCUser {
|
||||||
public ourMatrixUser: MatrixUser
|
public ourMatrixUser: MatrixUser
|
||||||
public txnIdStore: Map<string, Client>
|
public txnIdStore: Map<string, Client>
|
||||||
public nextBatch: string
|
public nextBatch: string
|
||||||
|
private initialSync: boolean
|
||||||
private isSyncing: boolean
|
private isSyncing: boolean
|
||||||
private currentSyncTime: number
|
private currentSyncTime: number
|
||||||
private syncIntervalID: NodeJS.Timeout;
|
private syncIntervalID: NodeJS.Timeout;
|
||||||
|
@ -25,6 +27,7 @@ export class IRCUser {
|
||||||
this.clients = new Set();
|
this.clients = new Set();
|
||||||
this.channels = new Map();
|
this.channels = new Map();
|
||||||
this.roomIdToChannel = new Map();
|
this.roomIdToChannel = new Map();
|
||||||
|
this.syncLocks = new Set();
|
||||||
this.matrixUsers = new Map();
|
this.matrixUsers = new Map();
|
||||||
this.nickToMatrixUser = new Map();
|
this.nickToMatrixUser = new Map();
|
||||||
const mxidSplit = mxid.split(':')
|
const mxidSplit = mxid.split(':')
|
||||||
|
@ -38,6 +41,7 @@ export class IRCUser {
|
||||||
this.nickToMatrixUser.set(this.nick, this.ourMatrixUser);
|
this.nickToMatrixUser.set(this.nick, this.ourMatrixUser);
|
||||||
this.txnIdStore = new Map();
|
this.txnIdStore = new Map();
|
||||||
this.nextBatch = "";
|
this.nextBatch = "";
|
||||||
|
this.initialSync = false;
|
||||||
this.isSyncing = false;
|
this.isSyncing = false;
|
||||||
this.currentSyncTime = 0;
|
this.currentSyncTime = 0;
|
||||||
this.syncIntervalID = setInterval(this.doSync.bind(this), 2000);
|
this.syncIntervalID = setInterval(this.doSync.bind(this), 2000);
|
||||||
|
@ -69,7 +73,8 @@ export class IRCUser {
|
||||||
if (maybeChannel)
|
if (maybeChannel)
|
||||||
return 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.roomIdToChannel.set(roomId, newChannel);
|
||||||
this.channels.set(roomId, newChannel);
|
this.channels.set(roomId, newChannel);
|
||||||
return newChannel;
|
return newChannel;
|
||||||
|
@ -79,6 +84,17 @@ export class IRCUser {
|
||||||
return this.nextBatch !== "";
|
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() {
|
getVerification() {
|
||||||
return axios.get(`https://${this.homeserver}/_matrix/client/v3/account/whoami?access_token=${this.accessToken}`, {
|
return axios.get(`https://${this.homeserver}/_matrix/client/v3/account/whoami?access_token=${this.accessToken}`, {
|
||||||
validateStatus: function (status) {
|
validateStatus: function (status) {
|
||||||
|
@ -107,7 +123,7 @@ export class IRCUser {
|
||||||
|
|
||||||
addClient(client: Client) {
|
addClient(client: Client) {
|
||||||
this.clients.add(client);
|
this.clients.add(client);
|
||||||
if (this.nextBatch !== "") {
|
if (this.initialSync) {
|
||||||
for (const channel of this.channels.values()) {
|
for (const channel of this.channels.values()) {
|
||||||
this.joinNewIRCClient(client, channel);
|
this.joinNewIRCClient(client, channel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class MatrixUser {
|
||||||
public channels: Set<Channel>
|
public channels: Set<Channel>
|
||||||
constructor(public mxid: string, public nick: string) {
|
constructor(public mxid: string, public nick: string) {
|
||||||
const mxidSplit = this.mxid.split(':')
|
const mxidSplit = this.mxid.split(':')
|
||||||
this.ident = mxidSplit[0].substr(1);
|
this.ident = mxidSplit[0].substring(1);
|
||||||
this.hostname = mxidSplit[1];
|
this.hostname = mxidSplit[1];
|
||||||
this.realname = this.mxid;
|
this.realname = this.mxid;
|
||||||
this.accountName = this.mxid.slice(1);
|
this.accountName = this.mxid.slice(1);
|
||||||
|
|
Loading…
Add table
Reference in a new issue