use anyhow::{anyhow, Context, Result}; use redis::AsyncCommands; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fs::File; #[derive(Default, Serialize, Deserialize)] struct PyindieblogData { posts: Vec<serde_json::Value>, cards: Vec<serde_json::Value>, } #[async_std::main] async fn main() -> Result<()> { let mut args = std::env::args(); args.next(); // skip argv[0] which is the name let redis_uri = args .next() .ok_or_else(|| anyhow!("No Redis URI provided"))?; let client = redis::Client::open(redis_uri.as_str()) .with_context(|| format!("Failed to construct Redis client on {}", redis_uri))?; let filename = args .next() .ok_or_else(|| anyhow!("No filename provided for export"))?; let mut data: Vec<serde_json::Value>; let file = File::create(filename)?; let mut conn = client .get_async_std_connection() .await .with_context(|| "Failed to connect to the Redis server")?; data = conn .hgetall::<&str, HashMap<String, String>>("posts") .await? .values() .map(|s| { serde_json::from_str::<serde_json::Value>(s) .with_context(|| format!("Failed to parse the following entry: {:?}", s)) }) .collect::<std::result::Result<Vec<serde_json::Value>, anyhow::Error>>() .with_context(|| "Failed to export h-entries from pyindieblog")?; data.extend( conn.hgetall::<&str, HashMap<String, String>>("hcards") .await? .values() .map(|s| { serde_json::from_str::<serde_json::Value>(s) .with_context(|| format!("Failed to parse the following card: {:?}", s)) }) .collect::<std::result::Result<Vec<serde_json::Value>, anyhow::Error>>() .with_context(|| "Failed to export h-cards from pyindieblog")?, ); data.sort_by_key(|v| { v["properties"]["published"][0] .as_str() .map(|s| s.to_string()) }); serde_json::to_writer(file, &data)?; Ok(()) }