| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #!/usr/bin/env node
- /**
- * 好友轮询兜底 Worker
- *
- * 独立运行,定期检查已加好友但尚未建群的客户,触发自动建群。
- *
- * 启动方式:
- * node scripts/friend-polling-worker.js
- * INTERVAL_MS=300000 node scripts/friend-polling-worker.js
- */
- const fs = require('fs');
- const path = require('path');
- const { outputsRoot } = require('../mcp/src/core/output-paths');
- const { readCustomerById, writeCustomer } = require('../mcp/src/core/customer-broker-store');
- const { readConfirmedMapping } = require('../mcp/src/core/webhook-processor');
- const { triggerAutoCreateGroup } = require('../mcp/src/core/webhook-processor');
- const INTERVAL_MS = Number(process.env.FRIEND_POLL_INTERVAL_MS || 300000);
- function customersDir() {
- return path.join(outputsRoot(), 'customers');
- }
- function safeReadJson(filePath) {
- try {
- if (!fs.existsSync(filePath)) return null;
- return JSON.parse(fs.readFileSync(filePath, 'utf8'));
- } catch {
- return null;
- }
- }
- function listCustomerFiles() {
- const dir = customersDir();
- if (!fs.existsSync(dir)) return [];
- return fs.readdirSync(dir)
- .filter(f => f.endsWith('.json') && !f.startsWith('index-'))
- .map(f => path.join(dir, f));
- }
- function hasActiveGroupForCustomer(customerId) {
- const mapping = readConfirmedMapping();
- for (const entry of Object.values(mapping)) {
- if (entry.customerId === customerId && entry.status === 'ACTIVE') return true;
- }
- return false;
- }
- async function runOnce() {
- const files = listCustomerFiles();
- let checked = 0;
- let created = 0;
- let ignored = 0;
- let errors = 0;
- for (const file of files) {
- const customer = safeReadJson(file);
- if (!customer || !customer.customerId) continue;
- // 只处理有 brokerId 且标记为已通过好友但尚未建群的客户
- if (!customer.brokerId) continue;
- if (customer.friendRequestStatus !== 'ACCEPTED' && customer.friendRequestStatus !== 'PENDING') continue;
- if (hasActiveGroupForCustomer(customer.customerId)) continue;
- checked++;
- const event = {
- parsedType: 'CONTACT_ADDED_OR_CHANGED',
- msgType: 2131,
- externalUserId: customer.externalUserId,
- guid: undefined,
- timestamp: Math.floor(Date.now() / 1000),
- eventId: `poll-${customer.customerId}-${Date.now()}`,
- raw: {}
- };
- const result = await triggerAutoCreateGroup(event);
- if (result.success) {
- created++;
- customer.friendRequestStatus = 'ACCEPTED';
- writeCustomer(customer);
- } else if (result.ignored) {
- ignored++;
- } else {
- errors++;
- }
- }
- console.log(`[FriendPolling] 本轮完成: 检查 ${checked}, 建群 ${created}, 忽略 ${ignored}, 错误 ${errors}`);
- return { checked, created, ignored, errors };
- }
- async function main() {
- console.log(`[FriendPolling] 启动,轮询间隔 ${INTERVAL_MS}ms`);
- while (true) {
- try {
- await runOnce();
- } catch (err) {
- console.error('[FriendPolling] 本轮异常:', err.message);
- }
- await new Promise(resolve => setTimeout(resolve, INTERVAL_MS));
- }
- }
- main().catch(err => {
- console.error('[FriendPolling] 致命错误:', err);
- process.exit(1);
- });
|