diff --git a/src/clients/irc.ts b/src/clients/irc.ts index 5f027db..e64b6ff 100644 --- a/src/clients/irc.ts +++ b/src/clients/irc.ts @@ -29,6 +29,11 @@ interface ParsedCommand { params: string[]; } +interface IRCEvents { + data: [string | [string, any]]; + error: [string]; +} + const colors = { white: "00", black: "01", navy: "02", green: "03", red: "04", brown: "05", purple: "06", orange: "07", yellow: "08", @@ -59,6 +64,14 @@ export default class irc extends EventEmitter { user: Map; }; + emit(event: K, ...args: IRCEvents[K]): boolean { + return super.emit(event, ...args); + } + + on(event: K, listener: (...args: IRCEvents[K]) => void): this { + return super.on(event, listener); + } + constructor(options: IRCOptions) { super(); this.options = { @@ -102,38 +115,29 @@ export default class irc extends EventEmitter { this.connect(); } - connect(reconnect: boolean = false): void { - if(reconnect) - this.socket = undefined; - - if(this.options.ssl) { - this.socket = tls.connect({ + private createSocket(): net.Socket | tls.TLSSocket { + return this.options.ssl + ? tls.connect({ host: this.options.host, port: this.options.port, rejectUnauthorized: !this.options.selfSigned, - }, () => this.handleConnection()); - } - else { - this.socket = net.connect({ + }) + : net.connect({ host: this.options.host, port: this.options.port, - }, () => this.handleConnection()); - } - - if(!this.socket) - throw new Error("Socket konnte nicht initialisiert werden."); - + }); + } + + connect(reconnect: boolean = false): void { + if(reconnect) + this.socket = undefined; + + this.socket = this.createSocket(); + this.socket.on("data", (msg: string) => this.handleData(msg)); + this.socket.on("end", () => this.handleDisconnect()); + this.socket.on("error", (err: Error) => this.handleError(err)); this.socket.setEncoding("utf-8"); - this.socket.on("data", (msg: string) => { - console.log("Received data:", msg); - this.handleData(msg); - }); - this.socket.on("end", () => { - this.handleDisconnect(); - }); - this.socket.on("error", (err: Error) => { - this.handleError(err); - }); + this.handleConnection(); } private handleConnection(): void { diff --git a/src/clients/slack.ts b/src/clients/slack.ts index 355f7f6..d0ebd09 100644 --- a/src/clients/slack.ts +++ b/src/clients/slack.ts @@ -40,12 +40,27 @@ interface SlackRTMStartResponse { description?: string; } +interface SlackEvents { + data: [string | [string, any]]; + error: [string]; + message: [SlackMessage]; +} + export default class slack extends EventEmitter { private options: Required; private token: string; private api: string = "https://slack.com/api"; private interval: NodeJS.Timeout | null = null; private server: ServerInfo; + private reconnectAttempts = 0; + + emit(event: K, ...args: SlackEvents[K]): boolean { + return super.emit(event, ...args); + } + + on(event: K, listener: (...args: SlackEvents[K]) => void): this { + return super.on(event, listener); + } constructor(options: SlackOptions) { super(); @@ -92,6 +107,7 @@ export default class slack extends EventEmitter { if(res.url) { this.server.wss.url = url.parse(res.url); + this.reconnectAttempts = 0; this.initializeWebSocket(); } else @@ -128,7 +144,7 @@ export default class slack extends EventEmitter { if(!this.server.wss.socket) return; - this.interval = setInterval(async () => await this.ping(), 30000); + this.interval = setInterval(async () => await this.ping(), 3e4); this.server.wss.socket.on("data", async (data: Buffer) => { try { @@ -158,12 +174,15 @@ export default class slack extends EventEmitter { } async reconnect(): Promise { - this.server.wss.url = null; - this.server.wss.socket = null; - if(this.interval) - clearInterval(this.interval); - this.emit("data", ["info", "reconnecting slack"]); - await this.connect(); + if(this.reconnectAttempts >= 5) { + this.emit("data", ["error", "Too many reconnect attempts"]); + return; + } + this.reconnectAttempts++; + setTimeout(async () => { + this.emit("data", ["info", "Reconnecting to Slack"]); + await this.connect(); + }, this.reconnectAttempts * 1e3); } async getChannel(channelId: string): Promise { @@ -247,8 +266,7 @@ export default class slack extends EventEmitter { private parseData(data: Buffer): SlackMessage | undefined { try { - const json = JSON.parse(data.toString()); - return json; + return JSON.parse(data.toString()) as SlackMessage; } catch(err: any) { this.emit("data", ["error", "failed to parse data"]); diff --git a/src/clients/tg.ts b/src/clients/tg.ts index cf6ed6b..3ee1f53 100644 --- a/src/clients/tg.ts +++ b/src/clients/tg.ts @@ -50,6 +50,11 @@ interface TelegramUpdate { inline_query?: any; } +interface TelegramEvents { + data: [string | [string, any]]; + error: [string]; +} + export default class tg extends EventEmitter { private options: Required; private token: string; @@ -64,6 +69,14 @@ export default class tg extends EventEmitter { me: {}, }; + emit(event: K, ...args: TelegramEvents[K]): boolean { + return super.emit(event, ...args); + } + + on(event: K, listener: (...args: TelegramEvents[K]) => void): this { + return super.on(event, listener); + } + constructor(options: TelegramOptions) { super(); this.options = { diff --git a/src/types.d.ts b/src/types.d.ts index 890bc15..73ac29b 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -11,7 +11,6 @@ export interface Bot { server: { channel: Map; motd: string; - //user: Map; user: { [channel: string]: any };