xiaohongshu-mcp-node 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +306 -0
  3. package/dist/actions/comment.action.d.ts +9 -0
  4. package/dist/actions/comment.action.d.ts.map +1 -0
  5. package/dist/actions/comment.action.js +38 -0
  6. package/dist/actions/comment.action.js.map +1 -0
  7. package/dist/actions/feed-detail.action.d.ts +17 -0
  8. package/dist/actions/feed-detail.action.d.ts.map +1 -0
  9. package/dist/actions/feed-detail.action.js +166 -0
  10. package/dist/actions/feed-detail.action.js.map +1 -0
  11. package/dist/actions/interaction.action.d.ts +12 -0
  12. package/dist/actions/interaction.action.d.ts.map +1 -0
  13. package/dist/actions/interaction.action.js +75 -0
  14. package/dist/actions/interaction.action.js.map +1 -0
  15. package/dist/actions/login.action.d.ts +12 -0
  16. package/dist/actions/login.action.d.ts.map +1 -0
  17. package/dist/actions/login.action.js +52 -0
  18. package/dist/actions/login.action.js.map +1 -0
  19. package/dist/actions/publish-video.action.d.ts +17 -0
  20. package/dist/actions/publish-video.action.d.ts.map +1 -0
  21. package/dist/actions/publish-video.action.js +139 -0
  22. package/dist/actions/publish-video.action.js.map +1 -0
  23. package/dist/actions/publish.action.d.ts +19 -0
  24. package/dist/actions/publish.action.d.ts.map +1 -0
  25. package/dist/actions/publish.action.js +157 -0
  26. package/dist/actions/publish.action.js.map +1 -0
  27. package/dist/actions/search.action.d.ts +23 -0
  28. package/dist/actions/search.action.d.ts.map +1 -0
  29. package/dist/actions/search.action.js +121 -0
  30. package/dist/actions/search.action.js.map +1 -0
  31. package/dist/config/index.d.ts +4 -0
  32. package/dist/config/index.d.ts.map +1 -0
  33. package/dist/config/index.js +15 -0
  34. package/dist/config/index.js.map +1 -0
  35. package/dist/config/schema.d.ts +34 -0
  36. package/dist/config/schema.d.ts.map +1 -0
  37. package/dist/config/schema.js +18 -0
  38. package/dist/config/schema.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +31 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/mcp/server.d.ts +22 -0
  44. package/dist/mcp/server.d.ts.map +1 -0
  45. package/dist/mcp/server.js +251 -0
  46. package/dist/mcp/server.js.map +1 -0
  47. package/dist/mcp/tools/index.d.ts +3 -0
  48. package/dist/mcp/tools/index.d.ts.map +1 -0
  49. package/dist/mcp/tools/index.js +264 -0
  50. package/dist/mcp/tools/index.js.map +1 -0
  51. package/dist/services/browser.service.d.ts +15 -0
  52. package/dist/services/browser.service.d.ts.map +1 -0
  53. package/dist/services/browser.service.js +67 -0
  54. package/dist/services/browser.service.js.map +1 -0
  55. package/dist/services/cookie.service.d.ts +9 -0
  56. package/dist/services/cookie.service.d.ts.map +1 -0
  57. package/dist/services/cookie.service.js +49 -0
  58. package/dist/services/cookie.service.js.map +1 -0
  59. package/dist/services/xiaohongshu.service.d.ts +32 -0
  60. package/dist/services/xiaohongshu.service.d.ts.map +1 -0
  61. package/dist/services/xiaohongshu.service.js +194 -0
  62. package/dist/services/xiaohongshu.service.js.map +1 -0
  63. package/dist/types/xiaohongshu.types.d.ts +55 -0
  64. package/dist/types/xiaohongshu.types.d.ts.map +1 -0
  65. package/dist/types/xiaohongshu.types.js +2 -0
  66. package/dist/types/xiaohongshu.types.js.map +1 -0
  67. package/dist/utils/image-processor.d.ts +11 -0
  68. package/dist/utils/image-processor.d.ts.map +1 -0
  69. package/dist/utils/image-processor.js +75 -0
  70. package/dist/utils/image-processor.js.map +1 -0
  71. package/dist/utils/logger.d.ts +2 -0
  72. package/dist/utils/logger.d.ts.map +1 -0
  73. package/dist/utils/logger.js +14 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/dist/utils/title-validator.d.ts +3 -0
  76. package/dist/utils/title-validator.d.ts.map +1 -0
  77. package/dist/utils/title-validator.js +39 -0
  78. package/dist/utils/title-validator.js.map +1 -0
  79. package/dist/utils/wait-helper.d.ts +5 -0
  80. package/dist/utils/wait-helper.d.ts.map +1 -0
  81. package/dist/utils/wait-helper.js +46 -0
  82. package/dist/utils/wait-helper.js.map +1 -0
  83. package/package.json +75 -0
