1
0

Fetch listenbrainz and set discord rpc

This commit is contained in:
ixhbinphoenix
2024-02-12 19:39:01 +01:00
parent 75b038bb06
commit f369ffb220
9 changed files with 1055 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
use std::{u8, usize};
use serde::Deserialize;
use ureq::{Agent, AgentBuilder, Response};
#[derive(Deserialize)]
pub struct LBResponse<T> {
pub payload: T
}
impl<T> LBResponse<T> {
pub fn inner(self) -> T {
self.payload
}
}
#[derive(Deserialize)]
pub struct ListenResponsePayload {
pub count: u32,
pub user_id: String,
pub listens: Vec<Listen>,
pub playing_now: Option<bool>
}
#[derive(Deserialize)]
pub struct Listen {
pub track_metadata: TrackMetadata,
pub listened_at: Option<u64>,
pub playing_now: Option<bool>
}
#[derive(Deserialize)]
pub struct TrackMetadata {
pub additional_info: Option<AdditionalListenInfo>,
pub artist_name: String,
pub track_name: String,
pub release_name: Option<String>
}
#[derive(Deserialize)]
pub struct AdditionalListenInfo {
pub artist_mbids: Option<Vec<String>>,
pub release_group_mbid: Option<String>,
pub release_mbid: Option<String>,
pub recording_mbid: Option<String>,
pub track_mbid: Option<String>,
pub work_mbids: Option<Vec<String>>,
pub tracknumber: Option<u8>,
pub isrc: Option<String>,
pub spotify_id: Option<String>,
pub tags: Option<Vec<String>>,
pub media_player: Option<String>,
pub media_player_version: Option<String>,
pub submission_client: Option<String>,
pub submission_client_version: Option<String>,
pub music_service: Option<String>,
pub music_service_name: Option<String>,
pub origin_url: Option<String>,
pub duration_ms: Option<usize>,
pub duration: Option<usize>
}
pub struct Client {
user_token: Option<String>,
agent: Agent
}
impl Client {
pub fn new() -> Self {
Self {
user_token: None,
agent: AgentBuilder::new()
.user_agent("lb-discord-rpc/0.1.0 (contact@ixhby.dev)")
.build()
}
}
#[allow(dead_code)]
pub fn new_authorized(user_token: String) -> Self {
Self {
user_token: Some(user_token),
agent: AgentBuilder::new()
.user_agent("lb-discord-rpc/0.1.0 (contact@ixhby.dev)")
.build()
}
}
fn get(&self, url: String) -> Result<Response, Box<ureq::Error>> {
let mut req = self.agent.get(&url);
if self.user_token.is_some() {
req = req.set("Authorization", &format!("Token {}", self.user_token.clone().unwrap()));
}
Ok(req.call()?)
}
pub fn now_playing(&self, user: &str) -> anyhow::Result<ListenResponsePayload> {
let res = self.get(format!("https://api.listenbrainz.org/1/user/{user}/playing-now"));
match res {
Err(e) => {
Err(e.into())
},
Ok(a) => {
Ok(serde_json::from_str::<LBResponse<ListenResponsePayload>>(&a.into_string()?)?.inner())
},
}
}
}
+46
View File
@@ -0,0 +1,46 @@
mod listenbrainz;
use core::time;
use std::{env, error::Error, thread};
use dotenv::dotenv;
use env_logger::Env;
use listenbrainz::Client;
fn main() -> Result<(), Box<dyn Error>> {
dotenv().ok();
if cfg!(debug_assertions) {
env_logger::init_from_env(Env::new().default_filter_or("debug"));
} else {
env_logger::init_from_env(Env::new().default_filter_or("info"));
}
let lb = Client::new();
let mut drpc = discord_rpc_client::Client::new(env::var("DISCORD_CLIENT_ID")?.parse()?);
drpc.start();
loop {
// TODO: Error handling lol
let np = lb.now_playing(&env::var("LB_USER")?)?;
let listen = np.listens.first();
if listen.is_none() {
drpc.clear_activity().unwrap();
thread::sleep(time::Duration::from_secs(15));
continue;
}
let metadata = &listen.unwrap().track_metadata;
let track = metadata.track_name.clone();
let artist = metadata.artist_name.clone();
// TODOOO: Fetch cover art and display it in the discord RPC
drpc.set_activity(|act|
act.state(artist).details(track)
).unwrap();
thread::sleep(time::Duration::from_secs(15));
}
}