wechat-article-uploader 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. wechat_article_uploader-0.1.0/LICENSE +21 -0
  2. wechat_article_uploader-0.1.0/PKG-INFO +220 -0
  3. wechat_article_uploader-0.1.0/README.md +196 -0
  4. wechat_article_uploader-0.1.0/pyproject.toml +52 -0
  5. wechat_article_uploader-0.1.0/setup.cfg +4 -0
  6. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/PKG-INFO +220 -0
  7. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/SOURCES.txt +21 -0
  8. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/dependency_links.txt +1 -0
  9. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/entry_points.txt +2 -0
  10. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/requires.txt +6 -0
  11. wechat_article_uploader-0.1.0/src/wechat_article_uploader.egg-info/top_level.txt +1 -0
  12. wechat_article_uploader-0.1.0/src/wechat_uploader/__init__.py +3 -0
  13. wechat_article_uploader-0.1.0/src/wechat_uploader/__main__.py +5 -0
  14. wechat_article_uploader-0.1.0/src/wechat_uploader/assets/__init__.py +1 -0
  15. wechat_article_uploader-0.1.0/src/wechat_uploader/assets/wechat_style.css +269 -0
  16. wechat_article_uploader-0.1.0/src/wechat_uploader/cli.py +319 -0
  17. wechat_article_uploader-0.1.0/src/wechat_uploader/config.py +249 -0
  18. wechat_article_uploader-0.1.0/src/wechat_uploader/parser.py +198 -0
  19. wechat_article_uploader-0.1.0/src/wechat_uploader/wechat_client.py +196 -0
  20. wechat_article_uploader-0.1.0/tests/test_cli.py +31 -0
  21. wechat_article_uploader-0.1.0/tests/test_config.py +63 -0
  22. wechat_article_uploader-0.1.0/tests/test_parser.py +36 -0
  23. wechat_article_uploader-0.1.0/tests/test_wechat_client.py +67 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: wechat-article-uploader
