Add interface package. Start adding auth stuff for refreshing tokens.
This commit is contained in:
@ -35,4 +35,4 @@ pub async fn update_playlists_daemon() -> Result<(), Box<dyn std::error::Error>>
|
||||
}
|
||||
}
|
||||
|
||||
async fn update_playlist(playlist: TrackedPlaylist) {}
|
||||
async fn update_playlist(_playlist: TrackedPlaylist) {}
|
||||
|
64
src/main.rs
64
src/main.rs
@ -2,17 +2,16 @@ mod daemon;
|
||||
mod listenbrainz;
|
||||
mod models;
|
||||
|
||||
use navidrome::{
|
||||
client::{builder::NavidromeBuilder, library::Library},
|
||||
models::navidrome::NavidromeTrack,
|
||||
};
|
||||
use navidrome::{client::builder::NavidromeBuilder, models::navidrome::NavidromeTrack};
|
||||
|
||||
use crate::daemon::{update_playlists_daemon, update_tracks_daemon};
|
||||
use crate::listenbrainz::StatsRange;
|
||||
use crate::models::{PartialTrackedPlaylist, TrackedPlaylist};
|
||||
use axum::extract::State;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use axum::routing::{get, put};
|
||||
use axum::{extract, Json, Router};
|
||||
use serde::Serialize;
|
||||
use sqlx::postgres::PgPool;
|
||||
use sqlx::Error;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::net::SocketAddr;
|
||||
@ -50,7 +49,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
let app = Router::new().route("/", get(index)).with_state(database);
|
||||
let app = Router::new()
|
||||
.route("/playlists", get(all_playlists))
|
||||
.route("/playlists", put(create_playlist))
|
||||
.with_state(database)
|
||||
.with_state(state);
|
||||
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||
axum::Server::bind(&addr)
|
||||
@ -60,15 +63,38 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn index(State(pool): State<PgPool>) -> String {
|
||||
let response = listenbrainz::recordings(env::var("LISTENBRAINZ_USER")?, StatsRange::Week)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
response
|
||||
.recordings
|
||||
.iter()
|
||||
.map(|a| a.track_name.clone())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
#[derive(Serialize)]
|
||||
struct JsonError {
|
||||
error: String,
|
||||
}
|
||||
|
||||
impl From<Error> for JsonError {
|
||||
fn from(value: Error) -> Self {
|
||||
Self {
|
||||
error: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum Response<T> {
|
||||
Success(T),
|
||||
Error(JsonError),
|
||||
}
|
||||
|
||||
async fn create_playlist(
|
||||
State(pool): State<PgPool>,
|
||||
extract::Json(partial): extract::Json<PartialTrackedPlaylist>,
|
||||
) -> Json<Response<TrackedPlaylist>> {
|
||||
match partial.record(&pool).await {
|
||||
Ok(playlist) => Json(Response::Success(playlist)),
|
||||
Err(e) => Json(Response::Error(e.into())),
|
||||
}
|
||||
}
|
||||
|
||||
async fn all_playlists(State(pool): State<PgPool>) -> Json<Vec<TrackedPlaylist>> {
|
||||
match TrackedPlaylist::all(&pool).await {
|
||||
Ok(playlists) => Json(playlists),
|
||||
Err(_) => Json(vec![]),
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,71 @@
|
||||
use sqlx::types::Uuid;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::error::Error;
|
||||
use sqlx::types::Uuid as UuidType;
|
||||
use sqlx::{Executor, Postgres};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct TrackedPlaylist {
|
||||
pub rule_id: i64,
|
||||
pub playlist_id: Option<Uuid>,
|
||||
#[derive(Deserialize)]
|
||||
pub struct PartialTrackedPlaylist {
|
||||
pub playlist_name: Option<String>,
|
||||
pub playlist_size: i32,
|
||||
pub tracking_user: Option<String>,
|
||||
pub tracking_type: Option<String>,
|
||||
pub reduce_duplication_on: Option<String>,
|
||||
}
|
||||
|
||||
impl PartialTrackedPlaylist {
|
||||
pub async fn record(
|
||||
&self,
|
||||
pool: impl Executor<'_, Database = Postgres> + Copy,
|
||||
) -> Result<TrackedPlaylist, Error> {
|
||||
let uuid = Uuid::new_v4();
|
||||
|
||||
sqlx::query!(
|
||||
r#"INSERT INTO "tracked_playlist"
|
||||
(rule_id, playlist_name, playlist_size, tracking_user, tracking_type, reduce_duplication_on)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)"#,
|
||||
uuid,
|
||||
self.playlist_name,
|
||||
self.playlist_size,
|
||||
self.tracking_user,
|
||||
self.tracking_type,
|
||||
self.reduce_duplication_on,
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
TrackedPlaylist::rule(pool, uuid).await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TrackedPlaylist {
|
||||
pub rule_id: Uuid,
|
||||
pub playlist_id: Option<UuidType>,
|
||||
pub playlist_name: Option<String>,
|
||||
pub playlist_size: i32,
|
||||
pub tracking_user: Option<String>,
|
||||
pub tracking_type: Option<String>,
|
||||
pub reduce_duplication_on: Option<String>,
|
||||
}
|
||||
|
||||
impl TrackedPlaylist {
|
||||
pub async fn all(pool: impl Executor<'_, Database = Postgres>) -> Result<Vec<Self>, Error> {
|
||||
sqlx::query_as!(Self, r#"SELECT * FROM "tracked_playlist""#)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn rule(
|
||||
pool: impl Executor<'_, Database = Postgres>,
|
||||
uuid: Uuid,
|
||||
) -> Result<Self, Error> {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
r#"SELECT * FROM "tracked_playlist" WHERE rule_id = $1"#,
|
||||
uuid
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user