Last active
February 11, 2026 07:52
-
-
Save erbanku/e2f9dd6e4a98591e823b6fd0d05f5037 to your computer and use it in GitHub Desktop.
Memos to Markdown Converter: Convert Memos (v0.21 tested) JSON export into a single Markdown file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import json | |
| from datetime import datetime, timezone, timedelta | |
| def safe_datetime(ts): | |
| if ts is None or ts == 0: | |
| return None | |
| if ts > 9999999999: | |
| ts = ts / 1000 | |
| try: | |
| return datetime.fromtimestamp(ts, tz=timezone.utc) | |
| except (OSError, ValueError, OverflowError): | |
| return None | |
| def to_blockquote(text): | |
| return "\n".join(f"> {line}" if line.strip() else ">" for line in text.splitlines()) | |
| def convert_memos_to_markdown(input_file="memos.json", output_file="memos.md"): | |
| with open(input_file, "r", encoding="utf-8") as f: | |
| data = json.load(f) | |
| if isinstance(data, dict): | |
| for key in ("data", "memos", "items"): | |
| if key in data and isinstance(data[key], list): | |
| data = data[key] | |
| break | |
| if not isinstance(data, list): | |
| data = [data] | |
| seen_ids = set() | |
| unique_data = [] | |
| for memo in data: | |
| mid = memo.get("id") or memo.get("name") | |
| if mid not in seen_ids: | |
| seen_ids.add(mid) | |
| unique_data.append(memo) | |
| data = unique_data | |
| pinned = [] | |
| archived = [] | |
| normal = [] | |
| for m in data: | |
| if m.get("rowStatus") == "ARCHIVED": | |
| archived.append(m) | |
| elif m.get("pinned"): | |
| pinned.append(m) | |
| else: | |
| normal.append(m) | |
| sort_key = lambda m: m.get("displayTs") or m.get("createdTs", 0) | |
| pinned.sort(key=sort_key, reverse=True) | |
| normal.sort(key=sort_key, reverse=True) | |
| archived.sort(key=sort_key, reverse=True) | |
| shanghai_tz = timezone(timedelta(hours=8)) | |
| now_str = datetime.now(tz=shanghai_tz).strftime("%Y-%m-%d %H:%M:%S") | |
| lines = [] | |
| lines.append("# All Memos Notes") | |
| lines.append("") | |
| lines.append(f"> **All**: {len(data)} **Pinned**: {len(pinned)} **Normal**: {len(normal)} **Archived**: {len(archived)}") | |
| lines.append(f"> Exported at: {now_str} Asia/Shanghai") | |
| lines.append("") | |
| skipped = 0 | |
| def write_memos(memos, label=""): | |
| nonlocal skipped | |
| for memo in memos: | |
| ts = memo.get("displayTs") or memo.get("createdTs", 0) | |
| dt = safe_datetime(ts) | |
| if dt is None: | |
| skipped += 1 | |
| print(f"Skipped memo id={memo.get('id')} (invalid timestamp: {ts})") | |
| continue | |
| time_str = dt.strftime("%Y-%m-%d %H:%M:%S") | |
| prefix = f"{label} " if label else "" | |
| lines.append(f"## {prefix}{time_str}") | |
| lines.append("") | |
| block_lines = [] | |
| content = memo.get("content", "").strip() | |
| if content: | |
| block_lines.append(to_blockquote(content)) | |
| image_lines = [] | |
| resources = memo.get("resourceList", []) | |
| for res in resources: | |
| if res.get("type", "").startswith("image/"): | |
| filename = res.get("filename", "image") | |
| link = res.get("externalLink", "") | |
| if link: | |
| image_lines.append(f"> ") | |
| if image_lines: | |
| block_lines.append("\n".join(image_lines)) | |
| if block_lines: | |
| lines.append("\n>\n".join(block_lines)) | |
| lines.append("") | |
| write_memos(pinned, label="Pinned") | |
| write_memos(normal) | |
| write_memos(archived, label="Archived") | |
| with open(output_file, "w", encoding="utf-8") as f: | |
| f.write("\n".join(lines)) | |
| total = len(data) - skipped | |
| print(f"Done. {total} note(s) (pinned: {len(pinned)}, normal: {len(normal)}, archived: {len(archived)}) written to '{output_file}' (skipped: {skipped})") | |
| if __name__ == "__main__": | |
| convert_memos_to_markdown() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Memos to Markdown Converter
Convert Memos (v0.21 tested) JSON export into a single Markdown file.
Usage
Export memos as JSON
Open in browser or
curl:Save the returned JSON as
memos.json.Run the script
Place
convert_memos.pyin the same directory asmemos.json, then:Output
A
memos.mdfile will be generated with:Requirements