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
129
130
131
132
133
134
135
136
137
138
139
//! 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.
//!
//! # Features
//!
//! - `websocket-client`: WebSocket client with automatic reconnection
//! - `websocket-router`: Event router with handler support and middleware layers
//!
//! # Quick Start
//!
//! ```toml
//! [dependencies]
//! twitch_highway = { version = "0.2", features = ["eventsub", "websocket"] }
//! tokio = { version = "1", features = ["full"] }
//! ```
//!
//! ```rust,no_run
//! 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
//!
//! ```rust
//! 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
//!
//! ```rust
//! 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 *;