use actix_web::{web, HttpResponse};
use crate::pages::templates::ATOM_GAMES;
use crate::{DataBaseRo, WebData};
#[derive(serde_derive::Serialize)]
struct FeedData {
upddatetime: String,
entries: Vec<EntriesData>,
selflink: String,
}
#[derive(serde_derive::Serialize)]
struct EntriesData {
gameuid: String,
gameuidenc: String,
start_ts: i64,
create_ts_str: String,
fo_forum_url: String,
notes_summ: String,
notes: String,
}
#[actix_web::get("/atoms/new-games.xml")]
pub async fn atom_games(
data: web::Data<WebData<'_>>,
data_ro: web::Data<DataBaseRo>,
) -> HttpResponse {
let dbclient = match data_ro.0.get().await {
Ok(client) => client,
Err(e) => {
log::error!("{}", e);
return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
}
};
let stmt = match dbclient.prepare("select g.game_uid, g.start_ts, g.fo_forum_url, g.create_ts, g.notes_html from games.games g where g.create_ts IS NOT NULL and g.fo_forum_url IS NOT NULL AND g.notes_html IS NOT NULL order by g.create_ts desc limit 50;").await {
Ok(stmt) => stmt,
Err(e) => {
log::error!("{}", e);
return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
}
};
let rows = match dbclient.query(&stmt, &[]).await {
Ok(rows) => rows,
Err(e) => {
log::error!("{}", e);
return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
}
};
let mut upd_date_time = None;
let mut entries = Vec::with_capacity(rows.len());
for row in rows {
let gameuid = row.get::<_, &str>(0);
use chrono::TimeZone;
let start_ts =
chrono::Utc::from_utc_datetime(&chrono::Utc, &row.get::<_, chrono::NaiveDateTime>(1));
let fo_forum_url = row
.get::<_, &str>(2)
.replace('&', "&")
.replace('<', "<");
let create_ts =
chrono::Utc::from_utc_datetime(&chrono::Utc, &row.get::<_, chrono::NaiveDateTime>(3));
let notes = row.get::<_, String>(4);
use base64::Engine;
use sha2::Digest;
let mut hasher = sha2::Sha224::new();
hasher.update(notes.as_bytes());
let notes_summ = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(hasher.finalize());
entries.insert(
0,
EntriesData {
gameuid: gameuid.to_string(),
gameuidenc: pct_str::PctString::encode(gameuid.chars(), pct_str::URIReserved)
.into_string(),
start_ts: start_ts.timestamp(),
create_ts_str: create_ts.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
fo_forum_url: fo_forum_url.to_string(),
notes,
notes_summ,
},
);
upd_date_time.get_or_insert(create_ts);
}
let upd_date_time = upd_date_time.unwrap_or_else(chrono::Utc::now);
let body = match data.handlebars_xml.render(
ATOM_GAMES,
&FeedData {
entries,
upddatetime: upd_date_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
selflink: format!("{}://{}/", data.base_proto, data.base_domain),
},
) {
Ok(b) => b,
Err(e) => {
log::error!("{}", e);
return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
}
};
HttpResponse::Ok()
.insert_header(("Content-Type", "application/atom+xml"))
.insert_header((
"Date",
upd_date_time
.format("%a, %d %b %Y %H:%M:%S GMT")
.to_string(),
))
.body(body)
}