sync.service.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import Parse from '../../../../shared/db/parse-client.js';
  2. import { getAllRooms, getSessionList } from './qiwe-api.service.js';
  3. import { initNewGroupDefaults, prepareGroupListForDisplay } from './groups.service.js';
  4. const GUID = process.env.QIWE_GUID || '';
  5. /** 从会话列表补全群(getRoomList 为空时,群会话 sessionType=1 仍可能有数据) */
  6. export async function syncGroupSessionsFromQiWe(): Promise<{
  7. created: number;
  8. updated: number;
  9. skipped: number;
  10. }> {
  11. const result = { created: 0, updated: 0, skipped: 0 };
  12. const sessions = await getSessionList(1);
  13. console.log(`[Sync] 会话列表中群会话 ${sessions.length} 个`);
  14. for (const session of sessions) {
  15. const roomId = String(session.sessionId ?? '');
  16. if (!roomId || roomId.length < 14 || !/^\d+$/.test(roomId)) {
  17. result.skipped++;
  18. continue;
  19. }
  20. try {
  21. const query = new Parse.Query('GroupChat');
  22. query.equalTo('roomId', roomId);
  23. query.equalTo('guid', GUID);
  24. const existing = await query.first({ useMasterKey: true });
  25. if (existing) {
  26. existing.set('status', 'active');
  27. await existing.save(null, { useMasterKey: true });
  28. result.updated++;
  29. } else {
  30. const obj = new Parse.Object('GroupChat');
  31. obj.set('roomId', roomId);
  32. obj.set('guid', GUID);
  33. obj.set('roomName', `群 ${roomId.slice(-6)}`);
  34. obj.set('status', 'active');
  35. obj.set('memberCount', 0);
  36. initNewGroupDefaults(obj);
  37. await obj.save(null, { useMasterKey: true });
  38. result.created++;
  39. }
  40. } catch (err: unknown) {
  41. const message = err instanceof Error ? err.message : String(err);
  42. console.warn(`[Sync] 会话群 roomId=${roomId} 写入失败: ${message}`);
  43. }
  44. }
  45. return result;
  46. }
  47. /** 一次性对齐群目录:企微群列表 + 会话 + 历史消息 */
  48. export async function reconcileGroupCatalog(): Promise<{
  49. rooms: { created: number; updated: number; errors: string[] };
  50. sessions: { created: number; updated: number; skipped: number };
  51. fromMessages: number;
  52. namesUpdated: number;
  53. }> {
  54. const rooms = await syncGroupsFromQiWe();
  55. const sessions = await syncGroupSessionsFromQiWe();
  56. const fromMessages = await prepareGroupListForDisplay(true);
  57. console.log(
  58. `[Sync] 群目录对齐完成 rooms+${rooms.created}/${rooms.updated} sessions+${sessions.created} messages+${fromMessages}`,
  59. );
  60. return { rooms, sessions, fromMessages, namesUpdated: 0 };
  61. }
  62. export async function syncGroupsFromQiWe(): Promise<{
  63. created: number;
  64. updated: number;
  65. errors: string[];
  66. }> {
  67. const result = { created: 0, updated: 0, errors: [] as string[] };
  68. console.log('[Sync] 开始从企微平台拉取群列表...');
  69. const rooms = await getAllRooms();
  70. console.log(`[Sync] 共获取 ${rooms.length} 个群`);
  71. for (const room of rooms) {
  72. try {
  73. const query = new Parse.Query('GroupChat');
  74. query.equalTo('roomId', room.roomId);
  75. query.equalTo('guid', GUID);
  76. const existing = await query.first({ useMasterKey: true });
  77. if (existing) {
  78. existing.set('roomName', room.roomName);
  79. existing.set('ownerId', room.roomOwnerId);
  80. existing.set('memberCount', room.roomMemberCount);
  81. existing.set('avatarUrl', room.roomAvatarUrl);
  82. existing.set('status', 'active');
  83. await existing.save(null, { useMasterKey: true });
  84. result.updated++;
  85. } else {
  86. const obj = new Parse.Object('GroupChat');
  87. obj.set('roomId', room.roomId);
  88. obj.set('guid', GUID);
  89. obj.set('roomName', room.roomName);
  90. obj.set('ownerId', room.roomOwnerId);
  91. obj.set('memberCount', room.roomMemberCount);
  92. obj.set('avatarUrl', room.roomAvatarUrl);
  93. obj.set('status', 'active');
  94. initNewGroupDefaults(obj);
  95. await obj.save(null, { useMasterKey: true });
  96. result.created++;
  97. }
  98. } catch (err: any) {
  99. result.errors.push(`roomId=${room.roomId}: ${err.message}`);
  100. }
  101. }
  102. console.log(`[Sync] 完成 — 新建 ${result.created}, 更新 ${result.updated}, 错误 ${result.errors.length}`);
  103. return result;
  104. }