diff --git a/packages/twitch/chat/src/db/watcher.ts b/packages/twitch/chat/src/db/watcher.ts deleted file mode 100644 index eb857f31..00000000 --- a/packages/twitch/chat/src/db/watcher.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Tables } from './supabase-types.js' -import supabase from './supabase.js' -import { chatClient } from '../index.js' - -const IS_DEV = process.env.NODE_ENV !== 'production' -const DEV_CHANNELS = process.env.DEV_CHANNELS?.split(',') ?? [] -const channel = supabase.channel(`${IS_DEV ? 'dev-' : ''}twitch-chat`) - -channel - .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'users' }, (payload: any) => { - const oldUser: Tables<'users'> = payload.old - const newUser: Tables<'users'> = payload.new - - if (IS_DEV && !DEV_CHANNELS.includes(newUser.name)) return - if (!IS_DEV && DEV_CHANNELS.includes(newUser.name)) return - - if (!oldUser.displayName && newUser.displayName) { - console.log('[SUPABASE] New user to send bot to: ', newUser.name) - try { - chatClient.join(newUser.name).catch((e) => { - console.log('[New user] Failed to enable client inside promise', { - channel, - error: e, - }) - }) - } catch (e) { - console.error('[SUPABASE] Error joining channel: ', { e }) - } - } else if (oldUser.name !== newUser.name) { - console.log('[SUPABASE] User changed name: ', { - oldName: oldUser.name, - newName: newUser.name, - }) - try { - chatClient.part(oldUser.name) - chatClient.join(newUser.name).catch((e) => { - console.log('[Name change] Failed to enable client inside promise', { - channel, - error: e, - }) - }) - } catch (e) { - console.error('[SUPABASE] Error joining channel: ', { e }) - } - } - }) - .subscribe((status, err) => { - if (status === 'SUBSCRIBED') { - console.log('[SUPABASE] Ready to receive database changes!') - } - }) diff --git a/packages/twitch/events/package.json b/packages/twitch/events/package.json index 37fdc339..b395e5ab 100644 --- a/packages/twitch/events/package.json +++ b/packages/twitch/events/package.json @@ -19,6 +19,8 @@ "@twurple/eventsub-base": "6.0.9", "@twurple/eventsub-http": "6.0.9", "express": "^4.18.2", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "node-gyp": "^9.4.0" }, "devDependencies": { diff --git a/packages/twitch/events/src/index.ts b/packages/twitch/events/src/index.ts index 83c4bb3e..ce695a1c 100644 --- a/packages/twitch/events/src/index.ts +++ b/packages/twitch/events/src/index.ts @@ -3,8 +3,8 @@ import http from 'http' import { EnvPortAdapter, EventSubHttpListener } from '@twurple/eventsub-http' import express from 'express' import { Server as SocketServer } from 'socket.io' +import { io } from 'socket.io-client' -import { Tables } from './db/supabase-types.js' import { handleNewUser } from './handleNewUser.js' import { SubscribeEvents } from './SubscribeEvents.js' import BotAPI from './twitch/lib/BotApiSingleton.js' @@ -13,8 +13,19 @@ import { getAccountIds } from './twitch/lib/getAccountIds.js' const socketApp = express() const webhookApp = express() -const server = http.createServer(socketApp) -export const io = new SocketServer(server) +export const twitchChat = io('ws://twitch-chat:5005') + +export const chatClient = { + join: (channel: string) => { + twitchChat.emit('join', channel) + }, + part: (channel: string) => { + twitchChat.emit('part', channel) + }, + say: (channel: string, text: string) => { + twitchChat.emit('say', channel, text) + }, +} if (!process.env.EVENTSUB_HOST || !process.env.TWITCH_EVENTSUB_SECRET) { throw new Error('Missing EVENTSUB_HOST or TWITCH_EVENTSUB_SECRET') @@ -23,6 +34,7 @@ if (!process.env.EVENTSUB_HOST || !process.env.TWITCH_EVENTSUB_SECRET) { const { EVENTSUB_HOST, TWITCH_EVENTSUB_SECRET } = process.env const IS_DEV = process.env.NODE_ENV !== 'production' +const DEV_CHANNELS = process.env.DEV_CHANNELS?.split(',') ?? [] const DEV_CHANNELIDS = process.env.DEV_CHANNELIDS?.split(',') ?? [] const botApi = BotAPI.getInstance() @@ -44,7 +56,9 @@ console.log('[TWITCHEVENTS] Started the event sub listener') export const DOTABOD_EVENTS_ROOM = 'twitch-channel-events' export let eventsIOConnected = false -io.on('connection', (socket) => { +const server = http.createServer(socketApp) +export const socketIo = new SocketServer(server) +socketIo.on('connection', (socket) => { console.log('Joining socket') try { void socket.join(DOTABOD_EVENTS_ROOM) @@ -77,6 +91,30 @@ getAccountIds() console.log('[TWITCHEVENTS] error getting accountIds', { e }) }) +type InsertPayload = { + type: 'INSERT' + table: string + schema: string + record: T + old_record: null +} + +type UpdatePayload = { + type: 'UPDATE' + table: string + schema: string + record: T + old_record: T +} + +type DeletePayload = { + type: 'DELETE' + table: string + schema: string + record: null + old_record: T +} + // set the expressjs host name webhookApp.post('/', express.json(), express.urlencoded({ extended: true }), (req, res) => { // check authorization beaerer token @@ -88,7 +126,8 @@ webhookApp.post('/', express.json(), express.urlencoded({ extended: true }), (re } if (req.body.type === 'INSERT' && req.body.table === 'accounts') { - const user: Tables<'accounts'> = req.body.record + const { body } = req + const user = body.record if (IS_DEV && !DEV_CHANNELIDS.includes(user.providerAccountId)) return if (!IS_DEV && DEV_CHANNELIDS.includes(user.providerAccountId)) return @@ -104,6 +143,25 @@ webhookApp.post('/', express.json(), express.urlencoded({ extended: true }), (re providerAccountId: user.providerAccountId, }) }) + } else if (req.body.type === 'UPDATE' && req.body.table === 'users') { + const { body } = req + const oldUser = body.old_record + const newUser = body.record + + if (IS_DEV && !DEV_CHANNELS.includes(newUser.name)) return + if (!IS_DEV && DEV_CHANNELS.includes(newUser.name)) return + + if (!oldUser.displayName && newUser.displayName) { + console.log('[SUPABASE] New user to send bot to: ', newUser.name) + chatClient.join(newUser.name) + } else if (oldUser.name !== newUser.name) { + console.log('[SUPABASE] User changed name: ', { + oldName: oldUser.name, + newName: newUser.name, + }) + chatClient.part(oldUser.name) + chatClient.join(newUser.name) + } } res.status(200).json({