Implement chat monitor for cross-platform keyword detection with shared storage#128
Implement chat monitor for cross-platform keyword detection with shared storage#128
Conversation
Co-authored-by: igorovh <37638480+igorovh@users.noreply.github.com>
|
Co-authored-by: igorovh <37638480+igorovh@users.noreply.github.com>
I've addressed all 4 points in commit ddc5429:
The chat monitor settings are now shown in the General tab (similar to Watchtime List) and work across both Twitch and Kick. |
| getChatMonitorMatches: { | ||
| payload: GetChatMonitorMatchesPayload; | ||
| response: GetChatMonitorMatchesResponse; | ||
| }; | ||
| clearChatMonitorMatches: { | ||
| payload: never; | ||
| response: ClearChatMonitorMatchesResponse; | ||
| }; | ||
| getChatMonitorStatus: { | ||
| payload: never; | ||
| response: GetChatMonitorStatusResponse; | ||
| }; | ||
| getChatMonitorStorageData: { | ||
| payload: never; | ||
| response: any; // ChatMonitorStorageData | ||
| }; | ||
| setChatMonitorStorageData: { | ||
| payload: SetChatMonitorStorageDataPayload; | ||
| response: SetChatMonitorStorageDataResponse; | ||
| }; |
There was a problem hiding this comment.
dont do it like this, lets do it as getSharedStorage, and then key chatMonitor
| }; | ||
| getChatMonitorStorageData: { | ||
| payload: never; | ||
| response: any; // ChatMonitorStorageData |
There was a problem hiding this comment.
Fixed in 2008585. Replaced all any types with proper types: ChatMonitorKeywordMatch[], Logger, and SharedStorageData.
| export type GetSettingsResponse = PlatformSettings; | ||
| export type UpdateSettingsResponse = { success: true }; | ||
|
|
||
| export interface GetChatMonitorMatchesPayload { |
There was a problem hiding this comment.
make all of the this as SharedStorage and then inside this let it be a chatMonitor
| const result = await handler.handle(payload); | ||
|
|
||
| // After setting chat monitor storage data, update the chat monitor service | ||
| if (action === "setChatMonitorStorageData") { |
There was a problem hiding this comment.
create "webhooks"/"callbacks" system, that when it is refresh it will call callback and then chat monitor logic will know that something changed
There was a problem hiding this comment.
Fixed in 2008585. Implemented callback system via SharedStorageService.onStorageChange(). Background worker registers a callback that's automatically invoked when storage changes, eliminating the need to check action names.
| private updateTabInfo(tabId: number, url: string) { | ||
| // Parse URL to detect platform and channel | ||
| try { | ||
| const parsedUrl = new URL(url); | ||
| if (parsedUrl.hostname.includes("twitch.tv")) { | ||
| const pathParts = parsedUrl.pathname.split("/").filter(Boolean); | ||
| if (pathParts.length > 0 && pathParts[0] !== "directory" && pathParts[0] !== "videos") { | ||
| this.currentTabs.set(tabId, { | ||
| platform: "twitch", | ||
| channel: pathParts[0], | ||
| }); | ||
| return; | ||
| } | ||
| } else if (parsedUrl.hostname.includes("kick.com")) { | ||
| const pathParts = parsedUrl.pathname.split("/").filter(Boolean); | ||
| if (pathParts.length > 0) { | ||
| this.currentTabs.set(tabId, { | ||
| platform: "kick", | ||
| channel: pathParts[0], | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| } catch (error) { | ||
| // Invalid URL, ignore | ||
| } | ||
| } |
There was a problem hiding this comment.
i dont like this, i think the chat monitor module should like be firing event every X seconds and then we will know what tab are active and used
|
|
||
| export class GetChatMonitorMatchesHandler extends MessageHandler { | ||
| constructor( | ||
| logger: any, |
There was a problem hiding this comment.
dont use any, we can use Logger type here
There was a problem hiding this comment.
Fixed in 2008585. Changed logger parameter type from any to Logger in all chat monitor handlers.
|
|
||
| export class SetChatMonitorStorageDataHandler extends MessageHandler { | ||
| constructor( | ||
| logger: any, |
There was a problem hiding this comment.
Fixed in 2008585. Handler now uses Logger type instead of any.
| chrome.runtime.onMessage.addListener((message) => { | ||
| if (message.action === "chatMonitorPing") { | ||
| // Show notification or update badge | ||
| this.showNotificationBadge(); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
we cannot do this here, content scripts does not have access to chrome.runtime, we need to do it via background bridge (which is already created) i would also like that there be like number of notifcations in the logo
There was a problem hiding this comment.
Fixed in 6778295. Added background message relay through worker bridge:
- Worker bridge listens for
chrome.runtime.onMessage(content script context) - Dispatches
enhancer-background-messagecustom event to page context - Added
WorkerService.onBackgroundMessage()for modules to listen - Chat monitor button modules now use worker service instead of chrome.runtime
For the notification count in logo - this will be implemented as part of the module restructuring in the next commit.
| import styled from "styled-components"; | ||
| import TwitchModule from "../../twitch.module.ts"; | ||
|
|
||
| export default class ChatMonitorButtonModule extends TwitchModule { |
There was a problem hiding this comment.
maybe move it to the settings-button module and rename this module to navbar-icons-module wdyt, we could also seperate logic in files in this module direcotry for settings and chat monitor
…ta/setSharedStorageData Co-authored-by: igorovh <37638480+igorovh@users.noreply.github.com>
…background messages Co-authored-by: igorovh <37638480+igorovh@users.noreply.github.com>
| const saveData = async (newData: ChatMonitorStorageData) => { | ||
| setSaving(true); | ||
| try { | ||
| // First get the full shared storage | ||
| const fullStorage = await workerService.send("getSharedStorageData", {}); | ||
| if (fullStorage?.data) { | ||
| // Update only the chatMonitor portion | ||
| const updatedStorage: SharedStorageData = { | ||
| ...fullStorage.data, | ||
| chatMonitor: newData, | ||
| }; | ||
| await workerService.send("setSharedStorageData", { data: updatedStorage }); | ||
| setData(newData); | ||
| } | ||
| } catch (error) { | ||
| console.error("Failed to save chat monitor data:", error); | ||
| } finally { | ||
| setSaving(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
we could create a SharedStorage object like the SettingsService and then create "utils" function that to get this data faster, like getSharedStorageKey('chatMonitor') but it need to be fully typed
There was a problem hiding this comment.
Implemented in d8fc45f. Created SharedStorageService with typed utility functions following the SettingsService pattern:
getSharedStorageKey<K>(key)- fully typed key accessupdateSharedStorageKey<K>(key, value)- fully typed key updates
Chat monitor settings component now uses:
const data = await sharedStorageService.getSharedStorageKey("chatMonitor");
await sharedStorageService.updateSharedStorageKey("chatMonitor", newData);TypeScript automatically infers the correct types for each key.
Co-authored-by: igorovh <37638480+igorovh@users.noreply.github.com>
❌ Invalid PR TitleYour current title does not follow the required semantic format. Example format: |
Adds opt-in chat monitoring across Twitch and Kick channels with keyword-based notifications. Users can monitor up to 50 channels and receive real-time alerts when specified keywords appear in chat.
Architecture
Shared Storage
SharedStorageServiceclass provides typed utility functions for accessing shared storagegetSharedStorageKey<K>(key),updateSharedStorageKey<K>(key, value)with automatic TypeScript inferencechatMonitorkey withinSharedStorageDatagetSharedStorageData,setSharedStorageDataonStorageChange()for automatic updatesBackground Service
Settings Integration
SharedStorageServiceUI Components
Background-to-Content Communication
WorkerService.onBackgroundMessage()chrome.runtime.onMessageusage in page contextExample Usage
User enables monitor in settings:
Access via SharedStorageService:
Background service connects to IRC, detects keywords, sends to content script:
Implementation Notes
getChatMonitorMatches,clearChatMonitorMatches,getChatMonitorStatus,getSharedStorageData,setSharedStorageDataSharedStorageServiceprovides type-safe access pattern matchingSettingsServiceOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.