138 lines
3.8 KiB
Rust
138 lines
3.8 KiB
Rust
use crate::{Db, SqlError, Timestamp, auth::BasicAuth};
|
|
use chrono::Utc;
|
|
use rocket::{
|
|
Route, get, post, put, routes,
|
|
serde::{Deserialize, Serialize, json::Json},
|
|
trace::debug,
|
|
};
|
|
use rocket_db_pools::Connection;
|
|
use sqlx::{Acquire, Execute};
|
|
|
|
#[put("/subscriptions/<_user>/<device>")]
|
|
pub fn set(_user: &str, device: &str, auth: BasicAuth) -> &'static str {
|
|
debug!("Attempting to set {}/{device}", auth.username());
|
|
""
|
|
}
|
|
|
|
#[get("/subscriptions/<_user>/<device>.opml")]
|
|
pub fn list_opml(_user: &str, device: &str, auth: BasicAuth) -> &'static str {
|
|
debug!("Attempting to list {}/{device}", auth.username());
|
|
""
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
pub struct Subscriptions {
|
|
add: Vec<String>,
|
|
remove: Vec<String>,
|
|
timestamp: i64,
|
|
}
|
|
|
|
#[get("/subscriptions/<_user>/<device>.json?<since>")]
|
|
pub async fn list_json(
|
|
_user: &str,
|
|
device: &str,
|
|
since: Option<i64>,
|
|
mut db: Connection<Db>,
|
|
auth: BasicAuth,
|
|
) -> Result<Json<Subscriptions>, SqlError> {
|
|
debug!(
|
|
"Attempting to list {}/{device}, since {since:?}",
|
|
auth.username()
|
|
);
|
|
let time = Utc::now().timestamp();
|
|
let username = auth.username();
|
|
let since = since.unwrap_or(0);
|
|
let results = sqlx::query!(
|
|
"SELECT * FROM subscriptions WHERE device = ? AND user = ? AND updated >= ?",
|
|
device,
|
|
username,
|
|
since,
|
|
)
|
|
.fetch_all(&mut **db)
|
|
.await?;
|
|
let mut res = Subscriptions {
|
|
add: vec![],
|
|
remove: vec![],
|
|
timestamp: time,
|
|
};
|
|
for record in results {
|
|
if record.current == 1 {
|
|
res.add.push(record.url);
|
|
} else if record.current == 0 {
|
|
res.remove.push(record.url);
|
|
} else {
|
|
debug!("Found current value of `{}`", record.current);
|
|
}
|
|
}
|
|
Ok(Json(res))
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
pub struct SubscriptionChanges {
|
|
add: Vec<String>,
|
|
remove: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
pub struct SubscriptionChangesResult {
|
|
pub update_urls: Vec<(String, String)>,
|
|
pub timestamp: i64,
|
|
}
|
|
|
|
#[post("/subscriptions/<_user>/<device>.json", data = "<updates>")]
|
|
pub async fn update_json(
|
|
_user: &str,
|
|
device: &str,
|
|
updates: Json<SubscriptionChanges>,
|
|
mut db: Connection<Db>,
|
|
auth: BasicAuth,
|
|
) -> Result<Json<SubscriptionChangesResult>, SqlError> {
|
|
let time = Utc::now().timestamp();
|
|
let updates = updates.into_inner();
|
|
debug!(
|
|
"Attempting to update {}/{device}, new: {:?}",
|
|
auth.username(),
|
|
updates
|
|
);
|
|
let mut trans = db.begin().await?;
|
|
for removed in &updates.remove {
|
|
sqlx::query("INSERT INTO subscriptions (url, device, user, current, updated) VALUES (?, ?, ?, ?, ?)")
|
|
.bind(removed)
|
|
.bind(device)
|
|
.bind(auth.username())
|
|
.bind(0)
|
|
.bind(time)
|
|
.execute(&mut *trans)
|
|
.await?;
|
|
}
|
|
for added in &updates.add {
|
|
sqlx::query("INSERT INTO subscriptions (url, device, user, current, updated) VALUES (?, ?, ?, ?, ?)")
|
|
.bind(added)
|
|
.bind(device)
|
|
.bind(auth.username())
|
|
.bind(1)
|
|
.bind(time)
|
|
.execute(&mut *trans)
|
|
.await?;
|
|
}
|
|
trans.commit().await?;
|
|
// sqlx::qu
|
|
Ok(Json(SubscriptionChangesResult {
|
|
update_urls: vec![],
|
|
timestamp: time,
|
|
}))
|
|
}
|
|
|
|
#[get("/subscriptions/<_user>.json")]
|
|
pub fn list_all_json(_user: &str, auth: BasicAuth) -> Json<Vec<String>> {
|
|
debug!("Attempting to list {}", auth.username());
|
|
Json(vec![])
|
|
}
|
|
|
|
pub fn routes() -> Vec<Route> {
|
|
routes![set, list_json, list_opml, list_all_json, update_json]
|
|
}
|