11using System ;
22using System . Collections . Concurrent ;
33using System . Collections . Generic ;
4+ using System . Net . Http ;
5+ using System . Net . Http . Headers ;
46using System . Threading . Tasks ;
7+ using Newtonsoft . Json ;
8+ using Newtonsoft . Json . Serialization ;
59using SCHIZO . Commands . Attributes ;
610using SCHIZO . Helpers ;
711using SCHIZO . SwarmControl ;
@@ -56,6 +60,7 @@ private void Awake()
5660 ConnectionCredentials credentials = new ( username , token ) ;
5761
5862 _client . Initialize ( credentials , targetChannel ) ;
63+ _httpClient . DefaultRequestHeaders . Authorization = AuthenticationHeaderValue . Parse ( $ "Bearer { token } ") ;
5964
6065 _client . Connect ( ) ;
6166 }
@@ -111,8 +116,8 @@ public static string SetTwitchLogin(string username, string token)
111116 return "Twitch login updated. Please restart Subnautica." ;
112117 }
113118
114- private static ConcurrentDictionary < string , ( Action < string > Callback , float ModerationDelay ) > _nextMessageCallbacks = [ ] ;
115- private static ConcurrentDictionary < string , Action > _timeoutCallbacks = [ ] ;
119+ private static readonly ConcurrentDictionary < string , ( Action < string > Callback , float ModerationDelay ) > _nextMessageCallbacks = [ ] ;
120+ private static readonly ConcurrentDictionary < string , Action > _timeoutCallbacks = [ ] ;
116121 public static void AddNextMessageCallback ( TwitchUser user , Action < string > callback , float moderationDelay = 5f )
117122 {
118123 _nextMessageCallbacks . AddOrUpdate ( user . Id , ( callback , moderationDelay ) , ( _ , existing ) =>
@@ -136,7 +141,7 @@ private static void InvokeCallbacksOnMessage(TwitchUser user, string message)
136141 }
137142 bool timedOut = false ;
138143 Action cb = ( ) => timedOut = true ;
139- _timeoutCallbacks . AddOrUpdate ( user . Id , cb , ( _ , existing ) => existing + cb ) ;
144+ _timeoutCallbacks . AddOrUpdate ( user . Id , cb , ( _ , curr ) => curr + cb ) ;
140145 Task . Delay ( TimeSpan . FromSeconds ( existing . delay ) ) . ContinueWith ( __ =>
141146 {
142147 _timeoutCallbacks . TryRemove ( user . Id , out _ ) ;
@@ -145,4 +150,47 @@ private static void InvokeCallbacksOnMessage(TwitchUser user, string message)
145150 SwarmControlManager . Instance . QueueOnMainThread ( ( ) => existing . callback ( message ) ) ;
146151 } ) ;
147152 }
153+
154+ private static readonly Dictionary < string , Color > _colors = [ ] ;
155+ private static bool _dead ; // in case clientid is wrong and twitch api call fails
156+
157+ public static async Task < Color > GetUserChatColor ( string userId )
158+ {
159+ if ( _colors . TryGetValue ( userId , out Color cached ) ) return cached ;
160+ if ( _dead ) return Color . white ;
161+
162+ try
163+ {
164+ // manual http call due to https://github.com/TwitchLib/TwitchLib/issues/1126
165+ string respJson = await _httpClient . GetStringAsync ( $ "helix/chat/color?user_id={ userId } ") ;
166+ if ( string . IsNullOrEmpty ( respJson ) ) return Color . white ;
167+
168+ UserColorResponseModel resp = JsonConvert . DeserializeObject < UserColorResponseModel > ( respJson ) ;
169+ string c = resp . Data [ 0 ] . Color ;
170+ return _colors [ userId ] = ColorUtility . TryParseHtmlString ( c , out Color color )
171+ ? color
172+ : Color . white ;
173+ }
174+ catch ( Exception e )
175+ {
176+ LOGGER . LogError ( $ "Failed to get user color for { userId } : { e } ") ;
177+ _dead = true ;
178+ return Color . white ;
179+ }
180+ }
181+
182+ private static readonly HttpClient _httpClient = new ( )
183+ {
184+ BaseAddress = new ( "https://api.twitch.tv/" ) ,
185+ DefaultRequestHeaders = { { "Client-Id" , "gp762nuuoqcoxypju8c569th9wz7q5" } } , // https://twitchtokengenerator.com
186+ } ;
187+
188+ [ JsonObject ( NamingStrategyType = typeof ( SnakeCaseNamingStrategy ) ) ]
189+ internal class UserColorResponseModel
190+ {
191+ public UserColorResponseItemModel [ ] Data { get ; set ; }
192+
193+ [ JsonObject ( NamingStrategyType = typeof ( SnakeCaseNamingStrategy ) ) ]
194+ public record UserColorResponseItemModel ( string UserId , string UserName , string UserLogin , string Color ) ;
195+ }
148196}
0 commit comments