about summary refs log tree commit diff
path: root/src/bin/kittybox_bulk_import.rs
diff options
context:
space:
mode:
authorVika Shleina <vika@fireburn.ru>2021-07-15 04:32:29 +0300
committerVika <vika@fireburn.ru>2021-07-19 04:57:11 +0300
commitd399fd0bd00c9ea073e5b057de70c9ffdd9356f8 (patch)
treea9dafbeb62fb2aeb56e2d190565c70cd7f4b9d7a /src/bin/kittybox_bulk_import.rs
parent93b56879298810d60d121203403e2416f35e4765 (diff)
Renamed main executable to kittybox, added tools
The new tools are:
 - kittybox-bulk-import, a bare-bones Micropub client that reads a JSON
   list of posts and then sends them one by one to the Micropub endpoint
 - pyindieblog-export, my personal tool which directly connects to
   Pyindieblog's redis instance and extracts data from it in JSON format
   suitable for use with kittybox-bulk-import.
Diffstat (limited to 'src/bin/kittybox_bulk_import.rs')
-rw-r--r--src/bin/kittybox_bulk_import.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/bin/kittybox_bulk_import.rs b/src/bin/kittybox_bulk_import.rs
new file mode 100644
index 0000000..652a4c2
--- /dev/null
+++ b/src/bin/kittybox_bulk_import.rs
@@ -0,0 +1,50 @@
+use std::io::{self, Read};
+use std::fs::File;
+use anyhow::{anyhow, Context, Result, bail};
+
+#[async_std::main]
+async fn main() -> Result<()> {
+    let args = std::env::args().collect::<Vec<String>>();
+    if args.iter().skip(1).any(|s| s == "--help") {
+        println!("Usage: {} <url> [file]", args[0]);
+        println!("\nIf launched with no arguments, reads from stdin.");
+        println!("\nUse KITTYBOX_AUTH_TOKEN environment variable to authorize to the Micropub endpoint.");
+        std::process::exit(0);
+    }
+
+    let token = std::env::var("KITTYBOX_AUTH_TOKEN").map_err(|_| anyhow!("No auth token found! Use KITTYBOX_AUTH_TOKEN env variable."))?;
+    let data: Vec<serde_json::Value> = (if args.len() == 2 || (args.len() == 3 && args[2] == "-") {
+        serde_json::from_reader(io::stdin())
+    } else if args.len() == 3 {
+        serde_json::from_reader(File::open(&args[2]).with_context(|| "Error opening input file")?)
+    } else {
+        bail!("See `{} --help` for usage.", args[0]);
+    }).with_context(|| "Error while loading the input file")?;
+
+    let url = surf::Url::parse(&args[1])?;
+    let client = surf::Client::new();
+
+    let mut iter = data.into_iter();
+
+    while let Some(post) = iter.next() {
+        println!("Processing {}...", post["properties"]["url"][0].as_str().or(post["properties"]["published"][0].as_str().or(post["properties"]["name"][0].as_str().or(Some("<unidentified post>")))).unwrap());
+        match client.post(&url)
+            .body(surf::http::Body::from_string(
+                serde_json::to_string(&post)?))
+            .header("Content-Type", "application/json")
+            .header("Authorization", format!("Bearer {}", &token))
+            .send().await {
+            Ok(mut response) => {
+                if response.status() == 201 || response.status() == 202 {
+                    println!("Posted at {}", response.header("location").unwrap().last());
+                } else {
+                    println!("Error: {:?}", response.body_string().await);
+                }
+            }
+            Err(err) => {
+                println!("{}", err);
+            }
+        }
+    }
+    Ok(())
+}