reflectionircd/src/IRCUser.ts

123 lines
4.5 KiB
TypeScript
Raw Normal View History

import axios from "axios";
2021-12-07 10:36:09 -05:00
import { randomUUID } from "crypto";
2021-12-05 18:33:49 -05:00
import { Channel } from "./Channel.js";
import { Client } from "./Client.js";
2021-12-07 10:36:09 -05:00
import { IRCMessage } from "./Message.js";
2021-12-05 18:33:49 -05:00
import { Server } from "./Server.js";
export class IRCUser {
private clients: Set<Client>
public channels: Set<Channel>
2021-12-05 18:33:49 -05:00
public nick: string
private ident: string
private hostname: string
public accountName: string
2021-12-06 10:23:29 -05:00
public realname: string
2021-12-07 10:36:09 -05:00
private txnIdStore: Map<string, Client>
2021-12-06 10:23:29 -05:00
public nextBatch: string
private initialSync: boolean
2021-12-06 18:33:32 -05:00
private syncIntervalID: NodeJS.Timeout;
2021-12-06 10:23:29 -05:00
constructor(public mxid: string, private accessToken: string, private server: Server) {
this.clients = new Set();
this.channels = new Set();
2021-12-05 18:33:49 -05:00
const mxidSplit = mxid.split(':')
this.nick = mxidSplit[0].substr(1);
this.ident = this.nick;
this.hostname = mxidSplit[1];
this.accountName = mxid.slice(1);
2021-12-06 10:23:29 -05:00
this.realname = this.accountName;
2021-12-07 10:36:09 -05:00
this.txnIdStore = new Map();
this.nextBatch = "";
this.initialSync = false;
2021-12-06 18:33:32 -05:00
this.syncIntervalID = setInterval(this.doSync.bind(this), 15000);
2021-12-05 18:33:49 -05:00
}
isSynced() {
2021-12-06 18:33:32 -05:00
return this.nextBatch !== "";
2021-12-06 10:23:29 -05:00
}
getVerification() {
return axios.get(`https://matrix.org/_matrix/client/v3/account/whoami?access_token=${this.accessToken}`);
2021-12-05 18:33:49 -05:00
}
2021-12-05 18:44:21 -05:00
getMask(): string {
return `${this.nick}!${this.ident}@${this.hostname}`;
}
2021-12-06 10:23:29 -05:00
addClient(client: Client, passedTags: Map<string, string>) {
this.clients.add(client);
if (this.nextBatch !== "") {
for (const channel of this.channels.values()) {
channel.joinNewIRCClient(client, passedTags);
}
}
}
doSync(): void {
2021-12-06 18:33:32 -05:00
if (!this.isSynced()) {
console.log("not syncing, initial sync not completed");
return;
}
const endpoint = `https://matrix.org/_matrix/client/v3/sync?access_token=${this.accessToken}&since=${this.nextBatch}`;
axios.get(endpoint).then(response => {
const data = response.data;
this.nextBatch = data.next_batch;
const rooms = data.rooms;
2021-12-06 18:33:32 -05:00
if (rooms && rooms['join']) {
for (const roomId of Object.keys(rooms.join)) {
2021-12-07 08:51:31 -05:00
const targetChannel = this.server.getOrCreateIRCChannel(roomId);
2021-12-06 18:33:32 -05:00
rooms.join[roomId].timeline.events.forEach((nextEvent: any) => {
targetChannel.routeMatrixEvent(nextEvent)
});
}
}
})
}
2021-12-07 10:36:09 -05:00
sendMessageToMatrix(message: IRCMessage, client: Client) {
const channel = this.server.ircChannels.get(message.params[0]);
2021-12-07 10:36:09 -05:00
if (!channel) {
return;
}
let msgtype = 'm.text';
let msgbody = message.params[1];
if (message.command === 'NOTICE')
msgtype = 'm.notice';
else if (message.params[1].startsWith('\x01')) {
msgtype = 'm.emote';
msgbody = msgbody.replace(/\x01(ACTION\s)?/gi, '');
}
const roomId = channel.roomId;
const content = {
"body": msgbody,
"msgtype": msgtype,
}
const newTxnid = randomUUID();
this.txnIdStore.set(newTxnid, client);
axios.put(`https://matrix.org/_matrix/client/v3/rooms/${channel.roomId}/send/m.room.message/${newTxnid}?access_token=${this.accessToken}`, content);
}
sendToAll(prefix: string, command: string, params: string[], tags: Map<string, string> = new Map(), skipClient: Client|null = null) {
this.clients.forEach(client => {
if (client !== skipClient) {
client.sendMessage(prefix, command, params, tags);
}
})
}
sendToAllWithCap(cap: string, prefix: string, command: string, params: string[], tags: Map<string, string> = new Map(), skipClient: Client|null = null) {
this.clients.forEach(client => {
if (client !== skipClient && client.enabledCaps.has(cap)) {
client.sendMessage(prefix, command, params, tags);
}
})
}
sendToAllWithoutCap(cap: string, prefix: string, command: string, params: string[], tags: Map<string, string> = new Map(), skipClient: Client|null = null) {
this.clients.forEach(client => {
if (client !== skipClient && !client.enabledCaps.has(cap)) {
client.sendMessage(prefix, command, params, tags);
}
})
}
2021-12-05 18:33:49 -05:00
}