@@ -0,0 +1,49 @@
1
+ import fs from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import { logger } from '../utils/logger.js';
4
+ export class CookieService {
5
+ cookiePath;
6
+ constructor(cookiePath) {
7
+ this.cookiePath = cookiePath;
8
+ }
9
+ async load() {
10
+ try {
11
+ if (!existsSync(this.cookiePath)) {
12
+ logger.warn('Cookie file not found', { path: this.cookiePath });
13
+ return null;
14
+ }
15
+ const data = await fs.readFile(this.cookiePath, 'utf-8');
16
+ const cookies = JSON.parse(data);
17
+ logger.info('Cookies loaded', { count: cookies.length });
18
+ return cookies;
19
+ }
20
+ catch (error) {
21
+ logger.error('Failed to load cookies', { error });
22
+ return null;
23
+ }
24
+ }
25
+ async save(cookies) {
26
+ try {
27
+ const data = JSON.stringify(cookies, null, 2);
28
+ await fs.writeFile(this.cookiePath, data, 'utf-8');
29
+ logger.info('Cookies saved', { count: cookies.length });
30
+ }
31
+ catch (error) {
32
+ logger.error('Failed to save cookies', { error });
33
+ throw error;
34
+ }
35
+ }
36
+ async delete() {
37
+ try {
38
+ if (existsSync(this.cookiePath)) {
39
+ await fs.unlink(this.cookiePath);
40
+ logger.info('Cookies deleted');
41
+ }
42
+ }
43
+ catch (error) {
44
+ logger.error('Failed to delete cookies', { error });
45
+ throw error;
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=cookie.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.service.js","sourceRoot":"","sources":["../../src/services/cookie.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,OAAO,aAAa;IACJ;IAApB,YAAoB,UAAkB;QAAlB,eAAU,GAAV,UAAU,CAAQ;IAAG,CAAC;IAE1C,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;gBAChE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC;YAE7C,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAiB;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACpD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import { BrowserService } from './browser.service.js';
2
+ import { CookieService } from './cookie.service.js';
3
+ import { type SearchFilters } from '../actions/search.action.js';
4
+ import type { PublishImageContent, PublishVideoContent, PublishResponse, Feed, FeedDetail } from '../types/xiaohongshu.types.js';
5
+ export declare class XiaohongshuService {
6
+ private browserService;
7
+ private cookieService;
8
+ constructor(browserService: BrowserService, cookieService: CookieService);
9
+ checkLoginStatus(): Promise<{
10
+ isLoggedIn: boolean;
11
+ username: string;
12
+ }>;
13
+ getLoginQRCode(): Promise<{
14
+ image: string;
15
+ isLoggedIn: boolean;
16
+ timeout: string;
17
+ }>;
18
+ private waitForLoginInBackground;
19
+ deleteCookies(): Promise<void>;
20
+ publishContent(content: PublishImageContent): Promise<PublishResponse>;
21
+ publishVideo(content: PublishVideoContent): Promise<PublishResponse>;
22
+ searchFeeds(keyword: string, filters?: SearchFilters): Promise<Feed[]>;
23
+ listFeeds(): Promise<Feed[]>;
24
+ getFeedDetail(feedId: string, xsecToken: string, loadAllComments?: boolean): Promise<FeedDetail>;
25
+ postComment(feedId: string, xsecToken: string, content: string): Promise<void>;
26
+ replyComment(feedId: string, xsecToken: string, commentId: string, content: string): Promise<void>;
27
+ likeFeed(feedId: string, xsecToken: string): Promise<void>;
28
+ unlikeFeed(feedId: string, xsecToken: string): Promise<void>;
29
+ favoriteFeed(feedId: string, xsecToken: string): Promise<void>;
30
+ unfavoriteFeed(feedId: string, xsecToken: string): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=xiaohongshu.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xiaohongshu.service.d.ts","sourceRoot":"","sources":["../../src/services/xiaohongshu.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAK/E,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,IAAI,EACJ,UAAU,EACX,MAAM,+BAA+B,CAAC;AAEvC,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,aAAa;gBADb,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa;IAGhC,gBAAgB,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAgBtE,cAAc,IAAI,OAAO,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,OAAO,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;YAwBY,wBAAwB;IAkBhC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkBtE,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkBpE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAWtE,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAW5B,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,OAAe,GAC/B,OAAO,CAAC,UAAU,CAAC;IAWhB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9E,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAWV,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5D,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9D,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAUvE"}
@@ -0,0 +1,194 @@
1
+ import { LoginAction } from '../actions/login.action.js';
2
+ import { PublishAction } from '../actions/publish.action.js';
3
+ import { PublishVideoAction } from '../actions/publish-video.action.js';
4
+ import { SearchAction } from '../actions/search.action.js';
5
+ import { FeedDetailAction } from '../actions/feed-detail.action.js';
6
+ import { CommentAction } from '../actions/comment.action.js';
7
+ import { InteractionAction } from '../actions/interaction.action.js';
8
+ import { logger } from '../utils/logger.js';
9
+ export class XiaohongshuService {
10
+ browserService;
11
+ cookieService;
12
+ constructor(browserService, cookieService) {
13
+ this.browserService = browserService;
14
+ this.cookieService = cookieService;
15
+ }
16
+ async checkLoginStatus() {
17
+ const page = await this.browserService.newPage();
18
+ try {
19
+ const loginAction = new LoginAction(page);
20
+ const isLoggedIn = await loginAction.checkLoginStatus();
21
+ return {
22
+ isLoggedIn,
23
+ username: isLoggedIn ? 'xiaohongshu-mcp-node' : '',
24
+ };
25
+ }
26
+ finally {
27
+ await page.close();
28
+ }
29
+ }
30
+ async getLoginQRCode() {
31
+ const page = await this.browserService.newPage();
32
+ try {
33
+ const loginAction = new LoginAction(page);
34
+ const result = await loginAction.getQRCode();
35
+ if (result.isLoggedIn) {
36
+ return { ...result, timeout: '0s' };
37
+ }
38
+ const timeout = 4 * 60 * 1000;
39
+ this.waitForLoginInBackground(page, timeout);
40
+ return {
41
+ ...result,
42
+ timeout: '4m',
43
+ };
44
+ }
45
+ catch (error) {
46
+ await page.close();
47
+ throw error;
48
+ }
49
+ }
50
+ async waitForLoginInBackground(page, timeout) {
51
+ setTimeout(async () => {
52
+ try {
53
+ const loginAction = new LoginAction(page);
54
+ const success = await loginAction.waitForLogin(timeout);
55
+ if (success) {
56
+ await this.browserService.saveCookies();
57
+ logger.info('Login successful, cookies saved');
58
+ }
59
+ }
60
+ catch (error) {
61
+ logger.error('Background login wait failed', { error });
62
+ }
63
+ finally {
64
+ await page.close();
65
+ }
66
+ }, 0);
67
+ }
68
+ async deleteCookies() {
69
+ await this.cookieService.delete();
70
+ }
71
+ async publishContent(content) {
72
+ const page = await this.browserService.newPage();
73
+ try {
74
+ const publishAction = new PublishAction(page);
75
+ await publishAction.publish(content);
76
+ return {
77
+ title: content.title,
78
+ content: content.content,
79
+ images: content.imagePaths.length,
80
+ status: '发布完成',
81
+ };
82
+ }
83
+ finally {
84
+ await page.close();
85
+ }
86
+ }
87
+ async publishVideo(content) {
88
+ const page = await this.browserService.newPage();
89
+ try {
90
+ const publishAction = new PublishVideoAction(page);
91
+ await publishAction.publish(content);
92
+ return {
93
+ title: content.title,
94
+ content: content.content,
95
+ video: content.videoPath,
96
+ status: '发布完成',
97
+ };
98
+ }
99
+ finally {
100
+ await page.close();
101
+ }
102
+ }
103
+ async searchFeeds(keyword, filters) {
104
+ const page = await this.browserService.newPage();
105
+ try {
106
+ const searchAction = new SearchAction(page);
107
+ return await searchAction.search(keyword, filters);
108
+ }
109
+ finally {
110
+ await page.close();
111
+ }
112
+ }
113
+ async listFeeds() {
114
+ const page = await this.browserService.newPage();
115
+ try {
116
+ const searchAction = new SearchAction(page);
117
+ return await searchAction.listFeeds();
118
+ }
119
+ finally {
120
+ await page.close();
121
+ }
122
+ }
123
+ async getFeedDetail(feedId, xsecToken, loadAllComments = false) {
124
+ const page = await this.browserService.newPage();
125
+ try {
126
+ const feedDetailAction = new FeedDetailAction(page);
127
+ return await feedDetailAction.getFeedDetail(feedId, xsecToken, loadAllComments);
128
+ }
129
+ finally {
130
+ await page.close();
131
+ }
132
+ }
133
+ async postComment(feedId, xsecToken, content) {
134
+ const page = await this.browserService.newPage();
135
+ try {
136
+ const commentAction = new CommentAction(page);
137
+ await commentAction.postComment(feedId, xsecToken, content);
138
+ }
139
+ finally {
140
+ await page.close();
141
+ }
142
+ }
143
+ async replyComment(feedId, xsecToken, commentId, content) {
144
+ const page = await this.browserService.newPage();
145
+ try {
146
+ const commentAction = new CommentAction(page);
147
+ await commentAction.replyComment(feedId, xsecToken, commentId, content);
148
+ }
149
+ finally {
150
+ await page.close();
151
+ }
152
+ }
153
+ async likeFeed(feedId, xsecToken) {
154
+ const page = await this.browserService.newPage();
155
+ try {
156
+ const interactionAction = new InteractionAction(page);
157
+ await interactionAction.likeFeed(feedId, xsecToken);
158
+ }
159
+ finally {
160
+ await page.close();
161
+ }
162
+ }
163
+ async unlikeFeed(feedId, xsecToken) {
164
+ const page = await this.browserService.newPage();
165
+ try {
166
+ const interactionAction = new InteractionAction(page);
167
+ await interactionAction.unlikeFeed(feedId, xsecToken);
168
+ }
169
+ finally {
170
+ await page.close();
171
+ }
172
+ }
173
+ async favoriteFeed(feedId, xsecToken) {
174
+ const page = await this.browserService.newPage();
175
+ try {
176
+ const interactionAction = new InteractionAction(page);
177
+ await interactionAction.favoriteFeed(feedId, xsecToken);
178
+ }
179
+ finally {
180
+ await page.close();
181
+ }
182
+ }
183
+ async unfavoriteFeed(feedId, xsecToken) {
184
+ const page = await this.browserService.newPage();
185
+ try {
186
+ const interactionAction = new InteractionAction(page);
187
+ await interactionAction.unfavoriteFeed(feedId, xsecToken);
188
+ }
189
+ finally {
190
+ await page.close();
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=xiaohongshu.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xiaohongshu.service.js","sourceRoot":"","sources":["../../src/services/xiaohongshu.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ export interface PublishImageContent {
2
+ title: string;
3
+ content: string;
4
+ tags?: string[];
5
+ imagePaths: string[];
6
+ scheduleTime?: Date;
7
+ isOriginal?: boolean;
8
+ visibility?: 'public' | 'private' | 'friends';
9
+ products?: string[];
10
+ }
11
+ export interface PublishVideoContent {
12
+ title: string;
13
+ content: string;
14
+ tags?: string[];
15
+ videoPath: string;
16
+ scheduleTime?: Date;
17
+ visibility?: 'public' | 'private' | 'friends';
18
+ products?: string[];
19
+ }
20
+ export interface PublishResponse {
21
+ title: string;
22
+ content: string;
23
+ images?: number;
24
+ video?: string;
25
+ status: string;
26
+ postId?: string;
27
+ }
28
+ export interface Feed {
29
+ id: string;
30
+ xsecToken: string;
31
+ title: string;
32
+ user: {
33
+ userId: string;
34
+ nickname: string;
35
+ avatar: string;
36
+ };
37
+ cover: string;
38
+ likeCount: string;
39
+ commentCount: string;
40
+ }
41
+ export interface FeedDetail extends Feed {
42
+ desc: string;
43
+ images: string[];
44
+ comments: Comment[];
45
+ }
46
+ export interface Comment {
47
+ id: string;
48
+ userId: string;
49
+ nickname: string;
50
+ content: string;
51
+ likeCount: string;
52
+ createTime: number;
53
+ subComments?: Comment[];
54
+ }
55
+ //# sourceMappingURL=xiaohongshu.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xiaohongshu.types.d.ts","sourceRoot":"","sources":["../../src/types/xiaohongshu.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=xiaohongshu.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xiaohongshu.types.js","sourceRoot":"","sources":["../../src/types/xiaohongshu.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ export declare class ImageProcessor {
2
+ private tempDir;
3
+ constructor();
4
+ private ensureTempDir;
5
+ process(images: string[]): Promise<string[]>;
6
+ private isURL;
7
+ private downloadImage;
8
+ private getExtensionFromURL;
9
+ cleanup(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=image-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-processor.d.ts","sourceRoot":"","sources":["../../src/utils/image-processor.ts"],"names":[],"mappings":"AAMA,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAmB;;YAMpB,aAAa;IAMrB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBlD,OAAO,CAAC,KAAK;YAIC,aAAa;IAuB3B,OAAO,CAAC,mBAAmB;IAKrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAa/B"}
@@ -0,0 +1,75 @@
1
+ import fs from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import path from 'path';
4
+ import axios from 'axios';
5
+ import { logger } from './logger.js';
6
+ export class ImageProcessor {
7
+ tempDir = './temp_images';
8
+ constructor() {
9
+ this.ensureTempDir();
10
+ }
11
+ async ensureTempDir() {
12
+ if (!existsSync(this.tempDir)) {
13
+ await fs.mkdir(this.tempDir, { recursive: true });
14
+ }
15
+ }
16
+ async process(images) {
17
+ const processedImages = [];
18
+ for (const image of images) {
19
+ if (this.isURL(image)) {
20
+ const localPath = await this.downloadImage(image);
21
+ processedImages.push(localPath);
22
+ }
23
+ else {
24
+ if (existsSync(image)) {
25
+ processedImages.push(image);
26
+ }
27
+ else {
28
+ logger.warn('Image file not found, skipping', { path: image });
29
+ }
30
+ }
31
+ }
32
+ return processedImages;
33
+ }
34
+ isURL(str) {
35
+ return str.startsWith('http://') || str.startsWith('https://');
36
+ }
37
+ async downloadImage(url) {
38
+ try {
39
+ logger.info('Downloading image', { url });
40
+ const response = await axios.get(url, {
41
+ responseType: 'arraybuffer',
42
+ timeout: 30000,
43
+ });
44
+ const ext = this.getExtensionFromURL(url) || '.jpg';
45
+ const filename = `${Date.now()}_${Math.random().toString(36).substring(7)}${ext}`;
46
+ const localPath = path.join(this.tempDir, filename);
47
+ await fs.writeFile(localPath, response.data);
48
+ logger.info('Image downloaded', { url, localPath });
49
+ return localPath;
50
+ }
51
+ catch (error) {
52
+ logger.error('Failed to download image', { url, error });
53
+ throw new Error(`Failed to download image from ${url}`);
54
+ }
55
+ }
56
+ getExtensionFromURL(url) {
57
+ const match = url.match(/\.(jpg|jpeg|png|gif|webp)(\?.*)?$/i);
58
+ return match ? `.${match[1].toLowerCase()}` : null;
59
+ }
60
+ async cleanup() {
61
+ try {
62
+ if (existsSync(this.tempDir)) {
63
+ const files = await fs.readdir(this.tempDir);
64
+ for (const file of files) {
65
+ await fs.unlink(path.join(this.tempDir, file));
66
+ }
67
+ logger.debug('Temp images cleaned up');
68
+ }
69
+ }
70
+ catch (error) {
71
+ logger.error('Failed to cleanup temp images', { error });
72
+ }
73
+ }
74
+ }
75
+ //# sourceMappingURL=image-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-processor.js","sourceRoot":"","sources":["../../src/utils/image-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const logger: import("pino").Logger<never>;
2
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,8BAUjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import pino from 'pino';
2
+ const logLevel = process.env.LOG_LEVEL || 'info';
3
+ export const logger = pino({
4
+ level: logLevel,
5
+ transport: {
6
+ target: 'pino-pretty',
7
+ options: {
8
+ colorize: true,
9
+ translateTime: 'SYS:standard',
10
+ ignore: 'pid,hostname',
11
+ },
12
+ },
13
+ });
14
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;AAEjD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE;QACT,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI;YACd,aAAa,EAAE,cAAc;YAC7B,MAAM,EAAE,cAAc;SACvB;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function validateTitle(title: string): void;
2
+ export declare function calculateTitleLength(title: string): number;
3
+ //# sourceMappingURL=title-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-validator.d.ts","sourceRoot":"","sources":["../../src/utils/title-validator.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CASjD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc1D"}
@@ -0,0 +1,39 @@
1
+ export function validateTitle(title) {
2
+ if (!title || title.trim().length === 0) {
3
+ throw new Error('标题不能为空');
4
+ }
5
+ const length = calculateTitleLength(title);
6
+ if (length > 20) {
7
+ throw new Error(`标题长度超过限制(当前:${length},最大:20)`);
8
+ }
9
+ }
10
+ export function calculateTitleLength(title) {
11
+ let length = 0;
12
+ for (const char of title) {
13
+ // 中文字符、全角字符算1个字
14
+ // 英文字母、数字、半角字符算0.5个字
15
+ if (isCJKChar(char) || isFullWidthChar(char)) {
16
+ length += 1;
17
+ }
18
+ else {
19
+ length += 0.5;
20
+ }
21
+ }
22
+ return Math.ceil(length);
23
+ }
24
+ function isCJKChar(char) {
25
+ const code = char.charCodeAt(0);
26
+ return ((code >= 0x4e00 && code <= 0x9fff) || // CJK Unified Ideographs
27
+ (code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A
28
+ (code >= 0x20000 && code <= 0x2a6df) || // CJK Extension B
29
+ (code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility Ideographs
30
+ (code >= 0x3040 && code <= 0x309f) || // Hiragana
31
+ (code >= 0x30a0 && code <= 0x30ff) || // Katakana
32
+ (code >= 0xac00 && code <= 0xd7af) // Hangul
33
+ );
34
+ }
35
+ function isFullWidthChar(char) {
36
+ const code = char.charCodeAt(0);
37
+ return code >= 0xff00 && code <= 0xffef;
38
+ }
39
+ //# sourceMappingURL=title-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-validator.js","sourceRoot":"","sources":["../../src/utils/title-validator.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAG,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,SAAS,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,gBAAgB;QAChB,qBAAqB;QACrB,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,CACL,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,yBAAyB;QAC/D,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,kBAAkB;QACxD,CAAC,IAAI,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,kBAAkB;QAC1D,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,+BAA+B;QACrE,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,WAAW;QACjD,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,WAAW;QACjD,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,SAAS;KAC7C,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Page, Locator } from 'playwright';
2
+ export declare function waitForElement(page: Page, selector: string, timeout?: number): Promise<Locator>;
3
+ export declare function waitForUploadComplete(page: Page, expectedCount: number, timeout?: number): Promise<void>;
4
+ export declare function clickWithRetry(element: Locator, maxRetries?: number): Promise<void>;
5
+ //# sourceMappingURL=wait-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-helper.d.ts","sourceRoot":"","sources":["../../src/utils/wait-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGhD,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CASlB;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,MAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,46 @@
1
+ import { logger } from './logger.js';
2
+ export async function waitForElement(page, selector, timeout = 30000) {
3
+ try {
4
+ const element = page.locator(selector).first();
5
+ await element.waitFor({ timeout, state: 'visible' });
6
+ return element;
7
+ }
8
+ catch (error) {
9
+ logger.error('Element not found', { selector, timeout });
10
+ throw new Error(`Element not found: ${selector}`);
11
+ }
12
+ }
13
+ export async function waitForUploadComplete(page, expectedCount, timeout = 60000) {
14
+ const startTime = Date.now();
15
+ let lastCount = 0;
16
+ while (Date.now() - startTime < timeout) {
17
+ const uploadedImages = await page.locator('.img-preview-area .pr').all();
18
+ const currentCount = uploadedImages.length;
19
+ if (currentCount !== lastCount) {
20
+ logger.debug('Upload progress', { current: currentCount, expected: expectedCount });
21
+ lastCount = currentCount;
22
+ }
23
+ if (currentCount >= expectedCount) {
24
+ logger.info('Upload complete', { count: currentCount });
25
+ return;
26
+ }
27
+ await page.waitForTimeout(500);
28
+ }
29
+ throw new Error(`Upload timeout: expected ${expectedCount} images`);
30
+ }
31
+ export async function clickWithRetry(element, maxRetries = 3) {
32
+ for (let i = 0; i < maxRetries; i++) {
33
+ try {
34
+ await element.click();
35
+ return;
36
+ }
37
+ catch (error) {
38
+ if (i === maxRetries - 1) {
39
+ throw error;
40
+ }
41
+ logger.warn('Click failed, retrying', { attempt: i + 1 });
42
+ await element.page().waitForTimeout(1000);
43
+ }
44
+ }
45
+ }
46
+ //# sourceMappingURL=wait-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-helper.js","sourceRoot":"","sources":["../../src/utils/wait-helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAU,EACV,QAAgB,EAChB,UAAkB,KAAK;IAEvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC/C,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAU,EACV,aAAqB,EACrB,UAAkB,KAAK;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,OAAO,EAAE,CAAC;QACxC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,GAAG,EAAE,CAAC;QACzE,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC;QAE3C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;YACpF,SAAS,GAAG,YAAY,CAAC;QAC3B,CAAC;QAED,IAAI,YAAY,IAAI,aAAa,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4BAA4B,aAAa,SAAS,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,aAAqB,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,UAAU,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1D,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;AACH,CAAC"}