use env_logger::{Builder, Env}; use log::LevelFilter; use log::{error, warn};
use std::time::Duration; use tiktoklive::{
core::live_client::TikTokLiveClient,
data::live_common::{ClientData, StreamData, TikTokLiveSettings},
errors::LibError,
generated::events::TikTokLiveEvent,
TikTokLive,
};
use tokio::signal;
#[tokio::main] async fn main() {
init_logger("info"); let user_name = "tragdate";
let client = create_client(user_name);
let handle = tokio::spawn(async move {
if let Err(e) = client.connect().await {
match e {
LibError::LiveStatusFieldMissing => {
warn!(
"Failed to get live status (probably needs authenticated client): {}",
e
);
let auth_client = create_client_with_cookies(user_name); if let Err(e) = auth_client.connect().await {
error!("Error connecting to TikTok Live after retry: {}", e);
}
}
LibError::HeaderNotReceived => {
error!("Error connecting to TikTok Live: {}", e);
}
_ => {
error!("Error connecting to TikTok Live: {}", e);
}
}
}
});
signal::ctrl_c().await.expect("Failed to listen for Ctrl+C");
handle.await.expect("The spawned task has panicked"); }
fn handle_event(client: &TikTokLiveClient, event: &TikTokLiveEvent) {
match event {
TikTokLiveEvent::OnConnected(..) => {
let room_info = client.get_room_info();
let client_data: ClientData = serde_json::from_str(room_info).unwrap();
let stream_data: StreamData = serde_json::from_str(
&client_data
.data
.stream_url
.live_core_sdk_data
.unwrap()
.pull_data
.stream_data,
)
.unwrap();
let video_url = stream_data
.data
.ld
.map(|ld| ld.main.flv)
.or_else(|| stream_data.data.sd.map(|sd| sd.main.flv))
.or_else(|| stream_data.data.origin.map(|origin| origin.main.flv))
.expect("None of the stream types set");
println!("room info: {}", video_url);
}
TikTokLiveEvent::OnMember(join_event) => {
println!("user: {} joined", join_event.raw_data.user.nickname);
}
TikTokLiveEvent::OnChat(chat_event) => {
println!(
"user: {} -> {}",
chat_event.raw_data.user.nickname, chat_event.raw_data.content
);
}
TikTokLiveEvent::OnGift(gift_event) => {
let nick = &gift_event.raw_data.user.nickname;
let gift_name = &gift_event.raw_data.gift.name;
let gifts_amount = gift_event.raw_data.gift.combo;
println!(
"user: {} sends gift: {} x {}",
nick, gift_name, gifts_amount
);
}
TikTokLiveEvent::OnLike(like_event) => {
let nick = &like_event.raw_data.user.nickname;
println!("user: {} likes", nick);
}
_ => {} }
}
fn init_logger(default_level: &str) {
let env = Env::default().filter_or("LOG_LEVEL", default_level); Builder::from_env(env) .filter_module("tiktoklive", LevelFilter::Debug) .init(); }
fn configure(settings: &mut TikTokLiveSettings) {
settings.http_data.time_out = Duration::from_secs(12); settings.sign_api_key = "".to_string(); }
fn configure_with_cookies(settings: &mut TikTokLiveSettings) {
settings.http_data.time_out = Duration::from_secs(12); settings.sign_api_key = "".to_string(); let contents = ""; settings
.http_data
.headers
.insert("Cookie".to_string(), contents.to_string());
}
fn create_client(user_name: &str) -> TikTokLiveClient {
TikTokLive::new_client(user_name) .configure(configure) .on_event(handle_event) .build() }
fn create_client_with_cookies(user_name: &str) -> TikTokLiveClient {
TikTokLive::new_client(user_name) .configure(configure_with_cookies) .on_event(handle_event) .build() }