aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/projects/index.md46
-rw-r--r--src/assets.rs11
-rw-r--r--src/bin/actix.rs12
-rw-r--r--src/bin/hyper.rs36
-rw-r--r--src/blog.rs21
-rw-r--r--src/router.rs9
-rw-r--r--templates/header.html1
-rw-r--r--templates/projects.html12
-rw-r--r--tests/test_router.rs15
-rwxr-xr-xwatch5
10 files changed, 149 insertions, 19 deletions
diff --git a/content/projects/index.md b/content/projects/index.md
new file mode 100644
index 0000000..2ae7015
--- /dev/null
+++ b/content/projects/index.md
@@ -0,0 +1,46 @@
+Just a list of some projects I have done and find useful on my day-to-day life.
+
+- [Hub Watcher](https://hub-watcher.gabrielgio.me/)
+ [[gitlab](https://gitlab.com/gabrielgio/hub-watcher)]
+
+ A small project to monitor changes in a docker image from [docker
+ hub](https://hub.docker.com/). By default every 5 minutes it will fetch the
+ digest of image and compare with the previous returned digest, if they are
+ different it will make a post request to a given url.
+
+ I created it so I can automatically trigger my gitlab pipeline to build my
+ custom nextcloud image everytime Nextcloud GmbH updates their image.
+
+- [Reddit to Nextcloud
+ importer](https://gabrielgio.gitlab.io/reddit-nextcloud-importer/)
+ [[github](https://gitlab.com/gabrielgio/reddit-nextcloud-importer)]
+
+ A small project that monitors user\'s saved posts on reddit, downloads its
+ media and uploads to a nextcloud instance.
+
+ It combines 3 projects: [praw](https://github.com/praw-dev/praw) to read and
+ motitor user's saved feed, [gallery-dl](https://github.com/mikf/gallery-dl)
+ to download media from several sources, and
+ [nextcloud-api-wrapper](https://github.com/luffah/nextcloud-API) to manage
+ folder and upload files to nexcloud instance.
+
+- [Filter for Nerdcast
+ (pt-BR)](https://gabrielgio.gitlab.io/jn_filter/)
+ [[gitlab](https://gitlab.com/gabrielgio/jn_filter)]
+
+ Just a small podcast filter to remove and/or split a feed from
+ [Nerdcast](https://www.jovemnerd.com.br/nerdcast/) into different segments.
+ The current feed its quite clustered with many programs/segments and this
+ project just helps to clean up so only the segment you want shows up on you
+ podcast client.
+
+- [Password generator](https://genpass.gabrielgio.me/)
+ [[gitlab](https://gitlab.com/gabrielgio/genpass)]
+
+ It started with me having fun with clojure script ([last
+ commit](https://gitlab.com/gabrielgio/genpass/-/tree/2db3d88503fbe219e99c464c4cc8e768613e1359)).
+ Now I have been using it as a playground to play a bit with rust/wasm and it
+ is a quite interesting comparacion to make. The cljs implementation could
+ not handle more than 1k chars, while the wasm can easly handle >100k. Is it
+ useful for a password generator? Probabally not, but if it is your use case
+ now I got you covered.
diff --git a/src/assets.rs b/src/assets.rs
index 2c39d1b..32d26e9 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -11,12 +11,23 @@ pub const BLOG_REGEX: &str = r"(?P<date>[\d]{4}-[\d]{2}-[\d]{2})(?P<title>[a-zA-
#[folder = "content/posts/"]
pub struct PostAsset;
+#[derive(RustEmbed)]
+#[folder = "content/projects/"]
+pub struct ProjectsAsset;
+
#[derive(TemplateOnce)]
#[template(path = "index.html")]
pub struct IndexTemplate {
pub posts: Vec<BlogEntry>,
}
+
+#[derive(TemplateOnce)]
+#[template(path = "projects.html")]
+pub struct ProjectsTemplate {
+ pub content: String,
+}
+
#[derive(TemplateOnce)]
#[template(path = "post.html")]
pub struct PostTemplate {
diff --git a/src/bin/actix.rs b/src/bin/actix.rs
index 101fe2e..978e8ed 100644
--- a/src/bin/actix.rs
+++ b/src/bin/actix.rs
@@ -1,5 +1,5 @@
use actix_web::{get, web, middleware, App, HttpResponse, HttpServer, Responder, http::header::ContentType};
-use macroblog::blog::{render_index_page, render_post_page};
+use macroblog::blog::{render_index_page, render_post_page, render_projects};
use macroblog::router::blog_post_exists;
use std::env;
@@ -12,6 +12,15 @@ async fn index() -> impl Responder {
.body(body)
}
+#[get("/projects")]
+async fn projects() -> impl Responder {
+ let body = render_projects();
+
+ HttpResponse::Ok()
+ .content_type(ContentType::html())
+ .body(body)
+}
+
#[get("/posts/{name}")]
async fn posts(name: web::Path<String>) -> impl Responder {
@@ -36,6 +45,7 @@ async fn main() -> std::io::Result<()> {
App::new()
.wrap(middleware::Compress::default())
.service(index)
+ .service(projects)
.service(posts)
})
.bind(("0.0.0.0", port))?
diff --git a/src/bin/hyper.rs b/src/bin/hyper.rs
index 3f23f18..f24cbe4 100644
--- a/src/bin/hyper.rs
+++ b/src/bin/hyper.rs
@@ -1,11 +1,10 @@
-use std::convert::Infallible;
-use std::{env};
-use std::net::SocketAddr;
-use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
+use hyper::{Body, Request, Response, Server};
+use macroblog::blog::{render_index_page, render_post_page, render_projects};
use macroblog::router::Router;
-use macroblog::blog::{render_index_page, render_post_page};
-
+use std::convert::Infallible;
+use std::env;
+use std::net::SocketAddr;
async fn not_found() -> Result<Response<Body>, Infallible> {
let resp: Response<Body> = Response::builder()
@@ -15,7 +14,6 @@ async fn not_found() -> Result<Response<Body>, Infallible> {
Ok(resp)
}
-
async fn index() -> Result<Response<Body>, Infallible> {
let body = render_index_page();
@@ -28,6 +26,17 @@ async fn index() -> Result<Response<Body>, Infallible> {
Ok(resp)
}
+async fn projects() -> Result<Response<Body>, Infallible> {
+ let body = render_projects();
+
+ let resp: Response<Body> = Response::builder()
+ .status(200)
+ .header("posts-type", "text/html")
+ .body(body.into())
+ .unwrap();
+
+ Ok(resp)
+}
async fn post(path: &String) -> Result<Response<Body>, Infallible> {
let body = render_post_page(path);
@@ -46,20 +55,21 @@ async fn request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
match Router::new(path) {
Router::Index => index().await,
+ Router::Projects => projects().await,
Router::Post { page } => post(&page).await,
- Router::NotFound => not_found().await
+ Router::NotFound => not_found().await,
}
}
-
#[tokio::main]
async fn main() {
- let port = env::var("PORT").unwrap_or("3000".into()).parse::<u16>().unwrap_or(3000);
+ let port = env::var("PORT")
+ .unwrap_or("3000".into())
+ .parse::<u16>()
+ .unwrap_or(3000);
let addr = SocketAddr::from(([0, 0, 0, 0], port));
- let make_svc = make_service_fn(|_conn| async {
- Ok::<_, Infallible>(service_fn(request))
- });
+ let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(request)) });
let server = Server::bind(&addr).serve(make_svc);
diff --git a/src/blog.rs b/src/blog.rs
index a1586f8..8c3af52 100644
--- a/src/blog.rs
+++ b/src/blog.rs
@@ -1,8 +1,7 @@
+use crate::assets::{BlogEntry, IndexTemplate, PostAsset, PostTemplate, ProjectsAsset, ProjectsTemplate};
use pulldown_cmark::{html, Options, Parser};
use sailfish::TemplateOnce;
use std::str;
-use crate::assets::{BlogEntry, PostAsset, IndexTemplate, PostTemplate};
-
pub fn read_assets() -> Vec<BlogEntry> {
let mut entries: Vec<BlogEntry> = PostAsset::iter()
@@ -26,6 +25,24 @@ fn get_file_content(path: &str) -> String {
return html_output.to_string();
}
+fn get_projects_content() -> String {
+ let buffer = ProjectsAsset::get("index.md").unwrap().data.into_owned();
+ let md = String::from_utf8(buffer).unwrap();
+ let mut options = Options::empty();
+ options.insert(Options::ENABLE_FOOTNOTES);
+ let parser = Parser::new_ext(&md, options);
+ let mut html_output = &mut String::new();
+ html::push_html(&mut html_output, parser);
+ return html_output.to_string();
+}
+
+pub fn render_projects() -> String {
+ ProjectsTemplate {
+ content: get_projects_content(),
+ }
+ .render_once()
+ .unwrap()
+}
pub fn render_post_page(path: &String) -> String {
let blog = BlogEntry::new(path);
diff --git a/src/router.rs b/src/router.rs
index 3227d66..c5efd9c 100644
--- a/src/router.rs
+++ b/src/router.rs
@@ -1,11 +1,12 @@
use crate::assets::PostAsset;
use regex::Regex;
-const ACTION_REGEX: &str = r"/{0,1}(?P<action>\w*)/(?P<id>.+)";
+const ACTION_REGEX: &str = r"/{0,1}(?P<action>\w*)/{0,1}(?P<id>.*)";
pub enum Router {
NotFound,
Index,
+ Projects,
Post { page: String },
}
@@ -17,11 +18,14 @@ impl Router {
pub fn new(path: &str) -> Router {
let re = Regex::new(ACTION_REGEX).unwrap();
let caps = re.captures(path);
- let action = match caps {
+ let mut action = match caps {
Some(ref value) => &value["action"],
None => "index",
};
+ if action == "" {
+ action = "index"
+ }
// this 7 means the "/posts/" from the full path
let trimmed_path: String = path.chars().skip(7).collect();
@@ -33,6 +37,7 @@ impl Router {
"posts" => Router::Post {
page: caps.unwrap()["id"].to_string(),
},
+ "projects" => Router::Projects,
"index" => Router::Index,
_ => Router::NotFound,
}
diff --git a/templates/header.html b/templates/header.html
index c830273..b81a09e 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -5,6 +5,7 @@
</a>
<nav class="container-fluid">
<ul>
+ <li><a href="/projects" class="secondary">Projects</a></li>
<li><a href="https://gitlab.com/gabrielgio/cv/-/raw/main/cv.pdf?inline=false" class="secondary">Resume</a></li>
</ul>
</nav>
diff --git a/templates/projects.html b/templates/projects.html
new file mode 100644
index 0000000..9aff1a6
--- /dev/null
+++ b/templates/projects.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html data-theme="light" lang="en">
+ <head>
+ <% include!("head.html"); %>
+ </head>
+ <body>
+ <div class="layout">
+ <% include!("header.html"); %>
+ <%- content %>
+ </div>
+ </body>
+</html>
diff --git a/tests/test_router.rs b/tests/test_router.rs
index cfd4c32..97f344c 100644
--- a/tests/test_router.rs
+++ b/tests/test_router.rs
@@ -5,15 +5,28 @@ fn test_router_new_posts() {
match Router::new("/posts/2021-12-26Enable_NFS_on_K3S.md") {
Router::NotFound => assert!(false, "Wrong type parse"),
Router::Index => assert!(false, "Wrong type parse"),
+ Router::Projects => assert!(false, "Wrong type parse"),
Router::Post { page } => assert_eq!(page, "2021-12-26Enable_NFS_on_K3S.md".to_string()),
};
}
+
+#[test]
+fn test_router_projects() {
+ match Router::new("/projects") {
+ Router::NotFound => assert!(false, "Wrong type parse"),
+ Router::Index => assert!(false, "Wrong type parse"),
+ Router::Projects => assert!(true),
+ Router::Post { page: _ } => assert!(false, "Wrong type parse"),
+ };
+}
+
#[test]
fn test_router_new_index() {
match Router::new("/") {
Router::Index => assert!(true),
Router::NotFound => assert!(false, "Wrong type parse"),
+ Router::Projects => assert!(false, "Wrong type parse"),
Router::Post { page: _ } => assert!(false, "Wrong type parse"),
};
}
@@ -23,6 +36,7 @@ fn test_router_new_not_found() {
match Router::new("/not_found") {
Router::NotFound => assert!(true),
Router::Index => assert!(false, "Wrong type parse"),
+ Router::Projects => assert!(false, "Wrong type parse"),
Router::Post { page: _ } => assert!(false, "Wrong type parse"),
};
}
@@ -32,6 +46,7 @@ fn test_router_new_not_found_matching_regex() {
match Router::new("/posts/2021-12-03Enable_NFS_on_K3S.html") {
Router::NotFound => assert!(true),
Router::Index => assert!(false, "Wrong type parse"),
+ Router::Projects => assert!(false, "Wrong type parse"),
Router::Post { page: _ } => assert!(false, "Wrong type parse"),
};
}
diff --git a/watch b/watch
index a9a0dba..5b17a42 100755
--- a/watch
+++ b/watch
@@ -4,7 +4,10 @@ case $1 in
actix)
cargo watch -x "run --bin actix"
;;
- *)
+ hyper)
cargo watch -x "run --bin hyper"
;;
+ *)
+ cargo watch -x "test"
+ ;;
esac