From 2d42e933c8d752f1844408bf1dfaf6643281993c Mon Sep 17 00:00:00 2001 From: Lumither Tao Date: Fri, 3 May 2024 02:17:11 +0800 Subject: [PATCH] feat(api) add refresh.rs --- backend/post.sql | 7 ++ backend/src/api/{ => get}/get_post.rs | 0 backend/src/api/{ => get}/get_post_list.rs | 0 backend/src/api/get/mod.rs | 2 + backend/src/api/mod.rs | 4 +- backend/src/api/post/mod.rs | 1 + backend/src/api/post/refresh.rs | 88 ++++++++++++++++++++++ backend/src/main.rs | 8 +- backend/src/model/mod.rs | 10 ++- backend/src/model/post.rs | 16 ++++ 10 files changed, 127 insertions(+), 9 deletions(-) rename backend/src/api/{ => get}/get_post.rs (100%) rename backend/src/api/{ => get}/get_post_list.rs (100%) create mode 100644 backend/src/api/get/mod.rs create mode 100644 backend/src/api/post/mod.rs create mode 100644 backend/src/api/post/refresh.rs create mode 100644 backend/src/model/post.rs diff --git a/backend/post.sql b/backend/post.sql index 5b874d1..fea0912 100644 --- a/backend/post.sql +++ b/backend/post.sql @@ -5,3 +5,10 @@ CREATE TABLE IF NOT EXISTS Post content TEXT NOT NULL, last_update TIMESTAMP ); + +INSERT INTO Post (post_id, title, content, last_update) +VALUES (?1, ?2, ?3, ?4) +ON CONFLICT (post_id) + DO UPDATE SET title = excluded.title, + content = excluded.content, + last_update = excluded.last_update diff --git a/backend/src/api/get_post.rs b/backend/src/api/get/get_post.rs similarity index 100% rename from backend/src/api/get_post.rs rename to backend/src/api/get/get_post.rs diff --git a/backend/src/api/get_post_list.rs b/backend/src/api/get/get_post_list.rs similarity index 100% rename from backend/src/api/get_post_list.rs rename to backend/src/api/get/get_post_list.rs diff --git a/backend/src/api/get/mod.rs b/backend/src/api/get/mod.rs new file mode 100644 index 0000000..44008d0 --- /dev/null +++ b/backend/src/api/get/mod.rs @@ -0,0 +1,2 @@ +pub mod get_post; +pub mod get_post_list; \ No newline at end of file diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs index a30b1d7..69e599d 100644 --- a/backend/src/api/mod.rs +++ b/backend/src/api/mod.rs @@ -1,2 +1,2 @@ -pub mod get_post; -pub mod get_post_list; +pub mod get; +pub mod post; diff --git a/backend/src/api/post/mod.rs b/backend/src/api/post/mod.rs new file mode 100644 index 0000000..1d2e0f5 --- /dev/null +++ b/backend/src/api/post/mod.rs @@ -0,0 +1 @@ +pub mod refresh; diff --git a/backend/src/api/post/refresh.rs b/backend/src/api/post/refresh.rs new file mode 100644 index 0000000..e322ff9 --- /dev/null +++ b/backend/src/api/post/refresh.rs @@ -0,0 +1,88 @@ +use std::env; +use std::path::Path; + +use axum::extract::State; +use axum::http::StatusCode; +use axum::Json; +use serde_json::{json, Value}; +use sqlx::{PgPool, query}; + +use crate::model::Post; + +pub async fn refresh( + State(db_connection): State, +) -> Result)> { + let data_repo_dir = match env::var("GIT_WORK_DIR") { + Ok(value) => value, + Err(_) => { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + Json::from(json!(format!( + "{{error: {}}}", + "error at parsing environment variable: GIT_WORK_DIR" + ))), + )); + } + }; + + let md_list = search_md(Path::new(&data_repo_dir)); + + let post_list: Vec = md_list + .into_iter() + .map(Post::from_path) + .collect(); + + for post in post_list { + match query( + r##" +INSERT INTO Post (post_id, title, content, last_update) +VALUES ($1, $2, $3, $4) +ON CONFLICT (post_id) + DO UPDATE SET title = excluded.title, + content = excluded.content, + last_update = excluded.last_update + "##, + ) + .bind(post.post_id) + .bind(post.title) + .bind(post.content) + .bind(post.last_update) + .execute(&db_connection) + .await + { + Ok(_) => { + dbg!("inserted"); + } + Err(e) => { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + Json::from(json!(format!("{{error: {}}}", e.to_string()))), + )); + } + } + } + + Ok(StatusCode::OK) +} + +fn search_md(entry: &Path) -> Vec { + if entry.ends_with(".git") { + return vec![]; + } + if entry.is_dir() { + if let Ok(files) = entry.read_dir() { + files + .flat_map(|file| { + let file_path = file.unwrap().path(); + search_md(file_path.as_path()) + }) + .collect() + } else { + vec![] + } + } else if entry.extension().is_some_and(|ext| ext == "md") { + vec![entry.to_str().unwrap().to_string()] + } else { + vec![] + } +} diff --git a/backend/src/main.rs b/backend/src/main.rs index 3127a2e..a13378b 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -2,12 +2,13 @@ use std::env; use std::error::Error; use axum::Router; -use axum::routing::get; +use axum::routing::{get, post}; use dotenv::dotenv; use sqlx::postgres::PgPoolOptions; -use crate::api::get_post::get_post; -use crate::api::get_post_list::get_post_list; +use crate::api::get::get_post::get_post; +use crate::api::get::get_post_list::get_post_list; +use crate::api::post::refresh::refresh; mod api; mod model; @@ -29,6 +30,7 @@ async fn main() -> Result<(), Box> { .expect("failed to load database"); let app = Router::new() + .route("/api/post/refresh", post(refresh)) .route("/api/get/post_list", get(get_post_list)) .route("/api/get/post/:post_id", get(get_post)) .with_state(db_pool); diff --git a/backend/src/model/mod.rs b/backend/src/model/mod.rs index 8d05202..94f60d1 100644 --- a/backend/src/model/mod.rs +++ b/backend/src/model/mod.rs @@ -3,10 +3,12 @@ use serde::{Deserialize, Serialize}; use sqlx::FromRow; use uuid::Uuid; +pub mod post; + #[derive(Debug, Serialize, Deserialize, FromRow)] pub struct Post { - post_id: Uuid, - title: String, - content: String, - last_update: NaiveDateTime, + pub post_id: Uuid, + pub title: String, + pub content: String, + pub last_update: NaiveDateTime, } diff --git a/backend/src/model/post.rs b/backend/src/model/post.rs new file mode 100644 index 0000000..d50b84c --- /dev/null +++ b/backend/src/model/post.rs @@ -0,0 +1,16 @@ +use chrono::Utc; +use uuid::Uuid; + +use crate::model::Post; + +impl super::Post { + pub fn from_path(path: String) -> Self { + // todo: remove test + Post { + post_id: Uuid::new_v4(), + title: "test title".to_string(), + content: "test content".to_string(), + last_update: Utc::now().naive_utc(), + } + } +}