You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Feature proposal: local per-message media manifest and transcript links #6
export_chat.py currently renders image messages as [Image]. The separate media exporter copies plaintext cache images and skips encrypted .dat originals, but does not associate exported assets with individual transcript messages.
Would a per-message local asset manifest be a useful first step toward linking transcripts and images?
A possible format could include:
Message identity scoped to an account snapshot: shard + local ID, with server ID when available. Server ID alone may be absent or insufficient for every message.
Asset kind, resolution status (resolved, not_found, encrypted_unsupported) and a relative exported path when available.
A resolver that uses verified resource-index relationships rather than assuming that the message XML MD5 appears in the filename.
TXT could render a relative path; Markdown/HTML could provide links or previews. Missing or unsupported assets would retain the current placeholder with an explicit status. Paths would stay local, and the manifest would exclude raw keys, image AES keys, authentication fields and CDN URLs.
This should be separate from implementing a decoder for encrypted image originals. That work needs format-specific fixtures and verification of the correct message-to-asset mapping. A collision-safe media layout is also helpful, but exporting all account media is not a substitute for selecting assets for one conversation and date window.
I can contribute a small manifest/export change once the intended scope and resource mapping are agreed. This proposal contains no private chat records or image encryption metadata.
Thanks for the proposal. A per-message local manifest is a useful next step, and the first-increment contract is now documented in docs/media-manifest-proposal.md.
The attachment prerequisites from #5 and #10 are adopted through #15: same-named attachments retain their directories, and Windows attachment lookup uses the original account rather than the database mirror.
For the manifest, please scope identity to account snapshot + conversation/table + shard + local ID, with an optional server ID. Local IDs can repeat across both shards and conversation tables. Resolved entries should use paths relative to the export root; missing, ambiguous and encrypted/unsupported assets must remain explicit. The resolver should use a demonstrated resource-index relationship, without assuming that an XML MD5 is the asset filename. Start with the JSON sidecar and TXT paths; Markdown/HTML previews and encrypted-image decoding can follow separately.
The missing prerequisite is a minimal, verified mapping fixture: table definitions and synthetic rows showing message -> resource index -> local image, with the tested WeChat version/platform. Please exclude private messages, account identifiers, keys, authentication fields and CDN URLs. The public image implementations inspected so far rely on filename/MD5 heuristics and do not establish that relationship for this repository.
Keeping this issue open until those fixtures, the resolver and transcript links meet the documented acceptance cases. This is an accepted feature direction, not a completed image-association implementation.
Implemented and merged in #16, with repeated-export asset isolation in #17.
export_chat.py CONTACT --with-media --no-transcribe -o chat.html now creates the transcript, chat.media.json and a fresh chat.assets-<export-id>/ directory recorded as assets_directory in the manifest. Earlier export directories are preserved; the current directory never inherits images from a previous date window. When none of the selected images is readable, only the transcript and sidecar are produced. TXT includes relative paths; Markdown and HTML embed supported local images. Only image messages belonging to the selected conversation/date window are exported.
The resolver uses the verified resource-index relationship: ChatName2Id / MessageResourceInfo, protobuf field 2.1, then the registered image_hardlink_info_v4 filenames and dir2id directories. It does not guess the filename from the message XML MD5. Snapshot/conversation/table/shard/local-ID identity handles missing server IDs and repeated local IDs. Missing, ambiguous, unknown-profile and encrypted assets keep explicit statuses; the original placeholder remains visible. Copied files and sidecars stay private, with no raw packed payloads, keys, authentication fields, CDN URLs or absolute source paths.
Validation includes 24 new synthetic cases and complete CLI exports in all three formats. All four macOS/Windows × Python 3.10/3.13 CI jobs passed: Windows 233 passed; macOS 232 passed with the Windows-only test skipped. A read-only native macOS WeChat 4.1.15 check confirmed an actual message/index/file association, and a browser smoke test confirmed the generated HTML loads its relative image. No private data was included in the fixtures or PR.
The former proposal document now documents the implemented interface and supported index profile. Encrypted-image decoding remains separate as originally scoped; existing encrypted originals are identified as encrypted_unsupported rather than linked to an incorrect plaintext file. This completes the manifest/transcript-link increment, so closing the issue. Thanks for the proposal.
Activity
freanocank commentedon Oct 13, 2026
Thanks for the proposal. A per-message local manifest is a useful next step, and the first-increment contract is now documented in docs/media-manifest-proposal.md.
The attachment prerequisites from #5 and #10 are adopted through #15: same-named attachments retain their directories, and Windows attachment lookup uses the original account rather than the database mirror.
For the manifest, please scope identity to account snapshot + conversation/table + shard + local ID, with an optional server ID. Local IDs can repeat across both shards and conversation tables. Resolved entries should use paths relative to the export root; missing, ambiguous and encrypted/unsupported assets must remain explicit. The resolver should use a demonstrated resource-index relationship, without assuming that an XML MD5 is the asset filename. Start with the JSON sidecar and TXT paths; Markdown/HTML previews and encrypted-image decoding can follow separately.
The missing prerequisite is a minimal, verified mapping fixture: table definitions and synthetic rows showing message -> resource index -> local image, with the tested WeChat version/platform. Please exclude private messages, account identifiers, keys, authentication fields and CDN URLs. The public image implementations inspected so far rely on filename/MD5 heuristics and do not establish that relationship for this repository.
Keeping this issue open until those fixtures, the resolver and transcript links meet the documented acceptance cases. This is an accepted feature direction, not a completed image-association implementation.
freanocank commentedon Oct 13, 2026
Implemented and merged in #16, with repeated-export asset isolation in #17.
export_chat.py CONTACT --with-media --no-transcribe -o chat.htmlnow creates the transcript,chat.media.jsonand a freshchat.assets-<export-id>/directory recorded asassets_directoryin the manifest. Earlier export directories are preserved; the current directory never inherits images from a previous date window. When none of the selected images is readable, only the transcript and sidecar are produced. TXT includes relative paths; Markdown and HTML embed supported local images. Only image messages belonging to the selected conversation/date window are exported.The resolver uses the verified resource-index relationship:
ChatName2Id/MessageResourceInfo, protobuf field 2.1, then the registeredimage_hardlink_info_v4filenames anddir2iddirectories. It does not guess the filename from the message XML MD5. Snapshot/conversation/table/shard/local-ID identity handles missing server IDs and repeated local IDs. Missing, ambiguous, unknown-profile and encrypted assets keep explicit statuses; the original placeholder remains visible. Copied files and sidecars stay private, with no raw packed payloads, keys, authentication fields, CDN URLs or absolute source paths.Validation includes 24 new synthetic cases and complete CLI exports in all three formats. All four macOS/Windows × Python 3.10/3.13 CI jobs passed: Windows 233 passed; macOS 232 passed with the Windows-only test skipped. A read-only native macOS WeChat 4.1.15 check confirmed an actual message/index/file association, and a browser smoke test confirmed the generated HTML loads its relative image. No private data was included in the fixtures or PR.
The former proposal document now documents the implemented interface and supported index profile. Encrypted-image decoding remains separate as originally scoped; existing encrypted originals are identified as
encrypted_unsupportedrather than linked to an incorrect plaintext file. This completes the manifest/transcript-link increment, so closing the issue. Thanks for the proposal.