Skip to content

Commit 2412f06

Browse files
committed
add debug for lastfm
1 parent 919d593 commit 2412f06

8 files changed

Lines changed: 54 additions & 32 deletions

File tree

.kube/deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ spec:
1717
- name: personal-api
1818
image: kokuzo.tailc38f.ts.net/personal-api:latest
1919
imagePullPolicy: "Always"
20+
env:
21+
- name: RUST_LOG
22+
value: "debug"
2023
ports:
2124
- containerPort: 3000
2225
args:

src/config.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::{borrow::Cow, collections::HashMap};
22

3-
use axum_extra::{headers::{authorization::Bearer, Authorization}, TypedHeader};
3+
use axum_extra::{
4+
TypedHeader,
5+
headers::{Authorization, authorization::Bearer},
6+
};
47
use serde::{Deserialize, Serialize};
58
use steam_rs::steam_id::SteamId;
69

@@ -36,13 +39,16 @@ pub struct AuthConfig {
3639
pub scopes: Vec<String>,
3740
}
3841

39-
pub fn scopes_from_bearer(bearer: Option<TypedHeader<Authorization<Bearer>>>, config: &'static Config) -> Cow<'static, [String]> {
42+
pub fn scopes_from_bearer(
43+
bearer: Option<TypedHeader<Authorization<Bearer>>>,
44+
config: &'static Config,
45+
) -> Cow<'static, [String]> {
4046
bearer
4147
.and_then(|auth| config.auth.get(auth.0.token()))
4248
.map(|auth| Cow::<'static, [String]>::Borrowed(&auth.scopes))
4349
.unwrap_or_default()
4450
}
4551

46-
pub fn has_scope(auth_scopes: &Cow<[String]>, scope: &'static str) -> bool{
52+
pub fn has_scope(auth_scopes: &Cow<[String]>, scope: &'static str) -> bool {
4753
auth_scopes.iter().any(|s| scope == s)
4854
}

src/fetchers/icloud.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct DeviceInfo {
3636
static DEVICE_INFO: LazyLock<RwLock<HashMap<String, DeviceInfo>>> = LazyLock::new(RwLock::default);
3737
static FINDER: LazyLock<DefaultFinder> = LazyLock::new(DefaultFinder::new);
3838

39-
pub fn get_user_info(device_id: &str, auth_scopes: Cow<'static, [String]>) -> Option<Location> {
39+
pub fn get_user_info(device_id: &str, auth_scopes: &Cow<'static, [String]>) -> Option<Location> {
4040
DEVICE_INFO
4141
.read()
4242
.unwrap()

src/fetchers/last_fm.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
use std::{
2-
collections::HashMap,
3-
sync::{LazyLock, RwLock},
4-
time::Duration,
5-
};
1+
use std::{borrow::Cow, collections::HashMap, sync::LazyLock, time::Duration};
62

7-
use chrono::{DateTime, SubsecRound, Utc};
8-
use futures::{FutureExt, TryFutureExt, future::join_all};
3+
use chrono::{DateTime, Local, SubsecRound, Utc};
4+
use futures::TryFutureExt;
95
use lastfm::{
106
artist::Artist,
117
imageset::ImageSet,
128
track::{NowPlayingTrack, Track},
139
};
1410
use reqwest::Response;
1511
use serde::{Deserialize, Serialize};
12+
use tokio::sync::Mutex;
13+
use tracing::debug;
1614
use ts_rs::TS;
1715

18-
use crate::config::Config;
16+
use crate::config::{Config, has_scope};
1917

2018
#[allow(unused)]
2119
#[derive(Clone, Serialize, TS)]
@@ -64,14 +62,23 @@ impl PartialEq<NowPlayingTrack> for TypescriptTrack {
6462
#[ts(rename = "LastFmUserInfo")]
6563
pub struct UserInfo {
6664
username: String,
65+
last_song_time: Option<DateTime<Local>>,
6766
currently_playing: Option<TypescriptTrack>,
6867
}
6968

70-
static PLAYING_TRACKS: LazyLock<RwLock<HashMap<String, UserInfo>>> =
71-
LazyLock::new(Default::default);
72-
73-
pub fn fetch_lastfm_info(username: &str) -> Option<UserInfo> {
74-
PLAYING_TRACKS.read().unwrap().get(username).cloned()
69+
static PLAYING_TRACKS: LazyLock<Mutex<HashMap<String, UserInfo>>> = LazyLock::new(Default::default);
70+
71+
pub fn fetch_lastfm_info(username: &str, auth_scopes: &Cow<'static, [String]>) -> Option<UserInfo> {
72+
PLAYING_TRACKS
73+
.blocking_lock()
74+
.get(username)
75+
.cloned()
76+
.map(|mut user| {
77+
user
78+
.last_song_time
79+
.take_if(|_| !has_scope(&auth_scopes, "lastfm.lasttime"));
80+
user
81+
})
7582
}
7683

7784
struct User {
@@ -83,7 +90,7 @@ pub async fn run(config: &'static Config) {
8390
return;
8491
};
8592

86-
*PLAYING_TRACKS.write().unwrap() = config
93+
*PLAYING_TRACKS.lock().await = config
8794
.users
8895
.values()
8996
.filter_map(|config| {
@@ -92,6 +99,7 @@ pub async fn run(config: &'static Config) {
9299
last_fm_username.to_owned(),
93100
UserInfo {
94101
username: last_fm_username,
102+
last_song_time: None,
95103
currently_playing: None,
96104
// currently_playing_recorded: None,
97105
},
@@ -112,20 +120,16 @@ pub async fn run(config: &'static Config) {
112120
.collect::<Vec<_>>();
113121

114122
let perform_update = async move || {
115-
join_all(
116-
users
117-
.iter()
118-
.map(|user| update_currently_listening(&user.username, &last_fm_key)),
119-
)
120-
.map(drop)
121-
.await;
123+
for user in &users {
124+
update_currently_listening(&user.username, &last_fm_key).await;
125+
}
122126
};
123127

124128
perform_update().await;
125129

126130
tokio::spawn(async move {
127131
loop {
128-
tokio::time::sleep(Duration::from_secs(10)).await;
132+
tokio::time::sleep(Duration::from_secs(15)).await;
129133
perform_update().await
130134
}
131135
});
@@ -152,11 +156,12 @@ pub async fn update_currently_listening(username: &str, api_key: &str) {
152156
Ok(response) => {
153157
let currently_playing = response.recent_tracks.track.into_iter().find_map(|track| {
154158
let Track::NowPlaying(now_playing) = track else {
159+
debug!("{username} is not listening to music");
155160
return None;
156161
};
157162
Some(now_playing)
158163
});
159-
let mut users = PLAYING_TRACKS.write().unwrap();
164+
let mut users = PLAYING_TRACKS.lock().await;
160165
if let Some(user) = users.get_mut(username) {
161166
user.currently_playing = currently_playing.map(|track| {
162167
let start_time = user
@@ -175,6 +180,7 @@ pub async fn update_currently_listening(username: &str, api_key: &str) {
175180
image: track.image,
176181
}
177182
});
183+
user.last_song_time = Some(Local::now());
178184
}
179185
}
180186
Err(error) => {

src/fetchers/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
pub mod discord;
2+
pub mod icloud;
23
pub mod last_fm;
34
pub mod steam;
4-
pub mod icloud;

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use routes::{
1212
get_host_user::get_host_user, get_user::get_user, get_users::get_users, root::root_page,
1313
};
1414
use tower::Layer;
15+
use tracing::debug;
1516

1617
#[tokio::main]
1718
async fn main() -> anyhow::Result<()> {
@@ -22,6 +23,8 @@ async fn main() -> anyhow::Result<()> {
2223
let config = read_to_string(config_arg).expect("failed to read config");
2324
let config = &*Box::leak(toml::from_str(&config).expect("failed to parse config"));
2425

26+
debug!("starting up fetchers");
27+
2528
fetchers::discord::run_discord_bot(&config).await?;
2629
fetchers::last_fm::run(&config).await;
2730
fetchers::steam::run(&config).await;

src/routes/get_host_user.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ use axum::{
33
extract::{Path, State},
44
response::Response,
55
};
6-
use axum_extra::{extract::Host, headers::{authorization::Bearer, Authorization}, TypedHeader};
6+
use axum_extra::{
7+
TypedHeader,
8+
extract::Host,
9+
headers::{Authorization, authorization::Bearer},
10+
};
711

812
use crate::host_config::HandlerConfig;
913

@@ -25,7 +29,7 @@ pub async fn get_host_user(
2529
.cloned()
2630
.unwrap_or_default(),
2731
),
28-
auth
32+
auth,
2933
)
3034
.await
3135
}

src/routes/get_user.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub async fn get_user(
4444
.icloud_device_id
4545
.as_ref()
4646
.map(String::as_str)
47-
.and_then(|id| icloud::get_user_info(id, auth_scopes));
47+
.and_then(|id| icloud::get_user_info(id, &auth_scopes));
4848

4949
Json(UserAggregate {
5050
name: &user.name,
@@ -59,7 +59,7 @@ pub async fn get_user(
5959
.last_fm_username
6060
.as_ref()
6161
.map(String::as_str)
62-
.and_then(last_fm::fetch_lastfm_info),
62+
.and_then(|username| last_fm::fetch_lastfm_info(username, &auth_scopes)),
6363
steam: user.steam_id.and_then(steam::get_user_info),
6464
location,
6565
})

0 commit comments

Comments
 (0)