init
This commit is contained in:
commit
e8e8d9d960
7 changed files with 3217 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
/db
|
||||||
|
/itemdb
|
3048
Cargo.lock
generated
Normal file
3048
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "cdb"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4.4.1"
|
||||||
|
env_logger = "0.10.1"
|
||||||
|
log = "0.4.20"
|
||||||
|
maud = "0.25.0"
|
||||||
|
mdq = { git = "https://git.hydrar.de/mdtools/mdq", version = "0.1.0" }
|
||||||
|
mongodb = "2.8.0"
|
||||||
|
serde = { version = "1.0.195", features = ["derive"] }
|
||||||
|
serde_json = "1.0.111"
|
||||||
|
tokio = { version = "1.35.1", features = ["full"] }
|
||||||
|
toml = "0.8.8"
|
||||||
|
web-base = "0.2.2"
|
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM rust as build
|
||||||
|
WORKDIR /build
|
||||||
|
COPY ./Cargo.toml /build/Cargo.toml
|
||||||
|
COPY ./Cargo.lock /build/Cargo.lock
|
||||||
|
COPY ./src /build/src
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
FROM rust
|
||||||
|
COPY --from=build /build/target/release/cdb /cdb
|
||||||
|
|
||||||
|
ENV RUST_LOG=debug
|
||||||
|
CMD ["/cdb"]
|
21
docker-compose.yml
Normal file
21
docker-compose.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
cdb:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- mongodb
|
||||||
|
volumes:
|
||||||
|
- ./itemdb:/itemdb
|
||||||
|
|
||||||
|
mongodb:
|
||||||
|
image: mongo:latest
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: user
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: pass
|
||||||
|
volumes:
|
||||||
|
- ./db:/data/db
|
||||||
|
|
50
src/item.rs
Normal file
50
src/item.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use mongodb::{Collection, bson::doc};
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct ItemEntry {
|
||||||
|
pub name: String,
|
||||||
|
pub category: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemEntry {
|
||||||
|
pub fn new(doc: mdq::Document) -> Self {
|
||||||
|
let name = std::path::Path::new(&doc.path).file_stem().unwrap().to_str().unwrap().to_string();
|
||||||
|
let category = doc.frontmatter.as_mapping().unwrap().get("category").unwrap().as_str().unwrap().to_string();
|
||||||
|
Self { name, category }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ItemDB {
|
||||||
|
index: mdq::Index,
|
||||||
|
mongodb: mongodb::Client
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemDB {
|
||||||
|
pub async fn new(dir: &str, mongodb: &str) -> Self {
|
||||||
|
// scan for markdown item entries
|
||||||
|
let index = mdq::Index::new(dir, true);
|
||||||
|
let mongodb = mongodb::Client::with_uri_str(mongodb).await.unwrap();
|
||||||
|
|
||||||
|
for item in &index.documents {
|
||||||
|
let item = ItemEntry::new(item.clone());
|
||||||
|
log::info!("Adding item {} to DB", item.name);
|
||||||
|
let items: Collection<ItemEntry> = mongodb.database("cdb").collection("items");
|
||||||
|
items.insert_one(item, None).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { index, mongodb }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_item(&self, item: &str) -> Option<ItemEntry> {
|
||||||
|
self.index.documents.iter().map(|x| ItemEntry::new(x.clone())).find(|x| x.name == item)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items(&self) -> Vec<String> {
|
||||||
|
let mut ret = vec![];
|
||||||
|
for item in &self.index.documents {
|
||||||
|
let item = ItemEntry::new(item.clone());
|
||||||
|
ret.push(item.name);
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
66
src/main.rs
Normal file
66
src/main.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use actix_web::{get, HttpRequest, Responder};
|
||||||
|
use maud::html;
|
||||||
|
mod item;
|
||||||
|
|
||||||
|
// ░░░░░░░░░░▀▀▀██████▄▄▄░░░░░░░░░░
|
||||||
|
// ░░░░░░░░░░░░░░░░░▀▀▀████▄░░░░░░░
|
||||||
|
// ░░░░░░░░░░▄███████▀░░░▀███▄░░░░░
|
||||||
|
// ░░░░░░░░▄███████▀░░░░░░░▀███▄░░░
|
||||||
|
// ░░░░░░▄████████░░░░░░░░░░░███▄░░
|
||||||
|
// ░░░░░██████████▄░░░░░░░░░░░███▌░ ▒█▀▀█ █▀▀█ █▀▄▀█ █▀▄▀█ ▒█▀▀▄ ▒█▀▀█
|
||||||
|
// ░░░░░▀█████▀░▀███▄░░░░░░░░░▐███░ ▒█░░░ █░░█ █░▀░█ █░▀░█ ▒█░▒█ ▒█▀▀▄
|
||||||
|
// ░░░░░░░▀█▀░░░░░▀███▄░░░░░░░▐███░ ▒█▄▄█ ▀▀▀▀ ▀░░░▀ ▀░░░▀ ▒█▄▄▀ ▒█▄▄█
|
||||||
|
// ░░░░░░░░░░░░░░░░░▀███▄░░░░░███▌░
|
||||||
|
// ░░░░▄██▄░░░░░░░░░░░▀███▄░░▐███░░
|
||||||
|
// ░░▄██████▄░░░░░░░░░░░▀███▄███░░░
|
||||||
|
// ░█████▀▀████▄▄░░░░░░░░▄█████░░░░
|
||||||
|
// ░████▀░░░▀▀█████▄▄▄▄█████████▄░░
|
||||||
|
// ░░▀▀░░░░░░░░░▀▀██████▀▀░░░▀▀██░░
|
||||||
|
|
||||||
|
#[get("/item/{item_id}")]
|
||||||
|
pub async fn item_page(r: HttpRequest) -> impl Responder {
|
||||||
|
let id = r.match_info().query("item_id");
|
||||||
|
println!("{}", id);
|
||||||
|
|
||||||
|
let itemdb: &actix_web::web::Data<item::ItemDB> = r.app_data().unwrap();
|
||||||
|
|
||||||
|
let item = itemdb.get_item(id).unwrap();
|
||||||
|
|
||||||
|
let content = html!(
|
||||||
|
p { "Item" };
|
||||||
|
p { (format!("Category: {}", item.category))}
|
||||||
|
).into_string();
|
||||||
|
|
||||||
|
web_base::build_site(&r, "Item", &content)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub(crate) async fn index(r: HttpRequest) -> impl Responder {
|
||||||
|
let itemdb: &actix_web::web::Data<item::ItemDB> = r.app_data().unwrap();
|
||||||
|
|
||||||
|
let content = html!(
|
||||||
|
p class="text-xl font-bold" { "Hello World" };
|
||||||
|
@for item in itemdb.items() {
|
||||||
|
a href=(format!("/item/{}", item)) { (item) };
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.into_string();
|
||||||
|
web_base::func::build_site(&r, "Index", &content)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
let itemdb = item::ItemDB::new("./itemdb", "mongodb://user:pass@mongodb:27017").await;
|
||||||
|
let itemdb = actix_web::web::Data::new(itemdb);
|
||||||
|
|
||||||
|
web_base::map!(
|
||||||
|
web_base::Site::new()
|
||||||
|
.head_content("<script src=\"https://cdn.tailwindcss.com\"></script>".to_string()),
|
||||||
|
|app: actix_web::App<_>| { app.app_data(itemdb.clone()).service(index).service(item_page) }
|
||||||
|
)
|
||||||
|
.bind(("0.0.0.0".to_string(), 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
Loading…
Reference in a new issue