91 lines
2.4 KiB
Rust
91 lines
2.4 KiB
Rust
use axum::{
|
|
extract::{Path, Query, State},
|
|
middleware,
|
|
routing::post,
|
|
Extension, Json, Router,
|
|
};
|
|
use serde::Deserialize;
|
|
|
|
use crate::server::{
|
|
error::{AppError, AppResult},
|
|
gpodder::{
|
|
auth_api_middleware,
|
|
format::{Format, StringWithFormat},
|
|
models::{SubscriptionDelta, SubscriptionDeltaResponse, UpdatedUrlsResponse},
|
|
},
|
|
Context,
|
|
};
|
|
|
|
pub fn router(ctx: Context) -> Router<Context> {
|
|
Router::new()
|
|
.route(
|
|
"/{username}/{id}",
|
|
post(post_subscription_changes).get(get_subscription_changes),
|
|
)
|
|
.layer(middleware::from_fn_with_state(ctx.clone(), auth_api_middleware))
|
|
}
|
|
|
|
pub async fn post_subscription_changes(
|
|
State(ctx): State<Context>,
|
|
Path((username, id)): Path<(String, StringWithFormat)>,
|
|
Extension(user): Extension<gpodder::User>,
|
|
Json(delta): Json<SubscriptionDelta>,
|
|
) -> AppResult<Json<UpdatedUrlsResponse>> {
|
|
if id.format != Format::Json {
|
|
return Err(AppError::NotFound);
|
|
}
|
|
|
|
if username != user.username {
|
|
return Err(AppError::BadRequest);
|
|
}
|
|
|
|
Ok(tokio::task::spawn_blocking(move || {
|
|
ctx.store
|
|
.update_subscriptions_for_device(&user, &id, delta.add, delta.remove)
|
|
})
|
|
.await
|
|
.unwrap()
|
|
.map(|time_changed| {
|
|
Json(UpdatedUrlsResponse {
|
|
timestamp: time_changed.timestamp(),
|
|
update_urls: Vec::new(),
|
|
})
|
|
})?)
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct SinceQuery {
|
|
#[serde(default)]
|
|
since: i64,
|
|
}
|
|
|
|
pub async fn get_subscription_changes(
|
|
State(ctx): State<Context>,
|
|
Path((username, id)): Path<(String, StringWithFormat)>,
|
|
Extension(user): Extension<gpodder::User>,
|
|
Query(query): Query<SinceQuery>,
|
|
) -> AppResult<Json<SubscriptionDeltaResponse>> {
|
|
if id.format != Format::Json {
|
|
return Err(AppError::NotFound);
|
|
}
|
|
|
|
if username != user.username {
|
|
return Err(AppError::BadRequest);
|
|
}
|
|
|
|
let since = chrono::DateTime::from_timestamp(query.since, 0).ok_or(AppError::BadRequest)?;
|
|
|
|
Ok(tokio::task::spawn_blocking(move || {
|
|
ctx.store.subscription_updates_for_device(&user, &id, since)
|
|
})
|
|
.await
|
|
.unwrap()
|
|
.map(|(next_time_changed, add, remove)| {
|
|
Json(SubscriptionDeltaResponse {
|
|
add: add.into_iter().map(|s| s.url).collect(),
|
|
remove: remove.into_iter().map(|s| s.url).collect(),
|
|
timestamp: next_time_changed.timestamp(),
|
|
})
|
|
})?)
|
|
}
|