返回 AiToEarn
index.ts
1 import requestNet, { IRequestNetParams } from '../requestNet';
2 import {
3 CommentAddResponse,
4 GetCommentListResponse,
5 GetPhotoListResponse,
6 GetSubCommentListResponse,
7 GetWorksListResponse,
8 IGetHomeInfoResponse,
9 IGetHomeOverview,
10 IKwaiGetLocationsResponse,
11 IKwaiGetTopicsResponse,
12 IKwaiGetUsersResponse,
13 IKwaiPubVideoParams,
14 IKwaiUserInfoResponse,
15 ILoginResponse,
16 KwaiSubmitResponse,
17 KwaiWorkItem,
18 RefreshWorksResponse,
19 UploadFinishResponse,
20 UploadPpreResponse,
21 } from './kwai.type';
22 import { CookieToString } from '../utils';
23 import { BrowserWindow, screen } from 'electron';
24 import kwaiSign from './sign/KwaiSign';
25 import { FileUtils } from '../../util/file';
26 import { getFilePathNameCommon, RetryWhile } from '../../../commont/utils';
27 import fs from 'fs';
28 import FormData from 'form-data';
29
30 interface IRequestApiParams extends IRequestNetParams {
31 cookie: Electron.Cookie[];
32 apiUrl?: string;
33 }
34
35 class KwaiPub {
36 fileBlockSize = 4194304;
37
38 // 普通参数转换为快手参数
39 convertKwaiParams(params: IKwaiPubVideoParams) {
40 const kwaiParams: any = {};
41 kwaiParams['caption'] = params.desc;
42
43 // 好友处理
44 if (params.mentions) {
45 kwaiParams['caption'] += ` ${params.mentions.join(' ')} `;
46 }
47
48 // 话题处理
49 if (params.topics) {
50 kwaiParams['caption'] += ` ${params.topics.join(' ')} `;
51 }
52
53 // 位置处理
54 if (params.poiInfo) {
55 kwaiParams['poiId'] = params.poiInfo.poiId;
56 kwaiParams['latitude'] = params.poiInfo.latitude;
57 kwaiParams['longitude'] = params.poiInfo.longitude;
58 }
59
60 return {
61 ...kwaiParams,
62 photoStatus: params.photoStatus,
63 publishTime: params.publishTime || 0,
64 };
65 }
66 // 发布视频
67 async pubVideo(params: IKwaiPubVideoParams): Promise<{
68 publishId: string;
69 shareLink: string;
70 }> {
71 console.log('快手原始参数:', {
72 ...params,
73 cookies: null,
74 });
75 return new Promise(async (resolve, reject) => {
76 try {
77 const callback = params.callback;
78 callback(5, '正在视频分片...');
79 const { filename, suffix } = getFilePathNameCommon(params.videoPath);
80 const filePartInfo = await FileUtils.getFilePartInfo(
81 params.videoPath,
82 this.fileBlockSize,
83 );
84 callback(10, '正在创建视频...');
85 const preRes = await this.requestApi<UploadPpreResponse>({
86 url: '/rest/cp/works/v2/video/pc/upload/pre',
87 cookie: params.cookies,
88 method: 'POST',
89 body: {
90 uploadType: 1,
91 },
92 proxy: params.proxy,
93 });
94 console.log('创建视频:', preRes);
95 if (!preRes.data.data) {
96 throw new Error(preRes.data.message);
97 }
98
99 for (const i in filePartInfo.blockInfo) {
100 callback(40, `上传视频(${i}/${filePartInfo.blockInfo.length})`);
101
102 const isSuccess = await RetryWhile(async () => {
103 const chunkStart =
104 i === '0' ? 0 : filePartInfo.blockInfo[parseInt(i) - 1];
105 const chunkEnd = filePartInfo.blockInfo[i] - 1;
106 const chunkContent = await FileUtils.getFilePartContent(
107 params.videoPath,
108 chunkStart,
109 chunkEnd,
110 );
111 const uploadVideoRes = await requestNet({
112 method: 'POST',
113 url: `https://upload.kuaishouzt.com/api/upload/fragment?upload_token=${preRes.data.data.token}&fragment_id=${i}`,
114 isFile: true,
115 body: chunkContent,
116 });
117 if (uploadVideoRes.data.result === 1) {
118 return true;
119 }
120 }, 3);
121 if (!isSuccess) {
122 throw new Error('分片上传失败,请稍后重试!');
123 }
124 }
125
126 callback(60, `查询分片上传结果...`);
127 const completeRes = await this.requestApi({
128 apiUrl: `https://upload.kuaishouzt.com/api/upload/complete?upload_token=${preRes.data.data.token}&fragment_count=${filePartInfo.blockInfo.length}`,
129 method: 'POST',
130 cookie: params.cookies,
131 body: {
132 uploadType: 1,
133 },
134 proxy: params.proxy,
135 });
136 console.log(`分片上传完成:`, completeRes.data);
137
138 callback(70, `分片上传完成,视频上传结束...`);
139 const finishRes = await this.requestApi<UploadFinishResponse>({
140 url: `/rest/cp/works/v2/video/pc/upload/finish`,
141 method: 'POST',
142 cookie: params.cookies,
143 body: {
144 token: preRes.data.data.token,
145 fileName: filename,
146 fileType: `video/${suffix}`,
147 fileLength: filePartInfo.fileSize,
148 },
149 proxy: params.proxy,
150 });
151 if (finishRes.data.result !== 1)
152 throw new Error(finishRes.data.message);
153 console.log(`视频上传结束:`, finishRes.data);
154
155 callback(80, `视频上传完成,正在上传封面...`);
156 const formData = new FormData();
157 formData.append('file', fs.createReadStream(params.coverPath));
158 const coverRes = await this.requestApi<{
159 data: {
160 coverKey: string;
161 };
162 }>({
163 formData,
164 url: '/rest/cp/works/v2/video/pc/upload/cover/upload',
165 method: 'POST',
166 cookie: params.cookies,
167 proxy: params.proxy,
168 });
169 console.log('上传封面结果:', coverRes.data);
170
171 callback(90, `正在发布...`);
172
173 const submitParams = {
174 ...finishRes.data.data,
175 coverKey: coverRes.data.data.coverKey,
176 coverTimeStamp: 0,
177 coverType: 1,
178 coverTitle: '',
179 photoType: 0,
180 collectionId: '',
181 publishTime: 0,
182 longitude: '',
183 latitude: '',
184 poiId: 0,
185 notifyResult: 0,
186 domain: '',
187 secondDomain: '',
188 coverCropped: false,
189 pkCoverKey: '',
190 profileCoverKey: '',
191 downloadType: 1,
192 disableNearbyShow: false,
193 allowSameFrame: true,
194 movieId: '',
195 openPrePreview: false,
196 declareInfo: {},
197 activityIds: [],
198 riseQuality: false,
199 chapters: [],
200 projectId: '',
201 recTagIdList: [],
202 videoInfoMeta: '',
203 previewUrlErrorMessage: '',
204 triggerH265: false,
205 ...this.convertKwaiParams(params),
206 };
207 console.log('快手最终发布参数:', submitParams);
208 const submitRes = await this.requestApi<KwaiSubmitResponse>({
209 url: `/rest/cp/works/v2/video/pc/submit`,
210 method: 'POST',
211 cookie: params.cookies,
212 body: submitParams,
213 proxy: params.proxy,
214 });
215 console.log(`视频发布完成:`, submitRes.data);
216 console.log(submitRes.data.result);
217 if (submitRes.data.result !== 1) {
218 return reject(submitRes.data.message);
219 }
220 callback(95, `正在查询发布结果...`);
221 let work: KwaiWorkItem | undefined;
222 await RetryWhile(async () => {
223 const worksList = await this.getWorks(params.cookies, {
224 queryType: '2',
225 limit: 20,
226 });
227 work = worksList.data.data.list.find(
228 (v) => v.unPublishCoverKey === coverRes.data.data.coverKey,
229 );
230 console.log('快手查询到的作品:', work);
231 if (work) return true;
232 }, 5);
233 console.log('发布成功!');
234 resolve({
235 shareLink: ``,
236 publishId: `${work?.publishId}`,
237 });
238 } catch (e: any) {
239 reject(`发布失败,失败原因:${e.message}`);
240 console.error(e);
241 }
242 });
243 }
244
245 // 发送请求
246 async requestApi<T>(params: IRequestApiParams) {
247 const { cookie, apiUrl = 'https://cp.kuaishou.com' } = params;
248
249 const api_ph = cookie.find(
250 (v) => v.name === 'kuaishou.web.cp.api_ph',
251 )!.value;
252
253 if (params.formData) {
254 params.formData.append('kuaishou.web.cp.api_ph', api_ph);
255 } else if (params.method === 'POST') {
256 params['body'] = {
257 ...(params['body'] ? params['body'] : {}),
258 'kuaishou.web.cp.api_ph': api_ph,
259 };
260 }
261
262 params['headers'] = {
263 ...(params['headers'] ? params['headers'] : {}),
264 cookie: CookieToString(cookie),
265 };
266
267 const signUrl = await kwaiSign.sign({
268 json: !params.formData
269 ? params.body || {}
270 : {
271 'kuaishou.web.cp.api_ph': api_ph,
272 },
273 type: params.formData ? 'form-data' : 'json',
274 url: `${apiUrl}${params.url || ''}`,
275 });
276
277 return await requestNet<T>({
278 ...params,
279 url: `${apiUrl == 'https://cp.kuaishou.com' ? signUrl : apiUrl}`,
280 });
281 }
282
283 async getHomeOverview(cookie: Electron.Cookie[]) {
284 return await this.requestApi<IGetHomeOverview>({
285 cookie,
286 url: '/rest/cp/creator/analysis/pc/home/author/overview',
287 method: 'POST',
288 body: {
289 timeType: 3,
290 },
291 });
292 }
293
294 // 快手登录
295 login(): Promise<ILoginResponse> {
296 return new Promise(async (resolve, reject) => {
297 const partition = Date.now().toString();
298 const { width, height } = screen.getPrimaryDisplay().workAreaSize;
299 const mainWindow = new BrowserWindow({
300 width: Math.ceil(width * 0.8),
301 height: Math.ceil(height * 0.8),
302 webPreferences: {
303 contextIsolation: false,
304 nodeIntegration: false,
305 partition,
306 },
307 });
308 mainWindow.webContents!.setUserAgent(
309 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0',
310 );
311 mainWindow.webContents.on(
312 'console-message',
313 (event, level, message, line, sourceId) => {
314 console.error(message);
315 // 如果需要禁用所有 JavaScript 错误
316 if (message.includes('Error')) {
317 event.preventDefault();
318 return; // 忽略错误
319 }
320 },
321 );
322 // 登录页面
323 await mainWindow.loadURL(
324 'https://passport.kuaishou.com/pc/account/login',
325 );
326 const session = mainWindow.webContents.session;
327 await session.clearCache();
328 // mainWindow.webContents.openDevTools();
329 let timeId1: NodeJS.Timeout | undefined = undefined;
330 let timeId2: NodeJS.Timeout | undefined = undefined;
331 mainWindow.on('closed', () => {
332 clearInterval(timeId1);
333 clearInterval(timeId2);
334 });
335 timeId1 = setInterval(async () => {
336 const cookies = await mainWindow.webContents.session.cookies.get({});
337 // 存在关键cookie
338 if (cookies.some((v) => v.name === 'kuaishou.server.webday7_ph')) {
339 clearInterval(timeId1);
340 // 开发者后台
341 await mainWindow.loadURL(
342 'https://cp.kuaishou.com/article/publish/video?origin=www.kuaishou.com',
343 );
344 // 检测创作者中心登录
345 timeId2 = setInterval(async () => {
346 const cookies = await mainWindow.webContents.session.cookies.get(
347 {},
348 );
349 // 存在关键cookie
350 if (cookies.some((v) => v.name === 'ks_onvideo_token')) {
351 const cookiesLast =
352 await mainWindow.webContents.session.cookies.get({});
353 const userInfoReq = await this.getAccountInfo(cookiesLast);
354 if (userInfoReq.status === 200 && userInfoReq.data.data) {
355 clearInterval(timeId2);
356 mainWindow.close();
357 resolve({
358 cookies: cookiesLast,
359 userInfo: userInfoReq,
360 });
361 } else {
362 clearInterval(timeId2);
363 reject('获取用户信息失败');
364 }
365 }
366 }, 500);
367 }
368 }, 500);
369 });
370 }
371
372 // 获取账户的粉丝数、关注、获赞
373 async getHomeInfo(cookie: Electron.Cookie[]) {
374 return await this.requestApi<IGetHomeInfoResponse>({
375 cookie: cookie,
376 url: '/rest/cp/creator/pc/home/infoV2',
377 method: 'POST',
378 });
379 }
380
381 // 获取账号信息
382 async getAccountInfo(cookie: Electron.Cookie[]) {
383 return await this.requestApi<IKwaiUserInfoResponse>({
384 cookie: cookie,
385 method: 'POST',
386 apiUrl: 'https://www.kuaishou.com/graphql',
387 body: {
388 operationName: 'userInfoQuery',
389 variables: {},
390 query:
391 'query userInfoQuery {\n userInfo {\n id\n name\n avatar\n eid\n userId\n __typename\n }\n}\n',
392 },
393 });
394 }
395
396 // 获取话题
397 async getTopics({
398 keyword,
399 cookies,
400 }: {
401 keyword: string;
402 cookies: Electron.Cookie[];
403 }) {
404 return await this.requestApi<IKwaiGetTopicsResponse>({
405 cookie: cookies,
406 url: `/rest/cp/works/v2/video/pc/tag/search`,
407 method: 'POST',
408 body: {
409 keyword,
410 },
411 });
412 }
413
414 // 获取关注用户
415 async getUsers({
416 page,
417 cookies,
418 }: {
419 page: number;
420 cookies: Electron.Cookie[];
421 }) {
422 return await this.requestApi<IKwaiGetUsersResponse>({
423 cookie: cookies,
424 url: `/rest/cp/works/v2/video/pc/at/list`,
425 method: 'POST',
426 body: {
427 atType: 3,
428 pageCount: page,
429 pageSize: 10,
430 },
431 });
432 }
433
434 // 获取快手位置
435 async getLocations({
436 cookies,
437 cityName,
438 keyword,
439 }: {
440 cookies: Electron.Cookie[];
441 cityName: string;
442 keyword: string;
443 }) {
444 return await this.requestApi<IKwaiGetLocationsResponse>({
445 cookie: cookies,
446 url: `/rest/zt/location/wi/poi/search?kpn=kuaishou_cp&subBiz=CP%2FCREATOR_PLATFORM&kuaishou.web.cp.api_ph=fe283c2f058ddb7a3098f89511fbd536dd82`,
447 method: 'POST',
448 body: {
449 cityName,
450 count: 50,
451 keyword,
452 pcursor: '',
453 },
454 });
455 }
456
457 // 刷新作品
458 async refreshWorks(cookies: Electron.Cookie[], ids: number[]) {
459 return await this.requestApi<RefreshWorksResponse>({
460 cookie: cookies,
461 url: `/rest/cp/works/v2/video/pc/publish/refresh`,
462 method: 'POST',
463 body: {
464 ids,
465 },
466 });
467 }
468
469 // 获取作品-开发者后台
470 async getWorks(
471 cookies: Electron.Cookie[],
472 params: {
473 // 0=全部作品,1=已发布,2=待发布,3=未通过
474 queryType: '0' | '1' | '2' | '3';
475 limit?: number;
476 },
477 ) {
478 return await this.requestApi<GetWorksListResponse>({
479 cookie: cookies,
480 url: `/rest/cp/works/v2/video/pc/photo/list`,
481 method: 'POST',
482 body: {
483 cursor: Date.now(),
484 queryType: params.queryType,
485 limit: params.limit || 100,
486 timeRangeType: 5,
487 keyword: '',
488 startTime: Date.now() - 1000 * 60 * 60 * 24 * 30,
489 endTime: Date.now(),
490 },
491 });
492 }
493
494 /**
495 * 获取作品列表
496 * @param cookies
497 * @param pcursor
498 * @returns
499 */
500 async getPhotoList(
501 cookies: Electron.Cookie[],
502 pcursor?: number, // 下一页页码
503 ) {
504 const res = await this.requestApi<GetPhotoListResponse>({
505 cookie: cookies,
506 url: `/rest/cp/creator/comment/photoList`,
507 method: 'POST',
508 body: {
509 ...(pcursor ? { pcursor } : {}),
510 },
511 });
512 return res;
513 }
514
515 // 搜索作品列表
516 async getsearchNodeList(
517 cookies: Electron.Cookie[],
518 qe: string,
519 pageInfo?: any,
520 ) {
521 const bodys: any = {
522 operationName: 'visionSearchPhoto',
523 variables: {
524 keyword: qe,
525 pcursor: pageInfo.pcursor < 1 ? '' : pageInfo.pcursor + '',
526 page: 'search',
527 },
528 query: `fragment photoContent on PhotoEntity {\n __typename\n id\n duration\n caption\n originCaption\n likeCount\n viewCount\n commentCount\n realLikeCount\n coverUrl\n photoUrl\n photoH265Url\n manifest\n manifestH265\n videoResource\n coverUrls {\n url\n __typename\n }\n timestamp\n expTag\n animatedCoverUrl\n distance\n videoRatio\n liked\n stereoType\n profileUserTopPhoto\n musicBlocked\n riskTagContent\n riskTagUrl\n}\n\nfragment recoPhotoFragment on recoPhotoEntity {\n __typename\n id\n duration\n caption\n originCaption\n likeCount\n viewCount\n commentCount\n realLikeCount\n coverUrl\n photoUrl\n photoH265Url\n manifest\n manifestH265\n videoResource\n coverUrls {\n url\n __typename\n }\n timestamp\n expTag\n animatedCoverUrl\n distance\n videoRatio\n liked\n stereoType\n profileUserTopPhoto\n musicBlocked\n riskTagContent\n riskTagUrl\n}\n\nfragment feedContent on Feed {\n type\n author {\n id\n name\n headerUrl\n following\n headerUrls {\n url\n __typename\n }\n __typename\n }\n photo {\n ...photoContent\n ...recoPhotoFragment\n __typename\n }\n canAddComment\n llsid\n status\n currentPcursor\n tags {\n type\n name\n __typename\n }\n __typename\n}\n\nquery visionSearchPhoto($keyword: String, $pcursor: String, $searchSessionId: String, $page: String, $webPageArea: String) {\n visionSearchPhoto(keyword: $keyword, pcursor: $pcursor, searchSessionId: $searchSessionId, page: $page, webPageArea: $webPageArea) {\n result\n llsid\n webPageArea\n feeds {\n ...feedContent\n __typename\n }\n searchSessionId\n pcursor\n aladdinBanner {\n imgUrl\n link\n __typename\n }\n __typename\n }\n}\n`,
529 };
530
531 if (pageInfo.postFirstId) {
532 bodys.variables.searchSessionId = pageInfo.postFirstId;
533 }
534
535 const res = await this.requestApi<any>({
536 cookie: cookies,
537 apiUrl: 'https://www.kuaishou.com/graphql',
538 method: 'POST',
539 body: bodys,
540 headers: {
541 Referer: `https://www.kuaishou.com/search?keyword=${qe}`,
542 'User-Agent':
543 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
544 },
545 });
546 return res;
547 }
548
549 // 获取评论列表
550 async getCommentList(
551 cookies: Electron.Cookie[],
552 photoId: string,
553 pcursor?: number,
554 ) {
555 const res = await this.requestApi<GetCommentListResponse>({
556 cookie: cookies,
557 url: `/rest/cp/creator/comment/commentList`,
558 method: 'POST',
559 body: {
560 photoId,
561 sortType: '',
562 selectedComment: false,
563 ...(pcursor ? { pcursor } : {}),
564 },
565 });
566
567 return res;
568 }
569
570 // 获取评论的回复列表
571 async getSubCommentList(
572 cookies: Electron.Cookie[],
573 photoId: string,
574 commentId: number,
575 ) {
576 const res = await this.requestApi<GetSubCommentListResponse>({
577 cookie: cookies,
578 url: `/rest/cp/creator/comment/subCommentList`,
579 method: 'POST',
580 body: {
581 commentId, // 969549966791,
582 photoId, //'3xsq95w5uxvjx7q',
583 },
584 });
585
586 return res;
587 }
588
589 /**
590 * 添加评论和回复评论
591 * @param cookie
592 * @param content
593 * @param reply
594 * @returns
595 */
596 async commentAdd(
597 cookie: Electron.Cookie[],
598 content: string,
599 reply: {
600 photoId?: string;
601 replyToCommentId?: number; // 969549966791;
602 replyTo?: number; // 798319351;
603 },
604 ) {
605 const res = await this.requestApi<CommentAddResponse>({
606 cookie: cookie,
607 url: '/rest/cp/creator/comment/add',
608 method: 'POST',
609 body: {
610 content,
611 ...reply,
612 },
613 });
614
615 return res;
616 }
617
618 /**
619 * 点赞
620 * @param cookie
621 * @param dataId
622 * @param option
623 * @returns
624 */
625 async dianzanDyOther(cookie: Electron.Cookie[], dataId: string, option: any) {
626 const res = await this.requestApi<CommentAddResponse>({
627 cookie: cookie,
628 apiUrl: 'https://www.kuaishou.com/graphql',
629 method: 'POST',
630 body: {
631 operationName: 'visionVideoLike',
632 variables: {
633 photoId: dataId,
634 photoAuthorId: option.authid,
635 cancel: 0,
636 expTag: '1_i/2008189535617610417_xpcwebdetailxxnull0',
637 },
638 query: `mutation visionVideoLike($photoId: String, $photoAuthorId: String, $cancel: Int, $expTag: String) {\n visionVideoLike(photoId: $photoId, photoAuthorId: $photoAuthorId, cancel: $cancel, expTag: $expTag) {\n result\n __typename\n }\n}\n`,
639 },
640 headers: {
641 Referer: `https://www.kuaishou.com/short-video/${dataId}`,
642 'User-Agent':
643 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
644 },
645 });
646
647 return res;
648 }
649
650 /**
651 * 视频评论
652 * @param cookie
653 * @param dataId
654 * @param content
655 * @param authorId
656 * @returns
657 */
658 async videoCommentByOther(
659 cookie: Electron.Cookie[],
660 dataId: string,
661 content: string,
662 authorId?: string,
663 ) {
664 const res = await this.requestApi<CommentAddResponse>({
665 cookie: cookie,
666 apiUrl: 'https://www.kuaishou.com/graphql',
667 method: 'POST',
668 body: {
669 operationName: 'visionAddComment',
670 variables: {
671 photoId: dataId,
672 photoAuthorId: authorId,
673 content: content,
674 expTag: '1_a/2004436422502146722_xpcwebdetailxxnull0',
675 },
676 query:
677 'mutation visionAddComment($photoId: String, $photoAuthorId: String, $content: String, $replyToCommentId: ID, $replyTo: ID, $expTag: String) {\n visionAddComment(photoId: $photoId, photoAuthorId: $photoAuthorId, content: $content, replyToCommentId: $replyToCommentId, replyTo: $replyTo, expTag: $expTag) {\n result\n commentId\n content\n timestamp\n status\n __typename\n }\n}\n',
678 },
679 headers: {
680 Referer: `https://www.kuaishou.com/short-video/${dataId}`,
681 'User-Agent':
682 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
683 },
684 });
685
686 return res;
687 }
688
689 /**
690 * 获取视频评论列表
691 * @param cookie
692 * @param dataId
693 * @param pcursor
694 * @returns
695 */
696 async getVideoCommentList(
697 cookie: Electron.Cookie[],
698 dataId: string,
699 pcursor?: string,
700 ) {
701 const res = await this.requestApi<any>({
702 cookie: cookie,
703 apiUrl: 'https://www.kuaishou.com/graphql',
704 method: 'POST',
705 body: {
706 operationName: 'commentListQuery',
707 variables: {
708 pcursor: '',
709 photoId: dataId,
710 },
711 query:
712 'query commentListQuery($photoId: String, $pcursor: String) {\n visionCommentList(photoId: $photoId, pcursor: $pcursor) {\n commentCount\n pcursor\n rootComments {\n commentId\n authorId\n authorName\n content\n headurl\n timestamp\n likedCount\n realLikedCount\n liked\n status\n authorLiked\n subCommentCount\n subCommentsPcursor\n subComments {\n commentId\n authorId\n authorName\n content\n headurl\n timestamp\n likedCount\n realLikedCount\n liked\n status\n authorLiked\n replyToUserName\n replyTo\n __typename\n }\n __typename\n }\n __typename\n }\n}\n',
713 },
714 headers: {
715 Referer: `https://www.kuaishou.com/short-video/${dataId}`,
716 'User-Agent':
717 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
718 },
719 });
720
721 return res;
722 }
723
724 /**
725 * 回复二级评论
726 * @param cookie
727 * @param content
728 * @param option
729 * @returns
730 */
731 async replyCommentByOther(
732 cookie: Electron.Cookie[],
733 content: string,
734 option: {
735 replyToCommentId?: any; // 969549966791;
736 replyTo?: any; // 798319351;
737 photoId?: string; // 作品ID
738 photoAuthorId: any; // 视频作者ID
739 },
740 ) {
741 const res = await this.requestApi<any>({
742 cookie: cookie,
743 apiUrl: 'https://www.kuaishou.com/graphql',
744 method: 'POST',
745 body: {
746 operationName: 'visionAddComment',
747 variables: {
748 photoId: option.photoId,
749 photoAuthorId: option.photoAuthorId,
750 content: content,
751 replyToCommentId: option.replyToCommentId,
752 replyTo: option.replyTo,
753 expTag: '1_a/2004436422502146722_xpcwebdetailxxnull0',
754 },
755 query:
756 'mutation visionAddComment($photoId: String, $photoAuthorId: String, $content: String, $replyToCommentId: ID, $replyTo: ID, $expTag: String) {\n visionAddComment(photoId: $photoId, photoAuthorId: $photoAuthorId, content: $content, replyToCommentId: $replyToCommentId, replyTo: $replyTo, expTag: $expTag) {\n result\n commentId\n content\n timestamp\n status\n __typename\n }\n}\n',
757 },
758 headers: {
759 Referer: `https://www.kuaishou.com/short-video/${option.photoId}`,
760 'User-Agent':
761 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
762 },
763 });
764
765 return res;
766 }
767 }
768
769 export const kwaiPub = new KwaiPub();
770
770 lines TYPESCRIPT