wechat-md-publisher 0.5.0 → 0.5.2
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.
- package/dist/{Logger-Cf88TYgK.js → Logger-CcLIDmU2.js} +25 -43
- package/dist/Logger-CcLIDmU2.js.map +1 -0
- package/dist/cli.js +22 -16
- package/dist/cli.js.map +1 -1
- package/dist/core/theme/loaders/BuiltinLoader.d.ts.map +1 -1
- package/dist/core/theme/loaders/BuiltinLoader.js +5 -31
- package/dist/core/theme/loaders/BuiltinLoader.js.map +1 -1
- package/package.json +1 -1
- package/themes/builtin/blackink.css +1 -1
- package/themes/builtin/default.css +2 -2
- package/themes/builtin/greenmint.css +1 -1
- package/themes/builtin/orangesun.css +1 -1
- package/themes/builtin/purplerain.css +1 -1
- package/themes/builtin/redruby.css +1 -1
- package/dist/Logger-Cf88TYgK.js.map +0 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
import { readFile } from "fs/promises";
|
|
2
5
|
import axios from "axios";
|
|
3
|
-
import { getTheme, createWenyanCore } from "@wenyan-md/core";
|
|
4
6
|
import { dirname, join } from "path";
|
|
5
7
|
import { fileURLToPath } from "url";
|
|
8
|
+
import { createWenyanCore } from "@wenyan-md/core";
|
|
6
9
|
import { JSDOM } from "jsdom";
|
|
7
10
|
import Conf from "conf";
|
|
8
11
|
import { z } from "zod";
|
|
@@ -346,6 +349,10 @@ class MaterialAPI {
|
|
|
346
349
|
}
|
|
347
350
|
class WechatClient {
|
|
348
351
|
constructor(appId, appSecret, httpClient, tokenCache, logger) {
|
|
352
|
+
__publicField(this, "token");
|
|
353
|
+
__publicField(this, "draft");
|
|
354
|
+
__publicField(this, "publish");
|
|
355
|
+
__publicField(this, "material");
|
|
349
356
|
this.appId = appId;
|
|
350
357
|
this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);
|
|
351
358
|
const getAccessToken = () => this.token.getAccessToken();
|
|
@@ -353,10 +360,6 @@ class WechatClient {
|
|
|
353
360
|
this.publish = new PublishAPI(getAccessToken, httpClient, logger);
|
|
354
361
|
this.material = new MaterialAPI(getAccessToken, httpClient, logger);
|
|
355
362
|
}
|
|
356
|
-
token;
|
|
357
|
-
draft;
|
|
358
|
-
publish;
|
|
359
|
-
material;
|
|
360
363
|
async getAccessToken() {
|
|
361
364
|
return await this.token.getAccessToken();
|
|
362
365
|
}
|
|
@@ -399,7 +402,9 @@ class LocalLoader {
|
|
|
399
402
|
}
|
|
400
403
|
}
|
|
401
404
|
class RemoteLoader {
|
|
402
|
-
|
|
405
|
+
constructor() {
|
|
406
|
+
__publicField(this, "configs", /* @__PURE__ */ new Map());
|
|
407
|
+
}
|
|
403
408
|
async addAPI(name, apiUrl, apiKey) {
|
|
404
409
|
this.configs.set(name, {
|
|
405
410
|
name,
|
|
@@ -478,17 +483,8 @@ class RemoteLoader {
|
|
|
478
483
|
}
|
|
479
484
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
480
485
|
const __dirname$1 = dirname(__filename$1);
|
|
481
|
-
const WENYAN_THEMES = [
|
|
482
|
-
{ id: "default", name: "默认", description: "A clean, classic layout ideal for long-form reading." },
|
|
483
|
-
{ id: "orangeheart", name: "Orange Heart", description: "A vibrant and elegant theme in warm orange tones." },
|
|
484
|
-
{ id: "rainbow", name: "Rainbow", description: "A colorful, lively theme with a clean layout." },
|
|
485
|
-
{ id: "lapis", name: "Lapis", description: "A minimal and refreshing theme in cool blue tones." },
|
|
486
|
-
{ id: "pie", name: "Pie", description: "Inspired by sspai.com and Misty — modern, sharp, and stylish." },
|
|
487
|
-
{ id: "maize", name: "Maize", description: "A crisp, light theme with a soft maize palette." },
|
|
488
|
-
{ id: "purple", name: "Purple", description: "Clean and minimalist, with a subtle purple accent." },
|
|
489
|
-
{ id: "phycat", name: "物理猫-薄荷", description: "A mint-green theme with clear structure and hierarchy." }
|
|
490
|
-
];
|
|
491
486
|
const LOCAL_THEMES = [
|
|
487
|
+
{ id: "default", name: "默认", description: "A clean, classic layout ideal for long-form reading." },
|
|
492
488
|
{ id: "orangesun", name: "Orange Sun", description: "A warm and bright theme with orange sunshine vibes." },
|
|
493
489
|
{ id: "redruby", name: "Red Ruby", description: "An elegant theme with bold ruby red accents." },
|
|
494
490
|
{ id: "greenmint", name: "Green Mint", description: "A fresh and calming mint green theme." },
|
|
@@ -498,24 +494,6 @@ const LOCAL_THEMES = [
|
|
|
498
494
|
class BuiltinLoader {
|
|
499
495
|
async loadAll() {
|
|
500
496
|
const themes = [];
|
|
501
|
-
for (const themeInfo of WENYAN_THEMES) {
|
|
502
|
-
try {
|
|
503
|
-
const wenyanTheme = getTheme(themeInfo.id);
|
|
504
|
-
if (!wenyanTheme) {
|
|
505
|
-
continue;
|
|
506
|
-
}
|
|
507
|
-
const css = await wenyanTheme.getCss();
|
|
508
|
-
themes.push({
|
|
509
|
-
id: themeInfo.id,
|
|
510
|
-
name: themeInfo.name,
|
|
511
|
-
type: "builtin",
|
|
512
|
-
description: themeInfo.description,
|
|
513
|
-
getCss: async () => css
|
|
514
|
-
});
|
|
515
|
-
} catch (error) {
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
497
|
for (const themeInfo of LOCAL_THEMES) {
|
|
520
498
|
try {
|
|
521
499
|
const themePath = join(__dirname$1, "../../../..", "themes", "builtin", `${themeInfo.id}.css`);
|
|
@@ -535,7 +513,9 @@ class BuiltinLoader {
|
|
|
535
513
|
}
|
|
536
514
|
}
|
|
537
515
|
class ThemeRegistry {
|
|
538
|
-
|
|
516
|
+
constructor() {
|
|
517
|
+
__publicField(this, "themes", /* @__PURE__ */ new Map());
|
|
518
|
+
}
|
|
539
519
|
register(theme) {
|
|
540
520
|
this.themes.set(theme.id, theme);
|
|
541
521
|
}
|
|
@@ -564,11 +544,11 @@ class ThemeRegistry {
|
|
|
564
544
|
}
|
|
565
545
|
}
|
|
566
546
|
class ThemeEngine {
|
|
567
|
-
registry;
|
|
568
|
-
localLoader;
|
|
569
|
-
remoteLoader;
|
|
570
|
-
builtinLoader;
|
|
571
547
|
constructor() {
|
|
548
|
+
__publicField(this, "registry");
|
|
549
|
+
__publicField(this, "localLoader");
|
|
550
|
+
__publicField(this, "remoteLoader");
|
|
551
|
+
__publicField(this, "builtinLoader");
|
|
572
552
|
this.registry = new ThemeRegistry();
|
|
573
553
|
this.localLoader = new LocalLoader();
|
|
574
554
|
this.remoteLoader = new RemoteLoader();
|
|
@@ -615,7 +595,9 @@ class ThemeEngine {
|
|
|
615
595
|
}
|
|
616
596
|
}
|
|
617
597
|
class MarkdownRenderer {
|
|
618
|
-
|
|
598
|
+
constructor() {
|
|
599
|
+
__publicField(this, "wenyan");
|
|
600
|
+
}
|
|
619
601
|
async initialize() {
|
|
620
602
|
this.wenyan = await createWenyanCore({
|
|
621
603
|
isConvertMathJax: true,
|
|
@@ -659,8 +641,8 @@ const AccountSchema = z.object({
|
|
|
659
641
|
updatedAt: z.date().optional()
|
|
660
642
|
});
|
|
661
643
|
class ConfigStore {
|
|
662
|
-
store;
|
|
663
644
|
constructor() {
|
|
645
|
+
__publicField(this, "store");
|
|
664
646
|
this.store = new Conf({
|
|
665
647
|
projectName: "wechat-md-publisher"
|
|
666
648
|
});
|
|
@@ -691,8 +673,8 @@ class ConfigStore {
|
|
|
691
673
|
}
|
|
692
674
|
}
|
|
693
675
|
class Logger {
|
|
694
|
-
logger;
|
|
695
676
|
constructor() {
|
|
677
|
+
__publicField(this, "logger");
|
|
696
678
|
this.logger = winston.createLogger({
|
|
697
679
|
level: process.env.LOG_LEVEL || "info",
|
|
698
680
|
format: winston.format.combine(
|
|
@@ -740,4 +722,4 @@ export {
|
|
|
740
722
|
WechatError as e,
|
|
741
723
|
WechatRateLimitError as f
|
|
742
724
|
};
|
|
743
|
-
//# sourceMappingURL=Logger-
|
|
725
|
+
//# sourceMappingURL=Logger-CcLIDmU2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger-CcLIDmU2.js","sources":["../src/errors/BaseError.ts","../src/errors/WechatError.ts","../src/core/wechat/constants.ts","../src/core/wechat/api/TokenAPI.ts","../src/core/wechat/api/DraftAPI.ts","../src/core/wechat/api/PublishAPI.ts","../src/core/wechat/api/MaterialAPI.ts","../src/core/wechat/WechatClient.ts","../src/errors/ThemeError.ts","../src/core/theme/loaders/LocalLoader.ts","../src/core/theme/loaders/RemoteLoader.ts","../src/core/theme/loaders/BuiltinLoader.ts","../src/core/theme/registry.ts","../src/core/theme/ThemeEngine.ts","../src/core/renderer/MarkdownRenderer.ts","../src/infrastructure/config/ConfigStore.ts","../src/infrastructure/logger/Logger.ts"],"sourcesContent":["export class BaseError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500,\n public details?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n };\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class WechatError extends BaseError {\n constructor(\n message: string,\n public errcode: number,\n public errmsg: string\n ) {\n super(message, 'WECHAT_API_ERROR', 500, { errcode, errmsg });\n }\n\n static fromResponse(data: { errcode: number; errmsg: string }): WechatError {\n return new WechatError(\n `微信 API 错误: ${data.errmsg} (${data.errcode})`,\n data.errcode,\n data.errmsg\n );\n }\n}\n\nexport class WechatAuthError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_AUTH_ERROR', 401);\n }\n}\n\nexport class WechatRateLimitError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_RATE_LIMIT_ERROR', 429);\n }\n}\n","export const WECHAT_API_BASE = 'https://api.weixin.qq.com';\n\nexport const WECHAT_API_ENDPOINTS = {\n TOKEN: '/cgi-bin/token',\n DRAFT_ADD: '/cgi-bin/draft/add',\n DRAFT_GET: '/cgi-bin/draft/get',\n DRAFT_DELETE: '/cgi-bin/draft/delete',\n DRAFT_UPDATE: '/cgi-bin/draft/update',\n DRAFT_BATCH_GET: '/cgi-bin/draft/batchget',\n DRAFT_COUNT: '/cgi-bin/draft/count',\n PUBLISH_SUBMIT: '/cgi-bin/freepublish/submit',\n PUBLISH_GET: '/cgi-bin/freepublish/get',\n PUBLISH_DELETE: '/cgi-bin/freepublish/delete',\n PUBLISH_BATCH_GET: '/cgi-bin/freepublish/batchget',\n PUBLISH_GET_STATUS: '/cgi-bin/freepublish/get',\n MATERIAL_ADD: '/cgi-bin/material/add_material',\n MATERIAL_GET: '/cgi-bin/material/get_material',\n MATERIAL_DELETE: '/cgi-bin/material/del_material',\n MATERIAL_BATCH_GET: '/cgi-bin/material/batchget_material',\n MATERIAL_COUNT: '/cgi-bin/material/get_materialcount',\n} as const;\n\nexport const WECHAT_ERROR_CODES = {\n SUCCESS: 0,\n INVALID_CREDENTIAL: 40001,\n ACCESS_TOKEN_EXPIRED: 42001,\n RATE_LIMIT_EXCEEDED: 45009,\n API_UNAUTHORIZED: 48001,\n} as const;\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport class TokenAPI {\n constructor(\n private appId: string,\n private appSecret: string,\n private httpClient: HttpClient,\n private tokenCache: TokenCache,\n private logger: Logger\n ) {}\n\n async getAccessToken(): Promise<string> {\n const cached = await this.tokenCache.getToken(this.appId);\n if (cached) {\n this.logger.debug('使用缓存的 Access Token', { appId: this.appId });\n return cached;\n }\n\n return await this.refreshAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n this.logger.info('刷新 Access Token', { appId: this.appId });\n\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.TOKEN}`;\n const response = await this.httpClient.get(url, {\n params: {\n grant_type: 'client_credential',\n appid: this.appId,\n secret: this.appSecret,\n },\n });\n\n const data = response.data;\n\n if (data.errcode) {\n throw WechatError.fromResponse(data);\n }\n\n await this.tokenCache.setToken(\n this.appId,\n data.access_token,\n data.expires_in\n );\n\n this.logger.info('Access Token 刷新成功', {\n appId: this.appId,\n expiresIn: data.expires_in,\n });\n\n return data.access_token;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { Draft, DraftList, DraftArticle } from '../../../types/draft';\n\nexport class DraftAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async create(article: DraftArticle): Promise<{ media_id: string }> {\n this.logger.info('创建草稿', { title: article.title });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_ADD}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n articles: [article],\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿创建成功', { media_id: data.media_id });\n return { media_id: data.media_id };\n }\n\n async get(mediaId: string): Promise<Draft> {\n this.logger.info('获取草稿详情', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<DraftList> {\n this.logger.info('获取草稿列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿删除成功');\n }\n\n async update(mediaId: string, article: DraftArticle, index: number = 0): Promise<void> {\n this.logger.info('更新草稿', { media_id: mediaId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_UPDATE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n index,\n articles: article,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿更新成功');\n }\n\n async count(): Promise<number> {\n this.logger.info('获取草稿总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data.total_count || 0;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../../../types/publish';\n\nexport class PublishAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_SUBMIT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('发布任务提交成功', { publish_id: data.publish_id });\n return {\n publish_id: data.publish_id,\n msg_data_id: data.msg_data_id,\n };\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n this.logger.info('获取已发布文章详情', { article_id: articleId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<PublishList> {\n this.logger.info('获取已发布文章列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n index,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n this.logger.info('获取发布状态', { publish_id: publishId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET_STATUS}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n publish_id: publishId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport interface UploadResult {\n media_id: string;\n url: string;\n}\n\nexport class MaterialAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async uploadImage(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传图片', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=image`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('图片上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async uploadThumb(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传封面图', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=thumb`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('封面图上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async getMaterialCount(): Promise<{ voice_count: number; video_count: number; image_count: number; news_count: number }> {\n this.logger.info('获取素材总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { TokenAPI } from './api/TokenAPI';\nimport { DraftAPI } from './api/DraftAPI';\nimport { PublishAPI } from './api/PublishAPI';\nimport { MaterialAPI } from './api/MaterialAPI';\nimport { HttpClient } from '../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\n\nexport class WechatClient {\n public readonly token: TokenAPI;\n public readonly draft: DraftAPI;\n public readonly publish: PublishAPI;\n public readonly material: MaterialAPI;\n\n constructor(\n private appId: string,\n appSecret: string,\n httpClient: HttpClient,\n tokenCache: TokenCache,\n logger: Logger\n ) {\n this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);\n \n const getAccessToken = () => this.token.getAccessToken();\n \n this.draft = new DraftAPI(getAccessToken, httpClient, logger);\n this.publish = new PublishAPI(getAccessToken, httpClient, logger);\n this.material = new MaterialAPI(getAccessToken, httpClient, logger);\n }\n\n async getAccessToken(): Promise<string> {\n return await this.token.getAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n return await this.token.refreshAccessToken();\n }\n\n getAppId(): string {\n return this.appId;\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class ThemeError extends BaseError {\n constructor(message: string, details?: any) {\n super(message, 'THEME_ERROR', 500, details);\n }\n}\n\nexport class ThemeNotFoundError extends BaseError {\n constructor(themeId: string) {\n super(`主题不存在: ${themeId}`, 'THEME_NOT_FOUND', 404, { themeId });\n }\n}\n\nexport class ThemeLoadError extends BaseError {\n constructor(themeId: string, reason: string) {\n super(`主题加载失败: ${themeId} - ${reason}`, 'THEME_LOAD_ERROR', 500, { themeId, reason });\n }\n}\n","import { readFile } from 'fs/promises';\nimport type { Theme } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class LocalLoader {\n async load(name: string, path: string): Promise<Theme> {\n try {\n const css = await readFile(path, 'utf-8');\n \n return {\n id: name,\n name,\n type: 'local',\n description: `本地主题: ${path}`,\n getCss: async () => css,\n };\n } catch (error) {\n throw new ThemeLoadError(name, `无法读取文件: ${path}`);\n }\n }\n}\n","import axios from 'axios';\nimport type { Theme, ThemeSource, RemoteThemeConfig } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class RemoteLoader {\n private configs: Map<string, RemoteThemeConfig> = new Map();\n\n async addAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.configs.set(name, {\n name,\n apiUrl,\n apiKey,\n enabled: true,\n });\n }\n\n async load(themeId: string): Promise<Theme | null> {\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const css = await this.fetchThemeCSS(config.apiUrl, config.apiKey, themeId);\n if (css) {\n return {\n id: themeId,\n name: `${name}:${themeId}`,\n type: 'remote',\n description: `远程主题来自 ${name}`,\n getCss: async () => css,\n };\n }\n } catch (error) {\n continue;\n }\n }\n\n return null;\n }\n\n async list(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const themeList = await this.fetchThemeList(config.apiUrl, config.apiKey);\n for (const themeId of themeList) {\n themes.push({\n type: 'remote',\n id: themeId,\n name: `${name}:${themeId}`,\n description: `远程主题来自 ${name}`,\n });\n }\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n\n getConfig(): RemoteThemeConfig[] {\n return Array.from(this.configs.values());\n }\n\n private async fetchThemeList(apiUrl: string, apiKey: string): Promise<string[]> {\n try {\n const response = await axios.get(`${apiUrl}/themes`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.themes || [];\n } catch (error) {\n throw new ThemeLoadError('remote', '无法获取远程主题列表');\n }\n }\n\n private async fetchThemeCSS(apiUrl: string, apiKey: string, themeId: string): Promise<string | null> {\n try {\n const response = await axios.get(`${apiUrl}/themes/${themeId}`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.css || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { Theme } from '../../../types/theme';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// FIXED: Removed broken WENYAN_THEMES that reference non-existent themes\n// Only keeping LOCAL_THEMES which match actual CSS files\n\nconst LOCAL_THEMES = [\n { id: 'default', name: '默认', description: 'A clean, classic layout ideal for long-form reading.' },\n { id: 'orangesun', name: 'Orange Sun', description: 'A warm and bright theme with orange sunshine vibes.' },\n { id: 'redruby', name: 'Red Ruby', description: 'An elegant theme with bold ruby red accents.' },\n { id: 'greenmint', name: 'Green Mint', description: 'A fresh and calming mint green theme.' },\n { id: 'purplerain', name: 'Purple Rain', description: 'A dreamy purple theme with soft gradients.' },\n { id: 'blackink', name: 'Black Ink', description: 'A dark mode theme with indigo accents for night reading.' },\n];\n\nexport class BuiltinLoader {\n async loadAll(): Promise<Theme[]> {\n const themes: Theme[] = [];\n\n // FIXED: Only load LOCAL_THEMES that have matching CSS files\n for (const themeInfo of LOCAL_THEMES) {\n try {\n const themePath = join(__dirname, '../../../..', 'themes', 'builtin', `${themeInfo.id}.css`);\n const css = await readFile(themePath, 'utf-8');\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n}\n","import type { Theme, ThemeSource } from '../../types/theme';\n\nexport class ThemeRegistry {\n private themes: Map<string, Theme> = new Map();\n\n register(theme: Theme): void {\n this.themes.set(theme.id, theme);\n }\n\n get(id: string): Theme | undefined {\n return this.themes.get(id);\n }\n\n has(id: string): boolean {\n return this.themes.has(id);\n }\n\n remove(id: string): void {\n this.themes.delete(id);\n }\n\n list(): ThemeSource[] {\n return Array.from(this.themes.values()).map(theme => ({\n type: theme.type,\n id: theme.id,\n name: theme.name,\n description: theme.description,\n }));\n }\n\n getLocalThemes(): ThemeSource[] {\n return this.list().filter(t => t.type === 'local');\n }\n\n clear(): void {\n this.themes.clear();\n }\n}\n","import { LocalLoader } from './loaders/LocalLoader';\nimport { RemoteLoader } from './loaders/RemoteLoader';\nimport { BuiltinLoader } from './loaders/BuiltinLoader';\nimport { ThemeRegistry } from './registry';\nimport { ThemeNotFoundError } from '../../errors/ThemeError';\nimport type { ThemeSource } from '../../types/theme';\n\nexport class ThemeEngine {\n private registry: ThemeRegistry;\n private localLoader: LocalLoader;\n private remoteLoader: RemoteLoader;\n private builtinLoader: BuiltinLoader;\n\n constructor() {\n this.registry = new ThemeRegistry();\n this.localLoader = new LocalLoader();\n this.remoteLoader = new RemoteLoader();\n this.builtinLoader = new BuiltinLoader();\n }\n\n async loadBuiltinThemes(): Promise<void> {\n const themes = await this.builtinLoader.loadAll();\n for (const theme of themes) {\n this.registry.register(theme);\n }\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n const theme = await this.localLoader.load(name, path);\n this.registry.register(theme);\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n await this.remoteLoader.addAPI(name, apiUrl, apiKey);\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const theme = this.registry.get(themeId);\n if (theme) {\n return await theme.getCss();\n }\n\n const remoteTheme = await this.remoteLoader.load(themeId);\n if (remoteTheme) {\n return await remoteTheme.getCss();\n }\n\n throw new ThemeNotFoundError(themeId);\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n \n themes.push(...this.registry.list());\n \n themes.push(...await this.remoteLoader.list());\n\n return themes;\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.registry.remove(themeId);\n }\n\n async getConfig(): Promise<any> {\n return {\n local: this.registry.getLocalThemes(),\n remote: this.remoteLoader.getConfig(),\n };\n }\n}\n","import { createWenyanCore } from '@wenyan-md/core';\nimport type { ApplyStylesOptions } from '@wenyan-md/core';\nimport { JSDOM } from 'jsdom';\n\nexport interface RenderResult {\n title: string;\n content: string;\n cover?: string;\n}\n\nexport class MarkdownRenderer {\n private wenyan: any;\n\n async initialize(): Promise<void> {\n this.wenyan = await createWenyanCore({\n isConvertMathJax: true,\n isWechat: true,\n });\n }\n\n async render(markdown: string, themeCss?: string): Promise<RenderResult> {\n if (!this.wenyan) {\n await this.initialize();\n }\n\n const result = await this.wenyan.handleFrontMatter(markdown);\n \n if (!result || !result.body) {\n throw new Error('Invalid markdown: handleFrontMatter returned empty data');\n }\n \n const html = await this.wenyan.renderMarkdown(result.body);\n\n const dom = new JSDOM(html);\n const document = dom.window.document;\n const wenyanElement = document.createElement('div');\n wenyanElement.id = 'wenyan';\n wenyanElement.innerHTML = html;\n\n const options: ApplyStylesOptions = {\n themeCss,\n isMacStyle: true,\n isAddFootnote: false,\n };\n\n const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);\n\n return {\n title: result.title || '',\n content: styledHtml,\n cover: result.cover,\n };\n }\n}\n","import Conf from 'conf';\nimport { z } from 'zod';\nimport type { Config } from '../../types/config';\n\nconst AccountSchema = z.object({\n id: z.string(),\n name: z.string(),\n appId: z.string().regex(/^wx[a-zA-Z0-9]{16}$/, '无效的 AppID 格式'),\n appSecret: z.string().min(32, 'AppSecret 长度不足'),\n isDefault: z.boolean().optional(),\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport class ConfigStore {\n private store: Conf<Config>;\n\n constructor() {\n this.store = new Conf<Config>({\n projectName: 'wechat-md-publisher',\n });\n }\n\n get<K extends keyof Config>(key: K): Config[K] | undefined;\n get<K extends keyof Config>(key: K, defaultValue: Config[K]): Config[K];\n get<K extends keyof Config>(key: K, defaultValue?: Config[K]): Config[K] | undefined {\n return this.store.get(key, defaultValue as any);\n }\n\n set<K extends keyof Config>(key: K, value: Config[K]): void {\n if (key === 'accounts') {\n z.array(AccountSchema).parse(value);\n }\n this.store.set(key, value);\n }\n\n has(key: keyof Config): boolean {\n return this.store.has(key);\n }\n\n delete(key: keyof Config): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n getAll(): Config {\n return this.store.store;\n }\n\n getPath(): string {\n return this.store.path;\n }\n}\n","import winston from 'winston';\n\nexport class Logger {\n private logger: winston.Logger;\n\n constructor() {\n this.logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';\n return `${timestamp} [${level}]: ${message} ${metaStr}`;\n })\n ),\n }),\n ],\n });\n }\n\n debug(message: string, meta?: any): void {\n this.logger.debug(message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.logger.info(message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.logger.warn(message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.logger.error(message, meta);\n }\n}\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2
5
|
import { Command } from "commander";
|
|
3
6
|
import { readFileSync } from "fs";
|
|
4
7
|
import { isAbsolute, resolve, dirname, join } from "path";
|
|
5
8
|
import { fileURLToPath } from "url";
|
|
6
|
-
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-
|
|
9
|
+
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-CcLIDmU2.js";
|
|
7
10
|
import axios from "axios";
|
|
8
11
|
import { JSDOM } from "jsdom";
|
|
9
12
|
import { readFile } from "fs/promises";
|
|
@@ -12,9 +15,9 @@ import chalk from "chalk";
|
|
|
12
15
|
import Table from "cli-table3";
|
|
13
16
|
import ora from "ora";
|
|
14
17
|
class CacheStore {
|
|
15
|
-
cache = /* @__PURE__ */ new Map();
|
|
16
|
-
maxSize;
|
|
17
18
|
constructor(maxSize = 100) {
|
|
19
|
+
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
20
|
+
__publicField(this, "maxSize");
|
|
18
21
|
this.maxSize = maxSize;
|
|
19
22
|
}
|
|
20
23
|
async get(key) {
|
|
@@ -105,6 +108,7 @@ class ThemeCache extends CacheStore {
|
|
|
105
108
|
}
|
|
106
109
|
class HttpClient {
|
|
107
110
|
constructor(logger) {
|
|
111
|
+
__publicField(this, "client");
|
|
108
112
|
this.logger = logger;
|
|
109
113
|
this.client = axios.create({
|
|
110
114
|
timeout: 3e4,
|
|
@@ -114,7 +118,6 @@ class HttpClient {
|
|
|
114
118
|
});
|
|
115
119
|
this.setupInterceptors();
|
|
116
120
|
}
|
|
117
|
-
client;
|
|
118
121
|
setupInterceptors() {
|
|
119
122
|
this.client.interceptors.request.use(
|
|
120
123
|
(config) => {
|
|
@@ -138,8 +141,9 @@ class HttpClient {
|
|
|
138
141
|
return response;
|
|
139
142
|
},
|
|
140
143
|
(error) => {
|
|
144
|
+
var _a;
|
|
141
145
|
this.logger.error("HTTP Response Error", {
|
|
142
|
-
status: error.response
|
|
146
|
+
status: (_a = error.response) == null ? void 0 : _a.status,
|
|
143
147
|
message: error.message
|
|
144
148
|
});
|
|
145
149
|
return Promise.reject(error);
|
|
@@ -607,17 +611,19 @@ class PublishService {
|
|
|
607
611
|
}
|
|
608
612
|
}
|
|
609
613
|
class Container {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
614
|
+
constructor() {
|
|
615
|
+
__publicField(this, "configStore");
|
|
616
|
+
__publicField(this, "logger");
|
|
617
|
+
__publicField(this, "httpClient");
|
|
618
|
+
__publicField(this, "tokenCache");
|
|
619
|
+
__publicField(this, "imageCache");
|
|
620
|
+
__publicField(this, "themeCache");
|
|
621
|
+
__publicField(this, "themeEngine");
|
|
622
|
+
__publicField(this, "renderer");
|
|
623
|
+
__publicField(this, "accountService");
|
|
624
|
+
__publicField(this, "themeService");
|
|
625
|
+
__publicField(this, "renderService");
|
|
626
|
+
}
|
|
621
627
|
async initialize() {
|
|
622
628
|
this.configStore = new ConfigStore();
|
|
623
629
|
this.logger = new Logger();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/infrastructure/cache/CacheStore.ts","../src/infrastructure/cache/TokenCache.ts","../src/infrastructure/cache/ImageCache.ts","../src/infrastructure/cache/ThemeCache.ts","../src/infrastructure/http/HttpClient.ts","../src/utils/image.ts","../src/utils/crypto.ts","../src/utils/file.ts","../src/core/renderer/ImageProcessor.ts","../src/services/AccountService.ts","../src/services/ThemeService.ts","../src/services/RenderService.ts","../src/services/DraftService.ts","../src/services/PublishService.ts","../src/container.ts","../src/cli/commands/account.ts","../src/cli/commands/theme.ts","../src/cli/commands/draft.ts","../src/cli/commands/publish.ts","../src/cli/index.ts"],"sourcesContent":["export interface CacheEntry<T> {\n value: T;\n expireAt: number;\n}\n\nexport class CacheStore<T = any> {\n private cache: Map<string, CacheEntry<T>> = new Map();\n private maxSize: number;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n }\n\n async get(key: string): Promise<T | null> {\n const entry = this.cache.get(key);\n \n if (!entry) {\n return null;\n }\n\n if (Date.now() > entry.expireAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.value;\n }\n\n async set(key: string, value: T, ttl: number = 3600): Promise<void> {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expireAt: Date.now() + ttl * 1000,\n });\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n\n async size(): Promise<number> {\n return this.cache.size;\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface TokenCacheEntry {\n access_token: string;\n expires_in: number;\n}\n\nexport class TokenCache extends CacheStore<TokenCacheEntry> {\n constructor() {\n super(10);\n }\n\n async getToken(appId: string): Promise<string | null> {\n const entry = await this.get(appId);\n return entry ? entry.access_token : null;\n }\n\n async setToken(appId: string, accessToken: string, expiresIn: number): Promise<void> {\n await this.set(\n appId,\n {\n access_token: accessToken,\n expires_in: expiresIn,\n },\n expiresIn - 200\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface ImageCacheEntry {\n media_id: string;\n url: string;\n}\n\nexport class ImageCache extends CacheStore<ImageCacheEntry> {\n constructor() {\n super(500);\n }\n\n async getMediaId(md5: string): Promise<string | null> {\n const entry = await this.get(md5);\n return entry ? entry.media_id : null;\n }\n\n async setImage(md5: string, mediaId: string, url: string, ttl: number = 86400): Promise<void> {\n await this.set(\n md5,\n {\n media_id: mediaId,\n url,\n },\n ttl\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport class ThemeCache extends CacheStore<string> {\n constructor() {\n super(50);\n }\n\n async getThemeCSS(themeId: string): Promise<string | null> {\n return await this.get(themeId);\n }\n\n async setThemeCSS(themeId: string, css: string, ttl: number = 3600): Promise<void> {\n await this.set(themeId, css, ttl);\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport { Logger } from '../logger/Logger';\n\nexport class HttpClient {\n private client: AxiosInstance;\n\n constructor(private logger: Logger) {\n this.client = axios.create({\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (config) => {\n this.logger.debug('HTTP Request', {\n method: config.method,\n url: config.url,\n });\n return config;\n },\n (error) => {\n this.logger.error('HTTP Request Error', { error: error.message });\n return Promise.reject(error);\n }\n );\n\n this.client.interceptors.response.use(\n (response) => {\n this.logger.debug('HTTP Response', {\n status: response.status,\n url: response.config.url,\n });\n return response;\n },\n (error) => {\n this.logger.error('HTTP Response Error', {\n status: error.response?.status,\n message: error.message,\n });\n return Promise.reject(error);\n }\n );\n }\n\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.get<T>(url, config);\n }\n\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.post<T>(url, data, config);\n }\n\n async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.put<T>(url, data, config);\n }\n\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.delete<T>(url, config);\n }\n}\n","import { readFile } from 'fs/promises';\nimport axios from 'axios';\n\nexport async function downloadImage(url: string): Promise<Buffer> {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n \n if (!response.data || response.data.byteLength === 0) {\n throw new Error('下载的图片大小为 0');\n }\n \n return Buffer.from(response.data);\n } catch (error) {\n throw new Error(`下载图片失败: ${url}`);\n }\n}\n\nexport async function readImageFile(filePath: string): Promise<Buffer> {\n try {\n const buffer = await readFile(filePath);\n \n if (buffer.length === 0) {\n throw new Error('图片文件大小为 0');\n }\n \n return buffer;\n } catch (error) {\n throw new Error(`读取图片文件失败: ${filePath}`);\n }\n}\n\nexport function isRemoteUrl(url: string): boolean {\n return url.startsWith('http://') || url.startsWith('https://');\n}\n\nexport function isWechatImageUrl(url: string): boolean {\n return url.startsWith('https://mmbiz.qpic.cn');\n}\n\nexport function getImageFilename(url: string): string {\n const urlWithoutQuery = url.split('?')[0];\n const parts = urlWithoutQuery.split('/');\n const filename = parts[parts.length - 1];\n \n const ext = filename.match(/\\.(jpg|jpeg|png|gif|webp|bmp)$/i);\n if (!ext) {\n return `${filename}.jpg`;\n }\n \n return filename;\n}\n","import { createHash } from 'crypto';\nimport { readFile } from 'fs/promises';\n\nexport function md5FromBuffer(buffer: Buffer): string {\n return createHash('md5').update(buffer).digest('hex');\n}\n\nexport function md5FromString(str: string): string {\n return createHash('md5').update(str).digest('hex');\n}\n\nexport async function md5FromFile(filePath: string): Promise<string> {\n const buffer = await readFile(filePath);\n return md5FromBuffer(buffer);\n}\n\nexport function generateId(prefix: string = ''): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return prefix ? `${prefix}_${timestamp}_${random}` : `${timestamp}_${random}`;\n}\n","import { readFile, writeFile, access, mkdir } from 'fs/promises';\nimport { dirname, resolve, isAbsolute } from 'path';\nimport { constants } from 'fs';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch (error) {\n throw new Error(`无法读取文件: ${filePath}`);\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string): Promise<void> {\n try {\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`无法写入文件: ${filePath}`);\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolvePath(filePath: string, basePath?: string): string {\n if (isAbsolute(filePath)) {\n return filePath;\n }\n \n if (basePath) {\n return resolve(basePath, filePath);\n }\n \n return resolve(process.cwd(), filePath);\n}\n\nexport function getFileExtension(filePath: string): string {\n const match = filePath.match(/\\.([^.]+)$/);\n return match ? match[1].toLowerCase() : '';\n}\n\nexport function isImageFile(filePath: string): boolean {\n const ext = getFileExtension(filePath);\n return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(ext);\n}\n","import { JSDOM } from 'jsdom';\nimport { MaterialAPI } from '../wechat/api/MaterialAPI';\nimport { ImageCache } from '../../infrastructure/cache/ImageCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\nimport { downloadImage, readImageFile, isRemoteUrl, isWechatImageUrl, getImageFilename } from '../../utils/image';\nimport { md5FromBuffer } from '../../utils/crypto';\nimport { resolvePath } from '../../utils/file';\n\nexport interface ProcessImagesResult {\n content: string;\n firstImageMediaId: string;\n}\n\nexport class ImageProcessor {\n constructor(\n private materialAPI: MaterialAPI,\n private imageCache: ImageCache,\n private logger: Logger\n ) {}\n\n async processImages(content: string, relativePath?: string): Promise<ProcessImagesResult> {\n if (!content.includes('<img')) {\n return { content, firstImageMediaId: '' };\n }\n\n const dom = new JSDOM(content);\n const images = dom.window.document.querySelectorAll('img');\n \n const uploadPromises = Array.from(images).map(async (element: any) => {\n const src = element.getAttribute('src');\n if (!src) return null;\n\n if (isWechatImageUrl(src)) {\n return src;\n }\n\n const result = await this.uploadImage(src, relativePath);\n element.setAttribute('src', result.url);\n return result.media_id;\n });\n\n const mediaIds = (await Promise.all(uploadPromises)).filter(Boolean) as string[];\n const firstImageMediaId = mediaIds[0] || '';\n\n return {\n content: dom.serialize(),\n firstImageMediaId,\n };\n }\n\n async uploadImage(imagePath: string, relativePath?: string): Promise<{ media_id: string; url: string }> {\n let buffer: Buffer;\n let filename: string;\n\n if (isRemoteUrl(imagePath)) {\n this.logger.info('下载远程图片', { url: imagePath });\n buffer = await downloadImage(imagePath);\n filename = getImageFilename(imagePath);\n } else {\n const resolvedPath = resolvePath(imagePath, relativePath);\n this.logger.info('读取本地图片', { path: resolvedPath });\n buffer = await readImageFile(resolvedPath);\n filename = getImageFilename(resolvedPath);\n }\n\n const md5 = md5FromBuffer(buffer);\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n this.logger.debug('使用缓存的图片', { md5 });\n const cachedEntry = await this.imageCache.get(md5);\n return { media_id: cached, url: cachedEntry!.url };\n }\n\n const result = await this.materialAPI.uploadImage(buffer, filename);\n await this.imageCache.setImage(md5, result.media_id, result.url);\n\n this.logger.info('图片上传成功', { media_id: result.media_id });\n return result;\n }\n\n async uploadCover(coverPath: string | undefined, relativePath?: string, fallbackMediaId?: string): Promise<string> {\n if (!coverPath) {\n if (fallbackMediaId) {\n return fallbackMediaId;\n }\n throw new Error('必须指定封面图或在正文中至少包含一张图片');\n }\n\n if (isWechatImageUrl(coverPath)) {\n const md5 = md5FromBuffer(Buffer.from(coverPath));\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n return cached;\n }\n }\n\n const result = await this.uploadImage(coverPath, relativePath);\n return result.media_id;\n }\n}\n","import { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { Account, AccountCreateOptions } from '../types/account';\nimport { generateId } from '../utils/crypto';\n\nexport class AccountService {\n constructor(\n private configStore: ConfigStore,\n private logger: Logger\n ) {}\n\n async addAccount(options: AccountCreateOptions): Promise<Account> {\n this.logger.info('添加账号', { name: options.name });\n\n const accounts = await this.listAccounts();\n \n const existingAccount = accounts.find(a => a.appId === options.appId);\n if (existingAccount) {\n throw new Error(`账号已存在: ${existingAccount.name}`);\n }\n\n const account: Account = {\n id: generateId('acc'),\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.isDefault || accounts.length === 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n if (account.isDefault) {\n accounts.forEach(a => a.isDefault = false);\n }\n\n accounts.push(account);\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号添加成功', { id: account.id, name: account.name });\n return account;\n }\n\n async listAccounts(): Promise<Account[]> {\n return this.configStore.get('accounts', []);\n }\n\n async getAccount(id: string): Promise<Account | null> {\n const accounts = await this.listAccounts();\n return accounts.find(a => a.id === id) || null;\n }\n\n async getCurrentAccount(): Promise<Account> {\n const accounts = await this.listAccounts();\n \n if (accounts.length === 0) {\n throw new Error('未配置账号,请先使用 account add 命令添加账号');\n }\n\n const defaultAccount = accounts.find(a => a.isDefault);\n if (defaultAccount) {\n return defaultAccount;\n }\n\n return accounts[0];\n }\n\n async setDefaultAccount(id: string): Promise<void> {\n this.logger.info('设置默认账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n accounts.forEach(a => {\n a.isDefault = a.id === id;\n if (a.id === id) {\n a.updatedAt = new Date();\n }\n });\n\n this.configStore.set('accounts', accounts);\n this.logger.info('默认账号设置成功', { name: account.name });\n }\n\n async removeAccount(id: string): Promise<void> {\n this.logger.info('删除账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n const filtered = accounts.filter(a => a.id !== id);\n\n if (account.isDefault && filtered.length > 0) {\n filtered[0].isDefault = true;\n }\n\n this.configStore.set('accounts', filtered);\n this.logger.info('账号删除成功', { name: account.name });\n }\n\n async updateAccount(id: string, updates: Partial<Account>): Promise<Account> {\n this.logger.info('更新账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n Object.assign(account, updates, { updatedAt: new Date() });\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号更新成功', { name: account.name });\n return account;\n }\n}\n","import { ThemeEngine } from '../core/theme/ThemeEngine';\nimport { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { ThemeCache } from '../infrastructure/cache/ThemeCache';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { ThemeSource } from '../types/theme';\n\nexport class ThemeService {\n constructor(\n private themeEngine: ThemeEngine,\n private configStore: ConfigStore,\n private themeCache: ThemeCache,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n this.logger.info('初始化主题系统');\n\n await this.themeEngine.loadBuiltinThemes();\n\n const config = this.configStore.get('themes');\n if (!config) {\n return;\n }\n\n if (config.local) {\n for (const theme of config.local) {\n try {\n await this.themeEngine.addLocalTheme(theme.name, theme.path);\n } catch (error) {\n this.logger.warn('加载本地主题失败', { name: theme.name, error });\n }\n }\n }\n\n if (config.remote) {\n for (const remote of config.remote) {\n if (remote.enabled) {\n try {\n await this.themeEngine.addRemoteAPI(remote.name, remote.apiUrl, remote.apiKey);\n } catch (error) {\n this.logger.warn('添加远程主题 API 失败', { name: remote.name, error });\n }\n }\n }\n }\n\n this.logger.info('主题系统初始化完成');\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n return await this.themeEngine.listThemes();\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const cached = await this.themeCache.getThemeCSS(themeId);\n if (cached) {\n this.logger.debug('使用缓存的主题', { themeId });\n return cached;\n }\n\n const css = await this.themeEngine.getThemeCSS(themeId);\n await this.themeCache.setThemeCSS(themeId, css);\n\n return css;\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n this.logger.info('添加本地主题', { name, path });\n\n await this.themeEngine.addLocalTheme(name, path);\n\n const config = this.configStore.get('themes') || {};\n if (!config.local) {\n config.local = [];\n }\n\n const existing = config.local.find(t => t.name === name);\n if (existing) {\n existing.path = path;\n } else {\n config.local.push({ name, path });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('本地主题添加成功');\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.logger.info('添加远程主题 API', { name, apiUrl });\n\n await this.themeEngine.addRemoteAPI(name, apiUrl, apiKey);\n\n const config = this.configStore.get('themes') || {};\n if (!config.remote) {\n config.remote = [];\n }\n\n const existing = config.remote.find(r => r.name === name);\n if (existing) {\n existing.apiUrl = apiUrl;\n existing.apiKey = apiKey;\n existing.enabled = true;\n } else {\n config.remote.push({ name, apiUrl, apiKey, enabled: true });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('远程主题 API 添加成功');\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.logger.info('删除主题', { themeId });\n\n await this.themeEngine.removeTheme(themeId);\n await this.themeCache.delete(themeId);\n\n const config = this.configStore.get('themes') || {};\n if (config.local) {\n config.local = config.local.filter(t => t.name !== themeId);\n }\n\n this.configStore.set('themes', config);\n this.logger.info('主题删除成功');\n }\n}\n","import { MarkdownRenderer, RenderResult } from '../core/renderer/MarkdownRenderer';\nimport { ThemeService } from './ThemeService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileContent } from '../utils/file';\n\nexport interface RenderOptions {\n markdown?: string;\n file?: string;\n theme?: string;\n}\n\nexport class RenderService {\n constructor(\n private renderer: MarkdownRenderer,\n private themeService: ThemeService,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n await this.renderer.initialize();\n }\n\n async render(options: RenderOptions): Promise<RenderResult> {\n let markdown: string;\n\n if (options.file) {\n this.logger.info('读取 Markdown 文件', { file: options.file });\n markdown = await readFileContent(options.file);\n } else if (options.markdown) {\n markdown = options.markdown;\n } else {\n throw new Error('必须提供 markdown 内容或 file 路径');\n }\n\n let themeCss: string | undefined;\n if (options.theme) {\n this.logger.info('加载主题', { theme: options.theme });\n themeCss = await this.themeService.getThemeCSS(options.theme);\n }\n\n this.logger.info('开始渲染 Markdown');\n const result = await this.renderer.render(markdown, themeCss);\n this.logger.info('Markdown 渲染完成', { title: result.title });\n\n return result;\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { RenderService } from './RenderService';\nimport { ImageProcessor } from '../core/renderer/ImageProcessor';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { DraftCreateOptions, Draft, DraftList } from '../types/draft';\nimport { dirname } from 'path';\n\nexport class DraftService {\n constructor(\n private wechatClient: WechatClient,\n private renderService: RenderService,\n private imageProcessor: ImageProcessor,\n private logger: Logger\n ) {}\n\n async create(options: DraftCreateOptions): Promise<{ media_id: string }> {\n this.logger.info('开始创建草稿', { file: options.file });\n\n const rendered = await this.renderService.render({\n markdown: options.markdown,\n file: options.file,\n theme: options.theme,\n });\n\n const relativePath = options.relativePath || (options.file ? dirname(options.file) : undefined);\n\n const { content, firstImageMediaId } = await this.imageProcessor.processImages(\n rendered.content,\n relativePath\n );\n\n const thumbMediaId = await this.imageProcessor.uploadCover(\n rendered.cover,\n relativePath,\n firstImageMediaId\n );\n\n const result = await this.wechatClient.draft.create({\n title: rendered.title,\n content,\n thumb_media_id: thumbMediaId,\n });\n\n this.logger.info('草稿创建成功', { media_id: result.media_id });\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<DraftList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.draft.list(offset, pageSize);\n }\n\n async get(mediaId: string): Promise<Draft> {\n return await this.wechatClient.draft.get(mediaId);\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n await this.wechatClient.draft.delete(mediaId);\n this.logger.info('草稿删除成功');\n }\n\n async batchDelete(mediaIds: string[]): Promise<void> {\n this.logger.info('批量删除草稿', { count: mediaIds.length });\n\n const results = await Promise.allSettled(\n mediaIds.map(id => this.delete(id))\n );\n\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0) {\n this.logger.warn('部分草稿删除失败', {\n failed: failed.length,\n total: mediaIds.length,\n });\n }\n }\n\n async count(): Promise<number> {\n return await this.wechatClient.draft.count();\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { DraftService } from './DraftService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../types/publish';\nimport type { DraftCreateOptions } from '../types/draft';\n\nexport class PublishService {\n constructor(\n private wechatClient: WechatClient,\n private draftService: DraftService,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n const result = await this.wechatClient.publish.submit(mediaId);\n this.logger.info('发布任务提交成功', { publish_id: result.publish_id });\n return result;\n }\n\n async createAndPublish(options: DraftCreateOptions): Promise<PublishResult> {\n this.logger.info('创建并发布文章');\n\n const { media_id } = await this.draftService.create(options);\n const result = await this.submit(media_id);\n\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<PublishList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.publish.list(offset, pageSize);\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n return await this.wechatClient.publish.get(articleId);\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n await this.wechatClient.publish.delete(articleId, index);\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n return await this.wechatClient.publish.getStatus(publishId);\n }\n}\n","import { ConfigStore } from './infrastructure/config/ConfigStore';\nimport { TokenCache } from './infrastructure/cache/TokenCache';\nimport { ImageCache } from './infrastructure/cache/ImageCache';\nimport { ThemeCache } from './infrastructure/cache/ThemeCache';\nimport { Logger } from './infrastructure/logger/Logger';\nimport { HttpClient } from './infrastructure/http/HttpClient';\nimport { WechatClient } from './core/wechat/WechatClient';\nimport { ThemeEngine } from './core/theme/ThemeEngine';\nimport { MarkdownRenderer } from './core/renderer/MarkdownRenderer';\nimport { ImageProcessor } from './core/renderer/ImageProcessor';\nimport { AccountService } from './services/AccountService';\nimport { ThemeService } from './services/ThemeService';\nimport { RenderService } from './services/RenderService';\nimport { DraftService } from './services/DraftService';\nimport { PublishService } from './services/PublishService';\n\nclass Container {\n\n private configStore!: ConfigStore;\n private logger!: Logger;\n private httpClient!: HttpClient;\n private tokenCache!: TokenCache;\n private imageCache!: ImageCache;\n private themeCache!: ThemeCache;\n private themeEngine!: ThemeEngine;\n private renderer!: MarkdownRenderer;\n private accountService!: AccountService;\n private themeService!: ThemeService;\n private renderService!: RenderService;\n\n async initialize(): Promise<void> {\n this.configStore = new ConfigStore();\n this.logger = new Logger();\n this.httpClient = new HttpClient(this.logger);\n this.tokenCache = new TokenCache();\n this.imageCache = new ImageCache();\n this.themeCache = new ThemeCache();\n this.themeEngine = new ThemeEngine();\n this.renderer = new MarkdownRenderer();\n \n this.accountService = new AccountService(this.configStore, this.logger);\n this.themeService = new ThemeService(\n this.themeEngine,\n this.configStore,\n this.themeCache,\n this.logger\n );\n this.renderService = new RenderService(\n this.renderer,\n this.themeService,\n this.logger\n );\n\n await this.themeService.initialize();\n await this.renderService.initialize();\n }\n\n getAccountService(): AccountService {\n return this.accountService;\n }\n\n getThemeService(): ThemeService {\n return this.themeService;\n }\n\n getRenderService(): RenderService {\n return this.renderService;\n }\n\n async getDraftService(): Promise<DraftService> {\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n const imageProcessor = new ImageProcessor(\n wechatClient.material,\n this.imageCache,\n this.logger\n );\n\n return new DraftService(\n wechatClient,\n this.renderService,\n imageProcessor,\n this.logger\n );\n }\n\n async getPublishService(): Promise<PublishService> {\n const draftService = await this.getDraftService();\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n return new PublishService(\n wechatClient,\n draftService,\n this.logger\n );\n }\n}\n\nexport const container = new Container();\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createAccountCommand(): Command {\n const cmd = new Command('account')\n .description('账号管理');\n\n cmd.command('add')\n .description('添加微信公众号账号')\n .requiredOption('--name <name>', '账号名称')\n .requiredOption('--app-id <appId>', '微信公众号 AppID')\n .requiredOption('--app-secret <appSecret>', '微信公众号 AppSecret')\n .option('--default', '设为默认账号')\n .action(async (options) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n\n const account = await accountService.addAccount({\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.default,\n });\n\n console.log(chalk.green('✓ 账号添加成功'));\n console.log(` ID: ${account.id}`);\n console.log(` 名称: ${account.name}`);\n console.log(` AppID: ${account.appId}`);\n console.log(` 默认账号: ${account.isDefault ? '是' : '否'}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出所有账号')\n .action(async () => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n const accounts = await accountService.listAccounts();\n\n if (accounts.length === 0) {\n console.log(chalk.yellow('未配置账号'));\n console.log('使用 account add 命令添加账号');\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', 'AppID', '默认'],\n colWidths: [25, 20, 20, 8],\n });\n\n accounts.forEach(account => {\n table.push([\n account.id,\n account.name,\n account.appId,\n account.isDefault ? chalk.green('是') : '否',\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取账号列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('switch <id>')\n .description('切换默认账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.setDefaultAccount(id);\n console.log(chalk.green('✓ 默认账号切换成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 切换账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <id>')\n .description('删除账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.removeAccount(id);\n console.log(chalk.green('✓ 账号删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createThemeCommand(): Command {\n const cmd = new Command('theme')\n .description('主题管理');\n\n cmd.command('list')\n .description('列出所有可用主题')\n .action(async () => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n const themes = await themeService.listThemes();\n\n if (themes.length === 0) {\n console.log(chalk.yellow('未找到主题'));\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', '类型', '描述'],\n colWidths: [20, 25, 12, 40],\n });\n\n themes.forEach(theme => {\n const typeColor = theme.type === 'builtin' ? chalk.green :\n theme.type === 'local' ? chalk.blue :\n theme.type === 'remote' ? chalk.magenta : chalk.gray;\n \n table.push([\n theme.id,\n theme.name,\n typeColor(theme.type),\n theme.description || '-',\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${themes.length} 个主题`);\n } catch (error: any) {\n console.error(chalk.red('✗ 获取主题列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-local')\n .description('添加本地主题')\n .requiredOption('--name <name>', '主题名称')\n .requiredOption('--path <path>', '主题 CSS 文件路径')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addLocalTheme(options.name, options.path);\n \n console.log(chalk.green('✓ 本地主题添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` 路径: ${options.path}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加本地主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-remote')\n .description('添加远程主题 API')\n .requiredOption('--name <name>', 'API 名称')\n .requiredOption('--url <url>', 'API URL')\n .requiredOption('--key <key>', 'API Key')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addRemoteAPI(options.name, options.url, options.key);\n \n console.log(chalk.green('✓ 远程主题 API 添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` URL: ${options.url}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加远程主题 API 失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <theme-id>')\n .description('删除主题')\n .action(async (themeId) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.removeTheme(themeId);\n \n console.log(chalk.green('✓ 主题删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createDraftCommand(): Command {\n const cmd = new Command('draft')\n .description('草稿管理');\n\n cmd.command('create')\n .description('创建草稿')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const result = await draftService.create({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('草稿创建成功');\n console.log(chalk.green(` Media ID: ${result.media_id}`));\n console.log(chalk.gray(' 提示: 使用 publish 命令发布此草稿'));\n } catch (error: any) {\n spinner.fail('创建草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出草稿')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取草稿列表...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await draftService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无草稿'));\n return;\n }\n\n const table = new Table({\n head: ['Media ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(draft => {\n const article = draft.content.news_item[0];\n const updateTime = new Date(draft.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n draft.media_id,\n article.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 个草稿 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取草稿列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <media-id>')\n .description('删除草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在删除草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n await draftService.delete(mediaId);\n \n spinner.succeed('草稿删除成功');\n } catch (error: any) {\n spinner.fail('删除草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('count')\n .description('获取草稿总数')\n .action(async () => {\n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const count = await draftService.count();\n \n console.log(chalk.green(`草稿总数: ${count}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 获取草稿总数失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createPublishCommand(): Command {\n const cmd = new Command('publish')\n .description('发布管理');\n\n cmd.command('submit <media-id>')\n .description('发布草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在发布草稿...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.submit(mediaId);\n \n spinner.succeed('发布任务提交成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n console.log(chalk.gray(' 提示: 使用 publish status 命令查看发布状态'));\n } catch (error: any) {\n spinner.fail('发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('create')\n .description('创建并发布文章')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建并发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.createAndPublish({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('文章创建并发布成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n } catch (error: any) {\n spinner.fail('创建并发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出已发布文章')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取已发布文章列表...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await publishService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无已发布文章'));\n return;\n }\n\n const table = new Table({\n head: ['Article ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(article => {\n const newsItem = article.content.news_item[0];\n const updateTime = new Date(article.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n article.article_id,\n newsItem.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 篇文章 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取已发布文章列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <article-id>')\n .description('删除已发布文章')\n .option('-i, --index <index>', '文章索引', '0')\n .action(async (articleId, options) => {\n const spinner = ora('正在删除已发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const index = parseInt(options.index);\n await publishService.delete(articleId, index);\n \n spinner.succeed('已发布文章删除成功');\n } catch (error: any) {\n spinner.fail('删除已发布文章失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('status <publish-id>')\n .description('查询发布状态')\n .action(async (publishId) => {\n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const status = await publishService.getStatus(publishId);\n \n console.log(chalk.green('发布状态:'));\n console.log(` Publish ID: ${status.publish_id}`);\n console.log(` 状态: ${status.publish_status === 0 ? '成功' : '失败'}`);\n \n if (status.article_id) {\n console.log(` Article ID: ${status.article_id}`);\n }\n \n if (status.article_detail) {\n console.log(` 文章数量: ${status.article_detail.count}`);\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 查询发布状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createAccountCommand } from './commands/account';\nimport { createThemeCommand } from './commands/theme';\nimport { createDraftCommand } from './commands/draft';\nimport { createPublishCommand } from './commands/publish';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('wechat-pub')\n .description('全功能微信公众号 Markdown 发布工具')\n .version(packageJson.version);\n\nprogram.addCommand(createAccountCommand());\nprogram.addCommand(createThemeCommand());\nprogram.addCommand(createDraftCommand());\nprogram.addCommand(createPublishCommand());\n\nprogram.parse();\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/infrastructure/cache/CacheStore.ts","../src/infrastructure/cache/TokenCache.ts","../src/infrastructure/cache/ImageCache.ts","../src/infrastructure/cache/ThemeCache.ts","../src/infrastructure/http/HttpClient.ts","../src/utils/image.ts","../src/utils/crypto.ts","../src/utils/file.ts","../src/core/renderer/ImageProcessor.ts","../src/services/AccountService.ts","../src/services/ThemeService.ts","../src/services/RenderService.ts","../src/services/DraftService.ts","../src/services/PublishService.ts","../src/container.ts","../src/cli/commands/account.ts","../src/cli/commands/theme.ts","../src/cli/commands/draft.ts","../src/cli/commands/publish.ts","../src/cli/index.ts"],"sourcesContent":["export interface CacheEntry<T> {\n value: T;\n expireAt: number;\n}\n\nexport class CacheStore<T = any> {\n private cache: Map<string, CacheEntry<T>> = new Map();\n private maxSize: number;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n }\n\n async get(key: string): Promise<T | null> {\n const entry = this.cache.get(key);\n \n if (!entry) {\n return null;\n }\n\n if (Date.now() > entry.expireAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.value;\n }\n\n async set(key: string, value: T, ttl: number = 3600): Promise<void> {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expireAt: Date.now() + ttl * 1000,\n });\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n\n async size(): Promise<number> {\n return this.cache.size;\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface TokenCacheEntry {\n access_token: string;\n expires_in: number;\n}\n\nexport class TokenCache extends CacheStore<TokenCacheEntry> {\n constructor() {\n super(10);\n }\n\n async getToken(appId: string): Promise<string | null> {\n const entry = await this.get(appId);\n return entry ? entry.access_token : null;\n }\n\n async setToken(appId: string, accessToken: string, expiresIn: number): Promise<void> {\n await this.set(\n appId,\n {\n access_token: accessToken,\n expires_in: expiresIn,\n },\n expiresIn - 200\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface ImageCacheEntry {\n media_id: string;\n url: string;\n}\n\nexport class ImageCache extends CacheStore<ImageCacheEntry> {\n constructor() {\n super(500);\n }\n\n async getMediaId(md5: string): Promise<string | null> {\n const entry = await this.get(md5);\n return entry ? entry.media_id : null;\n }\n\n async setImage(md5: string, mediaId: string, url: string, ttl: number = 86400): Promise<void> {\n await this.set(\n md5,\n {\n media_id: mediaId,\n url,\n },\n ttl\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport class ThemeCache extends CacheStore<string> {\n constructor() {\n super(50);\n }\n\n async getThemeCSS(themeId: string): Promise<string | null> {\n return await this.get(themeId);\n }\n\n async setThemeCSS(themeId: string, css: string, ttl: number = 3600): Promise<void> {\n await this.set(themeId, css, ttl);\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport { Logger } from '../logger/Logger';\n\nexport class HttpClient {\n private client: AxiosInstance;\n\n constructor(private logger: Logger) {\n this.client = axios.create({\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (config) => {\n this.logger.debug('HTTP Request', {\n method: config.method,\n url: config.url,\n });\n return config;\n },\n (error) => {\n this.logger.error('HTTP Request Error', { error: error.message });\n return Promise.reject(error);\n }\n );\n\n this.client.interceptors.response.use(\n (response) => {\n this.logger.debug('HTTP Response', {\n status: response.status,\n url: response.config.url,\n });\n return response;\n },\n (error) => {\n this.logger.error('HTTP Response Error', {\n status: error.response?.status,\n message: error.message,\n });\n return Promise.reject(error);\n }\n );\n }\n\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.get<T>(url, config);\n }\n\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.post<T>(url, data, config);\n }\n\n async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.put<T>(url, data, config);\n }\n\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.delete<T>(url, config);\n }\n}\n","import { readFile } from 'fs/promises';\nimport axios from 'axios';\n\nexport async function downloadImage(url: string): Promise<Buffer> {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n \n if (!response.data || response.data.byteLength === 0) {\n throw new Error('下载的图片大小为 0');\n }\n \n return Buffer.from(response.data);\n } catch (error) {\n throw new Error(`下载图片失败: ${url}`);\n }\n}\n\nexport async function readImageFile(filePath: string): Promise<Buffer> {\n try {\n const buffer = await readFile(filePath);\n \n if (buffer.length === 0) {\n throw new Error('图片文件大小为 0');\n }\n \n return buffer;\n } catch (error) {\n throw new Error(`读取图片文件失败: ${filePath}`);\n }\n}\n\nexport function isRemoteUrl(url: string): boolean {\n return url.startsWith('http://') || url.startsWith('https://');\n}\n\nexport function isWechatImageUrl(url: string): boolean {\n return url.startsWith('https://mmbiz.qpic.cn');\n}\n\nexport function getImageFilename(url: string): string {\n const urlWithoutQuery = url.split('?')[0];\n const parts = urlWithoutQuery.split('/');\n const filename = parts[parts.length - 1];\n \n const ext = filename.match(/\\.(jpg|jpeg|png|gif|webp|bmp)$/i);\n if (!ext) {\n return `${filename}.jpg`;\n }\n \n return filename;\n}\n","import { createHash } from 'crypto';\nimport { readFile } from 'fs/promises';\n\nexport function md5FromBuffer(buffer: Buffer): string {\n return createHash('md5').update(buffer).digest('hex');\n}\n\nexport function md5FromString(str: string): string {\n return createHash('md5').update(str).digest('hex');\n}\n\nexport async function md5FromFile(filePath: string): Promise<string> {\n const buffer = await readFile(filePath);\n return md5FromBuffer(buffer);\n}\n\nexport function generateId(prefix: string = ''): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return prefix ? `${prefix}_${timestamp}_${random}` : `${timestamp}_${random}`;\n}\n","import { readFile, writeFile, access, mkdir } from 'fs/promises';\nimport { dirname, resolve, isAbsolute } from 'path';\nimport { constants } from 'fs';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch (error) {\n throw new Error(`无法读取文件: ${filePath}`);\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string): Promise<void> {\n try {\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`无法写入文件: ${filePath}`);\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolvePath(filePath: string, basePath?: string): string {\n if (isAbsolute(filePath)) {\n return filePath;\n }\n \n if (basePath) {\n return resolve(basePath, filePath);\n }\n \n return resolve(process.cwd(), filePath);\n}\n\nexport function getFileExtension(filePath: string): string {\n const match = filePath.match(/\\.([^.]+)$/);\n return match ? match[1].toLowerCase() : '';\n}\n\nexport function isImageFile(filePath: string): boolean {\n const ext = getFileExtension(filePath);\n return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(ext);\n}\n","import { JSDOM } from 'jsdom';\nimport { MaterialAPI } from '../wechat/api/MaterialAPI';\nimport { ImageCache } from '../../infrastructure/cache/ImageCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\nimport { downloadImage, readImageFile, isRemoteUrl, isWechatImageUrl, getImageFilename } from '../../utils/image';\nimport { md5FromBuffer } from '../../utils/crypto';\nimport { resolvePath } from '../../utils/file';\n\nexport interface ProcessImagesResult {\n content: string;\n firstImageMediaId: string;\n}\n\nexport class ImageProcessor {\n constructor(\n private materialAPI: MaterialAPI,\n private imageCache: ImageCache,\n private logger: Logger\n ) {}\n\n async processImages(content: string, relativePath?: string): Promise<ProcessImagesResult> {\n if (!content.includes('<img')) {\n return { content, firstImageMediaId: '' };\n }\n\n const dom = new JSDOM(content);\n const images = dom.window.document.querySelectorAll('img');\n \n const uploadPromises = Array.from(images).map(async (element: any) => {\n const src = element.getAttribute('src');\n if (!src) return null;\n\n if (isWechatImageUrl(src)) {\n return src;\n }\n\n const result = await this.uploadImage(src, relativePath);\n element.setAttribute('src', result.url);\n return result.media_id;\n });\n\n const mediaIds = (await Promise.all(uploadPromises)).filter(Boolean) as string[];\n const firstImageMediaId = mediaIds[0] || '';\n\n return {\n content: dom.serialize(),\n firstImageMediaId,\n };\n }\n\n async uploadImage(imagePath: string, relativePath?: string): Promise<{ media_id: string; url: string }> {\n let buffer: Buffer;\n let filename: string;\n\n if (isRemoteUrl(imagePath)) {\n this.logger.info('下载远程图片', { url: imagePath });\n buffer = await downloadImage(imagePath);\n filename = getImageFilename(imagePath);\n } else {\n const resolvedPath = resolvePath(imagePath, relativePath);\n this.logger.info('读取本地图片', { path: resolvedPath });\n buffer = await readImageFile(resolvedPath);\n filename = getImageFilename(resolvedPath);\n }\n\n const md5 = md5FromBuffer(buffer);\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n this.logger.debug('使用缓存的图片', { md5 });\n const cachedEntry = await this.imageCache.get(md5);\n return { media_id: cached, url: cachedEntry!.url };\n }\n\n const result = await this.materialAPI.uploadImage(buffer, filename);\n await this.imageCache.setImage(md5, result.media_id, result.url);\n\n this.logger.info('图片上传成功', { media_id: result.media_id });\n return result;\n }\n\n async uploadCover(coverPath: string | undefined, relativePath?: string, fallbackMediaId?: string): Promise<string> {\n if (!coverPath) {\n if (fallbackMediaId) {\n return fallbackMediaId;\n }\n throw new Error('必须指定封面图或在正文中至少包含一张图片');\n }\n\n if (isWechatImageUrl(coverPath)) {\n const md5 = md5FromBuffer(Buffer.from(coverPath));\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n return cached;\n }\n }\n\n const result = await this.uploadImage(coverPath, relativePath);\n return result.media_id;\n }\n}\n","import { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { Account, AccountCreateOptions } from '../types/account';\nimport { generateId } from '../utils/crypto';\n\nexport class AccountService {\n constructor(\n private configStore: ConfigStore,\n private logger: Logger\n ) {}\n\n async addAccount(options: AccountCreateOptions): Promise<Account> {\n this.logger.info('添加账号', { name: options.name });\n\n const accounts = await this.listAccounts();\n \n const existingAccount = accounts.find(a => a.appId === options.appId);\n if (existingAccount) {\n throw new Error(`账号已存在: ${existingAccount.name}`);\n }\n\n const account: Account = {\n id: generateId('acc'),\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.isDefault || accounts.length === 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n if (account.isDefault) {\n accounts.forEach(a => a.isDefault = false);\n }\n\n accounts.push(account);\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号添加成功', { id: account.id, name: account.name });\n return account;\n }\n\n async listAccounts(): Promise<Account[]> {\n return this.configStore.get('accounts', []);\n }\n\n async getAccount(id: string): Promise<Account | null> {\n const accounts = await this.listAccounts();\n return accounts.find(a => a.id === id) || null;\n }\n\n async getCurrentAccount(): Promise<Account> {\n const accounts = await this.listAccounts();\n \n if (accounts.length === 0) {\n throw new Error('未配置账号,请先使用 account add 命令添加账号');\n }\n\n const defaultAccount = accounts.find(a => a.isDefault);\n if (defaultAccount) {\n return defaultAccount;\n }\n\n return accounts[0];\n }\n\n async setDefaultAccount(id: string): Promise<void> {\n this.logger.info('设置默认账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n accounts.forEach(a => {\n a.isDefault = a.id === id;\n if (a.id === id) {\n a.updatedAt = new Date();\n }\n });\n\n this.configStore.set('accounts', accounts);\n this.logger.info('默认账号设置成功', { name: account.name });\n }\n\n async removeAccount(id: string): Promise<void> {\n this.logger.info('删除账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n const filtered = accounts.filter(a => a.id !== id);\n\n if (account.isDefault && filtered.length > 0) {\n filtered[0].isDefault = true;\n }\n\n this.configStore.set('accounts', filtered);\n this.logger.info('账号删除成功', { name: account.name });\n }\n\n async updateAccount(id: string, updates: Partial<Account>): Promise<Account> {\n this.logger.info('更新账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n Object.assign(account, updates, { updatedAt: new Date() });\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号更新成功', { name: account.name });\n return account;\n }\n}\n","import { ThemeEngine } from '../core/theme/ThemeEngine';\nimport { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { ThemeCache } from '../infrastructure/cache/ThemeCache';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { ThemeSource } from '../types/theme';\n\nexport class ThemeService {\n constructor(\n private themeEngine: ThemeEngine,\n private configStore: ConfigStore,\n private themeCache: ThemeCache,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n this.logger.info('初始化主题系统');\n\n await this.themeEngine.loadBuiltinThemes();\n\n const config = this.configStore.get('themes');\n if (!config) {\n return;\n }\n\n if (config.local) {\n for (const theme of config.local) {\n try {\n await this.themeEngine.addLocalTheme(theme.name, theme.path);\n } catch (error) {\n this.logger.warn('加载本地主题失败', { name: theme.name, error });\n }\n }\n }\n\n if (config.remote) {\n for (const remote of config.remote) {\n if (remote.enabled) {\n try {\n await this.themeEngine.addRemoteAPI(remote.name, remote.apiUrl, remote.apiKey);\n } catch (error) {\n this.logger.warn('添加远程主题 API 失败', { name: remote.name, error });\n }\n }\n }\n }\n\n this.logger.info('主题系统初始化完成');\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n return await this.themeEngine.listThemes();\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const cached = await this.themeCache.getThemeCSS(themeId);\n if (cached) {\n this.logger.debug('使用缓存的主题', { themeId });\n return cached;\n }\n\n const css = await this.themeEngine.getThemeCSS(themeId);\n await this.themeCache.setThemeCSS(themeId, css);\n\n return css;\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n this.logger.info('添加本地主题', { name, path });\n\n await this.themeEngine.addLocalTheme(name, path);\n\n const config = this.configStore.get('themes') || {};\n if (!config.local) {\n config.local = [];\n }\n\n const existing = config.local.find(t => t.name === name);\n if (existing) {\n existing.path = path;\n } else {\n config.local.push({ name, path });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('本地主题添加成功');\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.logger.info('添加远程主题 API', { name, apiUrl });\n\n await this.themeEngine.addRemoteAPI(name, apiUrl, apiKey);\n\n const config = this.configStore.get('themes') || {};\n if (!config.remote) {\n config.remote = [];\n }\n\n const existing = config.remote.find(r => r.name === name);\n if (existing) {\n existing.apiUrl = apiUrl;\n existing.apiKey = apiKey;\n existing.enabled = true;\n } else {\n config.remote.push({ name, apiUrl, apiKey, enabled: true });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('远程主题 API 添加成功');\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.logger.info('删除主题', { themeId });\n\n await this.themeEngine.removeTheme(themeId);\n await this.themeCache.delete(themeId);\n\n const config = this.configStore.get('themes') || {};\n if (config.local) {\n config.local = config.local.filter(t => t.name !== themeId);\n }\n\n this.configStore.set('themes', config);\n this.logger.info('主题删除成功');\n }\n}\n","import { MarkdownRenderer, RenderResult } from '../core/renderer/MarkdownRenderer';\nimport { ThemeService } from './ThemeService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileContent } from '../utils/file';\n\nexport interface RenderOptions {\n markdown?: string;\n file?: string;\n theme?: string;\n}\n\nexport class RenderService {\n constructor(\n private renderer: MarkdownRenderer,\n private themeService: ThemeService,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n await this.renderer.initialize();\n }\n\n async render(options: RenderOptions): Promise<RenderResult> {\n let markdown: string;\n\n if (options.file) {\n this.logger.info('读取 Markdown 文件', { file: options.file });\n markdown = await readFileContent(options.file);\n } else if (options.markdown) {\n markdown = options.markdown;\n } else {\n throw new Error('必须提供 markdown 内容或 file 路径');\n }\n\n let themeCss: string | undefined;\n if (options.theme) {\n this.logger.info('加载主题', { theme: options.theme });\n themeCss = await this.themeService.getThemeCSS(options.theme);\n }\n\n this.logger.info('开始渲染 Markdown');\n const result = await this.renderer.render(markdown, themeCss);\n this.logger.info('Markdown 渲染完成', { title: result.title });\n\n return result;\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { RenderService } from './RenderService';\nimport { ImageProcessor } from '../core/renderer/ImageProcessor';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { DraftCreateOptions, Draft, DraftList } from '../types/draft';\nimport { dirname } from 'path';\n\nexport class DraftService {\n constructor(\n private wechatClient: WechatClient,\n private renderService: RenderService,\n private imageProcessor: ImageProcessor,\n private logger: Logger\n ) {}\n\n async create(options: DraftCreateOptions): Promise<{ media_id: string }> {\n this.logger.info('开始创建草稿', { file: options.file });\n\n const rendered = await this.renderService.render({\n markdown: options.markdown,\n file: options.file,\n theme: options.theme,\n });\n\n const relativePath = options.relativePath || (options.file ? dirname(options.file) : undefined);\n\n const { content, firstImageMediaId } = await this.imageProcessor.processImages(\n rendered.content,\n relativePath\n );\n\n const thumbMediaId = await this.imageProcessor.uploadCover(\n rendered.cover,\n relativePath,\n firstImageMediaId\n );\n\n const result = await this.wechatClient.draft.create({\n title: rendered.title,\n content,\n thumb_media_id: thumbMediaId,\n });\n\n this.logger.info('草稿创建成功', { media_id: result.media_id });\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<DraftList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.draft.list(offset, pageSize);\n }\n\n async get(mediaId: string): Promise<Draft> {\n return await this.wechatClient.draft.get(mediaId);\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n await this.wechatClient.draft.delete(mediaId);\n this.logger.info('草稿删除成功');\n }\n\n async batchDelete(mediaIds: string[]): Promise<void> {\n this.logger.info('批量删除草稿', { count: mediaIds.length });\n\n const results = await Promise.allSettled(\n mediaIds.map(id => this.delete(id))\n );\n\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0) {\n this.logger.warn('部分草稿删除失败', {\n failed: failed.length,\n total: mediaIds.length,\n });\n }\n }\n\n async count(): Promise<number> {\n return await this.wechatClient.draft.count();\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { DraftService } from './DraftService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../types/publish';\nimport type { DraftCreateOptions } from '../types/draft';\n\nexport class PublishService {\n constructor(\n private wechatClient: WechatClient,\n private draftService: DraftService,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n const result = await this.wechatClient.publish.submit(mediaId);\n this.logger.info('发布任务提交成功', { publish_id: result.publish_id });\n return result;\n }\n\n async createAndPublish(options: DraftCreateOptions): Promise<PublishResult> {\n this.logger.info('创建并发布文章');\n\n const { media_id } = await this.draftService.create(options);\n const result = await this.submit(media_id);\n\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<PublishList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.publish.list(offset, pageSize);\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n return await this.wechatClient.publish.get(articleId);\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n await this.wechatClient.publish.delete(articleId, index);\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n return await this.wechatClient.publish.getStatus(publishId);\n }\n}\n","import { ConfigStore } from './infrastructure/config/ConfigStore';\nimport { TokenCache } from './infrastructure/cache/TokenCache';\nimport { ImageCache } from './infrastructure/cache/ImageCache';\nimport { ThemeCache } from './infrastructure/cache/ThemeCache';\nimport { Logger } from './infrastructure/logger/Logger';\nimport { HttpClient } from './infrastructure/http/HttpClient';\nimport { WechatClient } from './core/wechat/WechatClient';\nimport { ThemeEngine } from './core/theme/ThemeEngine';\nimport { MarkdownRenderer } from './core/renderer/MarkdownRenderer';\nimport { ImageProcessor } from './core/renderer/ImageProcessor';\nimport { AccountService } from './services/AccountService';\nimport { ThemeService } from './services/ThemeService';\nimport { RenderService } from './services/RenderService';\nimport { DraftService } from './services/DraftService';\nimport { PublishService } from './services/PublishService';\n\nclass Container {\n\n private configStore!: ConfigStore;\n private logger!: Logger;\n private httpClient!: HttpClient;\n private tokenCache!: TokenCache;\n private imageCache!: ImageCache;\n private themeCache!: ThemeCache;\n private themeEngine!: ThemeEngine;\n private renderer!: MarkdownRenderer;\n private accountService!: AccountService;\n private themeService!: ThemeService;\n private renderService!: RenderService;\n\n async initialize(): Promise<void> {\n this.configStore = new ConfigStore();\n this.logger = new Logger();\n this.httpClient = new HttpClient(this.logger);\n this.tokenCache = new TokenCache();\n this.imageCache = new ImageCache();\n this.themeCache = new ThemeCache();\n this.themeEngine = new ThemeEngine();\n this.renderer = new MarkdownRenderer();\n \n this.accountService = new AccountService(this.configStore, this.logger);\n this.themeService = new ThemeService(\n this.themeEngine,\n this.configStore,\n this.themeCache,\n this.logger\n );\n this.renderService = new RenderService(\n this.renderer,\n this.themeService,\n this.logger\n );\n\n await this.themeService.initialize();\n await this.renderService.initialize();\n }\n\n getAccountService(): AccountService {\n return this.accountService;\n }\n\n getThemeService(): ThemeService {\n return this.themeService;\n }\n\n getRenderService(): RenderService {\n return this.renderService;\n }\n\n async getDraftService(): Promise<DraftService> {\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n const imageProcessor = new ImageProcessor(\n wechatClient.material,\n this.imageCache,\n this.logger\n );\n\n return new DraftService(\n wechatClient,\n this.renderService,\n imageProcessor,\n this.logger\n );\n }\n\n async getPublishService(): Promise<PublishService> {\n const draftService = await this.getDraftService();\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n return new PublishService(\n wechatClient,\n draftService,\n this.logger\n );\n }\n}\n\nexport const container = new Container();\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createAccountCommand(): Command {\n const cmd = new Command('account')\n .description('账号管理');\n\n cmd.command('add')\n .description('添加微信公众号账号')\n .requiredOption('--name <name>', '账号名称')\n .requiredOption('--app-id <appId>', '微信公众号 AppID')\n .requiredOption('--app-secret <appSecret>', '微信公众号 AppSecret')\n .option('--default', '设为默认账号')\n .action(async (options) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n\n const account = await accountService.addAccount({\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.default,\n });\n\n console.log(chalk.green('✓ 账号添加成功'));\n console.log(` ID: ${account.id}`);\n console.log(` 名称: ${account.name}`);\n console.log(` AppID: ${account.appId}`);\n console.log(` 默认账号: ${account.isDefault ? '是' : '否'}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出所有账号')\n .action(async () => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n const accounts = await accountService.listAccounts();\n\n if (accounts.length === 0) {\n console.log(chalk.yellow('未配置账号'));\n console.log('使用 account add 命令添加账号');\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', 'AppID', '默认'],\n colWidths: [25, 20, 20, 8],\n });\n\n accounts.forEach(account => {\n table.push([\n account.id,\n account.name,\n account.appId,\n account.isDefault ? chalk.green('是') : '否',\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取账号列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('switch <id>')\n .description('切换默认账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.setDefaultAccount(id);\n console.log(chalk.green('✓ 默认账号切换成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 切换账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <id>')\n .description('删除账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.removeAccount(id);\n console.log(chalk.green('✓ 账号删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createThemeCommand(): Command {\n const cmd = new Command('theme')\n .description('主题管理');\n\n cmd.command('list')\n .description('列出所有可用主题')\n .action(async () => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n const themes = await themeService.listThemes();\n\n if (themes.length === 0) {\n console.log(chalk.yellow('未找到主题'));\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', '类型', '描述'],\n colWidths: [20, 25, 12, 40],\n });\n\n themes.forEach(theme => {\n const typeColor = theme.type === 'builtin' ? chalk.green :\n theme.type === 'local' ? chalk.blue :\n theme.type === 'remote' ? chalk.magenta : chalk.gray;\n \n table.push([\n theme.id,\n theme.name,\n typeColor(theme.type),\n theme.description || '-',\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${themes.length} 个主题`);\n } catch (error: any) {\n console.error(chalk.red('✗ 获取主题列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-local')\n .description('添加本地主题')\n .requiredOption('--name <name>', '主题名称')\n .requiredOption('--path <path>', '主题 CSS 文件路径')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addLocalTheme(options.name, options.path);\n \n console.log(chalk.green('✓ 本地主题添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` 路径: ${options.path}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加本地主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-remote')\n .description('添加远程主题 API')\n .requiredOption('--name <name>', 'API 名称')\n .requiredOption('--url <url>', 'API URL')\n .requiredOption('--key <key>', 'API Key')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addRemoteAPI(options.name, options.url, options.key);\n \n console.log(chalk.green('✓ 远程主题 API 添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` URL: ${options.url}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加远程主题 API 失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <theme-id>')\n .description('删除主题')\n .action(async (themeId) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.removeTheme(themeId);\n \n console.log(chalk.green('✓ 主题删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createDraftCommand(): Command {\n const cmd = new Command('draft')\n .description('草稿管理');\n\n cmd.command('create')\n .description('创建草稿')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const result = await draftService.create({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('草稿创建成功');\n console.log(chalk.green(` Media ID: ${result.media_id}`));\n console.log(chalk.gray(' 提示: 使用 publish 命令发布此草稿'));\n } catch (error: any) {\n spinner.fail('创建草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出草稿')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取草稿列表...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await draftService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无草稿'));\n return;\n }\n\n const table = new Table({\n head: ['Media ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(draft => {\n const article = draft.content.news_item[0];\n const updateTime = new Date(draft.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n draft.media_id,\n article.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 个草稿 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取草稿列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <media-id>')\n .description('删除草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在删除草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n await draftService.delete(mediaId);\n \n spinner.succeed('草稿删除成功');\n } catch (error: any) {\n spinner.fail('删除草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('count')\n .description('获取草稿总数')\n .action(async () => {\n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const count = await draftService.count();\n \n console.log(chalk.green(`草稿总数: ${count}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 获取草稿总数失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createPublishCommand(): Command {\n const cmd = new Command('publish')\n .description('发布管理');\n\n cmd.command('submit <media-id>')\n .description('发布草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在发布草稿...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.submit(mediaId);\n \n spinner.succeed('发布任务提交成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n console.log(chalk.gray(' 提示: 使用 publish status 命令查看发布状态'));\n } catch (error: any) {\n spinner.fail('发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('create')\n .description('创建并发布文章')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建并发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.createAndPublish({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('文章创建并发布成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n } catch (error: any) {\n spinner.fail('创建并发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出已发布文章')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取已发布文章列表...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await publishService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无已发布文章'));\n return;\n }\n\n const table = new Table({\n head: ['Article ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(article => {\n const newsItem = article.content.news_item[0];\n const updateTime = new Date(article.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n article.article_id,\n newsItem.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 篇文章 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取已发布文章列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <article-id>')\n .description('删除已发布文章')\n .option('-i, --index <index>', '文章索引', '0')\n .action(async (articleId, options) => {\n const spinner = ora('正在删除已发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const index = parseInt(options.index);\n await publishService.delete(articleId, index);\n \n spinner.succeed('已发布文章删除成功');\n } catch (error: any) {\n spinner.fail('删除已发布文章失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('status <publish-id>')\n .description('查询发布状态')\n .action(async (publishId) => {\n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const status = await publishService.getStatus(publishId);\n \n console.log(chalk.green('发布状态:'));\n console.log(` Publish ID: ${status.publish_id}`);\n console.log(` 状态: ${status.publish_status === 0 ? '成功' : '失败'}`);\n \n if (status.article_id) {\n console.log(` Article ID: ${status.article_id}`);\n }\n \n if (status.article_detail) {\n console.log(` 文章数量: ${status.article_detail.count}`);\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 查询发布状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createAccountCommand } from './commands/account';\nimport { createThemeCommand } from './commands/theme';\nimport { createDraftCommand } from './commands/draft';\nimport { createPublishCommand } from './commands/publish';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('wechat-pub')\n .description('全功能微信公众号 Markdown 发布工具')\n .version(packageJson.version);\n\nprogram.addCommand(createAccountCommand());\nprogram.addCommand(createThemeCommand());\nprogram.addCommand(createDraftCommand());\nprogram.addCommand(createPublishCommand());\n\nprogram.parse();\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuiltinLoader.d.ts","sourceRoot":"","sources":["../../../../src/core/theme/loaders/BuiltinLoader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BuiltinLoader.d.ts","sourceRoot":"","sources":["../../../../src/core/theme/loaders/BuiltinLoader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAiBlD,qBAAa,aAAa;IAChB,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;CAuBpC"}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import { getTheme } from '@wenyan-md/core';
|
|
2
1
|
import { readFile } from 'fs/promises';
|
|
3
2
|
import { join } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
3
|
import { dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
6
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
6
|
const __dirname = dirname(__filename);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
{ id: 'orangeheart', name: 'Orange Heart', description: 'A vibrant and elegant theme in warm orange tones.' },
|
|
11
|
-
{ id: 'rainbow', name: 'Rainbow', description: 'A colorful, lively theme with a clean layout.' },
|
|
12
|
-
{ id: 'lapis', name: 'Lapis', description: 'A minimal and refreshing theme in cool blue tones.' },
|
|
13
|
-
{ id: 'pie', name: 'Pie', description: 'Inspired by sspai.com and Misty — modern, sharp, and stylish.' },
|
|
14
|
-
{ id: 'maize', name: 'Maize', description: 'A crisp, light theme with a soft maize palette.' },
|
|
15
|
-
{ id: 'purple', name: 'Purple', description: 'Clean and minimalist, with a subtle purple accent.' },
|
|
16
|
-
{ id: 'phycat', name: '物理猫-薄荷', description: 'A mint-green theme with clear structure and hierarchy.' },
|
|
17
|
-
];
|
|
7
|
+
// FIXED: Removed broken WENYAN_THEMES that reference non-existent themes
|
|
8
|
+
// Only keeping LOCAL_THEMES which match actual CSS files
|
|
18
9
|
const LOCAL_THEMES = [
|
|
10
|
+
{ id: 'default', name: '默认', description: 'A clean, classic layout ideal for long-form reading.' },
|
|
19
11
|
{ id: 'orangesun', name: 'Orange Sun', description: 'A warm and bright theme with orange sunshine vibes.' },
|
|
20
12
|
{ id: 'redruby', name: 'Red Ruby', description: 'An elegant theme with bold ruby red accents.' },
|
|
21
13
|
{ id: 'greenmint', name: 'Green Mint', description: 'A fresh and calming mint green theme.' },
|
|
@@ -25,25 +17,7 @@ const LOCAL_THEMES = [
|
|
|
25
17
|
export class BuiltinLoader {
|
|
26
18
|
async loadAll() {
|
|
27
19
|
const themes = [];
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
const wenyanTheme = getTheme(themeInfo.id);
|
|
31
|
-
if (!wenyanTheme) {
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
const css = await wenyanTheme.getCss();
|
|
35
|
-
themes.push({
|
|
36
|
-
id: themeInfo.id,
|
|
37
|
-
name: themeInfo.name,
|
|
38
|
-
type: 'builtin',
|
|
39
|
-
description: themeInfo.description,
|
|
40
|
-
getCss: async () => css,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
20
|
+
// FIXED: Only load LOCAL_THEMES that have matching CSS files
|
|
47
21
|
for (const themeInfo of LOCAL_THEMES) {
|
|
48
22
|
try {
|
|
49
23
|
const themePath = join(__dirname, '../../../..', 'themes', 'builtin', `${themeInfo.id}.css`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuiltinLoader.js","sourceRoot":"","sources":["../../../../src/core/theme/loaders/BuiltinLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"BuiltinLoader.js","sourceRoot":"","sources":["../../../../src/core/theme/loaders/BuiltinLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,yEAAyE;AACzE,yDAAyD;AAEzD,MAAM,YAAY,GAAG;IACjB,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,sDAAsD,EAAE;IAClG,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,qDAAqD,EAAE;IAC3G,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAChG,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,uCAAuC,EAAE;IAC7F,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,4CAA4C,EAAE;IACpG,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,0DAA0D,EAAE;CACjH,CAAC;AAEF,MAAM,OAAO,aAAa;IACtB,KAAK,CAAC,OAAO;QACT,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,6DAA6D;QAC7D,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;YACnC,IAAI,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;gBAC7F,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAE/C,MAAM,CAAC,IAAI,CAAC;oBACR,EAAE,EAAE,SAAS,CAAC,EAAE;oBAChB,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,SAAS,CAAC,WAAW;oBAClC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,GAAG;iBAC1B,CAAC,CAAC;YACP,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,SAAS;YACb,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
:root {
|
|
2
2
|
--primary-color: #3b82f6;
|
|
3
3
|
--text-color: #1e293b;
|
|
4
|
-
--bg-color:
|
|
4
|
+
--bg-color: transparent;
|
|
5
5
|
--border-color: #e2e8f0;
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
|
|
82
82
|
#wenyan ul,
|
|
83
83
|
#wenyan ol {
|
|
84
|
-
padding-left:
|
|
84
|
+
padding-left: 1em;
|
|
85
85
|
margin: 1em 0;
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Logger-Cf88TYgK.js","sources":["../src/errors/BaseError.ts","../src/errors/WechatError.ts","../src/core/wechat/constants.ts","../src/core/wechat/api/TokenAPI.ts","../src/core/wechat/api/DraftAPI.ts","../src/core/wechat/api/PublishAPI.ts","../src/core/wechat/api/MaterialAPI.ts","../src/core/wechat/WechatClient.ts","../src/errors/ThemeError.ts","../src/core/theme/loaders/LocalLoader.ts","../src/core/theme/loaders/RemoteLoader.ts","../src/core/theme/loaders/BuiltinLoader.ts","../src/core/theme/registry.ts","../src/core/theme/ThemeEngine.ts","../src/core/renderer/MarkdownRenderer.ts","../src/infrastructure/config/ConfigStore.ts","../src/infrastructure/logger/Logger.ts"],"sourcesContent":["export class BaseError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500,\n public details?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n };\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class WechatError extends BaseError {\n constructor(\n message: string,\n public errcode: number,\n public errmsg: string\n ) {\n super(message, 'WECHAT_API_ERROR', 500, { errcode, errmsg });\n }\n\n static fromResponse(data: { errcode: number; errmsg: string }): WechatError {\n return new WechatError(\n `微信 API 错误: ${data.errmsg} (${data.errcode})`,\n data.errcode,\n data.errmsg\n );\n }\n}\n\nexport class WechatAuthError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_AUTH_ERROR', 401);\n }\n}\n\nexport class WechatRateLimitError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_RATE_LIMIT_ERROR', 429);\n }\n}\n","export const WECHAT_API_BASE = 'https://api.weixin.qq.com';\n\nexport const WECHAT_API_ENDPOINTS = {\n TOKEN: '/cgi-bin/token',\n DRAFT_ADD: '/cgi-bin/draft/add',\n DRAFT_GET: '/cgi-bin/draft/get',\n DRAFT_DELETE: '/cgi-bin/draft/delete',\n DRAFT_UPDATE: '/cgi-bin/draft/update',\n DRAFT_BATCH_GET: '/cgi-bin/draft/batchget',\n DRAFT_COUNT: '/cgi-bin/draft/count',\n PUBLISH_SUBMIT: '/cgi-bin/freepublish/submit',\n PUBLISH_GET: '/cgi-bin/freepublish/get',\n PUBLISH_DELETE: '/cgi-bin/freepublish/delete',\n PUBLISH_BATCH_GET: '/cgi-bin/freepublish/batchget',\n PUBLISH_GET_STATUS: '/cgi-bin/freepublish/get',\n MATERIAL_ADD: '/cgi-bin/material/add_material',\n MATERIAL_GET: '/cgi-bin/material/get_material',\n MATERIAL_DELETE: '/cgi-bin/material/del_material',\n MATERIAL_BATCH_GET: '/cgi-bin/material/batchget_material',\n MATERIAL_COUNT: '/cgi-bin/material/get_materialcount',\n} as const;\n\nexport const WECHAT_ERROR_CODES = {\n SUCCESS: 0,\n INVALID_CREDENTIAL: 40001,\n ACCESS_TOKEN_EXPIRED: 42001,\n RATE_LIMIT_EXCEEDED: 45009,\n API_UNAUTHORIZED: 48001,\n} as const;\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport class TokenAPI {\n constructor(\n private appId: string,\n private appSecret: string,\n private httpClient: HttpClient,\n private tokenCache: TokenCache,\n private logger: Logger\n ) {}\n\n async getAccessToken(): Promise<string> {\n const cached = await this.tokenCache.getToken(this.appId);\n if (cached) {\n this.logger.debug('使用缓存的 Access Token', { appId: this.appId });\n return cached;\n }\n\n return await this.refreshAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n this.logger.info('刷新 Access Token', { appId: this.appId });\n\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.TOKEN}`;\n const response = await this.httpClient.get(url, {\n params: {\n grant_type: 'client_credential',\n appid: this.appId,\n secret: this.appSecret,\n },\n });\n\n const data = response.data;\n\n if (data.errcode) {\n throw WechatError.fromResponse(data);\n }\n\n await this.tokenCache.setToken(\n this.appId,\n data.access_token,\n data.expires_in\n );\n\n this.logger.info('Access Token 刷新成功', {\n appId: this.appId,\n expiresIn: data.expires_in,\n });\n\n return data.access_token;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { Draft, DraftList, DraftArticle } from '../../../types/draft';\n\nexport class DraftAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async create(article: DraftArticle): Promise<{ media_id: string }> {\n this.logger.info('创建草稿', { title: article.title });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_ADD}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n articles: [article],\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿创建成功', { media_id: data.media_id });\n return { media_id: data.media_id };\n }\n\n async get(mediaId: string): Promise<Draft> {\n this.logger.info('获取草稿详情', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<DraftList> {\n this.logger.info('获取草稿列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿删除成功');\n }\n\n async update(mediaId: string, article: DraftArticle, index: number = 0): Promise<void> {\n this.logger.info('更新草稿', { media_id: mediaId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_UPDATE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n index,\n articles: article,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿更新成功');\n }\n\n async count(): Promise<number> {\n this.logger.info('获取草稿总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data.total_count || 0;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../../../types/publish';\n\nexport class PublishAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_SUBMIT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('发布任务提交成功', { publish_id: data.publish_id });\n return {\n publish_id: data.publish_id,\n msg_data_id: data.msg_data_id,\n };\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n this.logger.info('获取已发布文章详情', { article_id: articleId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<PublishList> {\n this.logger.info('获取已发布文章列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n index,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n this.logger.info('获取发布状态', { publish_id: publishId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET_STATUS}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n publish_id: publishId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport interface UploadResult {\n media_id: string;\n url: string;\n}\n\nexport class MaterialAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async uploadImage(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传图片', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=image`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('图片上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async uploadThumb(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传封面图', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=thumb`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('封面图上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async getMaterialCount(): Promise<{ voice_count: number; video_count: number; image_count: number; news_count: number }> {\n this.logger.info('获取素材总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { TokenAPI } from './api/TokenAPI';\nimport { DraftAPI } from './api/DraftAPI';\nimport { PublishAPI } from './api/PublishAPI';\nimport { MaterialAPI } from './api/MaterialAPI';\nimport { HttpClient } from '../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\n\nexport class WechatClient {\n public readonly token: TokenAPI;\n public readonly draft: DraftAPI;\n public readonly publish: PublishAPI;\n public readonly material: MaterialAPI;\n\n constructor(\n private appId: string,\n appSecret: string,\n httpClient: HttpClient,\n tokenCache: TokenCache,\n logger: Logger\n ) {\n this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);\n \n const getAccessToken = () => this.token.getAccessToken();\n \n this.draft = new DraftAPI(getAccessToken, httpClient, logger);\n this.publish = new PublishAPI(getAccessToken, httpClient, logger);\n this.material = new MaterialAPI(getAccessToken, httpClient, logger);\n }\n\n async getAccessToken(): Promise<string> {\n return await this.token.getAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n return await this.token.refreshAccessToken();\n }\n\n getAppId(): string {\n return this.appId;\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class ThemeError extends BaseError {\n constructor(message: string, details?: any) {\n super(message, 'THEME_ERROR', 500, details);\n }\n}\n\nexport class ThemeNotFoundError extends BaseError {\n constructor(themeId: string) {\n super(`主题不存在: ${themeId}`, 'THEME_NOT_FOUND', 404, { themeId });\n }\n}\n\nexport class ThemeLoadError extends BaseError {\n constructor(themeId: string, reason: string) {\n super(`主题加载失败: ${themeId} - ${reason}`, 'THEME_LOAD_ERROR', 500, { themeId, reason });\n }\n}\n","import { readFile } from 'fs/promises';\nimport type { Theme } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class LocalLoader {\n async load(name: string, path: string): Promise<Theme> {\n try {\n const css = await readFile(path, 'utf-8');\n \n return {\n id: name,\n name,\n type: 'local',\n description: `本地主题: ${path}`,\n getCss: async () => css,\n };\n } catch (error) {\n throw new ThemeLoadError(name, `无法读取文件: ${path}`);\n }\n }\n}\n","import axios from 'axios';\nimport type { Theme, ThemeSource, RemoteThemeConfig } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class RemoteLoader {\n private configs: Map<string, RemoteThemeConfig> = new Map();\n\n async addAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.configs.set(name, {\n name,\n apiUrl,\n apiKey,\n enabled: true,\n });\n }\n\n async load(themeId: string): Promise<Theme | null> {\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const css = await this.fetchThemeCSS(config.apiUrl, config.apiKey, themeId);\n if (css) {\n return {\n id: themeId,\n name: `${name}:${themeId}`,\n type: 'remote',\n description: `远程主题来自 ${name}`,\n getCss: async () => css,\n };\n }\n } catch (error) {\n continue;\n }\n }\n\n return null;\n }\n\n async list(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const themeList = await this.fetchThemeList(config.apiUrl, config.apiKey);\n for (const themeId of themeList) {\n themes.push({\n type: 'remote',\n id: themeId,\n name: `${name}:${themeId}`,\n description: `远程主题来自 ${name}`,\n });\n }\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n\n getConfig(): RemoteThemeConfig[] {\n return Array.from(this.configs.values());\n }\n\n private async fetchThemeList(apiUrl: string, apiKey: string): Promise<string[]> {\n try {\n const response = await axios.get(`${apiUrl}/themes`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.themes || [];\n } catch (error) {\n throw new ThemeLoadError('remote', '无法获取远程主题列表');\n }\n }\n\n private async fetchThemeCSS(apiUrl: string, apiKey: string, themeId: string): Promise<string | null> {\n try {\n const response = await axios.get(`${apiUrl}/themes/${themeId}`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.css || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { getTheme } from '@wenyan-md/core';\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\nimport type { Theme } from '../../../types/theme';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst WENYAN_THEMES = [\n { id: 'default', name: '默认', description: 'A clean, classic layout ideal for long-form reading.' },\n { id: 'orangeheart', name: 'Orange Heart', description: 'A vibrant and elegant theme in warm orange tones.' },\n { id: 'rainbow', name: 'Rainbow', description: 'A colorful, lively theme with a clean layout.' },\n { id: 'lapis', name: 'Lapis', description: 'A minimal and refreshing theme in cool blue tones.' },\n { id: 'pie', name: 'Pie', description: 'Inspired by sspai.com and Misty — modern, sharp, and stylish.' },\n { id: 'maize', name: 'Maize', description: 'A crisp, light theme with a soft maize palette.' },\n { id: 'purple', name: 'Purple', description: 'Clean and minimalist, with a subtle purple accent.' },\n { id: 'phycat', name: '物理猫-薄荷', description: 'A mint-green theme with clear structure and hierarchy.' },\n];\n\nconst LOCAL_THEMES = [\n { id: 'orangesun', name: 'Orange Sun', description: 'A warm and bright theme with orange sunshine vibes.' },\n { id: 'redruby', name: 'Red Ruby', description: 'An elegant theme with bold ruby red accents.' },\n { id: 'greenmint', name: 'Green Mint', description: 'A fresh and calming mint green theme.' },\n { id: 'purplerain', name: 'Purple Rain', description: 'A dreamy purple theme with soft gradients.' },\n { id: 'blackink', name: 'Black Ink', description: 'A dark mode theme with indigo accents for night reading.' },\n];\n\nexport class BuiltinLoader {\n async loadAll(): Promise<Theme[]> {\n const themes: Theme[] = [];\n\n for (const themeInfo of WENYAN_THEMES) {\n try {\n const wenyanTheme = getTheme(themeInfo.id);\n if (!wenyanTheme) {\n continue;\n }\n\n const css = await wenyanTheme.getCss();\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n continue;\n }\n }\n\n for (const themeInfo of LOCAL_THEMES) {\n try {\n const themePath = join(__dirname, '../../../..', 'themes', 'builtin', `${themeInfo.id}.css`);\n const css = await readFile(themePath, 'utf-8');\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n}\n","import type { Theme, ThemeSource } from '../../types/theme';\n\nexport class ThemeRegistry {\n private themes: Map<string, Theme> = new Map();\n\n register(theme: Theme): void {\n this.themes.set(theme.id, theme);\n }\n\n get(id: string): Theme | undefined {\n return this.themes.get(id);\n }\n\n has(id: string): boolean {\n return this.themes.has(id);\n }\n\n remove(id: string): void {\n this.themes.delete(id);\n }\n\n list(): ThemeSource[] {\n return Array.from(this.themes.values()).map(theme => ({\n type: theme.type,\n id: theme.id,\n name: theme.name,\n description: theme.description,\n }));\n }\n\n getLocalThemes(): ThemeSource[] {\n return this.list().filter(t => t.type === 'local');\n }\n\n clear(): void {\n this.themes.clear();\n }\n}\n","import { LocalLoader } from './loaders/LocalLoader';\nimport { RemoteLoader } from './loaders/RemoteLoader';\nimport { BuiltinLoader } from './loaders/BuiltinLoader';\nimport { ThemeRegistry } from './registry';\nimport { ThemeNotFoundError } from '../../errors/ThemeError';\nimport type { ThemeSource } from '../../types/theme';\n\nexport class ThemeEngine {\n private registry: ThemeRegistry;\n private localLoader: LocalLoader;\n private remoteLoader: RemoteLoader;\n private builtinLoader: BuiltinLoader;\n\n constructor() {\n this.registry = new ThemeRegistry();\n this.localLoader = new LocalLoader();\n this.remoteLoader = new RemoteLoader();\n this.builtinLoader = new BuiltinLoader();\n }\n\n async loadBuiltinThemes(): Promise<void> {\n const themes = await this.builtinLoader.loadAll();\n for (const theme of themes) {\n this.registry.register(theme);\n }\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n const theme = await this.localLoader.load(name, path);\n this.registry.register(theme);\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n await this.remoteLoader.addAPI(name, apiUrl, apiKey);\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const theme = this.registry.get(themeId);\n if (theme) {\n return await theme.getCss();\n }\n\n const remoteTheme = await this.remoteLoader.load(themeId);\n if (remoteTheme) {\n return await remoteTheme.getCss();\n }\n\n throw new ThemeNotFoundError(themeId);\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n \n themes.push(...this.registry.list());\n \n themes.push(...await this.remoteLoader.list());\n\n return themes;\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.registry.remove(themeId);\n }\n\n async getConfig(): Promise<any> {\n return {\n local: this.registry.getLocalThemes(),\n remote: this.remoteLoader.getConfig(),\n };\n }\n}\n","import { createWenyanCore } from '@wenyan-md/core';\nimport type { ApplyStylesOptions } from '@wenyan-md/core';\nimport { JSDOM } from 'jsdom';\n\nexport interface RenderResult {\n title: string;\n content: string;\n cover?: string;\n}\n\nexport class MarkdownRenderer {\n private wenyan: any;\n\n async initialize(): Promise<void> {\n this.wenyan = await createWenyanCore({\n isConvertMathJax: true,\n isWechat: true,\n });\n }\n\n async render(markdown: string, themeCss?: string): Promise<RenderResult> {\n if (!this.wenyan) {\n await this.initialize();\n }\n\n const result = await this.wenyan.handleFrontMatter(markdown);\n \n if (!result || !result.body) {\n throw new Error('Invalid markdown: handleFrontMatter returned empty data');\n }\n \n const html = await this.wenyan.renderMarkdown(result.body);\n\n const dom = new JSDOM(html);\n const document = dom.window.document;\n const wenyanElement = document.createElement('div');\n wenyanElement.id = 'wenyan';\n wenyanElement.innerHTML = html;\n\n const options: ApplyStylesOptions = {\n themeCss,\n isMacStyle: true,\n isAddFootnote: false,\n };\n\n const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);\n\n return {\n title: result.title || '',\n content: styledHtml,\n cover: result.cover,\n };\n }\n}\n","import Conf from 'conf';\nimport { z } from 'zod';\nimport type { Config } from '../../types/config';\n\nconst AccountSchema = z.object({\n id: z.string(),\n name: z.string(),\n appId: z.string().regex(/^wx[a-zA-Z0-9]{16}$/, '无效的 AppID 格式'),\n appSecret: z.string().min(32, 'AppSecret 长度不足'),\n isDefault: z.boolean().optional(),\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport class ConfigStore {\n private store: Conf<Config>;\n\n constructor() {\n this.store = new Conf<Config>({\n projectName: 'wechat-md-publisher',\n });\n }\n\n get<K extends keyof Config>(key: K): Config[K] | undefined;\n get<K extends keyof Config>(key: K, defaultValue: Config[K]): Config[K];\n get<K extends keyof Config>(key: K, defaultValue?: Config[K]): Config[K] | undefined {\n return this.store.get(key, defaultValue as any);\n }\n\n set<K extends keyof Config>(key: K, value: Config[K]): void {\n if (key === 'accounts') {\n z.array(AccountSchema).parse(value);\n }\n this.store.set(key, value);\n }\n\n has(key: keyof Config): boolean {\n return this.store.has(key);\n }\n\n delete(key: keyof Config): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n getAll(): Config {\n return this.store.store;\n }\n\n getPath(): string {\n return this.store.path;\n }\n}\n","import winston from 'winston';\n\nexport class Logger {\n private logger: winston.Logger;\n\n constructor() {\n this.logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';\n return `${timestamp} [${level}]: ${message} ${metaStr}`;\n })\n ),\n }),\n ],\n });\n }\n\n debug(message: string, meta?: any): void {\n this.logger.debug(message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.logger.info(message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.logger.warn(message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.logger.error(message, meta);\n }\n}\n"],"names":["__filename","__dirname"],"mappings":"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"}
|