``` ├── .github/ ├── workflows/ ├── release.yml ├── .gitignore ├── .goreleaser.yaml ├── DISCLAIMER.md ├── LICENSE ├── Makefile ├── README.md ├── cmd/ ├── chatlog/ ├── cmd_decrypt.go ├── cmd_dumpmemory.go ├── cmd_key.go ├── cmd_server.go ├── cmd_version.go ├── log.go ├── root.go ├── docs/ ├── mcp.md ├── prompt.md ├── go.mod ├── go.sum ├── internal/ ├── chatlog/ ├── app.go ├── conf/ ├── config.go ├── service.go ├── ctx/ ├── context.go ├── database/ ├── service.go ├── http/ ├── route.go ├── service.go ├── static/ ├── index.htm ├── manager.go ├── mcp/ ├── const.go ├── service.go ├── wechat/ ├── service.go ├── errors/ ├── errors.go ├── http_errors.go ├── middleware.go ├── os_errors.go ├── wechat_errors.go ├── wechatdb_errors.go ├── mcp/ ├── error.go ├── initialize.go ├── jsonrpc.go ├── mcp.go ├── prompt.go ├── resource.go ├── session.go ├── sse.go ├── stdio.go ├── tool.go ├── model/ ├── chatroom.go ├── chatroom_darwinv3.go ├── chatroom_v4.go ├── contact.go ├── contact_darwinv3.go ├── contact_v4.go ├── media.go ├── media_darwinv3.go ├── media_v4.go ├── mediamessage.go ├── message.go ├── message_darwinv3.go ├── message_v3.go ├── message_v4.go ├── session.go ├── session_darwinv3.go ├── session_v4.go ├── wxproto/ ├── bytesextra.pb.go ├── bytesextra.proto ├── packedinfo.pb.go ├── packedinfo.proto ├── roomdata.pb.go ``` ## /.github/workflows/release.yml ```yml path="/.github/workflows/release.yml" name: Release on: push: tags: - 'v*' env: ENABLE_UPX: 1 jobs: release: name: Release Binary runs-on: ubuntu-latest container: image: goreleaser/goreleaser-cross:v1.24 steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - run: git config --global --add safe.directory "$(pwd)" - name: Setup Go uses: actions/setup-go@v4 with: go-version: '^1.24' - name: Cache go module uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Install UPX uses: crazy-max/ghaction-upx@v3 with: install-only: true - name: Run GoReleaser run: goreleaser release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ENABLE_UPX: true ``` ## /.gitignore ```gitignore path="/.gitignore" # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) # vendor/ # Go workspace file go.work go.work.sum # env file .env # syncthing files .stfolder chatlog.exe# Added by goreleaser init: dist/ ``` ## /.goreleaser.yaml ```yaml path="/.goreleaser.yaml" # GoReleaser v2 配置 version: 2 before: hooks: - go mod tidy builds: - id: darwin-amd64 binary: chatlog env: - CGO_ENABLED=1 - CC=o64-clang - CXX=o64-clang++ goos: - darwin goarch: - amd64 ldflags: - -s -w -X github.com/sjzar/chatlog/pkg/version.Version={{.Version}} - id: darwin-arm64 binary: chatlog env: - CGO_ENABLED=1 - CC=oa64-clang - CXX=oa64-clang++ goos: - darwin goarch: - arm64 ldflags: - -s -w -X github.com/sjzar/chatlog/pkg/version.Version={{.Version}} - id: windows-amd64 binary: chatlog env: - CGO_ENABLED=1 - CC=x86_64-w64-mingw32-gcc - CXX=x86_64-w64-mingw32-g++ goos: - windows goarch: - amd64 ldflags: - -s -w -X github.com/sjzar/chatlog/pkg/version.Version={{.Version}} - id: windows-arm64 binary: chatlog env: - CGO_ENABLED=1 - CC=/llvm-mingw/bin/aarch64-w64-mingw32-gcc - CXX=/llvm-mingw/bin/aarch64-w64-mingw32-g++ goos: - windows goarch: - arm64 ldflags: - -s -w -X github.com/sjzar/chatlog/pkg/version.Version={{.Version}} archives: - id: default format: tar.gz name_template: >- {{ .ProjectName }}_ {{- .Version }}_ {{- .Os }}_ {{- .Arch }} format_overrides: - goos: windows format: zip files: - LICENSE - README.md upx: - enabled: "{{ .Env.ENABLE_UPX }}" goos: [darwin, windows] goarch: [amd64] compress: best checksum: name_template: 'checksums.txt' algorithm: sha256 # 配置 GitHub Release release: draft: true prerelease: auto mode: replace ``` ## /DISCLAIMER.md # Chatlog 免责声明 ## 1. 定义 在本免责声明中,除非上下文另有说明,下列术语应具有以下含义: - **"本项目"或"Chatlog"**:指本开源软件项目,包括其源代码、可执行程序、文档及相关资源。 - **"开发者"**:指本项目的创建者、维护者及代码贡献者。 - **"用户"**:指下载、安装、使用或以任何方式接触本项目的个人或实体。 - **"聊天数据"**:指通过各类即时通讯软件生成的对话内容及相关元数据。 - **"合法授权"**:指根据适用法律法规,由数据所有者或数据主体明确授予的处理其聊天数据的权限。 - **"第三方服务"**:指由非本项目开发者提供的外部服务,如大型语言模型(LLM) API 服务。 ## 2. 使用目的与法律遵守 本项目仅供学习、研究和个人合法使用。用户须严格遵守所在国家/地区的法律法规使用本工具。任何违反法律法规、侵犯他人合法权益的行为,均与本项目及其开发者无关,相关法律责任由用户自行承担。 ⚠️ **用户应自行了解并遵守当地有关数据访问、隐私保护、计算机安全和网络安全的法律法规。不同司法管辖区对数据处理有不同的法律要求,用户有责任确保其使用行为符合所有适用法规。** ## 3. 授权范围与隐私保护 - 本工具仅限于处理用户自己合法拥有的聊天数据,或已获得数据所有者明确授权的数据。 - 严禁将本工具用于未经授权获取、查看或分析他人聊天记录,或侵犯他人隐私权。 - 用户应采取适当措施保护通过本工具获取和处理的聊天数据安全,包括但不限于加密存储、限制访问权限、定期删除不必要数据等。 - 用户应确保其处理的聊天数据符合相关数据保护法规,包括但不限于获得必要的同意、保障数据主体权利、遵守数据最小化原则等。 ## 4. 使用限制 - 本项目仅允许在合法授权情况下对聊天数据库进行备份与查看。 - 未经明确授权,严禁将本项目用于访问、查看、分析或处理任何第三方聊天数据。 - 使用第三方 LLM 服务时,用户应遵守相关服务提供商的服务条款和使用政策。 - 用户不得规避本项目中的任何技术限制,或尝试反向工程、反编译或反汇编本项目,除非适用法律明确允许此类活动。 ## 5. 技术风险声明 ⚠️ **使用本项目存在以下技术风险,用户应充分了解并自行承担:** - 本工具需要访问聊天软件的数据库文件,可能因聊天软件版本更新导致功能失效或数据不兼容。 - 在 macOS 系统上使用时,需要临时关闭 SIP 安全机制,这可能降低系统安全性,用户应了解相关风险并自行决定是否使用。 - 本项目可能存在未知的技术缺陷或安全漏洞,可能导致数据损坏、丢失或泄露。 - 使用本项目处理大量数据可能导致系统性能下降或资源占用过高。 - 第三方依赖库或 API 的变更可能影响本项目的功能或安全性。 ## 6. 禁止非法用途 严禁将本项目用于以下用途: - 从事任何形式的非法活动,包括但不限于未授权系统测试、网络渗透或其他违反法律法规的行为。 - 监控、窃取或未经授权获取他人聊天记录或个人信息。 - 将获取的数据用于骚扰、诈骗、敲诈、威胁或其他侵害他人合法权益的行为。 - 规避任何安全措施或访问控制机制。 - 传播虚假信息、仇恨言论或违反公序良俗的内容。 - 侵犯任何第三方的知识产权、隐私权或其他合法权益。 **违反上述规定的,用户应自行承担全部法律责任,并赔偿因此给开发者或第三方造成的全部损失。** ## 7. 第三方服务集成 - 用户将聊天数据与第三方 LLM 服务(如 OpenAI、Claude 等)结合使用时,应仔细阅读并遵守这些服务的使用条款、隐私政策和数据处理协议。 - 用户应了解,向第三方服务传输数据可能导致数据离开用户控制范围,并受第三方服务条款约束。 - 本项目开发者不对第三方服务的可用性、安全性、准确性或数据处理行为负责,用户应自行评估相关风险。 - 用户应确保其向第三方服务传输数据的行为符合适用的数据保护法规和第三方服务条款。 ## 8. 责任限制 **在法律允许的最大范围内:** - 本项目按"原样"和"可用"状态提供,不对功能的适用性、可靠性、准确性、完整性或及时性做任何明示或暗示的保证。 - 开发者明确否认对适销性、特定用途适用性、不侵权以及任何其他明示或暗示的保证。 - 本项目开发者和贡献者不对用户使用本工具的行为及后果承担任何法律责任。 - 对于因使用本工具而可能导致的任何直接、间接、附带、特殊、惩罚性或后果性损失,包括但不限于数据丢失、业务中断、隐私泄露、声誉损害、利润损失、法律纠纷等,本项目开发者概不负责,即使开发者已被告知此类损失的可能性。 - 在任何情况下,开发者对用户的全部责任累计不超过用户为获取本软件实际支付的金额(如为免费获取则为零)。 ## 9. 知识产权声明 - 本项目基于 Apache-2.0 许可证开源,用户在使用、修改和分发时应严格遵守该许可证的所有条款。 - 本项目的名称"Chatlog"、相关标识及商标权(如有)归开发者所有,未经明确授权,用户不得以任何方式使用这些标识进行商业活动。 - 根据 Apache-2.0 许可证,用户可自由使用、修改和分发本项目代码,但须遵守许可证规定的归属声明等要求。 - 用户对其修改版本自行承担全部责任,且不得以原项目名义发布,必须明确标明其为修改版本并与原项目区分。 - 用户不得移除或更改本项目中的版权声明、商标或其他所有权声明。 ## 10. 数据处理合规性 - 用户在使用本项目处理个人数据时,应遵守适用的数据保护法规,包括但不限于《中华人民共和国个人信息保护法》、《通用数据保护条例》(GDPR)等。 - 用户应确保其具有处理相关数据的合法依据,如获得数据主体的明确同意。 - 用户应实施适当的技术和组织措施,确保数据安全,防止未授权访问、意外丢失或泄露。 - 在跨境传输数据时,用户应确保符合相关法律对数据出境的要求。 - 用户应尊重数据主体权利,包括访问权、更正权、删除权等。 ## 11. 免责声明接受 下载、安装、使用本项目,表示用户已阅读、理解并同意遵守本免责声明的所有条款。如不同意,请立即停止使用本工具并删除相关代码和程序。 **用户确认:** - 已完整阅读并理解本免责声明的全部内容 - 自愿接受本免责声明的全部条款 - 具有完全民事行为能力,能够理解并承担使用本项目的风险和责任 - 将遵守本免责声明中规定的所有义务和限制 ## 12. 免责声明修改与通知 - 本免责声明可能根据项目发展和法律法规变化进行修改和调整,修改后的声明将在项目官方仓库页面公布。 - 开发者没有义务个别通知用户免责声明的变更,用户应定期查阅最新版本。 - 重大变更将通过项目仓库的 Release Notes 或 README 文件更新进行通知。 - 在免责声明更新后继续使用本项目,即视为接受修改后的条款。 ## 13. 法律适用与管辖 - 本免责声明受中华人民共和国法律管辖,并按其解释。 - 任何与本免责声明有关的争议,应首先通过友好协商解决;协商不成的,提交至本项目开发者所在地有管辖权的人民法院诉讼解决。 - 对于中国境外用户,如本免责声明与用户所在地强制性法律规定冲突,应以不违反该强制性规定的方式解释和适用本声明,但本声明的其余部分仍然有效。 ## 14. 可分割性 如本免责声明中的任何条款被有管辖权的法院或其他权威机构认定为无效、不合法或不可执行,不影响其余条款的有效性和可执行性。无效条款应被视为从本声明中分割,并在法律允许的最大范围内由最接近原条款意图的有效条款替代。 ## 15. 完整协议 本免责声明构成用户与开发者之间关于本项目使用的完整协议,取代先前或同时期关于本项目的所有口头或书面协议、提议和陈述。本声明的任何豁免、修改或补充均应以书面形式作出并经开发者签署方为有效。 ## /LICENSE ``` path="/LICENSE" Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` ## /Makefile ``` path="/Makefile" BINARY_NAME := chatlog GO := go ifeq ($(VERSION),) VERSION := $(shell git describe --tags --always --dirty="-dev") endif LDFLAGS := -ldflags '-X "github.com/sjzar/chatlog/pkg/version.Version=$(VERSION)" -w -s' PLATFORMS := \ darwin/amd64 \ darwin/arm64 \ windows/amd64 \ windows/arm64 UPX_PLATFORMS := \ darwin/amd64 \ windows/386 \ windows/amd64 .PHONY: all clean lint tidy test build crossbuild upx all: clean lint tidy test build clean: @echo "🧹 Cleaning..." @rm -rf bin/ lint: @echo "🕵️‍♂️ Running linters..." golangci-lint run ./... tidy: @echo "🧼 Tidying up dependencies..." $(GO) mod tidy test: @echo "🧪 Running tests..." $(GO) test ./... -cover build: @echo "🔨 Building for current platform..." CGO_ENABLED=1 $(GO) build -trimpath $(LDFLAGS) -o bin/$(BINARY_NAME) main.go crossbuild: clean @echo "🌍 Building for multiple platforms..." for platform in $(PLATFORMS); do \ os=$$(echo $$platform | cut -d/ -f1); \ arch=$$(echo $$platform | cut -d/ -f2); \ float=$$(echo $$platform | cut -d/ -f3); \ output_name=bin/chatlog_$${os}_$${arch}; \ [ "$$float" != "" ] && output_name=$$output_name_$$float; \ echo "🔨 Building for $$os/$$arch..."; \ echo "🔨 Building for $$output_name..."; \ GOOS=$$os GOARCH=$$arch CGO_ENABLED=1 GOARM=$$float $(GO) build -trimpath $(LDFLAGS) -o $$output_name main.go ; \ if [ "$(ENABLE_UPX)" = "1" ] && echo "$(UPX_PLATFORMS)" | grep -q "$$os/$$arch"; then \ echo "⚙️ Compressing binary $$output_name..." && upx --best $$output_name; \ fi; \ done ``` ## /README.md
# Chatlog ![chatlog](https://socialify.git.ci/sjzar/chatlog/image?font=Rokkitt&forks=1&issues=1&name=1&pattern=Diagonal+Stripes&stargazers=1&theme=Auto) _聊天记录工具,帮助大家轻松使用自己的聊天数据_ [![Go Report Card](https://goreportcard.com/badge/github.com/sjzar/chatlog)](https://goreportcard.com/report/github.com/sjzar/chatlog) [![GoDoc](https://godoc.org/github.com/sjzar/chatlog?status.svg)](https://godoc.org/github.com/sjzar/chatlog) [![GitHub release](https://img.shields.io/github/release/sjzar/chatlog.svg)](https://github.com/sjzar/chatlog/releases) [![GitHub license](https://img.shields.io/github/license/sjzar/chatlog.svg)](https://github.com/sjzar/chatlog/blob/main/LICENSE)
![chatlog](https://github.com/user-attachments/assets/e085d3a2-e009-4463-b2fd-8bd7df2b50c3) ## Feature - 从本地数据库文件获取聊天数据 - 支持 Windows / macOS 系统 - 支持微信 3.x / 4.0 版本 - 提供 Terminal UI 界面 & 命令行工具 - 提供 HTTP API 服务,支持查询聊天记录、联系人、群聊、最近会话等信息 - 支持 MCP SSE 协议,可与支持 MCP 的 AI 助手无缝集成 - 支持多媒体消息,支持解密图片、语音 - 支持自动解密数据,简化使用流程 - 支持多账号管理,可在不同账号间切换 ## TODO - 聊天数据全文索引 - 聊天数据统计 & Dashboard ## Quick Start ### 基本步骤 1. **安装 Chatlog**:[下载预编译版本](#下载预编译版本) 或 [使用 Go 安装](#从源码安装) 2. **运行程序**:执行 `chatlog` 启动 Terminal UI 界面 3. **解密数据**:选择 `解密数据` 菜单项 4. **开启 HTTP 服务**:选择 `开启 HTTP 服务` 菜单项 5. **访问数据**:通过 [HTTP API](#http-api) 或 [MCP 集成](#mcp-集成) 访问聊天记录 > 💡 **提示**:如果电脑端微信聊天记录不全,可以[从手机端迁移数据](#从手机迁移聊天记录) ### 常见问题快速解决 - **macOS 用户**:获取密钥前需[临时关闭 SIP](#macos-版本说明) - **Windows 用户**:遇到界面显示问题请[使用 Windows Terminal](#windows-版本说明) - **集成 AI 助手**:查看 [MCP 集成指南](#mcp-集成) ## 安装指南 ### 从源码安装 ```bash go install github.com/sjzar/chatlog@latest ``` ### 下载预编译版本 访问 [Releases](https://github.com/sjzar/chatlog/releases) 页面下载适合您系统的预编译版本。 ## 使用指南 ### Terminal UI 模式 最简单的使用方式是通过 Terminal UI 界面操作: ```bash chatlog ``` 操作方法: - 使用 `↑` `↓` 键选择菜单项 - 按 `Enter` 确认选择 - 按 `Esc` 返回上级菜单 - 按 `Ctrl+C` 退出程序 ### 命令行模式 对于熟悉命令行的用户,可以直接使用以下命令: ```bash # 获取微信数据密钥 chatlog key # 解密数据库文件 chatlog decrypt # 启动 HTTP 服务 chatlog server ``` ### 从手机迁移聊天记录 如果电脑端微信聊天记录不全,可以从手机端迁移数据: 1. 打开手机微信,进入 `我 - 设置 - 通用 - 聊天记录迁移与备份` 2. 选择 `迁移 - 迁移到电脑`,按照提示操作 3. 完成迁移后,重新运行 `chatlog` 获取密钥并解密数据 > 此操作不会影响手机上的聊天记录,只是将数据复制到电脑端 ## 平台特定说明 ### Windows 版本说明 如遇到界面显示异常(如花屏、乱码等),请使用 [Windows Terminal](https://github.com/microsoft/terminal) 运行程序 ### macOS 版本说明 macOS 用户在获取密钥前需要临时关闭 SIP(系统完整性保护): 1. **关闭 SIP**: ```shell # 进入恢复模式 # Intel Mac: 重启时按住 Command + R # Apple Silicon: 重启时长按电源键 # 在恢复模式中打开终端并执行 csrutil disable # 重启系统 ``` 2. **安装必要工具**: ```shell # 安装 Xcode Command Line Tools xcode-select --install ``` 3. **获取密钥后**:可以重新启用 SIP(`csrutil enable`),不影响后续使用 > Apple Silicon 用户注意:确保微信、chatlog 和终端都不在 Rosetta 模式下运行 ## HTTP API 启动 HTTP 服务后(默认地址 `http://127.0.0.1:5030`),可通过以下 API 访问数据: ### 聊天记录查询 ``` GET /api/v1/chatlog?time=2023-01-01&talker=wxid_xxx ``` 参数说明: - `time`: 时间范围,格式为 `YYYY-MM-DD` 或 `YYYY-MM-DD~YYYY-MM-DD` - `talker`: 聊天对象标识(支持 wxid、群聊 ID、备注名、昵称等) - `limit`: 返回记录数量 - `offset`: 分页偏移量 - `format`: 输出格式,支持 `json`、`csv` 或纯文本 ### 其他 API 接口 - **联系人列表**:`GET /api/v1/contact` - **群聊列表**:`GET /api/v1/chatroom` - **会话列表**:`GET /api/v1/session` ### 多媒体内容 聊天记录中的多媒体内容会通过 HTTP 服务进行提供,可通过以下路径访问: - **图片内容**:`GET /image/` - **视频内容**:`GET /video/` - **文件内容**:`GET /file/` - **语音内容**:`GET /voice/` - **多媒体内容**:`GET /data/` 当请求图片、视频、文件内容时,将返回 302 跳转到多媒体内容 URL。 当请求语音内容时,将直接返回语音内容,并对原始 SILK 语音做了实时转码 MP3 处理。 多媒体内容 URL 地址为基于`数据目录`的相对地址,请求多媒体内容将直接返回对应文件,并针对加密图片做了实时解密处理。 ## MCP 集成 Chatlog 支持 MCP (Model Context Protocol) SSE 协议,可与支持 MCP 的 AI 助手无缝集成。 启动 HTTP 服务后,通过 SSE Endpoint 访问服务: ``` GET /sse ``` ### 快速集成 Chatlog 可以与多种支持 MCP 的 AI 助手集成,包括: - **ChatWise**: 直接支持 SSE,在工具设置中添加 `http://127.0.0.1:5030/sse` - **Cherry Studio**: 直接支持 SSE,在 MCP 服务器设置中添加 `http://127.0.0.1:5030/sse` 对于不直接支持 SSE 的客户端,可以使用 [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy) 工具转发请求: - **Claude Desktop**: 通过 mcp-proxy 支持,需要配置 `claude_desktop_config.json` - **Monica Code**: 通过 mcp-proxy 支持,需要配置 VSCode 插件设置 ### 详细集成指南 查看 [MCP 集成指南](docs/mcp.md) 获取各平台的详细配置步骤和注意事项。 ## Prompt 示例 为了帮助大家更好地利用 Chatlog 与 AI 助手,我们整理了一些 prompt 示例。希望这些 prompt 可以启发大家更有效地查询和分析聊天记录,获取更精准的信息。 查看 [Prompt 指南](docs/prompt.md) 获取详细示例。 同时欢迎大家分享使用经验和 prompt!如果您有好的 prompt 示例或使用技巧,请通过 [Discussions](https://github.com/sjzar/chatlog/discussions) 进行分享,共同进步。 ## 免责声明 ⚠️ **重要提示:使用本项目前,请务必阅读并理解完整的 [免责声明](./DISCLAIMER.md)。** 本项目仅供学习、研究和个人合法使用,禁止用于任何非法目的或未授权访问他人数据。下载、安装或使用本工具即表示您同意遵守免责声明中的所有条款,并自行承担使用过程中的全部风险和法律责任。 ### 摘要(请阅读完整免责声明) - 仅限处理您自己合法拥有的聊天数据或已获授权的数据 - 严禁用于未经授权获取、查看或分析他人聊天记录 - 开发者不对使用本工具可能导致的任何损失承担责任 - 使用第三方 LLM 服务时,您应遵守这些服务的使用条款和隐私政策 **本项目完全免费开源,任何以本项目名义收费的行为均与本项目无关。** ## License 本项目基于 [Apache-2.0 许可证](./LICENSE) 开源。 ## 隐私政策 本项目不收集任何用户数据。所有数据处理均在用户本地设备上进行。使用第三方服务时,请参阅相应服务的隐私政策。 ## Thanks - [@0xlane](https://github.com/0xlane) 的 [wechat-dump-rs](https://github.com/0xlane/wechat-dump-rs) 项目 - [@xaoyaoo](https://github.com/xaoyaoo) 的 [PyWxDump](https://github.com/xaoyaoo/PyWxDump) 项目 - [@git-jiadong](https://github.com/git-jiadong) 的 [go-lame](https://github.com/git-jiadong/go-lame) 和 [go-silk](https://github.com/git-jiadong/go-silk) 项目 - [Anthropic](https://www.anthropic.com/) 的 [MCP]((https://github.com/modelcontextprotocol) ) 协议 - 各个 Go 开源库的贡献者们 ## /cmd/chatlog/cmd_decrypt.go ```go path="/cmd/chatlog/cmd_decrypt.go" package chatlog import ( "fmt" "runtime" "github.com/sjzar/chatlog/internal/chatlog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(decryptCmd) decryptCmd.Flags().StringVarP(&dataDir, "data-dir", "d", "", "data dir") decryptCmd.Flags().StringVarP(&workDir, "work-dir", "w", "", "work dir") decryptCmd.Flags().StringVarP(&key, "key", "k", "", "key") decryptCmd.Flags().StringVarP(&decryptPlatform, "platform", "p", runtime.GOOS, "platform") decryptCmd.Flags().IntVarP(&decryptVer, "version", "v", 3, "version") } var ( dataDir string workDir string key string decryptPlatform string decryptVer int ) var decryptCmd = &cobra.Command{ Use: "decrypt", Short: "decrypt", Run: func(cmd *cobra.Command, args []string) { m, err := chatlog.New("") if err != nil { log.Err(err).Msg("failed to create chatlog instance") return } if err := m.CommandDecrypt(dataDir, workDir, key, decryptPlatform, decryptVer); err != nil { log.Err(err).Msg("failed to decrypt") return } fmt.Println("decrypt success") }, } ``` ## /cmd/chatlog/cmd_dumpmemory.go ```go path="/cmd/chatlog/cmd_dumpmemory.go" package chatlog import ( "archive/zip" "fmt" "io" "os" "path/filepath" "runtime" "time" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/sjzar/chatlog/internal/wechat" "github.com/sjzar/chatlog/internal/wechat/key/darwin/glance" ) func init() { rootCmd.AddCommand(dumpmemoryCmd) } var dumpmemoryCmd = &cobra.Command{ Use: "dumpmemory", Short: "dump memory", Run: func(cmd *cobra.Command, args []string) { if runtime.GOOS != "darwin" { log.Info().Msg("dump memory only support macOS") } session := time.Now().Format("20060102150405") dir, err := os.Getwd() if err != nil { log.Fatal().Err(err).Msg("get current directory failed") return } log.Info().Msgf("current directory: %s", dir) // step 1. check pid if err = wechat.Load(); err != nil { log.Fatal().Err(err).Msg("load wechat failed") return } accounts := wechat.GetAccounts() if len(accounts) == 0 { log.Fatal().Msg("no wechat account found") return } log.Info().Msgf("found %d wechat account", len(accounts)) for i, a := range accounts { log.Info().Msgf("%d. %s %d %s", i, a.FullVersion, a.PID, a.DataDir) } // step 2. dump memory account := accounts[0] file := fmt.Sprintf("wechat_%s_%d_%s.bin", account.FullVersion, account.PID, session) path := filepath.Join(dir, file) log.Info().Msgf("dumping memory to %s", path) g := glance.NewGlance(account.PID) b, err := g.Read() if err != nil { log.Fatal().Err(err).Msg("read memory failed") return } if err = os.WriteFile(path, b, 0644); err != nil { log.Fatal().Err(err).Msg("write memory failed") return } log.Info().Msg("dump memory success") // step 3. copy encrypted database file dbFile := "db_storage/session/session.db" if account.Version == 3 { dbFile = "Session/session_new.db" } from := filepath.Join(account.DataDir, dbFile) to := filepath.Join(dir, fmt.Sprintf("wechat_%s_%d_session.db", account.FullVersion, account.PID)) log.Info().Msgf("copying %s to %s", from, to) b, err = os.ReadFile(from) if err != nil { log.Fatal().Err(err).Msg("read session.db failed") return } if err = os.WriteFile(to, b, 0644); err != nil { log.Fatal().Err(err).Msg("write session.db failed") return } log.Info().Msg("copy session.db success") // step 4. package zipFile := fmt.Sprintf("wechat_%s_%d_%s.zip", account.FullVersion, account.PID, session) zipPath := filepath.Join(dir, zipFile) log.Info().Msgf("packaging to %s", zipPath) zf, err := os.Create(zipPath) if err != nil { log.Fatal().Err(err).Msg("create zip file failed") return } defer zf.Close() zw := zip.NewWriter(zf) for _, file := range []string{file, to} { f, err := os.Open(file) if err != nil { log.Fatal().Err(err).Msg("open file failed") return } defer f.Close() info, err := f.Stat() if err != nil { log.Fatal().Err(err).Msg("get file info failed") return } header, err := zip.FileInfoHeader(info) if err != nil { log.Fatal().Err(err).Msg("create zip file info header failed") return } header.Name = filepath.Base(file) header.Method = zip.Deflate writer, err := zw.CreateHeader(header) if err != nil { log.Fatal().Err(err).Msg("create zip file header failed") return } if _, err = io.Copy(writer, f); err != nil { log.Fatal().Err(err).Msg("copy file to zip failed") return } } if err = zw.Close(); err != nil { log.Fatal().Err(err).Msg("close zip writer failed") return } log.Info().Msgf("package success, please send %s to developer", zipPath) }, } ``` ## /cmd/chatlog/cmd_key.go ```go path="/cmd/chatlog/cmd_key.go" package chatlog import ( "fmt" "github.com/sjzar/chatlog/internal/chatlog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(keyCmd) keyCmd.Flags().IntVarP(&pid, "pid", "p", 0, "pid") } var pid int var keyCmd = &cobra.Command{ Use: "key", Short: "key", Run: func(cmd *cobra.Command, args []string) { m, err := chatlog.New("") if err != nil { log.Err(err).Msg("failed to create chatlog instance") return } ret, err := m.CommandKey(pid) if err != nil { log.Err(err).Msg("failed to get key") return } fmt.Println(ret) }, } ``` ## /cmd/chatlog/cmd_server.go ```go path="/cmd/chatlog/cmd_server.go" package chatlog import ( "runtime" "github.com/sjzar/chatlog/internal/chatlog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(serverCmd) serverCmd.Flags().StringVarP(&serverAddr, "addr", "a", "127.0.0.1:5030", "server address") serverCmd.Flags().StringVarP(&serverDataDir, "data-dir", "d", "", "data dir") serverCmd.Flags().StringVarP(&serverWorkDir, "work-dir", "w", "", "work dir") serverCmd.Flags().StringVarP(&serverPlatform, "platform", "p", runtime.GOOS, "platform") serverCmd.Flags().IntVarP(&serverVer, "version", "v", 3, "version") } var ( serverAddr string serverDataDir string serverWorkDir string serverPlatform string serverVer int ) var serverCmd = &cobra.Command{ Use: "server", Short: "Start HTTP server", Run: func(cmd *cobra.Command, args []string) { m, err := chatlog.New("") if err != nil { log.Err(err).Msg("failed to create chatlog instance") return } if err := m.CommandHTTPServer(serverAddr, serverDataDir, serverWorkDir, serverPlatform, serverVer); err != nil { log.Err(err).Msg("failed to start server") return } }, } ``` ## /cmd/chatlog/cmd_version.go ```go path="/cmd/chatlog/cmd_version.go" package chatlog import ( "fmt" "github.com/sjzar/chatlog/pkg/version" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(versionCmd) versionCmd.Flags().BoolVarP(&versionM, "module", "m", false, "module version information") } var versionM bool var versionCmd = &cobra.Command{ Use: "version [-m]", Short: "Show the version of chatlog", Run: func(cmd *cobra.Command, args []string) { if versionM { fmt.Println(version.GetMore(true)) } else { fmt.Printf("chatlog %s\n", version.GetMore(false)) } }, } ``` ## /cmd/chatlog/log.go ```go path="/cmd/chatlog/log.go" package chatlog import ( "io" "os" "path/filepath" "time" "github.com/sjzar/chatlog/pkg/util" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var Debug bool func initLog(cmd *cobra.Command, args []string) { zerolog.SetGlobalLevel(zerolog.InfoLevel) if Debug { zerolog.SetGlobalLevel(zerolog.DebugLevel) } log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}) } func initTuiLog(cmd *cobra.Command, args []string) { logOutput := io.Discard debug, _ := cmd.Flags().GetBool("debug") if debug { logpath := util.DefaultWorkDir("") util.PrepareDir(logpath) logFD, err := os.OpenFile(filepath.Join(logpath, "chatlog.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm) if err != nil { panic(err) } logOutput = logFD } log.Logger = log.Output(zerolog.ConsoleWriter{Out: logOutput, NoColor: true, TimeFormat: time.RFC3339}) logrus.SetOutput(logOutput) } ``` ## /cmd/chatlog/root.go ```go path="/cmd/chatlog/root.go" package chatlog import ( "github.com/sjzar/chatlog/internal/chatlog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) func init() { // windows only cobra.MousetrapHelpText = "" rootCmd.PersistentFlags().BoolVar(&Debug, "debug", false, "debug") rootCmd.PersistentPreRun = initLog } func Execute() { if err := rootCmd.Execute(); err != nil { log.Err(err).Msg("command execution failed") } } var rootCmd = &cobra.Command{ Use: "chatlog", Short: "chatlog", Long: `chatlog`, Example: `chatlog`, Args: cobra.MinimumNArgs(0), CompletionOptions: cobra.CompletionOptions{ HiddenDefaultCmd: true, }, PreRun: initTuiLog, Run: Root, } func Root(cmd *cobra.Command, args []string) { m, err := chatlog.New("") if err != nil { log.Err(err).Msg("failed to create chatlog instance") return } if err := m.Run(); err != nil { log.Err(err).Msg("failed to run chatlog instance") } } ``` ## /docs/mcp.md # MCP 集成指南 ## 目录 - [MCP 集成指南](#mcp-集成指南) - [目录](#目录) - [前期准备](#前期准备) - [mcp-proxy](#mcp-proxy) - [ChatWise](#chatwise) - [Cherry Studio](#cherry-studio) - [Claude Desktop](#claude-desktop) - [Monica Code](#monica-code) ## 前期准备 运行 `chatlog`,完成数据解密并开启 HTTP 服务 ### mcp-proxy 如果遇到不支持 `SSE` 的客户端,可以尝试使用 `mcp-proxy` 将 `stdio` 的请求转换为 `SSE`。 项目地址:https://github.com/sparfenyuk/mcp-proxy 安装方式: ```shell # 使用 uv 工具安装,也可参考项目文档的其他安装方式 uv tool install mcp-proxy # 查询 mcp-proxy 的路径,后续可直接使用该路径 which mcp-proxy /Users/sarv/.local/bin/mcp-proxy ``` ## ChatWise - 官网:https://chatwise.app/ - 使用方式:MCP SSE - 注意事项:使用 ChatWise 的 MCP 功能需要 Pro 权限 1. 在 `设置 - 工具` 下新建 `SSE 请求` 工具 ![chatwise-1](https://github.com/user-attachments/assets/87e40f39-9fbc-4ff1-954a-d95548cde4c2) 1. 在 URL 中填写 `http://127.0.0.1:5030/sse`,并勾选 `自动执行工具`,点击 `查看工具` 即可检查连接 `chatlog` 是否正常 ![chatwise-2](https://github.com/user-attachments/assets/8f98ef18-8e6c-40e6-ae78-8cd13e411c36) 3. 返回主页,选择支持 MCP 调用的模型,打开 `chatlog` 工具选项 ![chatwise-3](https://github.com/user-attachments/assets/ea2aa178-5439-492b-a92f-4f4fc08828e7) 4. 测试功能是否正常 ![chatwise-4](https://github.com/user-attachments/assets/8f82cb53-8372-40ee-a299-c02d3399403a) ## Cherry Studio - 官网:https://cherry-ai.com/ - 使用方式:MCP SSE 1. 在 `设置 - MCP 服务器` 下点击 `添加服务器`,输入名称为 `chatlog`,选择类型为 `服务器发送事件(sse)`,填写 URL 为 `http://127.0.0.1:5030/sse`,点击 `保存`。(注意:点击保存前不要先点击左侧的开启按钮) ![cherry-1](https://github.com/user-attachments/assets/93fc8b0a-9d95-499e-ab6c-e22b0c96fd6a) 2. 选择支持 MCP 调用的模型,打开 `chatlog` 工具选项 ![cherry-2](https://github.com/user-attachments/assets/4e5bf752-2eab-4e7c-b73b-1b759d4a5f29) 3. 测试功能是否正常 ![cherry-3](https://github.com/user-attachments/assets/c58a019f-fd5f-4fa3-830a-e81a60f2aa6f) ## Claude Desktop - 官网:https://claude.ai/download - 使用方式:mcp-proxy - 参考资料:https://modelcontextprotocol.io/quickstart/user#2-add-the-filesystem-mcp-server 1. 请先参考 [mcp-proxy](#mcp-proxy) 安装 `mcp-proxy` 2. 进入 Claude Desktop `Settings - Developer`,点击 `Edit Config` 按钮,这样会创建一个 `claude_desktop_config.json` 配置文件,并引导你编辑该文件 3. 编辑 `claude_desktop_config.json` 文件,配置名称为 `chatlog`,command 为 `mcp-proxy` 的路径,args 为 `http://127.0.0.1:5030/sse`,如下所示: ```json { "mcpServers": { "chatlog": { "command": "/Users/sarv/.local/bin/mcp-proxy", "args": [ "http://localhost:5030/sse" ] } }, "globalShortcut": "" } ``` 4. 保存 `claude_desktop_config.json` 文件,重启 Claude Desktop,可以看到 `chatlog` 已经添加成功 ![claude-1](https://github.com/user-attachments/assets/f4e872cc-e6c1-4e24-97da-266466949cdf) 5. 测试功能是否正常 ![claude-2](https://github.com/user-attachments/assets/832bb4d2-3639-4cbc-8b17-f4b812ea3637) ## Monica Code - 官网:https://monica.im/en/code - 使用方式:mcp-proxy - 参考资料:https://github.com/Monica-IM/Monica-Code/blob/main/Reference/config.md#modelcontextprotocolserver 1. 请先参考 [mcp-proxy](#mcp-proxy) 安装 `mcp-proxy` 2. 在 vscode 插件文件夹(`~/.vscode/extensions`)下找到 Monica Code 的目录,编辑 `config_schema.json` 文件。将 `experimental - modelContextProtocolServer` 中 `transport` 设置为如下内容: ```json { "experimental": { "type": "object", "title": "Experimental", "description": "Experimental properties are subject to change.", "properties": { "modelContextProtocolServer": { "type": "object", "properties": { "transport": { "type": "stdio", "command": "/Users/sarv/.local/bin/mcp-proxy", "args": [ "http://localhost:5030/sse" ] } }, "required": [ "transport" ] } } } } ``` 3. 重启 vscode,可以看到 `chatlog` 已经添加成功 ![monica-1](https://github.com/user-attachments/assets/8d0a96f2-ed05-48aa-a99a-06648ae1c500) 4. 测试功能是否正常 ![monica-2](https://github.com/user-attachments/assets/054e0a30-428a-48a6-9f31-d2596fb8f743) ## /docs/prompt.md # Prompt 指南 ## 概述 优秀的 `prompt` 可以极大的提高 `chatlog` 使用体验,收集了部分群友分享的 `prompt`,供大家参考。 在处理聊天记录时,尽量选择上下文长度足够的 LLM,例如 `Gemini 2.5 Pro`、`Claude 3.5 Sonnet` 等。 欢迎大家在 [Discussions](https://github.com/sjzar/chatlog/discussions/47) 中分享自己的使用方式,共同进步。 ## 群聊总结 作者:@eyaeya ```md 你是一个中文的群聊总结的助手,你可以为一个微信的群聊记录,提取并总结每个时间段大家在重点讨论的话题内容。 请帮我将 "" 在