A decentralized music tracking and discovery platform built on AT Protocol 馃幍
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
1use std::{env, sync::Arc, time::Duration};
2
3use actix_limitation::{Limiter, RateLimiter};
4use actix_session::SessionExt;
5use actix_web::{
6 dev::ServiceRequest,
7 web::{self, Data},
8 App, HttpServer,
9};
10use anyhow::Error;
11use owo_colors::OwoColorize;
12use sqlx::postgres::PgPoolOptions;
13
14use crate::{cache::Cache, consts::BANNER, musicbrainz::client::MusicbrainzClient};
15
16pub mod auth;
17pub mod cache;
18pub mod consts;
19pub mod crypto;
20pub mod handlers;
21pub mod musicbrainz;
22pub mod repo;
23pub mod rocksky;
24pub mod scrobbler;
25pub mod spotify;
26pub mod types;
27pub mod xata;
28
29pub async fn start_server() -> Result<(), Error> {
30 println!("{}", BANNER.magenta());
31
32 let cache = Cache::new()?;
33
34 let pool = PgPoolOptions::new()
35 .max_connections(5)
36 .connect(&env::var("XATA_POSTGRES_URL")?)
37 .await?;
38
39 let conn = Arc::new(pool);
40
41 let mb_client = MusicbrainzClient::new().await?;
42 let mb_client = Arc::new(mb_client);
43
44 let host = env::var("WEBSCROBBLER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
45 let port = env::var("WEBSCROBBLER_PORT")
46 .unwrap_or_else(|_| "7883".to_string())
47 .parse::<u16>()
48 .unwrap_or(7883);
49
50 tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting WebScrobbler server @");
51
52 let limiter = web::Data::new(
53 Limiter::builder("redis://127.0.0.1")
54 .key_by(|req: &ServiceRequest| {
55 req.get_session()
56 .get(&"session-id")
57 .unwrap_or_else(|_| req.cookie(&"rate-api-id").map(|c| c.to_string()))
58 })
59 .limit(100)
60 .period(Duration::from_secs(60)) // 60 minutes
61 .build()
62 .unwrap(),
63 );
64
65 HttpServer::new(move || {
66 App::new()
67 .wrap(RateLimiter::default())
68 .app_data(limiter.clone())
69 .app_data(Data::new(conn.clone()))
70 .app_data(Data::new(cache.clone()))
71 .app_data(Data::new(mb_client.clone()))
72 .service(handlers::index)
73 .service(handlers::handle_scrobble)
74 })
75 .bind((host, port))?
76 .run()
77 .await?;
78 Ok(())
79}