summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2020-05-25 18:32:15 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2020-05-25 18:32:15 -0400
commit899f517859fe2d2981ec5214892c1af966358c6a (patch)
tree2bc5e8e07cd3afc349f4310106ea779a89a233e1
parent30a4fc7365ffa4842275bc9513e3e458308b596d (diff)
Implement posts endpoint.
-rw-r--r--Cargo.lock77
-rw-r--r--Cargo.toml3
-rw-r--r--src/database.rs38
-rw-r--r--src/main.rs50
4 files changed, 127 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 42fe9d5..6178093 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -84,6 +84,9 @@ dependencies = [
"rocket",
"rocket_contrib",
"rusqlite",
+ "serde",
+ "serde_derive",
+ "serde_json",
]
[[package]]
@@ -262,7 +265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7"
dependencies = [
"devise_core",
- "quote",
+ "quote 0.6.13",
]
[[package]]
@@ -272,9 +275,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487"
dependencies = [
"bitflags",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "syn 0.15.44",
]
[[package]]
@@ -807,9 +810,9 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "syn 0.15.44",
"version_check 0.1.5",
"yansi 0.4.0",
]
@@ -844,7 +847,16 @@ version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
- "unicode-xid",
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
+dependencies = [
+ "unicode-xid 0.2.0",
]
[[package]]
@@ -853,7 +865,16 @@ version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
- "proc-macro2",
+ "proc-macro2 0.4.30",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
+dependencies = [
+ "proc-macro2 1.0.17",
]
[[package]]
@@ -939,7 +960,7 @@ dependencies = [
"devise",
"glob",
"indexmap",
- "quote",
+ "quote 0.6.13",
"rocket_http",
"version_check 0.9.2",
"yansi 0.5.0",
@@ -972,7 +993,7 @@ dependencies = [
"smallvec",
"state",
"time",
- "unicode-xid",
+ "unicode-xid 0.1.0",
]
[[package]]
@@ -1042,6 +1063,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
[[package]]
+name = "serde_derive"
+version = "1.0.110"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
+dependencies = [
+ "proc-macro2 1.0.17",
+ "quote 1.0.6",
+ "syn 1.0.25",
+]
+
+[[package]]
name = "serde_json"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1082,9 +1114,20 @@ version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f14a640819f79b72a710c0be059dce779f9339ae046c8bef12c361d56702146f"
+dependencies = [
+ "proc-macro2 1.0.17",
+ "quote 1.0.6",
+ "unicode-xid 0.2.0",
]
[[package]]
@@ -1169,6 +1212,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+
+[[package]]
name = "untrusted"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 629f2e3..9a47e7d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,6 +18,9 @@ rusqlite = "0.21.0"
image = "0.23.4"
rocket = "0.4.4"
rocket_contrib = "0.4.4"
+serde = "1.0"
+serde_json = "1.0"
+serde_derive = "1.0"
[[bin]]
name = "birka-cli"
diff --git a/src/database.rs b/src/database.rs
index d27646b..7b69a21 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -26,9 +26,9 @@ pub struct TagDatabase(Connection);
/// Tag query with a sense of "state" for pagination.
#[derive(Debug)]
pub struct Query<'a> {
- tags: &'a [&'a str],
- last_id: Option<i64>,
- limit: Option<i64>,
+ pub tags: &'a [&'a str],
+ pub last_id: Option<i64>,
+ pub limit: Option<i64>,
}
impl TagDatabase {
@@ -144,6 +144,22 @@ impl TagDatabase {
Ok(())
}
+ /// Return the tags for the image specified by `image_id`.
+ pub fn tags_for_image(&self, image_id: i64) -> Result<Vec<String>> {
+ Ok(self
+ .0
+ .prepare(
+ "SELECT tags.name, COUNT(mapping.tag) as tag_count
+ FROM mapping
+ INNER JOIN images ON images.id = ?
+ INNER JOIN tags
+ GROUP BY tags.name;",
+ )?
+ .query_map(params![image_id], |row| row.get(0))?
+ .filter_map(|tag| tag.ok())
+ .collect())
+ }
+
/// Return the intersection of the sets of images matching each of `tags`.
pub fn query(&self, q: Query) -> Result<Vec<Image>> {
let ids: Vec<i64> = q
@@ -257,22 +273,6 @@ mod tests {
tb.initialize_tables()?;
Ok(tb)
}
-
- /// Return the tags for the image specified by `image_id`.
- pub fn tags_for_image(&self, image_id: i64) -> Result<Vec<String>> {
- Ok(self
- .0
- .prepare(
- "SELECT tags.name, COUNT(mapping.tag) as tag_count
- FROM mapping
- INNER JOIN images ON images.id = ?
- INNER JOIN tags
- GROUP BY tags.name;",
- )?
- .query_map(params![image_id], |row| row.get(0))?
- .filter_map(|tag| tag.ok())
- .collect())
- }
}
#[test]
diff --git a/src/main.rs b/src/main.rs
index b5665b9..a4f5946 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -24,30 +24,59 @@ extern crate image;
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
+#[macro_use]
+extern crate serde_derive;
mod database;
-use database::TagDatabase;
+use database::{Query, TagDatabase};
use image::{GenericImageView, ImageFormat};
+use rocket::State;
use rocket_contrib::json::{Json, JsonValue};
use std::env;
use std::fs;
use std::fs::File;
use std::os::unix::fs::symlink;
use std::path::Path;
+use std::sync::Mutex;
#[get("/")]
-fn index() -> &'static str {
+fn index(tb: State<Mutex<TagDatabase>>) -> &'static str {
"Hello, world!"
}
+#[derive(Serialize)]
+struct ImageResult {
+ filename: String,
+ tags: Vec<String>,
+}
+
#[get("/posts?<tags>")]
-fn posts(tags: String) -> Json<Vec<String>> {
- let tags: Vec<String> = tags.split(",").map(|s| s.into()).collect();
- Json(tags)
+fn posts(tb: State<Mutex<TagDatabase>>, tags: String) -> Json<Vec<ImageResult>> {
+ let tb = tb.inner().lock().unwrap();
+
+ let tags = tags.split(",").collect::<Vec<&str>>();
+ let results = tb
+ .query(Query {
+ tags: &tags[..],
+ last_id: Some(0),
+ limit: Some(50),
+ })
+ .unwrap();
+
+ Json(
+ results
+ .iter()
+ .map(|image| ImageResult {
+ filename: image.filename.clone(),
+ tags: tb.tags_for_image(image.id).unwrap(),
+ })
+ .collect(),
+ )
}
-fn create_image_directory() {
+/// Maybe initialize the directory for storing image symlinks and thumbnails.
+fn create_image_directory() -> TagDatabase {
let bin = env::current_exe().unwrap();
let image_dir = bin.parent().unwrap().join("image/");
fs::create_dir(&image_dir).ok();
@@ -72,9 +101,14 @@ fn create_image_directory() {
.unwrap();
}
}
+
+ tb
}
fn main() {
- create_image_directory();
- rocket::ignite().mount("/", routes![index, posts]).launch();
+ let tb = create_image_directory();
+ rocket::ignite()
+ .manage(Mutex::new(tb))
+ .mount("/", routes![index, posts])
+ .launch();
}