3
+ Version: 0.1.0
4
+ Summary: Upload local Markdown or text articles to WeChat Official Accounts drafts.
5
+ License-Expression: MIT
6
+ Keywords: wechat,weixin,cli,markdown
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: End Users/Desktop
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: beautifulsoup4>=4.12
20
+ Requires-Dist: markdown>=3.6
21
+ Requires-Dist: requests>=2.31
22
+ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
23
+ Dynamic: license-file
24
+
25
+ # wechat-article-uploader
26
+
27
+ 把本地 `md` / `txt` 文章上传到微信公众号草稿箱的命令行工具。
28
+
29
+ 它会自动完成这些事:
30
+
31
+ - 解析本地文章标题、正文和摘要
32
+ - 把正文里的本地图片先上传到公众号素材库,再替换为远程 URL
33
+ - 自动套用内置公众号样式,并转换为行内样式,降低微信编辑器兼容问题
34
+ - 支持单文件上传、目录批量上传和 `dry-run` 预演
35
+
36
+ ## 安装
37
+
38
+ 发布到 PyPI 后,直接安装:
39
+
40
+ ```bash
41
+ python3 -m pip install wechat-article-uploader
42
+ ```
43
+
44
+ 如果你是在仓库里本地开发:
45
+
46
+ ```bash
47
+ uv sync --dev
48
+ ```
49
+
50
+ 执行命令时,推荐统一走 `uv run`:
51
+
52
+ ```bash
53
+ uv run wechat-article-uploader --help
54
+ ```
55
+
56
+ ## 配置文件
57
+
58
+ 这个项目已经改为使用 `config.toml`,不再依赖 `.env`。
59
+
60
+ 你可以用下面两种方式提供配置:
61
+
62
+ 1. 在当前运行目录放一个 `config.toml`
63
+ 2. 放到系统默认配置路径
64
+
65
+ 查看默认配置路径:
66
+
67
+ ```bash
68
+ uv run wechat-article-uploader --print-config-path
69
+ ```
70
+
71
+ 创建配置文件最简单的方法:
72
+
73
+ ```bash
74
+ cp config.example.toml config.toml
75
+ ```
76
+
77
+ 配置内容示例:
78
+
79
+ ```toml
80
+ [wechat_article_uploader]
81
+ app_id = "your_app_id"
82
+ app_secret = "your_app_secret"
83
+ default_author = ""
84
+ default_thumb_media_id = ""
85
+ default_content_source_url = ""
86
+ default_need_open_comment = 0
87
+ default_only_fans_can_comment = 0
88
+ request_timeout = 20
89
+ retry_times = 3
90
+ retry_backoff_seconds = 1.5
91
+ token_cache_file = ""
92
+ style_file = ""
93
+ ```
94
+
95
+ 字段说明:
96
+
97
+ - `app_id`:公众号 AppID
98
+ - `app_secret`:公众号 AppSecret
99
+ - `default_author`:默认作者,可留空
100
+ - `default_thumb_media_id`:默认封面素材 ID,可留空;留空时会自动使用正文里第一张成功上传到素材库的本地图片
101
+ - `default_content_source_url`:原文链接,可留空
102
+ - `default_need_open_comment`:默认评论开关,`0` 或 `1`
103
+ - `default_only_fans_can_comment`:默认仅粉丝评论,`0` 或 `1`
104
+ - `request_timeout`:接口超时秒数
105
+ - `retry_times`:失败重试次数
106
+ - `retry_backoff_seconds`:每次重试的退避间隔倍率
107
+ - `token_cache_file`:token 缓存文件路径;留空时使用系统缓存目录
108
+ - `style_file`:自定义 CSS 文件路径;留空时使用包内默认样式
109
+
110
+ ## 用法
111
+
112
+ ### 单文件上传
113
+
114
+ ```bash
115
+ uv run wechat-article-uploader --file "/path/to/article.md"
116
+ ```
117
+
118
+ ### 目录批量上传
119
+
120
+ ```bash
121
+ uv run wechat-article-uploader --dir "/path/to/articles"
122
+ ```
123
+
124
+ ### 指定配置文件
125
+
126
+ ```bash
127
+ uv run wechat-article-uploader --config "/path/to/config.toml" --file "/path/to/article.md"
128
+ ```
129
+
130
+ ### 预演模式
131
+
132
+ ```bash
133
+ uv run wechat-article-uploader --dir "/path/to/articles" --dry-run
134
+ ```
135
+
136
+ `dry-run` 不会调用微信接口,适合先检查标题、解析和日志输出。
137
+
138
+ 如果没有显式传 `--thumb-media-id`,也没有在配置文件中设置 `default_thumb_media_id`,程序会默认使用正文里第一张成功上传到素材库的本地图片作为封面。
139
+
140
+ ### 常用覆盖参数
141
+
142
+ ```bash
143
+ uv run wechat-article-uploader \
144
+ --file "/path/to/article.md" \
145
+ --author "作者名" \
146
+ --thumb-media-id "封面素材ID" \
147
+ --digest "摘要文本" \
148
+ --content-source-url "https://example.com/source" \
149
+ --need-open-comment 0 \
150
+ --only-fans-can-comment 0
151
+ ```
152
+
153
+ 如果你还在仓库里直接运行,也可以继续用兼容入口:
154
+
155
+ ```bash
156
+ uv run python main.py --file "/path/to/article.md"
157
+ ```
158
+
159
+ ## 输入规则
160
+
161
+ - 支持后缀:`md`、`txt`
162
+ - Markdown:
163
+ - 首个非空行为 `# 标题` 或 `## 标题` 时,会作为文章标题
164
+ - 否则使用文件名作为标题
165
+ - Text:
166
+ - 首个非空行作为标题
167
+ - 后续内容作为正文
168
+
169
+ ## 日志与失败重试
170
+
171
+ 每次运行会在 `logs/` 生成:
172
+
173
+ - `upload_results_时间戳.json`:完整结果
174
+ - `failed.json`:仅失败项
175
+
176
+ 你可以根据 `failed.json` 中的文件路径做二次重传。
177
+
178
+ ## 开发与发布
179
+
180
+ 本项目已经整理为标准 Python 包结构,支持构建 wheel 和 sdist:
181
+
182
+ ```bash
183
+ uv build
184
+ ```
185
+
186
+ 本地测试:
187
+
188
+ ```bash
189
+ uv run pytest
190
+ ```
191
+
192
+ 如果你准备正式发 GitHub Release 和 PyPI,完整流程见 `RELEASING.md`。
193
+
194
+ 如果你刚克隆仓库,推荐流程是:
195
+
196
+ ```bash
197
+ uv sync --dev
198
+ uv run pytest
199
+ uv build
200
+ ```
201
+
202
+ ## 常见错误
203
+
204
+ - `未找到配置文件`:先创建 `config.toml`,或通过 `--config` 指定
205
+ - `缺少配置项`:检查 `app_id`、`app_secret` 是否填写
206
+ - `未提供封面 thumb_media_id,且自动获取失败`:检查素材库权限、IP 白名单,或手动填写 `default_thumb_media_id`
207
+ - `加载样式文件失败`:检查 `style_file` 路径是否正确、文件是否为空
208
+ - `创建草稿失败 errcode=...`:检查公众号权限、素材 ID 是否有效、内容是否符合微信限制
209
+ - `上传素材库图片失败`:检查本地图片路径、公众号素材权限、图片格式与大小限制
210
+
211
+ ## 已知限制
212
+
213
+ - 微信 `draft/add` 接口当前不支持通过 API 设置“原创声明”和“创作来源”
214
+ - 若需要这两项,请在公众号后台草稿编辑页手动设置后再发布
215
+
216
+ ## 发布说明
217
+
218
+ - 项目许可证已设为 `MIT`
219
+ - PyPI 自动发布工作流已配置在 `.github/workflows/publish-pypi.yml`
220
+ - 首次公开前,仍建议轮换一次公众号密钥
@@ -0,0 +1,196 @@
1
+ # wechat-article-uploader
2
+
3
+ 把本地 `md` / `txt` 文章上传到微信公众号草稿箱的命令行工具。
4
+
5
+ 它会自动完成这些事:
6
+
7
+ - 解析本地文章标题、正文和摘要
8
+ - 把正文里的本地图片先上传到公众号素材库,再替换为远程 URL
9
+ - 自动套用内置公众号样式,并转换为行内样式,降低微信编辑器兼容问题
10
+ - 支持单文件上传、目录批量上传和 `dry-run` 预演
11
+
12
+ ## 安装
13
+
14
+ 发布到 PyPI 后,直接安装:
15
+
16
+ ```bash
17
+ python3 -m pip install wechat-article-uploader
18
+ ```
19
+
20
+ 如果你是在仓库里本地开发:
21
+
22
+ ```bash
23
+ uv sync --dev
24
+ ```
25
+
26
+ 执行命令时,推荐统一走 `uv run`:
27
+
28
+ ```bash
29
+ uv run wechat-article-uploader --help
30
+ ```
31
+
32
+ ## 配置文件
33
+
34
+ 这个项目已经改为使用 `config.toml`,不再依赖 `.env`。
35
+
36
+ 你可以用下面两种方式提供配置:
37
+
38
+ 1. 在当前运行目录放一个 `config.toml`
39
+ 2. 放到系统默认配置路径
40
+
41
+ 查看默认配置路径:
42
+
43
+ ```bash
44
+ uv run wechat-article-uploader --print-config-path
45
+ ```
46
+
47
+ 创建配置文件最简单的方法:
48
+
49
+ ```bash
50
+ cp config.example.toml config.toml
51
+ ```
52
+
53
+ 配置内容示例:
54
+
55
+ ```toml
56
+ [wechat_article_uploader]
57
+ app_id = "your_app_id"
58
+ app_secret = "your_app_secret"
59
+ default_author = ""
60
+ default_thumb_media_id = ""
61
+ default_content_source_url = ""
62
+ default_need_open_comment = 0
63
+ default_only_fans_can_comment = 0
64
+ request_timeout = 20
65
+ retry_times = 3
66
+ retry_backoff_seconds = 1.5
67
+ token_cache_file = ""
68
+ style_file = ""
69
+ ```
70
+
71
+ 字段说明:
72
+
73
+ - `app_id`:公众号 AppID
74
+ - `app_secret`:公众号 AppSecret
75
+ - `default_author`:默认作者,可留空
76
+ - `default_thumb_media_id`:默认封面素材 ID,可留空;留空时会自动使用正文里第一张成功上传到素材库的本地图片
77
+ - `default_content_source_url`:原文链接,可留空
78
+ - `default_need_open_comment`:默认评论开关,`0` 或 `1`
79
+ - `default_only_fans_can_comment`:默认仅粉丝评论,`0` 或 `1`
80
+ - `request_timeout`:接口超时秒数
81
+ - `retry_times`:失败重试次数
82
+ - `retry_backoff_seconds`:每次重试的退避间隔倍率
83
+ - `token_cache_file`:token 缓存文件路径;留空时使用系统缓存目录
84
+ - `style_file`:自定义 CSS 文件路径;留空时使用包内默认样式
85
+
86
+ ## 用法
87
+
88
+ ### 单文件上传
89
+
90
+ ```bash
91
+ uv run wechat-article-uploader --file "/path/to/article.md"
92
+ ```
93
+
94
+ ### 目录批量上传
95
+
96
+ ```bash
97
+ uv run wechat-article-uploader --dir "/path/to/articles"
98
+ ```
99
+
100
+ ### 指定配置文件
101
+
102
+ ```bash
103
+ uv run wechat-article-uploader --config "/path/to/config.toml" --file "/path/to/article.md"
104
+ ```
105
+
106
+ ### 预演模式
107
+
108
+ ```bash
109
+ uv run wechat-article-uploader --dir "/path/to/articles" --dry-run
110
+ ```
111
+
112
+ `dry-run` 不会调用微信接口,适合先检查标题、解析和日志输出。
113
+
114
+ 如果没有显式传 `--thumb-media-id`,也没有在配置文件中设置 `default_thumb_media_id`,程序会默认使用正文里第一张成功上传到素材库的本地图片作为封面。
115
+
116
+ ### 常用覆盖参数
117
+
118
+ ```bash
119
+ uv run wechat-article-uploader \
120
+ --file "/path/to/article.md" \
121
+ --author "作者名" \
122
+ --thumb-media-id "封面素材ID" \
123
+ --digest "摘要文本" \
124
+ --content-source-url "https://example.com/source" \
125
+ --need-open-comment 0 \
126
+ --only-fans-can-comment 0
127
+ ```
128
+
129
+ 如果你还在仓库里直接运行,也可以继续用兼容入口:
130
+
131
+ ```bash
132
+ uv run python main.py --file "/path/to/article.md"
133
+ ```
134
+
135
+ ## 输入规则
136
+
137
+ - 支持后缀:`md`、`txt`
138
+ - Markdown:
139
+ - 首个非空行为 `# 标题` 或 `## 标题` 时,会作为文章标题
140
+ - 否则使用文件名作为标题
141
+ - Text:
142
+ - 首个非空行作为标题
143
+ - 后续内容作为正文
144
+
145
+ ## 日志与失败重试
146
+
147
+ 每次运行会在 `logs/` 生成:
148
+
149
+ - `upload_results_时间戳.json`:完整结果
150
+ - `failed.json`:仅失败项
151
+
152
+ 你可以根据 `failed.json` 中的文件路径做二次重传。
153
+
154
+ ## 开发与发布
155
+
156
+ 本项目已经整理为标准 Python 包结构,支持构建 wheel 和 sdist:
157
+
158
+ ```bash
159
+ uv build
160
+ ```
161
+
162
+ 本地测试:
163
+
164
+ ```bash
165
+ uv run pytest
166
+ ```
167
+
168
+ 如果你准备正式发 GitHub Release 和 PyPI,完整流程见 `RELEASING.md`。
169
+
170
+ 如果你刚克隆仓库,推荐流程是:
171
+
172
+ ```bash
173
+ uv sync --dev
174
+ uv run pytest
175
+ uv build
176
+ ```
177
+
178
+ ## 常见错误
179
+
180
+ - `未找到配置文件`:先创建 `config.toml`,或通过 `--config` 指定
181
+ - `缺少配置项`:检查 `app_id`、`app_secret` 是否填写
182
+ - `未提供封面 thumb_media_id,且自动获取失败`:检查素材库权限、IP 白名单,或手动填写 `default_thumb_media_id`
183
+ - `加载样式文件失败`:检查 `style_file` 路径是否正确、文件是否为空
184
+ - `创建草稿失败 errcode=...`:检查公众号权限、素材 ID 是否有效、内容是否符合微信限制
185
+ - `上传素材库图片失败`:检查本地图片路径、公众号素材权限、图片格式与大小限制
186
+
187
+ ## 已知限制
188
+
189
+ - 微信 `draft/add` 接口当前不支持通过 API 设置“原创声明”和“创作来源”
190
+ - 若需要这两项,请在公众号后台草稿编辑页手动设置后再发布
191
+
192
+ ## 发布说明
193
+
194
+ - 项目许可证已设为 `MIT`
195
+ - PyPI 自动发布工作流已配置在 `.github/workflows/publish-pypi.yml`
196
+ - 首次公开前,仍建议轮换一次公众号密钥
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "wechat-article-uploader"
7
+ version = "0.1.0"
8
+ description = "Upload local Markdown or text articles to WeChat Official Accounts drafts."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ dependencies = [
14
+ "beautifulsoup4>=4.12",
15
+ "markdown>=3.6",
16
+ "requests>=2.31",
17
+ "tomli>=2.0.1; python_version < '3.11'",
18
+ ]
19
+ keywords = ["wechat", "weixin", "cli", "markdown"]
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Environment :: Console",
23
+ "Intended Audience :: End Users/Desktop",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Topic :: Utilities",
30
+ ]
31
+
32
+ [project.scripts]
33
+ wechat-article-uploader = "wechat_uploader.cli:main"
34
+
35
+ [dependency-groups]
36
+ dev = [
37
+ "build>=1.2",
38
+ "pytest>=8.0",
39
+ "twine>=5.0",
40
+ ]
41
+
42
+ [tool.uv]
43
+ package = true
44
+
45
+ [tool.setuptools]
46
+ package-dir = {"" = "src"}
47
+
48
+ [tool.setuptools.packages.find]
49
+ where = ["src"]
50
+
51
+ [tool.setuptools.package-data]
52
+ wechat_uploader = ["assets/*.css"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: wechat-article-uploader
3
+ Version: 0.1.0
4
+ Summary: Upload local Markdown or text articles to WeChat Official Accounts drafts.
5
+ License-Expression: MIT
6
+ Keywords: wechat,weixin,cli,markdown
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: End Users/Desktop
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: beautifulsoup4>=4.12
20
+ Requires-Dist: markdown>=3.6
21
+ Requires-Dist: requests>=2.31
22
+ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
23
+ Dynamic: license-file
24
+
25
+ # wechat-article-uploader
26
+
27
+ 把本地 `md` / `txt` 文章上传到微信公众号草稿箱的命令行工具。
28
+
29
+ 它会自动完成这些事:
30
+
31
+ - 解析本地文章标题、正文和摘要
32
+ - 把正文里的本地图片先上传到公众号素材库,再替换为远程 URL
33
+ - 自动套用内置公众号样式,并转换为行内样式,降低微信编辑器兼容问题
34
+ - 支持单文件上传、目录批量上传和 `dry-run` 预演
35
+
36
+ ## 安装
37
+
38
+ 发布到 PyPI 后,直接安装:
39
+
40
+ ```bash
41
+ python3 -m pip install wechat-article-uploader
42
+ ```
43
+
44
+ 如果你是在仓库里本地开发:
45
+
46
+ ```bash
47
+ uv sync --dev
48
+ ```
49
+
50
+ 执行命令时,推荐统一走 `uv run`:
51
+
52
+ ```bash
53
+ uv run wechat-article-uploader --help
54
+ ```
55
+
56
+ ## 配置文件
57
+
58
+ 这个项目已经改为使用 `config.toml`,不再依赖 `.env`。
59
+
60
+ 你可以用下面两种方式提供配置:
61
+
62
+ 1. 在当前运行目录放一个 `config.toml`
63
+ 2. 放到系统默认配置路径
64
+
65
+ 查看默认配置路径:
66
+
67
+ ```bash
68
+ uv run wechat-article-uploader --print-config-path
69
+ ```
70
+
71
+ 创建配置文件最简单的方法:
72
+
73
+ ```bash
74
+ cp config.example.toml config.toml
75
+ ```
76
+
77
+ 配置内容示例:
78
+
79
+ ```toml
80
+ [wechat_article_uploader]
81
+ app_id = "your_app_id"
82
+ app_secret = "your_app_secret"
83
+ default_author = ""
84
+ default_thumb_media_id = ""
85
+ default_content_source_url = ""
86
+ default_need_open_comment = 0
87
+ default_only_fans_can_comment = 0
88
+ request_timeout = 20
89
+ retry_times = 3
90
+ retry_backoff_seconds = 1.5
91
+ token_cache_file = ""
92
+ style_file = ""
93
+ ```
94
+
95
+ 字段说明:
96
+
97
+ - `app_id`:公众号 AppID
98
+ - `app_secret`:公众号 AppSecret
99
+ - `default_author`:默认作者,可留空
100
+ - `default_thumb_media_id`:默认封面素材 ID,可留空;留空时会自动使用正文里第一张成功上传到素材库的本地图片
101
+ - `default_content_source_url`:原文链接,可留空
102
+ - `default_need_open_comment`:默认评论开关,`0` 或 `1`
103
+ - `default_only_fans_can_comment`:默认仅粉丝评论,`0` 或 `1`
104
+ - `request_timeout`:接口超时秒数
105
+ - `retry_times`:失败重试次数
106
+ - `retry_backoff_seconds`:每次重试的退避间隔倍率
107
+ - `token_cache_file`:token 缓存文件路径;留空时使用系统缓存目录
108
+ - `style_file`:自定义 CSS 文件路径;留空时使用包内默认样式
109
+
110
+ ## 用法
111
+
112
+ ### 单文件上传
113
+
114
+ ```bash
115
+ uv run wechat-article-uploader --file "/path/to/article.md"
116
+ ```
117
+
118
+ ### 目录批量上传
119
+
120
+ ```bash
121
+ uv run wechat-article-uploader --dir "/path/to/articles"
122
+ ```
123
+
124
+ ### 指定配置文件
125
+
126
+ ```bash
127
+ uv run wechat-article-uploader --config "/path/to/config.toml" --file "/path/to/article.md"
128
+ ```
129
+
130
+ ### 预演模式
131
+
132
+ ```bash
133
+ uv run wechat-article-uploader --dir "/path/to/articles" --dry-run
134
+ ```
135
+
136
+ `dry-run` 不会调用微信接口,适合先检查标题、解析和日志输出。
137
+
138
+ 如果没有显式传 `--thumb-media-id`,也没有在配置文件中设置 `default_thumb_media_id`,程序会默认使用正文里第一张成功上传到素材库的本地图片作为封面。
139
+
140
+ ### 常用覆盖参数
141
+
142
+ ```bash
143
+ uv run wechat-article-uploader \
144
+ --file "/path/to/article.md" \
145
+ --author "作者名" \
146
+ --thumb-media-id "封面素材ID" \
147
+ --digest "摘要文本" \
148
+ --content-source-url "https://example.com/source" \
149
+ --need-open-comment 0 \
150
+ --only-fans-can-comment 0
151
+ ```
152
+
153
+ 如果你还在仓库里直接运行,也可以继续用兼容入口:
154
+
155
+ ```bash
156
+ uv run python main.py --file "/path/to/article.md"
157
+ ```
158
+
159
+ ## 输入规则
160
+
161
+ - 支持后缀:`md`、`txt`
162
+ - Markdown:
163
+ - 首个非空行为 `# 标题` 或 `## 标题` 时,会作为文章标题
164
+ - 否则使用文件名作为标题
165
+ - Text:
166
+ - 首个非空行作为标题
167
+ - 后续内容作为正文
168
+
169
+ ## 日志与失败重试
170
+
171
+ 每次运行会在 `logs/` 生成:
172
+
173
+ - `upload_results_时间戳.json`:完整结果
174
+ - `failed.json`:仅失败项
175
+
176
+ 你可以根据 `failed.json` 中的文件路径做二次重传。
177
+
178
+ ## 开发与发布
179
+
180
+ 本项目已经整理为标准 Python 包结构,支持构建 wheel 和 sdist:
181
+
182
+ ```bash
183
+ uv build
184
+ ```
185
+
186
+ 本地测试:
187
+
188
+ ```bash
189
+ uv run pytest
190
+ ```
191
+
192
+ 如果你准备正式发 GitHub Release 和 PyPI,完整流程见 `RELEASING.md`。
193
+
194
+ 如果你刚克隆仓库,推荐流程是:
195
+
196
+ ```bash
197
+ uv sync --dev
198
+ uv run pytest
199
+ uv build
200
+ ```
201
+
202
+ ## 常见错误
203
+
204
+ - `未找到配置文件`:先创建 `config.toml`,或通过 `--config` 指定
205
+ - `缺少配置项`:检查 `app_id`、`app_secret` 是否填写
206
+ - `未提供封面 thumb_media_id,且自动获取失败`:检查素材库权限、IP 白名单,或手动填写 `default_thumb_media_id`
207
+ - `加载样式文件失败`:检查 `style_file` 路径是否正确、文件是否为空
208
+ - `创建草稿失败 errcode=...`:检查公众号权限、素材 ID 是否有效、内容是否符合微信限制
209
+ - `上传素材库图片失败`:检查本地图片路径、公众号素材权限、图片格式与大小限制
210
+
211
+ ## 已知限制
212
+
213
+ - 微信 `draft/add` 接口当前不支持通过 API 设置“原创声明”和“创作来源”
214
+ - 若需要这两项,请在公众号后台草稿编辑页手动设置后再发布
215
+
216
+ ## 发布说明
217
+
218
+ - 项目许可证已设为 `MIT`
219
+ - PyPI 自动发布工作流已配置在 `.github/workflows/publish-pypi.yml`
220
+ - 首次公开前,仍建议轮换一次公众号密钥