A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at feat/pgpull 104 lines 3.4 kB view raw
1pub mod auth; 2pub mod cache; 3pub mod crypto; 4pub mod handlers; 5pub mod listenbrainz; 6pub mod musicbrainz; 7pub mod params; 8pub mod repo; 9pub mod response; 10pub mod rocksky; 11pub mod scrobbler; 12pub mod signature; 13pub mod spotify; 14pub mod types; 15pub mod xata; 16 17use std::{env, sync::Arc, time::Duration}; 18 19use actix_limitation::{Limiter, RateLimiter}; 20use actix_session::SessionExt; 21use actix_web::{ 22 dev::ServiceRequest, 23 web::{self, Data}, 24 App, HttpServer, 25}; 26use anyhow::Error; 27use owo_colors::OwoColorize; 28use sqlx::postgres::PgPoolOptions; 29 30use crate::{cache::Cache, musicbrainz::client::MusicbrainzClient}; 31 32pub const BANNER: &str = r#" 33 ___ ___ _____ __ __ __ 34 / | __ ______/ (_)___ / ___/______________ / /_ / /_ / /__ _____ 35 / /| |/ / / / __ / / __ \ \__ \/ ___/ ___/ __ \/ __ \/ __ \/ / _ \/ ___/ 36 / ___ / /_/ / /_/ / / /_/ / ___/ / /__/ / / /_/ / /_/ / /_/ / / __/ / 37/_/ |_\__,_/\__,_/_/\____/ /____/\___/_/ \____/_.___/_.___/_/\___/_/ 38 39 This is the Rocksky Scrobbler API compatible with Last.fm AudioScrobbler API 40"#; 41 42pub async fn run() -> Result<(), Error> { 43 println!("{}", BANNER.magenta()); 44 45 let cache = Cache::new()?; 46 47 let pool = PgPoolOptions::new() 48 .max_connections(5) 49 .connect(&env::var("XATA_POSTGRES_URL")?) 50 .await?; 51 let conn = Arc::new(pool); 52 53 let host = env::var("SCROBBLE_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); 54 let port = env::var("SCROBBLE_PORT") 55 .unwrap_or_else(|_| "7882".to_string()) 56 .parse::<u16>() 57 .unwrap_or(7882); 58 59 tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting Scrobble server @"); 60 61 let limiter = web::Data::new( 62 Limiter::builder("redis://127.0.0.1") 63 .key_by(|req: &ServiceRequest| { 64 req.get_session() 65 .get(&"session-id") 66 .unwrap_or_else(|_| req.cookie(&"rate-api-id").map(|c| c.to_string())) 67 }) 68 .limit(100) 69 .period(Duration::from_secs(60)) // 60 minutes 70 .build() 71 .unwrap(), 72 ); 73 74 let mb_client = MusicbrainzClient::new().await?; 75 let mb_client = Arc::new(mb_client); 76 77 HttpServer::new(move || { 78 App::new() 79 .wrap(RateLimiter::default()) 80 .app_data(limiter.clone()) 81 .app_data(Data::new(conn.clone())) 82 .app_data(Data::new(cache.clone())) 83 .app_data(Data::new(mb_client.clone())) 84 .service(handlers::handle_methods) 85 .service(handlers::handle_nowplaying) 86 .service(handlers::handle_submission) 87 .service(listenbrainz::handlers::handle_submit_listens) 88 .service(listenbrainz::handlers::handle_validate_token) 89 .service(listenbrainz::handlers::handle_search_users) 90 .service(listenbrainz::handlers::handle_get_playing_now) 91 .service(listenbrainz::handlers::handle_get_listens) 92 .service(listenbrainz::handlers::handle_get_listen_count) 93 .service(listenbrainz::handlers::handle_get_artists) 94 .service(listenbrainz::handlers::handle_get_recordings) 95 .service(listenbrainz::handlers::handle_get_release_groups) 96 .service(handlers::index) 97 .service(handlers::handle_get) 98 }) 99 .bind((host, port))? 100 .run() 101 .await?; 102 103 Ok(()) 104}