feat(blogs): just need to convert into a docker container, once that it is confirmed to work with the front end

This commit is contained in:
2025-05-15 17:48:55 -06:00
parent 9d678776a5
commit 0589f9cb2a
7 changed files with 404 additions and 29 deletions

View File

@ -1,11 +1,10 @@
use actix_web::{HttpRequest, HttpResponse, Responder, get, web};
// use actix_web::{HttpResponse, post};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::fs;
use std::{fs, path::Path};
use time::{OffsetDateTime, format_description::well_known::Iso8601};
pub fn log_incoming(req: HttpRequest, method: &str, path_source: &str) {
pub fn log_incoming(req: HttpRequest, method: &'static str, path_source: &str) {
let peer_addr = req.peer_addr();
if let Some(ip_addr_other) = peer_addr {
println!(
@ -113,31 +112,95 @@ pub async fn project(limit: web::Path<usize>, req: HttpRequest) -> impl Responde
web::Json(res_vec)
}
// a successful version of a webhook
// now the more idiomatic way of sending a json
// #[get("/test_reqwest")]
// pub async fn test_reqwest(req: HttpRequest) -> impl Responder {
// log_incoming(req, "GET", "/test_reqwest");
// let json_to_send = serde_json::json!({
// "content": "Hey, from Rust, welcome to <:discohook:736648398081622016> **Discohook**! The easiest way to personalise your Discord server.\n\nThere's more info below, but you don't have to read it. If you're ready press **Clear All** in the top of the editor to get started.\n\nDiscohook has a [support server](https://discohook.app/discord), if you need help feel free to join in and ask questions, suggest features, or just chat with the community.\n\nWe also have [complementary bot](https://discohook.app/bot) that may help out, featuring reaction roles and other utilities.\n_ _"
// });
// {how_many} how_many: {} how_many,
#[get("/blog/{blog_name}")]
pub async fn get_blog(
blog_name: web::Path<String>,
// how_many: web::Path<i32>,
req: HttpRequest,
) -> impl Responder {
log_incoming(req, "GET", "/blogs/blog/{blog_name}");
let blog = fs::read_to_string(format!("./data_txt/{blog_name}.md")).unwrap_or("".to_string());
let html_blog = comrak::markdown_to_html(&blog, &comrak::Options::default());
HttpResponse::Ok().body(html_blog)
}
// // let json_to_send = serde_json::to_string(&json_to_send).unwrap();
#[derive(Deserialize, Serialize, Debug)]
struct BlogPreview {
pub blog_file_name: String,
pub date_last_edit: String,
pub html_preview: String,
}
// let client = Client::new();
// let res = client
// .post("https://discord.com/api/webhooks/1369370183541461072/tuO93OJvdUsDzbHMBwHtQex11ijpfYLZMOvMov84eUPH5or3ziU03aOUmTZkfuibdhUp")
// // .header("Content-Type", "application/json")
// .json(&json_to_send)
// .send()
// .await;
// match res {
// Ok(response) => println!("Success: {:#?}", response),
// Err(e) => eprintln!("Error sending request: {}", e),
// }
// HttpResponse::Ok().body("Hello there!\nGeneral Kenobi")
// }
#[get("/{num_limit}/{page_num}")]
pub async fn get_blogs_preview(props: web::Path<(u8, u32)>, req: HttpRequest) -> impl Responder {
log_incoming(req, "GET", "blogs/{num_limit}/{page_num}");
let (num_limit, page_num) = props.into_inner();
let mut available_blogs: Vec<String> = Vec::new();
let dir = Path::new("./data_txt/blogs");
if dir.is_dir() {
for entry in fs::read_dir(dir).unwrap() {
let entry = entry
.unwrap()
.file_name()
.into_string()
.unwrap_or("".to_string());
let _ = &available_blogs.push(entry);
}
}
let start: usize = page_num as usize * num_limit as usize;
let end: usize = start + num_limit as usize;
if start >= available_blogs.len().try_into().unwrap_or(0) {
return web::Json(serde_json::json!("Blogs: []"));
}
let end = end.min(available_blogs.len());
let blogs_to_get = &available_blogs[start..end];
let mut blogs_preview: Vec<BlogPreview> = Vec::new();
for blog_info in blogs_to_get {
let path = dir.join(blog_info);
let date_last_edit = get_date_modified(&path).unwrap();
let blog = fs::read_to_string(&path).unwrap_or("".to_string());
let raw_blog = blog
.lines()
.filter(|line| !line.trim().is_empty())
.take(3)
.collect::<Vec<_>>()
.join("\n");
let html_blog = comrak::markdown_to_html(&raw_blog, &comrak::Options::default());
blogs_preview.push(BlogPreview {
blog_file_name: blog_info.to_string(),
date_last_edit: date_last_edit,
html_preview: html_blog,
});
}
// println!("{:?}", blogs_preview);
// web::Json(serde_json::json!(
// { "Hello there!": "General Kenobi", "Available in dir": format!("{:?}",blogs_to_get) }
// ))
web::Json(serde_json::json!({ "Blogs": blogs_preview }))
}
fn get_date_modified(path: &Path) -> Option<String> {
let metadata = fs::metadata(path).ok()?;
let system_time = metadata.modified().ok()?;
let offset_time = OffsetDateTime::from(system_time);
// Format just the date part of ISO 8601 (e.g. "2025-05-15")
let iso_string = offset_time.format(&Iso8601::DEFAULT).ok()?;
let date_only = iso_string.split('T').next()?.to_string();
Some(date_only)
}
// #[cfg(test)]
// mod tests {
// use super::*;

View File

@ -1,21 +1,37 @@
use actix_cors::Cors;
use actix_web::{App, HttpServer, web};
use darkicewolf50_cloud::{hello, project, skills_home, test_reqwest};
use darkicewolf50_cloud::{get_blog, get_blogs_preview, hello, project, skills_home};
// use darkicewolf50_cloud:: {echo, manual_hello, resend,};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Running on port 8000");
HttpServer::new(|| {
App::new()
.wrap(
Cors::default()
// Allow any origin — or use `.allowed_origin("http://localhost:8080")` to restrict
.allow_any_origin()
// Allow common methods
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"])
// Allow any headers
.allow_any_header(), // Optionally enable sending cookies, etc.
//.supports_credentials()
)
.service(hello)
// .service(echo)
// .service(resend)
// .route("/hey", web::get().to(manual_hello))
.service(project)
.service(test_reqwest)
.service(
web::scope("/blogs")
.service(get_blog)
.service(get_blogs_preview),
)
.service(web::scope("/home").service(skills_home))
})
.bind(("127.0.0.1", 8080))?
.bind(("127.0.0.1", 8000))?
.run()
.await
}