/ clis / boss / exchange.js
exchange.js
 1  /**
 2   * BOSS直聘 exchange — request phone/wechat exchange with a candidate.
 3   */
 4  import { cli, Strategy } from '@jackwener/opencli/registry';
 5  import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './utils.js';
 6  cli({
 7      site: 'boss',
 8      name: 'exchange',
 9      description: 'BOSS直聘交换联系方式(请求手机/微信)',
10      domain: 'www.zhipin.com',
11      strategy: Strategy.COOKIE,
12      navigateBefore: false,
13      browser: true,
14      args: [
15          { name: 'uid', required: true, positional: true, help: 'Encrypted UID of the candidate' },
16          { name: 'type', default: 'phone', choices: ['phone', 'wechat'], help: 'Exchange type: phone or wechat' },
17      ],
18      columns: ['status', 'detail'],
19      func: async (page, kwargs) => {
20          requirePage(page);
21          const exchangeType = kwargs.type || 'phone';
22          verbose(`Requesting ${exchangeType} exchange for ${kwargs.uid}...`);
23          await navigateToChat(page);
24          const friend = await findFriendByUid(page, kwargs.uid, { checkGreetList: true });
25          if (!friend)
26              throw new Error('未找到该候选人');
27          const friendName = friend.name || '候选人';
28          const typeId = exchangeType === 'wechat' ? 2 : 1;
29          const params = new URLSearchParams({
30              type: String(typeId),
31              securityId: friend.securityId || '',
32              uniqueId: String(friend.uid),
33              name: friendName,
34          });
35          await bossFetch(page, 'https://www.zhipin.com/wapi/zpchat/exchange/request', {
36              method: 'POST',
37              body: params.toString(),
38          });
39          const typeLabel = exchangeType === 'wechat' ? '微信' : '手机号';
40          return [{
41                  status: '✅ 交换请求已发送',
42                  detail: `已向 ${friendName} 发送${typeLabel}交换请求`,
43              }];
44      },
45  });