kick_api/lib.rs
1//! # kick-api
2//!
3//! Rust client for the [Kick.com](https://kick.com) API.
4//!
5//! Covers channels, users, chat, moderation, rewards, event subscriptions, and
6//! live chat over WebSocket. Handles OAuth 2.1 (PKCE) authentication and
7//! automatic retry on rate limits (429).
8//!
9//! ## Live Chat (no auth required)
10//!
11//! ```no_run
12//! use kick_api::LiveChatClient;
13//!
14//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
15//! // Connect by username
16//! let mut chat = LiveChatClient::connect_by_username("xqc").await?;
17//!
18//! // Or connect by chatroom ID directly
19//! // let mut chat = LiveChatClient::connect(668).await?;
20//!
21//! while let Some(msg) = chat.next_message().await? {
22//! println!("{}: {}", msg.sender.username, msg.content);
23//! }
24//! # Ok(())
25//! # }
26//! ```
27//!
28//! ## REST API (requires OAuth token)
29//!
30//! ```no_run
31//! use kick_api::{KickApiClient, SendMessageRequest};
32//!
33//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
34//! let client = KickApiClient::with_token("your_oauth_token".to_string());
35//!
36//! // Channels
37//! let channel = client.channels().get("xqc").await?;
38//!
39//! // Users
40//! let me = client.users().get_me().await?;
41//!
42//! // Chat
43//! let msg = SendMessageRequest {
44//! r#type: "user".to_string(),
45//! content: "Hello chat!".to_string(),
46//! broadcaster_user_id: Some(12345),
47//! reply_to_message_id: None,
48//! };
49//! client.chat().send_message(msg).await?;
50//! # Ok(())
51//! # }
52//! ```
53//!
54//! ## Unofficial API
55//!
56//! Some features use Kick's **internal v2 API** (`kick.com/api/v2/...`) rather
57//! than the public API. These are reverse-engineered and **may break without
58//! notice**. They use `curl` as a subprocess to bypass Cloudflare TLS
59//! fingerprinting.
60//!
61//! | Function | Auth | Description |
62//! |----------|------|-------------|
63//! | [`LiveChatClient`] | None | Real-time chat via Pusher WebSocket |
64//! | [`fetch_channel_info`] | None | Chatroom settings, badges, livestream status |
65//! | [`fetch_followed_channels`] | Session token | Paginated list of followed channels ([`FollowedChannelsResponse`]) |
66//!
67//! ```no_run
68//! use kick_api::{fetch_channel_info, fetch_followed_channels};
69//!
70//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
71//! // Public — no auth
72//! let info = fetch_channel_info("xqc").await?;
73//! println!("Chatroom ID: {}", info.chatroom.id);
74//!
75//! // Requires session token (from browser cookies, not an OAuth app token)
76//! let resp = fetch_followed_channels("your_session_token").await?;
77//! for ch in &resp.channels {
78//! println!("{}: {} viewers",
79//! ch.user_username.as_deref().unwrap_or("?"), ch.viewer_count);
80//! }
81//! # Ok(())
82//! # }
83//! ```
84//!
85//! ## Authentication
86//!
87//! Kick uses OAuth 2.1 with PKCE. Use [`KickOAuth`] to handle the flow:
88//!
89//! ```no_run
90//! use kick_api::KickOAuth;
91//!
92//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
93//! // Load from KICK_CLIENT_ID, KICK_CLIENT_SECRET, KICK_REDIRECT_URI
94//! let oauth = KickOAuth::from_env()?;
95//! let scopes = vec!["chat:write", "user:read", "channel:read"];
96//! let (auth_url, csrf_token, pkce_verifier) = oauth.get_authorization_url(scopes);
97//! // Send the user to auth_url, then exchange the code:
98//! // let token = oauth.exchange_code(code, pkce_verifier).await?;
99//! # Ok(())
100//! # }
101//! ```
102//!
103//! For server-to-server access (no user interaction), use an App Access Token:
104//!
105//! ```no_run
106//! use kick_api::KickOAuth;
107//!
108//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
109//! // Only needs KICK_CLIENT_ID and KICK_CLIENT_SECRET
110//! let oauth = KickOAuth::from_env_server()?;
111//! let token = oauth.get_app_access_token().await?;
112//! let client = kick_api::KickApiClient::with_token(token.access_token);
113//! # Ok(())
114//! # }
115//! ```
116
117mod error;
118mod client;
119mod http;
120mod live_chat;
121mod models;
122mod oauth;
123mod api;
124
125pub use error::{KickApiError, Result};
126pub use client::KickApiClient;
127pub use live_chat::{LiveChatClient, fetch_channel_info, fetch_followed_channels};
128pub use models::*;
129pub use oauth::{KickOAuth, OAuthTokenResponse};
130pub use api::{ChannelsApi, ChatApi, EventsApi, LivestreamsApi, ModerationApi, RewardsApi, UsersApi};