diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..b19a15a --- /dev/null +++ b/src/api.rs @@ -0,0 +1,25 @@ +use reqwest::{ + header::{HeaderMap, HeaderValue}, + Client, +}; +use std::env; + +pub fn helix_client() -> Client { + let twitch_client_id = env::var("TWITCH_CLIENT_ID").expect("a"); + let twitch_bearer = env::var("TWITCH_BEARER").expect("a"); + + let mut headers = HeaderMap::new(); + + headers.insert( + "Authorization", + HeaderValue::from_str(&twitch_bearer).expect("a"), + ); + headers.insert( + "Client-Id", + HeaderValue::from_str(&twitch_client_id).expect("a"), + ); + + let client = Client::builder().default_headers(headers).build().unwrap(); + + return client; +} diff --git a/src/client.rs b/src/client.rs index 0f0fffd..2d8914d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -11,7 +11,7 @@ pub struct TwitchClient { pub twitch_client: TwitchIRCClient, } -pub fn create_client() -> ClientConfig { +pub fn client_config() -> ClientConfig { dotenv().ok(); let twitch_id = env::var("TWITCH_ID").expect("Failed to load twitch id"); @@ -23,7 +23,7 @@ pub fn create_client() -> ClientConfig { } pub fn client() -> TwitchClient { - let config = create_client(); + let config = client_config(); let (incoming_messages, twitch_client) = TwitchIRCClient::::new(config); diff --git a/src/commands/lastfm.rs b/src/commands/lastfm.rs index 9f11464..79f28fc 100644 --- a/src/commands/lastfm.rs +++ b/src/commands/lastfm.rs @@ -91,7 +91,7 @@ pub async fn lastfm_command(m: &PrivmsgMessage, c: &TwitchClient) { match client.get(recent_tracks_url).send().await { Ok(response) => { if response.status().is_success() { - let body = response.text().await.unwrap(); + let body = response.text().await.unwrap_or_default(); match serde_json::from_str::(&body) { Ok(payload) => { if let Some(tracks) = payload.recenttracks.track.first() { @@ -105,7 +105,7 @@ pub async fn lastfm_command(m: &PrivmsgMessage, c: &TwitchClient) { .expect("Error sending message to twitch"); } } - Err(e) => eprintln!("{}", e), + Err(e) => error!("{}", e), } } else { error!("Response error: {}", response.status()); diff --git a/src/commands/logs.rs b/src/commands/logs.rs new file mode 100644 index 0000000..8d13ead --- /dev/null +++ b/src/commands/logs.rs @@ -0,0 +1,18 @@ +use dotenv::dotenv; +use twitch_irc::message::PrivmsgMessage; + +use crate::client::TwitchClient; + +pub async fn logs_command(m: &PrivmsgMessage, c: &TwitchClient, a: &[&str]) { + dotenv().ok(); + + let url = format!( + "https://logs.flake.sh/?channel={}&username={}", + a.first().unwrap(), + a.get(1).unwrap() + ); + + let twitch_client = c.twitch_client.clone(); + + let _response = twitch_client.say(m.channel_login.to_owned(), url).await; +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2d56aed..22d442b 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,4 @@ pub mod lastfm; +pub mod logs; pub mod ping; +pub mod user; diff --git a/src/commands/ping.rs b/src/commands/ping.rs index e2a4fd5..3d747c4 100644 --- a/src/commands/ping.rs +++ b/src/commands/ping.rs @@ -21,12 +21,9 @@ pub async fn ping_command(m: &PrivmsgMessage, c: &TwitchClient) { let host = System::name().unwrap(); let s = format!( - "Pong! | โ†‘: {}m {}s | Host: {} | Mem: {:.2} MB", + "๐Ÿš€Pong! | โ†‘: {}m {}s | Host: {} | Mem: {:.2} MB", uptime_minute, remaining_seconds, host, mem ); - let _message = c - .twitch_client - .say(m.channel_login.to_owned(), s.to_owned()) - .await; + let _message = c.twitch_client.say(m.channel_login.to_owned(), s).await; } } diff --git a/src/commands/user.rs b/src/commands/user.rs new file mode 100644 index 0000000..f502a33 --- /dev/null +++ b/src/commands/user.rs @@ -0,0 +1,71 @@ +use dotenv::dotenv; +use twitch_irc::message::PrivmsgMessage; + +use serde::{Deserialize, Serialize}; + +use crate::api::helix_client; +use crate::client::TwitchClient; + +#[derive(Debug, Serialize, Deserialize)] +struct Data { + data: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +struct UserData { + broadcaster_type: String, + created_at: String, + description: String, + display_name: String, + id: String, + login: String, + offline_image_url: String, + profile_image_url: String, + #[serde(rename = "type")] + datum_type: String, + view_count: i64, +} + +pub async fn get_user_command(m: &PrivmsgMessage, c: &TwitchClient, a: &[&str]) { + dotenv().ok(); + + let url = format!("https://api.twitch.tv/helix/users?login={}", a.join(" ")); + + let helix_client = helix_client(); + + let twitch_client = c.twitch_client.clone(); + + match helix_client.get(url).send().await { + Ok(response) => { + if response.status().is_success() { + let body = response.text().await.unwrap_or_default(); + match serde_json::from_str::(&body) { + Ok(payload) => { + for items in payload.data { + let s = format!( + "Name: {} | Created: {} | ID: {} | Broadcaster status: {} | PFP: {}", + items.display_name, + items.created_at, + items.id, + items.broadcaster_type.to_uppercase(), + items.profile_image_url + ); + twitch_client + .say(m.channel_login.to_owned(), s) + .await + .expect("Failed to send message"); + } + } + Err(e) => error!("Failed: {}", e), + } + } else { + let error = format!("Error with response: {}", response.status()); + twitch_client + .say(m.channel_login.to_owned(), error) + .await + .expect("Error sending message to twitch."); + } + } + Err(e) => error!("Error sending request: {}", e), + } +} diff --git a/src/main.rs b/src/main.rs index 7676eb4..59df8f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,13 @@ use commands::lastfm::lastfm_command; +use commands::logs::logs_command; use commands::ping::ping_command; +use commands::user::get_user_command; use std::collections::HashMap; use client::client; use twitch_irc::message::ServerMessage; +mod api; mod client; mod commands; @@ -22,7 +25,6 @@ pub async fn main() { initial_channels.insert("notnotoh", ()); initial_channels.insert("notohh", ()); initial_channels.insert("daph", ()); - initial_channels.insert("elis", ()); for (channels, _) in initial_channels.iter() { match client.twitch_client.join(channels.to_owned().to_string()) { @@ -35,14 +37,23 @@ pub async fn main() { while let Some(message) = client.incoming_messages.recv().await { match message { ServerMessage::Privmsg(msg) => { - println!( - "(#{}) {}: {}", - msg.channel_login, msg.sender.name, msg.message_text - ); - if msg.sender.name == "notohh" { - match msg.message_text.as_str() { - "*ping" => ping_command(&msg, &client).await, - "*song" => lastfm_command(&msg, &client).await, + let channel = msg.channel_login.clone(); + let sender = msg.sender.name.clone(); + let contents = msg.message_text.clone(); + let prefix = "*"; + + println!("(#{}) {}: {}", &channel, &sender, &contents); + + if sender == "notohh" && contents.starts_with(prefix) { + let mut parts = contents.split_whitespace(); + let command = parts.next().unwrap_or("").trim_start_matches(prefix); + let arguments: Vec<&str> = parts.collect(); + + match command { + "ping" => ping_command(&msg, &client).await, + "song" => lastfm_command(&msg, &client).await, + "user" => get_user_command(&msg, &client, &arguments).await, + "logs" => logs_command(&msg, &client, &arguments).await, _ => {} } }