|
|
@@ -1,8 +1,9 @@
|
|
|
import { AppDataSource, Work, PlatformAccount, Comment, WorkDayStatistics } from '../models/index.js';
|
|
|
import { AppError } from '../middleware/error.js';
|
|
|
-import { ERROR_CODES, HTTP_STATUS } from '@media-manager/shared';
|
|
|
+import { ERROR_CODES, HTTP_STATUS, WS_EVENTS } from '@media-manager/shared';
|
|
|
import type { PlatformType, Work as WorkType, WorkStats, WorksQueryParams } from '@media-manager/shared';
|
|
|
import { logger } from '../utils/logger.js';
|
|
|
+import { parseCookieString } from '../utils/cookieParser.js';
|
|
|
import { headlessBrowserService } from './HeadlessBrowserService.js';
|
|
|
import { CookieManager } from '../automation/cookie.js';
|
|
|
import { WorkDayStatisticsService } from './WorkDayStatisticsService.js';
|
|
|
@@ -238,7 +239,7 @@ export class WorkService {
|
|
|
logger.info(`[SyncAccountWorks] Parsed ${cookieList.length} cookies from JSON format`);
|
|
|
} catch {
|
|
|
// 如果 JSON 解析失败,尝试解析 "name=value; name2=value2" 格式
|
|
|
- cookieList = this.parseCookieString(decryptedCookies, platform);
|
|
|
+ cookieList = parseCookieString(decryptedCookies, platform);
|
|
|
logger.info(`[SyncAccountWorks] Parsed ${cookieList.length} cookies from string format`);
|
|
|
if (cookieList.length === 0) {
|
|
|
logger.error(`Invalid cookie format for account ${account.id}`);
|
|
|
@@ -299,7 +300,7 @@ export class WorkService {
|
|
|
for (const workItem of accountInfo.worksList) {
|
|
|
const titleForId = (workItem.title || '').trim();
|
|
|
const publishTimeForId = (workItem.publishTime || '').trim();
|
|
|
- const legacyFallbackId = `${platform}_${titleForId}_${publishTimeForId}`.substring(0, 100);
|
|
|
+ const legacyFallbackId = `${platform}_${titleForId}_${publishTimeForId}`;
|
|
|
let canonicalVideoId = (workItem.videoId || '').trim() || legacyFallbackId;
|
|
|
|
|
|
// 小红书每日同步只同步三个月内的作品(原为一年内,现改为三个月)
|
|
|
@@ -401,7 +402,7 @@ export class WorkService {
|
|
|
});
|
|
|
} else {
|
|
|
// 创建新作品
|
|
|
- const work = this.workRepository.create({
|
|
|
+ const newWork = this.workRepository.create({
|
|
|
userId,
|
|
|
accountId: account.id,
|
|
|
platform,
|
|
|
@@ -425,7 +426,7 @@ export class WorkService {
|
|
|
yesterdayCollectCount: workItem.collectCount || 0,
|
|
|
});
|
|
|
|
|
|
- await this.workRepository.save(work);
|
|
|
+ await this.workRepository.save(newWork);
|
|
|
}
|
|
|
syncedCount++;
|
|
|
if (syncedCount === 1 || syncedCount === total || syncedCount % 10 === 0) {
|
|
|
@@ -822,57 +823,6 @@ export class WorkService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 将 cookie 字符串解析为 cookie 列表
|
|
|
- */
|
|
|
- private parseCookieString(cookieString: string, platform: PlatformType): {
|
|
|
- name: string;
|
|
|
- value: string;
|
|
|
- domain: string;
|
|
|
- path: string;
|
|
|
- }[] {
|
|
|
- // 获取平台对应的域名
|
|
|
- const domainMap: Record<string, string> = {
|
|
|
- douyin: '.douyin.com',
|
|
|
- kuaishou: '.kuaishou.com',
|
|
|
- xiaohongshu: '.xiaohongshu.com',
|
|
|
- weixin_video: '.qq.com',
|
|
|
- bilibili: '.bilibili.com',
|
|
|
- toutiao: '.toutiao.com',
|
|
|
- baijiahao: '.baidu.com',
|
|
|
- qie: '.qq.com',
|
|
|
- dayuhao: '.alibaba.com',
|
|
|
- };
|
|
|
-
|
|
|
- const domain = domainMap[platform] || `.${platform}.com`;
|
|
|
-
|
|
|
- // 解析 "name=value; name2=value2" 格式的 cookie 字符串
|
|
|
- const cookies: { name: string; value: string; domain: string; path: string }[] = [];
|
|
|
-
|
|
|
- const pairs = cookieString.split(';');
|
|
|
- for (const pair of pairs) {
|
|
|
- const trimmed = pair.trim();
|
|
|
- if (!trimmed) continue;
|
|
|
-
|
|
|
- const eqIndex = trimmed.indexOf('=');
|
|
|
- if (eqIndex === -1) continue;
|
|
|
-
|
|
|
- const name = trimmed.substring(0, eqIndex).trim();
|
|
|
- const value = trimmed.substring(eqIndex + 1).trim();
|
|
|
-
|
|
|
- if (name && value) {
|
|
|
- cookies.push({
|
|
|
- name,
|
|
|
- value,
|
|
|
- domain,
|
|
|
- path: '/',
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return cookies;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
* 格式化作品
|
|
|
*/
|
|
|
private formatWork(work: Work): WorkType {
|