@@ -139,15 +139,42 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
139139
140140 const mentionColorCache = useRef < Map < string , string > > ( new Map ( ) ) ;
141141 const fetchedCosmeticsUsers = useRef < Set < string > > ( new Set ( ) ) ;
142+ const chatStartTimeRef = useRef < number | null > ( null ) ;
142143
143144 useTwitchWs ( ) ;
144145
146+ useEffect ( ( ) => {
147+ chatStartTimeRef . current = Date . now ( ) ;
148+ } , [ channelId ] ) ;
149+
150+ const canFetchCosmetics = useCallback ( ( ) : boolean => {
151+ const chatStartTime = chatStartTimeRef . current ;
152+ if ( ! chatStartTime ) {
153+ return true ;
154+ }
155+
156+ const elapsedSeconds = ( Date . now ( ) - chatStartTime ) / 1000 ;
157+ return elapsedSeconds <= 10 ;
158+ } , [ ] ) ;
159+
145160 const fetchUserCosmetics = useCallback (
146161 async ( twitchUserId : string ) => {
147162 if ( fetchedCosmeticsUsers . current . has ( twitchUserId ) ) {
148163 return ;
149164 }
150165
166+ // Only fetch cosmetics for the first 10 seconds of chat to prevent API overload
167+ if ( ! canFetchCosmetics ( ) ) {
168+ const chatStartTime = chatStartTimeRef . current ;
169+ const elapsedSeconds = chatStartTime
170+ ? ( Date . now ( ) - chatStartTime ) / 1000
171+ : 0 ;
172+ logger . stvWs . debug (
173+ `Skipping cosmetic fetch for ${ twitchUserId } - chat has been active for ${ elapsedSeconds . toFixed ( 1 ) } s (limit: 10s)` ,
174+ ) ;
175+ return ;
176+ }
177+
151178 // Mark as fetching to prevent duplicate requests
152179 fetchedCosmeticsUsers . current . add ( twitchUserId ) ;
153180
@@ -181,7 +208,7 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
181208 ) ;
182209 }
183210 } ,
184- [ userPaints ] ,
211+ [ userPaints , canFetchCosmetics ] ,
185212 ) ;
186213
187214 const {
@@ -490,8 +517,14 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
490517 if ( paintId ) {
491518 const existingPaint = getPaint ( paintId ) ;
492519 if ( ! existingPaint && sevenTvUserId ) {
493- // Paint not in cache, fetch user's cosmetics via GQL
494- await fetchAndCacheUserCosmetics ( sevenTvUserId ) ;
520+ // Paint not in cache, fetch user's cosmetics via GQL (only if within 10s limit)
521+ if ( canFetchCosmetics ( ) ) {
522+ await fetchAndCacheUserCosmetics ( sevenTvUserId ) ;
523+ } else {
524+ logger . stvWs . debug (
525+ `Skipping cosmetic fetch for entitlement - 10s limit exceeded` ,
526+ ) ;
527+ }
495528 } else if ( data . ttvUserId ) {
496529 // Paint already cached, just link the user
497530 setUserPaint ( data . ttvUserId , paintId ) ;
@@ -504,8 +537,14 @@ export const Chat = memo(({ channelName, channelId }: ChatProps) => {
504537 if ( badgeId ) {
505538 const existingBadge = getBadge ( badgeId ) ;
506539 if ( ! existingBadge && sevenTvUserId ) {
507- // Badge not in cache, fetch user's cosmetics via GQL
508- await fetchAndCacheUserCosmetics ( sevenTvUserId ) ;
540+ // Badge not in cache, fetch user's cosmetics via GQL (only if within 10s limit)
541+ if ( canFetchCosmetics ( ) ) {
542+ await fetchAndCacheUserCosmetics ( sevenTvUserId ) ;
543+ } else {
544+ logger . stvWs . debug (
545+ `Skipping cosmetic fetch for entitlement - 10s limit exceeded` ,
546+ ) ;
547+ }
509548 } else if ( data . ttvUserId ) {
510549 // Badge already cached, just link the user
511550 setUserBadge ( data . ttvUserId , badgeId ) ;
0 commit comments