diff --git a/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s.json b/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s.json index e38992b..3abbea1 100644 --- a/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s.json +++ b/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s.json @@ -1,18 +1,17 @@ { - "cid": "bafyreielgn743kg5xotfj5x53edl25vkbbd2d6v7s3tydyyjsvczcluyme", + "cid": "bafyreigwaeqfluw7btvnmxfogd77gtk4efwomvjsvq2yxmmxr2665zwwbi", "uri": "at://did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s", "value": { "$type": "ai.syui.log.post", - "cid": "bafyreidymanu2xk4ftmvfdna3j7ixyijc37s6h3aytstuqgzatgjl4tp7e", - "content": "## ailogとは\n\natprotoと連携するサイトジェネレータ。\n\n## ailogの使い方\n\n```sh\n$ git clone https://git.syui.ai/ai/log\n$ cd log\n$ cat public/config.json\n{\n \"title\": \"syui.ai\",\n \"handle\": \"syui.syui.ai\",\n \"collection\": \"ai.syui.log.post\",\n \"network\": \"syu.is\",\n \"color\": \"#0066cc\",\n \"siteUrl\": \"https://syui.ai\"\n}\n---\n$ npm run dev\n```\n\n## ailogのコンセプト\n\n1. at-browserを基本にする\n2. atproto oauthでログインする\n3. ログインしたアカウントで記事をポストする\n\n## ailogの追加機能\n\n1. atproto recordからjsonをdownloadすると表示速度が上がる(ただし更新はlocalから)\n2. コメントはurlの言及を検索して表示\n\n```sh\n$ npm run fetch\n$ npm run generate\n```", - "createdAt": "2026-01-15T13:59:52.367Z", + "content": "## ailogとは\n\natprotoと連携するサイトジェネレータ。\n\n## ailogの使い方\n\n```sh\n$ git clone https://git.syui.ai/ai/log\n$ cd log\n$ cat public/config.json\n{\n \"title\": \"syui.ai\",\n \"handle\": \"syui.syui.ai\",\n \"collection\": \"ai.syui.log.post\",\n \"network\": \"syu.is\",\n \"color\": \"#0066cc\",\n \"siteUrl\": \"https://syui.ai\"\n}\n---\n$ npm run dev\n```\n\n## ailogのコンセプト\n\n1. at-browserを基本にする\n2. atproto oauthでログインする\n3. ログインしたアカウントで記事をポストする", + "createdAt": "2026-01-18T08:31:52.715Z", "title": "ailogを作り直した", "translations": { "en": { - "content": "## What is ailog?\n\nA site generator that integrates with the atproto framework.\n\n## How to Use ailog\n\n```sh\n$ git clone https://git.syui.ai/ai/log\n$ cd log\n$ cat public/config.json\n{\n \"title\": \"syui.ai\",\n \"handle\": \"syui.syui.ai\",\n \"collection\": \"ai.syui.log.post\",\n \"network\": \"syu.is\",\n \"color\": \"#0066cc\",\n \"siteUrl\": \"https://syui.ai\"\n}\n---\n$ npm run dev\n```\n\n## ailog's Concept\n\n1. Based on at-browser as its foundation\n2. Authentication via atproto oAuth\n3. Post articles using the logged-in account\n\n## Additional Features of ailog\n\n1. Downloading JSON from atproto record improves display speed (though updates still come from local storage)\n2. Comments are displayed by searching for URL mentions\n\n```sh\n$ npm run fetch\n$ npm run generate\n```", + "content": "## About ailog\n\nA site generator that integrates with atproto.\n\n## How to Use ailog\n\n```sh\n$ git clone https://git.syui.ai/ai/log\n$ cd log\n$ cat public/config.json\n{\n \"title\": \"syui.ai\",\n \"handle\": \"syui.syui.ai\",\n \"collection\": \"ai.syui.log.post\",\n \"network\": \"syu.is\",\n \"color\": \"#0066cc\",\n \"siteUrl\": \"https://syui.ai\"\n}\n---\n$ npm run dev\n```\n\n## ailog's Concept\n\n1. Based on at-browser architecture\n2. Uses atproto oAuth for login\n3. Allows posting articles through the logged-in account", "title": "recreated ailog" } }, - "uri": "at://did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/3mchqlshygs2s" + "lang": "ja" } -} \ No newline at end of file +} diff --git a/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/index.json b/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/index.json new file mode 100644 index 0000000..506d423 --- /dev/null +++ b/public/content/did:plc:vzsvtbtbnwn22xjqhcu3vd6y/ai.syui.log.post/index.json @@ -0,0 +1 @@ +["3mchqlshygs2s"] diff --git a/src/commands/post.rs b/src/commands/post.rs index 9c20841..b8a2291 100644 --- a/src/commands/post.rs +++ b/src/commands/post.rs @@ -323,8 +323,10 @@ pub async fn sync_to_local(output: &str) -> Result<()> { let collection_dir = format!("{}/{}", did_dir, collection); fs::create_dir_all(&collection_dir)?; + let mut rkeys: Vec = Vec::new(); for record in &list.records { let rkey = record.uri.split('/').last().unwrap_or("unknown"); + rkeys.push(rkey.to_string()); let record_path = format!("{}/{}.json", collection_dir, rkey); let record_json = serde_json::json!({ "uri": record.uri, @@ -334,6 +336,12 @@ pub async fn sync_to_local(output: &str) -> Result<()> { fs::write(&record_path, serde_json::to_string_pretty(&record_json)?)?; println!("Saved: {}", record_path); } + + // Create index.json with list of rkeys + let index_path = format!("{}/index.json", collection_dir); + fs::write(&index_path, serde_json::to_string_pretty(&rkeys)?)?; + println!("Saved: {}", index_path); + println!("Synced {} records from {}", list.records.len(), collection); } diff --git a/src/lms/translate.rs b/src/lms/translate.rs index 4b9928e..a255ec7 100644 --- a/src/lms/translate.rs +++ b/src/lms/translate.rs @@ -170,18 +170,27 @@ async fn translate_file(input: &Path, from: &str, to: &str) -> Result<()> { Ok(()) } -async fn translate_folder(dir: &Path, from: &str, to: &str) -> Result<()> { - let mut files: Vec<_> = fs::read_dir(dir)? - .filter_map(|e| e.ok()) - .filter(|e| { - e.path() - .extension() - .map(|ext| ext == "json") - .unwrap_or(false) - }) - .collect(); +fn collect_json_files(dir: &Path, files: &mut Vec) -> Result<()> { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + collect_json_files(&path, files)?; + } else if path.extension().map(|e| e == "json").unwrap_or(false) { + // Skip non-post files (describe.json, self.json, index.json) + let filename = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); + if filename != "describe.json" && filename != "self.json" && filename != "index.json" { + files.push(path); + } + } + } + Ok(()) +} - files.sort_by_key(|e| e.path()); +async fn translate_folder(dir: &Path, from: &str, to: &str) -> Result<()> { + let mut files = Vec::new(); + collect_json_files(dir, &mut files)?; + files.sort(); println!("Translating {} files ({} -> {})", files.len(), from, to); @@ -189,9 +198,8 @@ async fn translate_folder(dir: &Path, from: &str, to: &str) -> Result<()> { let mut skipped = 0; let mut failed = 0; - for entry in files { - let path = entry.path(); - match translate_file(&path, from, to).await { + for path in &files { + match translate_file(path, from, to).await { Ok(_) => { // Check if it was actually translated or skipped let content = fs::read_to_string(&path)?;