/ clis / ones / login.js
login.js
 1  import { cli, Strategy } from '@jackwener/opencli/registry';
 2  import { CliError } from '@jackwener/opencli/errors';
 3  import { getOnesBaseUrl, onesFetchInPage } from './common.js';
 4  cli({
 5      site: 'ones',
 6      name: 'login',
 7      description: 'ONES Project API — login via Chrome Bridge (POST auth/login); stderr prints export hints for ONES_USER_ID / TOKEN',
 8      domain: 'ones.cn',
 9      strategy: Strategy.COOKIE,
10      browser: true,
11      navigateBefore: false,
12      args: [
13          {
14              name: 'email',
15              type: 'str',
16              required: false,
17              help: 'Account email (or set ONES_EMAIL)',
18          },
19          {
20              name: 'phone',
21              type: 'str',
22              required: false,
23              help: 'Account phone (or set ONES_PHONE); ignored if email is set',
24          },
25          {
26              name: 'password',
27              type: 'str',
28              required: false,
29              help: 'Password (or set ONES_PASSWORD)',
30          },
31      ],
32      columns: ['uuid', 'name', 'email', 'token_preview'],
33      func: async (page, kwargs) => {
34          const email = kwargs.email?.trim() || process.env.ONES_EMAIL?.trim();
35          const phone = kwargs.phone?.trim() || process.env.ONES_PHONE?.trim();
36          const password = kwargs.password || process.env.ONES_PASSWORD || '';
37          if (!password) {
38              throw new CliError('CONFIG', 'Password required', 'Pass --password or set ONES_PASSWORD for non-interactive use.');
39          }
40          if (!email && !phone) {
41              throw new CliError('CONFIG', 'email or phone required', 'Pass --email or --phone (or set ONES_EMAIL / ONES_PHONE).');
42          }
43          getOnesBaseUrl();
44          const bodyObj = { password };
45          if (email)
46              bodyObj.email = email;
47          else
48              bodyObj.phone = phone;
49          const parsed = (await onesFetchInPage(page, 'auth/login', {
50              method: 'POST',
51              body: JSON.stringify(bodyObj),
52              auth: false,
53          }));
54          const user = parsed.user;
55          if (!user?.uuid || !user?.token) {
56              throw new CliError('FETCH_ERROR', 'ONES login response missing user.uuid or user.token', 'Your server build may differ from documented Project API.');
57          }
58          const uuid = String(user.uuid);
59          const token = String(user.token);
60          const name = String(user.name ?? '');
61          const em = String(user.email ?? '');
62          const base = getOnesBaseUrl();
63          console.error([
64              '',
65              '后续请求会优先使用当前 Chrome 会话 Cookie;若接口仍要求 Header,可 export:',
66              `  export ONES_BASE_URL=${JSON.stringify(base)}`,
67              `  export ONES_USER_ID=${JSON.stringify(uuid)}`,
68              `  export ONES_AUTH_TOKEN=${JSON.stringify(token)}`,
69              '',
70          ].join('\n'));
71          return [
72              {
73                  uuid,
74                  name,
75                  email: em,
76                  token_preview: token.length > 12 ? `${token.slice(0, 6)}…${token.slice(-4)}` : '***',
77              },
78          ];
79      },
80  });