From 30eb512aca3d6d2db1e9f6163361ba5c778b73de Mon Sep 17 00:00:00 2001 From: notohh Date: Sun, 16 Jun 2024 07:15:54 -0400 Subject: [PATCH] feat: add basic lastfm command --- Cargo.lock | 2 + Cargo.toml | 2 + src/commands/lastfm.rs | 116 +++++++++++++++++++++++++++++++++++++++++ src/commands/mod.rs | 1 + src/main.rs | 4 +- 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/commands/lastfm.rs diff --git a/Cargo.lock b/Cargo.lock index 8698962..e102cab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,8 @@ dependencies = [ "dotenv", "pretty_env_logger", "reqwest", + "serde", + "serde_json", "sysinfo", "tokio", "twitch-irc", diff --git a/Cargo.toml b/Cargo.toml index 9360878..4b66e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" dotenv = "0.15.0" pretty_env_logger = "0.5.0" reqwest = { version = "0.12.4", features = ["json"] } +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1.0.117" sysinfo = "0.30.12" tokio = { version = "1.37.0", features = ["full"] } twitch-irc = "5.0.1" diff --git a/src/commands/lastfm.rs b/src/commands/lastfm.rs new file mode 100644 index 0000000..c224471 --- /dev/null +++ b/src/commands/lastfm.rs @@ -0,0 +1,116 @@ +use crate::client::TwitchClient; +use dotenv::dotenv; +use serde::{Deserialize, Serialize}; +use std::env; + +use twitch_irc::message::PrivmsgMessage; + +#[derive(Debug, Serialize, Deserialize)] +struct Data { + recenttracks: Recenttracks, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Image { + size: String, + #[serde(rename = "#text")] + text: String, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Registered { + unixtime: String, + #[serde(rename = "#text")] + text: i64, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Recenttracks { + track: Vec, + #[serde(rename = "@attr")] + attr: Attr, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Attr { + user: String, + total_pages: String, + page: String, + per_page: String, + total: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Track { + artist: Album, + streamable: String, + image: Vec, + mbid: String, + album: Album, + name: String, + url: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Album { + mbid: String, + #[serde(rename = "#text")] + text: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Date { + uts: String, + #[serde(rename = "#text")] + text: String, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum Size { + Extralarge, + Large, + Medium, + Small, +} + +pub async fn lastfm_command(m: &PrivmsgMessage, c: &TwitchClient) { + dotenv().ok(); + + let lastfm_api_key = env::var("LASTFM_API_KEY").expect("Failed to load lastfm api key."); + let user = "notoh"; + + let recent_tracks_url = format!( + "http://ws.audioscrobbler.com/2.0/?method=user.getRecentTracks&user={}&api_key={}&format=json&nowplaying=true", user, + lastfm_api_key + ); + + let client = reqwest::Client::new(); + + match client.get(recent_tracks_url).send().await { + Ok(response) => { + if response.status().is_success() { + let body = response.text().await.unwrap(); + match serde_json::from_str::(&body) { + Ok(payload) => { + if let Some(tracks) = payload.recenttracks.track.first() { + let s = format!( + "Listening to: {} - {} {}", + tracks.name, tracks.artist.text, tracks.url + ); + c.twitch_client + .say(m.channel_login.to_owned(), s.to_owned()) + .await + .expect("Error sending message to twitch"); + } + } + Err(e) => eprintln!("{}", e), + } + } else { + println!("Response error: {}", response.status()); + } + } + Err(e) => eprintln!("Error sending request: {}", e), + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index f458a8d..f88abee 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,3 @@ +pub mod lastfm; pub mod ping; pub mod test; diff --git a/src/main.rs b/src/main.rs index 82bfbff..188412e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ +use commands::lastfm::lastfm_command; use commands::ping::ping_command; -use commands::test::test_command; use std::collections::HashMap; use client::client; @@ -36,7 +36,7 @@ pub async fn main() { if msg.sender.name == "notohh" { match msg.message_text.as_str() { "*ping" => ping_command(&msg, &client).await, - "*test" => test_command(&msg, &client).await, + "*song" => lastfm_command(&msg, &client).await, _ => {} } }