1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Twitch EventSub WebSocket client and router.
//!
//! This module provides a WebSocket client for receiving Twitch EventSub notifications in real-time,
//! along with a router for handling different event types. The design is similar to axum's routing pattern.
//!
//! # Quick Start
//!
//! ```ignore
//! use std::sync::Arc;
//!
//! use tokio::sync::RwLock;
//! use twitch_highway::{
//! eventsub::{
//! events::channels::follow::ChannelFollow,
//! websocket::{
//! self,
//! extract::{Event, State},
//! routes::{channel_follow, welcome},
//! Router,
//! },
//! },
//! types::SessionId,
//! };
//!
//! #[derive(Clone)]
//! struct AppState {
//! session_id: Arc<RwLock<SessionId>>,
//! }
//!
//! async fn on_welcome() {
//! println!("Connected to Twitch EventSub!");
//! }
//!
//! async fn on_follow(Event(event): Event<ChannelFollow>, State(state): State<AppState>) {
//! println!("New follower: {}", event.user_name);
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let state = AppState {
//! session_id: Arc::new(RwLock::new(SessionId::from("initial"))),
//! };
//!
//! let app = Router::new()
//! .route(welcome(on_welcome))
//! .route(channel_follow(on_follow))
//! .with_state(state);
//!
//! websocket::client("wss://eventsub.wss.twitch.tv/ws", app)
//! .await
//! .unwrap();
//! }
//! ```
//!
//! # Router and Handlers
//!
//! The router system works similarly to axum:
//!
//! - Define handlers as async functions
//! - Use extractors to access request data (Event, Session, State, etc.)
//! - Route messages to handlers based on message type or subscription type
//! - Apply middleware layers for logging, rate limiting, etc.
//!
//! ## Extractors
//!
//! ```ignore
//! use twitch_highway::eventsub::{
//! events::hype_train,
//! websocket::extract::{Event, Meta, Session, State},
//! };
//!
//! # #[derive(Clone)]
//! # struct AppState;
//!
//! async fn handler(
//! Event(event): Event<hype_train::v2::HypeTrainBegin>, // The event data
//! Meta(meta): Meta, // Message metadata
//! Session(session): Session, // Session information (for welcome/reconnect)
//! State(state): State<AppState>, // Application state
//! ) {
//!
//! }
//! ```
//!
//! ## Middleware Layers
//!
//! ```ignore
//! use twitch_highway::eventsub::websocket::{layer::TraceLayer, Router, routes::welcome};
//! # async fn example(state:String) {
//! let app = Router::new()
//! .route(welcome(on_welcome))
//! .layer(TraceLayer::new())
//! .with_state(state);
//!
//! # twitch_highway::eventsub::websocket::client("wss://eventsub.wss.twitch.tv/ws", app).await.unwrap();
//! # }
//!
//! # async fn on_welcome() {}
//! ```
//!
//! # Reconnection Handling
//!
//! The client automatically handles:
//! - Keepalive messages (sent every 10 seconds by Twitch)
//! - Reconnection requests from the server
//! - Connection failures with exponential backoff
pub use ;
pub use ;
pub use ;
pub use *;
pub use ;
pub use *;