diff --git a/weread-sync/sync.py b/weread-sync/sync.py
index 7cfa015..1b6baa2 100755
--- a/weread-sync/sync.py
+++ b/weread-sync/sync.py
@@ -28,6 +28,7 @@ REPO_DIR = os.path.expanduser("~/weread-notes")
SKILL_VERSION = "1.0.3"
OUTPUT_DIR = os.path.join(REPO_DIR, "notes")
+
# ─── API 调用 ─────────────────────────────────────────
def call_weread(api_name, **params):
@@ -73,10 +74,43 @@ def get_notebooks():
"title": book.get("title", "未知书名"),
"author": book.get("author", ""),
"reviewCount": b.get("reviewCount", 0),
+ "noteCount": b.get("noteCount", 0),
+ "readingProgress": b.get("readingProgress", 0),
})
return result
+def get_book_info(book_id):
+ """获取书籍详细信息"""
+ data = call_weread("/book/info", bookId=book_id)
+ if not data:
+ return {}
+ return {
+ "cover": data.get("cover", ""),
+ "translator": data.get("translator", ""),
+ "publisher": data.get("publisher", ""),
+ "isbn": data.get("isbn", ""),
+ "category": data.get("category", ""),
+ "intro": data.get("intro", ""),
+ "publishTime": data.get("publishTime", ""),
+ }
+
+
+def get_book_progress(book_id):
+ """获取阅读进度"""
+ data = call_weread("/book/getprogress", bookId=book_id)
+ if not data:
+ return {}
+ book = data.get("book", {})
+ return {
+ "progress": book.get("progress", 0),
+ "readingTime": book.get("readingTime", 0),
+ "startReadingTime": book.get("startReadingTime", 0),
+ "updateTime": book.get("updateTime", 0),
+ "chapterIdx": book.get("chapterIdx", 0),
+ }
+
+
def get_bookmarks(book_id):
"""获取一本书的划线"""
data = call_weread("/book/bookmarklist", bookId=book_id)
@@ -129,15 +163,84 @@ def format_time(ts):
return datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M")
-def generate_markdown(book, bookmarks, reviews):
- """生成一本书的笔记 Markdown"""
+def format_duration(minutes):
+ """分钟 → 可读时长"""
+ if not minutes:
+ return "—"
+ h = minutes // 60
+ m = minutes % 60
+ if h > 0:
+ return f"{h}小时{m}分钟"
+ return f"{m}分钟"
+
+
+def generate_header(book, book_info, progress):
+ """生成书籍信息头部"""
lines = []
lines.append(f"# {book['title']}")
- if book.get("author"):
- lines.append(f"> 作者:{book['author']}")
lines.append("")
- lines.append(f"> 同步时间:{format_time(time.time())}")
+
+ # 封面图(居中显示,宽350px)
+ cover = book_info.get("cover", "")
+ if cover:
+ lines.append('
')
+ lines.append(f'
')
+ lines.append('
')
+ lines.append("")
+
+ # 基本信息表(居中)
+ lines.append('')
lines.append("")
+ lines.append("| | |")
+ lines.append("|:---|:---|")
+ lines.append(f"| **作者** | {book.get('author', '—')} |")
+ if book_info.get("translator"):
+ lines.append(f"| **译者** | {book_info['translator']} |")
+ if book_info.get("publisher"):
+ lines.append(f"| **出版社** | {book_info['publisher']} |")
+ if book_info.get("category"):
+ lines.append(f"| **分类** | {book_info['category']} |")
+ if book_info.get("isbn"):
+ lines.append(f"| **ISBN** | {book_info['isbn']} |")
+ if book_info.get("publishTime"):
+ lines.append(f"| **出版时间** | {book_info['publishTime']} |")
+
+ # 阅读进度
+ pct = progress.get("progress", 0)
+ read_minutes = progress.get("readingTime", 0)
+ start_ts = progress.get("startReadingTime", 0)
+ update_ts = progress.get("updateTime", 0)
+
+ lines.append(f"| **阅读进度** | {pct}% |")
+ if read_minutes:
+ lines.append(f"| **阅读时长** | {format_duration(read_minutes)} |")
+ if start_ts:
+ lines.append(f"| **开始阅读** | {format_time(start_ts)} |")
+ if update_ts:
+ lines.append(f"| **最近阅读** | {format_time(update_ts)} |")
+
+ lines.append(f"| **划线数量** | {book.get('noteCount', '—')} 条 |")
+ lines.append("")
+ lines.append('
')
+ lines.append("")
+
+ # 简介
+ intro = book_info.get("intro", "")
+ if intro:
+ # 取前 200 字作为摘要
+ short_intro = intro[:200] + ("..." if len(intro) > 200 else "")
+ lines.append("> " + short_intro)
+ lines.append("")
+
+ return lines
+
+
+def generate_markdown(book, bookmarks, reviews, book_info, progress):
+ """生成一本书的笔记 Markdown"""
+ lines = []
+
+ # 书籍信息头部
+ lines.extend(generate_header(book, book_info, progress))
# 划线
if bookmarks:
@@ -145,40 +248,48 @@ def generate_markdown(book, bookmarks, reviews):
lines.append("## 划线笔记")
lines.append("")
current_chapter = None
+ first = True
for bm in bookmarks:
+ if not first:
+ lines.append("---")
+ first = False
if bm["chapter"] != current_chapter:
lines.append(f"### {bm['chapter']}")
lines.append("")
current_chapter = bm["chapter"]
lines.append(f"> {bm['text']}")
if bm["time"]:
- lines.append(f"> [{format_time(bm['time'])}]")
+ lines.append(f"> 🕐 {format_time(bm['time'])}")
lines.append("")
# 想法
if reviews:
lines.append("---")
- lines.append("## 笔记/想法")
+ lines.append("## 💬 笔记/想法")
lines.append("")
current_chapter = None
+ first = True
for r in reviews:
+ if not first:
+ lines.append("---")
+ first = False
# 按章节分组(跳过空章节名)
chapter = r.get("chapter", "").strip()
if chapter and chapter != current_chapter:
- if current_chapter is not None:
- lines.append("")
lines.append(f"### {chapter}")
lines.append("")
current_chapter = chapter
elif not chapter:
current_chapter = None
- # 原文 + 想法组合展示
+ # 原文在引用框内,想法在引用框外(加粗)
if r.get("abstract"):
lines.append(f"> {r['abstract']}")
- lines.append(">")
- lines.append(f"> {r['content']}")
- if r["time"]:
- lines.append(f"> [{format_time(r['time'])}]")
+ if r["time"]:
+ lines.append(f"> 🕐 {format_time(r['time'])}")
+ lines.append("")
+ lines.append(f"💬 **{r['content']}**")
+ if r["time"] and not r.get("abstract"):
+ lines.append(f"🕐 {format_time(r['time'])}")
lines.append("")
return "\n".join(lines)
@@ -221,7 +332,7 @@ def main():
print(f" 找到 {len(books)} 本书")
# 2. 逐本获取笔记
- print("\n[2/3] 拉取笔记...")
+ print("\n[2/3] 拉取笔记 + 书籍信息...")
total_bookmarks = 0
total_reviews = 0
os.makedirs(OUTPUT_DIR, exist_ok=True)
@@ -230,6 +341,11 @@ def main():
bid = book["bookId"]
title = book["title"]
print(f" [{i+1}/{len(books)}] {title}...", end=" ")
+ sys.stdout.flush()
+
+ # 获取书籍信息
+ book_info = get_book_info(bid)
+ progress = get_book_progress(bid)
# 获取划线
bookmarks, _ = get_bookmarks(bid)
@@ -242,7 +358,8 @@ def main():
# 生成 Markdown
safe_title = title.replace("/", "_").replace("\\", "_").replace(":", "_")
- md = generate_markdown(book, bookmarks, reviews)
+ safe_title = safe_title.replace("(", "(").replace(")", ")").replace("[", "【").replace("]", "】")
+ md = generate_markdown(book, bookmarks, reviews, book_info, progress)
filepath = os.path.join(OUTPUT_DIR, f"{safe_title}.md")
with open(filepath, "w", encoding="utf-8") as f:
f.write(md)
@@ -257,11 +374,12 @@ def main():
print("\n[3/3] 生成索引...")
index_lines = ["# 微信读书笔记索引", "", "| 书名 | 作者 | 划线 | 想法 | 最后同步 |", "|:---|:---|:---:|:---:|:---:|"]
for book in books:
- safe_title = book['title'].replace('/','_').replace('\\','_').replace(':','_')
+ safe_title = book['title'].replace('/', '_').replace('\\', '_').replace(':', '_')
+ safe_title = safe_title.replace('(', '(').replace(')', ')').replace('[', '【').replace(']', '】')
md_file = os.path.join(OUTPUT_DIR, f"{safe_title}.md")
if os.path.exists(md_file):
- index_lines.append(f"| [{book['title']}](notes/{os.path.basename(md_file)}) | {book.get('author','')} | {book.get('reviewCount',0)} | — | {format_time(time.time())} |")
-
+ index_lines.append(f"| [{book['title']}](notes/{os.path.basename(md_file)}) | {book.get('author', '')} | {book.get('noteCount', 0)} | {book.get('reviewCount', 0)} | {format_time(time.time())} |")
+
index_path = os.path.join(REPO_DIR, "README.md")
with open(index_path, "w", encoding="utf-8") as f:
f.write("\n".join(index_lines))