fix translate

This commit is contained in:
2026-01-18 17:34:30 +09:00
parent 97bcd13a8d
commit 65f921f471
5 changed files with 45 additions and 31 deletions

View File

@@ -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"
}
}
}

View File

@@ -0,0 +1 @@
["3mchqlshygs2s"]

View File

@@ -2,22 +2,20 @@
ATProto blog CLI
## Install
```sh
$ git clone https://git.syui.ai/ai/log
$ cd log
$ cat public/config.json
$ npm run dev
```
## Commands
```sh
$ cargo build --release
$ cp target/release/ailog ~/.cargo/bin/
```
## Setup
```sh
$ vim public/config.json
$ npm run build
```
## Commands
### login (l)
Login to ATProto PDS.

View File

@@ -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<String> = 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);
}

View File

@@ -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<std::path::PathBuf>) -> 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)?;