1- use std:: { collections:: { BinaryHeap , HashMap , HashSet , VecDeque } , error :: Error , sync:: Arc , time:: Duration } ;
1+ use std:: { collections:: { BinaryHeap , HashMap , HashSet , VecDeque } , sync:: Arc , time:: Duration } ;
22
33use tokio:: sync:: { Mutex , Notify , watch:: Receiver } ;
44
@@ -96,7 +96,7 @@ pub async fn filter_streams (client: Arc<TwitchClient>, campaigns_arc: Arc<Mutex
9696 * video_ids_lock = video_vec;
9797 drop ( video_ids_lock) ;
9898 debug ! ( "Drop video_ids_lock" ) ;
99- spawn_ws ( client. access_token . clone ( ) . unwrap ( ) , state. clone ( ) ) . await ;
99+ spawn_ws ( client. access_token . clone ( ) . expect ( "Access token is required" ) , state. clone ( ) ) . await ;
100100
101101 tokio:: spawn ( async move {
102102 loop {
@@ -202,7 +202,7 @@ async fn spawn_ws (auth_token: String, state: Arc<AppState>) {
202202 "auth_token" : auth_token
203203 }
204204 } ) ;
205- let payload = serde_json:: to_string ( & payload) . unwrap ( ) ;
205+ let payload = serde_json:: to_string ( & payload) . expect ( "json! macro production is guaranteed to be serializable" ) ;
206206 let payload = tokio_tungstenite:: tungstenite:: Message :: Text ( payload. into ( ) ) ;
207207 write. send ( payload) . await . unwrap_or_else ( |e| error ! ( "Failed to send payload to WebSocket: {e}" ) ) ;
208208 send_channels. extend ( new_channels) ;
@@ -217,7 +217,7 @@ async fn spawn_ws (auth_token: String, state: Arc<AppState>) {
217217 "auth_token" : auth_token
218218 }
219219 } ) ;
220- let payload = serde_json:: to_string ( & payload) . unwrap ( ) ;
220+ let payload = serde_json:: to_string ( & payload) . expect ( "json! macro production is guaranteed to be serializable" ) ;
221221 let payload = tokio_tungstenite:: tungstenite:: Message :: Text ( payload. into ( ) ) ;
222222 write. send ( payload) . await . unwrap_or_else ( |e| error ! ( "Failed to send payload to WebSocket: {e}" ) ) ;
223223 for delete in delete_channels {
@@ -229,39 +229,58 @@ async fn spawn_ws (auth_token: String, state: Arc<AppState>) {
229229 match msg {
230230 Ok ( Message :: Text ( text) ) => {
231231 debug ! ( "Received WebSocket message: {text}" ) ;
232- if text. contains ( "\" type\" :\" PING\" " ) {
233- debug ! ( "Received PING from WebSocket, sending PONG" ) ;
234- let pong = Message :: Text ( "{\" type\" :\" PONG\" }" . into ( ) ) ;
235- write. send ( pong) . await . unwrap ( ) ;
236- }
237- let json: Value = serde_json:: from_str ( & text) . unwrap ( ) ;
238- if let Some ( err) = json. get ( "error" ) . and_then ( |e| e. as_str ( ) ) {
239- if !err. is_empty ( ) {
240- error ! ( "{err}" )
232+ let json: Value = match serde_json:: from_str ( & text) {
233+ Ok ( v) => v,
234+ Err ( e) => {
235+ error ! ( "Failed to parse JSON text: {e}" ) ;
236+ continue ;
241237 }
242- continue ;
243- } else {
244- let data = check_json ( & json, "data" ) . unwrap_or_else ( |e| { error ! ( "{e}" ) ; & Value :: Null } ) ;
245- let message = check_json ( & data, "message" ) . unwrap_or_else ( |e| { error ! ( "{e}" ) ; & Value :: Null } ) . as_str ( ) . unwrap_or_default ( ) ;
246- let topic = check_json ( data, "topic" ) . unwrap_or_else ( |e| { error ! ( "{e}" ) ; & Value :: Null } ) . as_str ( ) . unwrap_or_default ( ) ;
247- let message_json: Value = serde_json:: from_str ( & message) . unwrap ( ) ;
248-
249- if let Some ( viewers) = message_json. get ( "viewers" ) . and_then ( |s| s. as_u64 ( ) ) {
250- debug ! ( "Stream {} has {} viewers" , topic, viewers) ;
251- if viewers == 0 {
252- if let Some ( id_str) = topic. split ( '.' ) . last ( ) {
253- let mut channel_pool = state. channel_pool . lock ( ) . await ;
254- if let Some ( to_remove) = channel_pool. iter ( ) . find ( |channel| channel. channel_id == id_str) . cloned ( ) {
255- channel_pool. remove ( & to_remove) ;
238+ } ;
239+ let msg_type = json. get ( "type" ) . and_then ( |t| t. as_str ( ) ) . unwrap_or ( "" ) ;
240+ match msg_type {
241+ "PING" => {
242+ debug ! ( "Received PING from WebSocket, sending PONG" ) ;
243+ let pong = Message :: Text ( "{\" type\" :\" PONG\" }" . into ( ) ) ;
244+ let _ = write. send ( pong) . await ;
245+ continue ;
246+ } ,
247+ "PONG" => { continue ; }
248+ "RECCONECT" => {
249+ warn ! ( "Received RECONNECT from WebSocket, reconnecting..." ) ;
250+ break ;
251+ } ,
252+ "RESPONSE" => {
253+ if let Some ( err) = json. get ( "error" ) . and_then ( |e| e. as_str ( ) ) {
254+ if !err. is_empty ( ) {
255+ error ! ( "WebSocket RESPONSE error: {err}" ) ;
256+ }
257+ }
258+ continue ;
259+ } ,
260+ "MESSAGE" => {
261+ if let Some ( data) = json. get ( "data" ) {
262+ let topic = data. get ( "topic" ) . and_then ( |t| t. as_str ( ) ) . unwrap_or_default ( ) ;
263+ let message_str = data. get ( "message" ) . and_then ( |m| m. as_str ( ) ) . unwrap_or_default ( ) ;
264+ if let Ok ( message_json) = serde_json:: from_str :: < Value > ( message_str) {
265+ if let Some ( viewers) = message_json. get ( "viewers" ) . and_then ( |v| v. as_u64 ( ) ) {
266+ debug ! ( "Stream {} has {} viewers" , topic, viewers) ;
267+ if viewers == 0 {
268+ if let Some ( id_str) = topic. split ( '.' ) . last ( ) {
269+ let mut channel_pool = state. channel_pool . lock ( ) . await ;
270+ channel_pool. retain ( |channel| channel. channel_id != id_str) ;
271+ send_channels. retain ( |channel| channel. channel_id != id_str) ;
272+ }
273+ }
274+ } else {
275+ debug ! ( "No viewers field in message for topic {}" , topic) ;
256276 }
257- send_channels. retain ( |channel| channel. channel_id != id_str ) ;
277+ } else {
278+ error ! ( "Failed to parse message JSON for topic {}" , topic) ;
258279 }
259280 }
260- } else {
261- debug ! ( "No viewers field in message for topic {}" , topic) ;
262- }
281+ } ,
282+ _ => { debug ! ( "Received unknown message type: {}" , msg_type) }
263283 }
264-
265284 } ,
266285 Ok ( Message :: Ping ( ping) ) => write. send ( Message :: Pong ( ping) ) . await . unwrap_or_else ( |e| error ! ( "Failed to send PONG to WebSocket: {e}" ) ) ,
267286 Ok ( _) => { } ,
@@ -279,14 +298,6 @@ async fn spawn_ws (auth_token: String, state: Arc<AppState>) {
279298 } ) ;
280299}
281300
282- fn check_json < ' a > ( v : & ' a Value , data : & str ) -> Result < & ' a Value , Box < dyn Error > > {
283- if let Some ( key) = v. get ( & data) {
284- return Ok ( key) ;
285- } else {
286- return Err ( format ! ( "Failed to find '{}' in JSON" , data) ) ?;
287- }
288- }
289-
290301#[ derive( PartialEq , Eq , Clone ) ]
291302struct Priority {
292303 priority : u32 ,
0 commit comments