From 4dd2ef902fe50f7defa3d3d2dbcd2b29ed5685d3 Mon Sep 17 00:00:00 2001 From: Adrian <107351903+6lr61@users.noreply.github.com> Date: Wed, 11 Sep 2024 13:19:10 +0200 Subject: [PATCH] feat: twitch chat hook --- src/hooks/useTwitchChat.ts | 93 +++++++++++++++++++ src/utils/event-sub/events/chat/clearUser.ts | 2 +- src/utils/event-sub/events/chat/message.ts | 2 +- .../event-sub/events/chat/messageDelete.ts | 2 +- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/hooks/useTwitchChat.ts diff --git a/src/hooks/useTwitchChat.ts b/src/hooks/useTwitchChat.ts new file mode 100644 index 0000000..22b6c21 --- /dev/null +++ b/src/hooks/useTwitchChat.ts @@ -0,0 +1,93 @@ +import { useCallback, useContext, useEffect, useState } from "react"; +import { AuthStateContext } from "../contexts/auth-state/AuthStateContext"; +import type { ChatMessageEvent } from "../utils/event-sub/events/chat/message"; +import { EventSubContext } from "../contexts/event-sub/EventSubContext"; +import type { ChatEventCommon } from "../utils/event-sub/events/chat/_common"; +import type { ChatClearUserMessageEvent } from "../utils/event-sub/events/chat/clearUser"; +import type { ChatMessageDeleteEvent } from "../utils/event-sub/events/chat/messageDelete"; + +type ChatEvent = + | ChatMessage + | ({ type: "channel.chat.clear" } & ChatEventCommon) + | ({ type: "channel.chat.clear_user_messages" } & ChatClearUserMessageEvent) + | ({ type: "channel.chat.message_delete" } & ChatMessageDeleteEvent); + +type ChatMessage = { + type: "channel.chat.message"; +} & ChatMessageEvent; + +const subscriptions = [ + "channel.chat.clear", + "channel.chat.clear_user_messages", + "channel.chat.message", + "channel.chat.message_delete", +]; + +export function useTwitchChat(bufferSize = 50, channelId?: string) { + const authStateContext = useContext(AuthStateContext); + const eventSubContext = useContext(EventSubContext); + const [messages, setMessages] = useState([]); + + if (!authStateContext) { + throw new Error("useTwitchChat: Needs an AuthStateContext Provider!"); + } + + if (!eventSubContext) { + throw new Error("useTwitchChat: Needs a EventSubContext Provider!"); + } + + const { subscribe } = eventSubContext; + + const handleMessage = useCallback( + (event: Record) => { + const messageEvent = event as unknown as ChatEvent; // FIXME! + + switch (messageEvent.type) { + case "channel.chat.clear": + setMessages(() => []); + break; + case "channel.chat.clear_user_messages": + setMessages((messages) => + messages.filter( + (message) => + message.chatter_user_id !== messageEvent.target_user_id + ) + ); + break; + case "channel.chat.message_delete": + setMessages((messages) => + messages.filter( + (message) => message.message_id !== messageEvent.message_id + ) + ); + break; + case "channel.chat.message": + setMessages((messages) => [ + ...messages.slice(-bufferSize + 1), + messageEvent, + ]); + break; + default: + console.error("useTwitchChat: Called with unknown event:", event); + } + }, + [bufferSize] + ); + + useEffect(() => { + const { authState } = authStateContext; + + if (!authState) { + return; + } + + const condition = { + broadcaster_user_id: channelId ?? authState.user.id, + user_id: authState.user.id, + }; + + return subscribe(authState, subscriptions, condition, handleMessage); + }, [authStateContext, channelId, handleMessage, subscribe]); + + return messages; +} diff --git a/src/utils/event-sub/events/chat/clearUser.ts b/src/utils/event-sub/events/chat/clearUser.ts index 5e9a253..bfd5f51 100644 --- a/src/utils/event-sub/events/chat/clearUser.ts +++ b/src/utils/event-sub/events/chat/clearUser.ts @@ -18,7 +18,7 @@ export interface ChatClearUserMessagePayload { event: ChatClearUserMessageEvent; } -interface ChatClearUserMessageEvent extends ChatEventCommon { +export interface ChatClearUserMessageEvent extends ChatEventCommon { target_user_id: string; target_user_name: string; target_user_login: string; diff --git a/src/utils/event-sub/events/chat/message.ts b/src/utils/event-sub/events/chat/message.ts index 0b58798..f6062d5 100644 --- a/src/utils/event-sub/events/chat/message.ts +++ b/src/utils/event-sub/events/chat/message.ts @@ -18,7 +18,7 @@ export interface ChatMessagePayload { event: ChatMessageEvent; } -interface ChatMessageEvent extends ChatEventCommon { +export interface ChatMessageEvent extends ChatEventCommon { chatter_user_id: string; chatter_user_name: string; chatter_user_login: string; diff --git a/src/utils/event-sub/events/chat/messageDelete.ts b/src/utils/event-sub/events/chat/messageDelete.ts index a432dbe..aa858a5 100644 --- a/src/utils/event-sub/events/chat/messageDelete.ts +++ b/src/utils/event-sub/events/chat/messageDelete.ts @@ -18,7 +18,7 @@ export interface ChatMessageDeletePayload { event: ChatMessageDeleteEvent; } -interface ChatMessageDeleteEvent extends ChatEventCommon { +export interface ChatMessageDeleteEvent extends ChatEventCommon { target_user_id: string; target_user_name: string; target_user_login: string;