add: last.fm status integration

This commit is contained in:
trisua 2025-04-26 19:23:30 -04:00
parent 3e2bdceb99
commit 0765156697
17 changed files with 397 additions and 3 deletions

View file

@ -18,6 +18,10 @@ tetratto-l10n = { path = "../l10n" }
serde_json = "1.0.140"
totp-rs = { version = "5.7.0", features = ["qr", "gen_secret"] }
reqwest = { version = "0.12.15", features = ["json"] }
bitflags = "2.9.0"
async-recursion = "1.1.1"
md-5 = "0.10.6"
base16ct = { version = "0.2.0", features = ["alloc"] }
redis = { version = "0.30.0", optional = true }
@ -25,5 +29,3 @@ rusqlite = { version = "0.35.0", optional = true }
tokio-postgres = { version = "0.7.13", optional = true }
bb8-postgres = { version = "0.9.0", optional = true }
bitflags = "2.9.0"
async-recursion = "1.1.1"

View file

@ -155,12 +155,20 @@ pub struct ConnectionsConfig {
/// <https://developer.spotify.com/documentation/web-api>
#[serde(default)]
pub spotify_client_id: Option<String>,
/// <https://www.last.fm/api/authspec>
#[serde(default)]
pub last_fm_key: Option<String>,
/// <https://www.last.fm/api/authspec>
#[serde(default)]
pub last_fm_secret: Option<String>,
}
impl Default for ConnectionsConfig {
fn default() -> Self {
Self {
spotify_client_id: None,
last_fm_key: None,
last_fm_secret: None,
}
}
}

View file

@ -0,0 +1,42 @@
use std::collections::HashMap;
use crate::{
config::Config,
model::auth::{ConnectionType, ExternalConnectionInfo, UserConnections},
};
use md5::{Md5, Digest};
use base16ct::upper::encode_string;
/// A connection to last.fm.
pub struct LastFmConnection(pub UserConnections, pub Config);
impl LastFmConnection {
/// Create a legacy MD5 signature, since last.fm is old.
pub fn signature(params: HashMap<String, String>, secret: String) -> String {
let mut params_string = String::new();
let mut params = params.clone();
params.remove("format");
let mut x = params.iter().collect::<Vec<(&String, &String)>>();
x.sort_by(|a, b| a.0.cmp(b.0));
for param in x {
params_string.push_str(&format!("{}{}", param.0, param.1));
}
let mut hasher = Md5::new();
hasher.update(format!("{params_string}{secret}"));
let hash = hasher.finalize();
encode_string(&hash)
}
/// Create a new [`ExternalConnectionInfo`] for the connection.
pub fn connection() -> ExternalConnectionInfo {
ExternalConnectionInfo {
con_type: ConnectionType::Token,
data: HashMap::new(),
show_on_profile: true,
}
}
}

View file

@ -1 +1,2 @@
pub mod last_fm;
pub mod spotify;

View file

@ -346,6 +346,8 @@ impl User {
pub enum ConnectionService {
/// A connection to a Spotify account.
Spotify,
/// A connection to a last.fm account.
LastFm,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]