/* * asklyphe-frontend routes/announcement.rs * - http routes for announcements * * Copyright (C) 2025 Real Microsoft, LLC * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use std::sync::Arc; use askama::Template; use asklyphe_common::nats::authservice::{AuthServiceQuery, AuthServiceRequest, AuthServiceResponse}; use asklyphe_common::nats::authservice::announcements::{AnnouncementFullRequest, AnnouncementFullResponse, LatestAnnouncementRequest, LatestAnnouncementResponse}; use asklyphe_common::nats::comms; use asklyphe_common::nats::comms::ServiceResponse; use async_nats::jetstream; use axum::Extension; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use serde::Serialize; use tracing::{debug, error}; use tracing::log::warn; use crate::{Opts, ALPHA, BUILT_ON, GIT_COMMIT, VERSION, YEAR}; use crate::routes::index::FrontpageAnnouncement; #[derive(Serialize, Debug)] struct FullAnnouncement { title: String, date: String, creator: String, full: String } async fn announcement(nats: Arc, slug: String) -> Option { let response = comms::query_service( comms::Query::AuthService(AuthServiceQuery { request: AuthServiceRequest::AnnouncementFullRequest(AnnouncementFullRequest { slug }), replyto: "".to_string(), }), &nats, false, ).await; if let Err(e) = response { error!("nats error: {:?}", e); None } else { let response = response.unwrap(); match response { ServiceResponse::SearchService(_) => { error!("sent search service response when asking for auth service!! investigate ASAP!!!"); None } ServiceResponse::BingService(_) => { error!("sent bing service response when asking for auth service!! investigate ASAP!!!"); None } ServiceResponse::AuthService(r) => match r { AuthServiceResponse::AnnouncementFullResponse(v) => { match v { AnnouncementFullResponse::Some(v) => { Some(FullAnnouncement { title: v.title, date: chrono::DateTime::from_timestamp(v.created_on, 0).unwrap().to_rfc2822(), creator: v.creator, full: v.markdown_text.replace("\n", "
"), }) } AnnouncementFullResponse::NotFound => { None } AnnouncementFullResponse::InternalServerError(e) => { warn!("internal server error while getting announcement: {}", e); None } } } x => { error!("auth service gave {} to our user info request!", x); None } }, } } } #[derive(Template)] #[template(path = "announcement.html")] pub struct AnnouncementTemplate { version: String, git_commit: String, built_on: String, year: String, alpha: bool, theme: String, announcement: FullAnnouncement, } pub async fn announcement_full(Extension(nats): Extension>, Extension(opts): Extension, Path(slug): Path) -> impl IntoResponse { debug!("looking up {slug}"); if let Some(announcement) = announcement(nats.clone(), slug.clone()).await { AnnouncementTemplate { version: VERSION.to_string(), git_commit: GIT_COMMIT.to_string(), built_on: BUILT_ON.to_string(), year: YEAR.to_string(), alpha: ALPHA, theme: "default".to_string(), announcement, }.into_response() } else { StatusCode::NOT_FOUND.into_response() } }