1688-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +118 -0
- package/README.md +48 -0
- package/dist/auth/cookies.js +31 -0
- package/dist/auth/cookies.js.map +1 -0
- package/dist/auth/verify.js +25 -0
- package/dist/auth/verify.js.map +1 -0
- package/dist/cli.js +373 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cart-add.js +199 -0
- package/dist/commands/cart-add.js.map +1 -0
- package/dist/commands/cart-list.js +168 -0
- package/dist/commands/cart-list.js.map +1 -0
- package/dist/commands/cart-remove.js +119 -0
- package/dist/commands/cart-remove.js.map +1 -0
- package/dist/commands/checkout-confirm.js +407 -0
- package/dist/commands/checkout-confirm.js.map +1 -0
- package/dist/commands/checkout-prepare.js +244 -0
- package/dist/commands/checkout-prepare.js.map +1 -0
- package/dist/commands/doctor.js +246 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/image-search.js +210 -0
- package/dist/commands/image-search.js.map +1 -0
- package/dist/commands/login.js +209 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.js +59 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/offer.js +185 -0
- package/dist/commands/offer.js.map +1 -0
- package/dist/commands/order-get.js +76 -0
- package/dist/commands/order-get.js.map +1 -0
- package/dist/commands/order-list.js +176 -0
- package/dist/commands/order-list.js.map +1 -0
- package/dist/commands/order-logistics.js +152 -0
- package/dist/commands/order-logistics.js.map +1 -0
- package/dist/commands/search.js +250 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/seller-chat.js +213 -0
- package/dist/commands/seller-chat.js.map +1 -0
- package/dist/commands/seller-inquire.js +110 -0
- package/dist/commands/seller-inquire.js.map +1 -0
- package/dist/commands/seller-lookup-ww.js +6 -0
- package/dist/commands/seller-lookup-ww.js.map +1 -0
- package/dist/commands/seller-messages.js +181 -0
- package/dist/commands/seller-messages.js.map +1 -0
- package/dist/commands/whoami.js +53 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/workflows.js +264 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/daemon/client.js +75 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/manager.js +128 -0
- package/dist/daemon/manager.js.map +1 -0
- package/dist/daemon/protocol.js +5 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/server.js +197 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/throttle.js +17 -0
- package/dist/daemon/throttle.js.map +1 -0
- package/dist/io/errors.js +10 -0
- package/dist/io/errors.js.map +1 -0
- package/dist/io/output.js +17 -0
- package/dist/io/output.js.map +1 -0
- package/dist/io/prompt.js +17 -0
- package/dist/io/prompt.js.map +1 -0
- package/dist/session/context.js +91 -0
- package/dist/session/context.js.map +1 -0
- package/dist/session/dispatch.js +50 -0
- package/dist/session/dispatch.js.map +1 -0
- package/dist/session/lock.js +23 -0
- package/dist/session/lock.js.map +1 -0
- package/dist/session/paths.js +31 -0
- package/dist/session/paths.js.map +1 -0
- package/dist/session/shared.js +104 -0
- package/dist/session/shared.js.map +1 -0
- package/dist/session/state.js +27 -0
- package/dist/session/state.js.map +1 -0
- package/dist/util/time.js +17 -0
- package/dist/util/time.js.map +1 -0
- package/package.json +44 -0
- package/scripts/postinstall.mjs +49 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { dispatch } from '../session/dispatch.js';
|
|
5
|
+
import { emit, info } from '../io/output.js';
|
|
6
|
+
import { CliError } from '../io/errors.js';
|
|
7
|
+
import { extractOffers } from './search.js';
|
|
8
|
+
const UPLOAD_PAGE = 'https://s.1688.com/youyuan/index.htm';
|
|
9
|
+
const RESULT_URL = (imageId) => `https://s.1688.com/selloffer/offer_search.htm?imageId=${imageId}`;
|
|
10
|
+
export async function execute(ctx, args) {
|
|
11
|
+
// The daemon runs on the same host; the imagePath must be an existing
|
|
12
|
+
// absolute path readable by this process.
|
|
13
|
+
try {
|
|
14
|
+
await fs.access(args.imagePath, fs.constants.R_OK);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new CliError(2, 'BAD_INPUT', `Cannot read image: ${args.imagePath}`);
|
|
18
|
+
}
|
|
19
|
+
info('Uploading image to 1688...');
|
|
20
|
+
const imageId = await uploadAndGetImageId(ctx, args.imagePath);
|
|
21
|
+
info(`Image uploaded (imageId=${imageId}). Fetching results...`);
|
|
22
|
+
const offers = await searchByImageId(ctx, imageId);
|
|
23
|
+
return {
|
|
24
|
+
imageId,
|
|
25
|
+
total: offers.length,
|
|
26
|
+
offers: offers.slice(0, args.max),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function uploadAndGetImageId(ctx, imagePath) {
|
|
30
|
+
const page = await ctx.newPage();
|
|
31
|
+
try {
|
|
32
|
+
page.on('filechooser', async (chooser) => {
|
|
33
|
+
try {
|
|
34
|
+
await chooser.setFiles(imagePath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
/* ignore — handled by waitForURL timeout */
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
await page.goto(UPLOAD_PAGE, {
|
|
41
|
+
waitUntil: 'domcontentloaded',
|
|
42
|
+
timeout: 30000,
|
|
43
|
+
});
|
|
44
|
+
if (/login\.1688\.com|login\.taobao\.com/.test(page.url())) {
|
|
45
|
+
throw new CliError(3, 'NOT_LOGGED_IN', 'Session expired. Run `1688 login`.');
|
|
46
|
+
}
|
|
47
|
+
// Click the upload button — filechooser handler picks up the file.
|
|
48
|
+
await page
|
|
49
|
+
.locator('.image-upload-button-container')
|
|
50
|
+
.first()
|
|
51
|
+
.click({ force: true, timeout: 8000 });
|
|
52
|
+
// Upload happens silently in background; "搜索图片" button appears only
|
|
53
|
+
// after the image is processed. Wait up to 20s for it.
|
|
54
|
+
const searchBtn = page.locator('text=搜索图片').first();
|
|
55
|
+
try {
|
|
56
|
+
await searchBtn.waitFor({ state: 'visible', timeout: 20000 });
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Diagnostic: snapshot the page state to help debug
|
|
60
|
+
const state = await page
|
|
61
|
+
.evaluate(() => ({
|
|
62
|
+
url: location.href,
|
|
63
|
+
title: document.title,
|
|
64
|
+
bodyHead: (document.body?.innerText ?? '').slice(0, 300),
|
|
65
|
+
}))
|
|
66
|
+
.catch(() => null);
|
|
67
|
+
throw new CliError(13, 'UPLOAD_FAILED', `Upload appeared to fail — "搜索图片" button never showed.\n` +
|
|
68
|
+
(state
|
|
69
|
+
? `URL: ${state.url}\nTitle: ${state.title}\nBody: ${state.bodyHead}`
|
|
70
|
+
: ''));
|
|
71
|
+
}
|
|
72
|
+
await Promise.all([
|
|
73
|
+
page
|
|
74
|
+
.waitForURL(/imageId=\d+/, { timeout: 20000 })
|
|
75
|
+
.catch(() => undefined),
|
|
76
|
+
searchBtn.click({ force: true }),
|
|
77
|
+
]);
|
|
78
|
+
const match = page.url().match(/imageId=(\d+)/);
|
|
79
|
+
if (!match) {
|
|
80
|
+
throw new CliError(13, 'UPLOAD_FAILED', 'No imageId in URL after upload. Try again or use --headed.');
|
|
81
|
+
}
|
|
82
|
+
return match[1];
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
await page.close().catch(() => { });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function searchByImageId(ctx, imageId) {
|
|
89
|
+
const page = await ctx.newPage();
|
|
90
|
+
try {
|
|
91
|
+
await page.goto(RESULT_URL(imageId), {
|
|
92
|
+
waitUntil: 'domcontentloaded',
|
|
93
|
+
timeout: 30000,
|
|
94
|
+
});
|
|
95
|
+
try {
|
|
96
|
+
await page.waitForSelector('.search-offer-item a[href*="detail.m.1688.com"]', { timeout: 15000 });
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
/* extractor may still find some, or return [] */
|
|
100
|
+
}
|
|
101
|
+
await page.evaluate(() => window.scrollBy(0, 2000));
|
|
102
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
103
|
+
await page.evaluate(() => window.scrollBy(0, 2000));
|
|
104
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
105
|
+
return await extractOffers(page);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await page.close().catch(() => { });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function run(opts) {
|
|
112
|
+
if (!opts.imagePath) {
|
|
113
|
+
throw new CliError(2, 'BAD_INPUT', 'Image path or URL required.');
|
|
114
|
+
}
|
|
115
|
+
const max = Math.max(1, parseInt(opts.max ?? '20', 10));
|
|
116
|
+
let abs;
|
|
117
|
+
let cleanup = null;
|
|
118
|
+
if (/^https?:\/\//i.test(opts.imagePath)) {
|
|
119
|
+
info(`Downloading image from URL...`);
|
|
120
|
+
const t = await downloadToTemp(opts.imagePath);
|
|
121
|
+
abs = t.path;
|
|
122
|
+
cleanup = t.cleanup;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
abs = path.resolve(opts.imagePath);
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const data = await dispatch('image-search', { imagePath: abs, max }, { headed: opts.headed, profile: opts.profile });
|
|
129
|
+
emit({
|
|
130
|
+
human: () => printResults(data),
|
|
131
|
+
data,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
if (cleanup)
|
|
136
|
+
await cleanup().catch(() => { });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async function downloadToTemp(url) {
|
|
140
|
+
let res;
|
|
141
|
+
try {
|
|
142
|
+
res = await fetch(url);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
throw new CliError(9, 'NETWORK_ERROR', `Failed to download image: ${e.message}`);
|
|
146
|
+
}
|
|
147
|
+
if (!res.ok) {
|
|
148
|
+
throw new CliError(9, 'NETWORK_ERROR', `Download failed: HTTP ${res.status} ${res.statusText}`);
|
|
149
|
+
}
|
|
150
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
151
|
+
if (buf.length === 0) {
|
|
152
|
+
throw new CliError(9, 'NETWORK_ERROR', 'Downloaded image is empty.');
|
|
153
|
+
}
|
|
154
|
+
if (buf.length > 20 * 1024 * 1024) {
|
|
155
|
+
throw new CliError(2, 'BAD_INPUT', `Image too large (${(buf.length / 1024 / 1024).toFixed(1)}MB > 20MB).`);
|
|
156
|
+
}
|
|
157
|
+
const ext = guessExt(url, res.headers.get('content-type'));
|
|
158
|
+
const tmpPath = path.join(os.tmpdir(), `bb1688-img-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`);
|
|
159
|
+
await fs.writeFile(tmpPath, buf);
|
|
160
|
+
return {
|
|
161
|
+
path: tmpPath,
|
|
162
|
+
cleanup: () => fs.rm(tmpPath, { force: true }),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function guessExt(url, contentType) {
|
|
166
|
+
const m = url.match(/\.(jpe?g|png|webp|bmp)(\?|$|#)/i);
|
|
167
|
+
if (m)
|
|
168
|
+
return '.' + m[1].toLowerCase().replace('jpeg', 'jpg');
|
|
169
|
+
if (contentType) {
|
|
170
|
+
if (/jpeg/i.test(contentType))
|
|
171
|
+
return '.jpg';
|
|
172
|
+
if (/png/i.test(contentType))
|
|
173
|
+
return '.png';
|
|
174
|
+
if (/webp/i.test(contentType))
|
|
175
|
+
return '.webp';
|
|
176
|
+
if (/bmp/i.test(contentType))
|
|
177
|
+
return '.bmp';
|
|
178
|
+
}
|
|
179
|
+
return '.jpg';
|
|
180
|
+
}
|
|
181
|
+
function printResults(r) {
|
|
182
|
+
if (r.offers.length === 0) {
|
|
183
|
+
process.stdout.write(`No offers found (imageId=${r.imageId}).\n`);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
process.stdout.write(`Image search (imageId=${r.imageId}):\n\n`);
|
|
187
|
+
const w = String(r.offers.length).length;
|
|
188
|
+
r.offers.forEach((o, i) => {
|
|
189
|
+
const idx = String(i + 1).padStart(w, ' ');
|
|
190
|
+
const price = o.price.text || '(n/a)';
|
|
191
|
+
process.stdout.write(`${idx}. ${o.title}\n`);
|
|
192
|
+
const pad = ' '.repeat(w + 2);
|
|
193
|
+
process.stdout.write(`${pad}${price}`);
|
|
194
|
+
if (o.turnover)
|
|
195
|
+
process.stdout.write(` · ${o.turnover}`);
|
|
196
|
+
process.stdout.write('\n');
|
|
197
|
+
const supplierBits = [
|
|
198
|
+
o.supplier.name,
|
|
199
|
+
o.supplier.years ? `${o.supplier.years}年` : null,
|
|
200
|
+
]
|
|
201
|
+
.filter(Boolean)
|
|
202
|
+
.join(' · ');
|
|
203
|
+
if (supplierBits)
|
|
204
|
+
process.stdout.write(`${pad}${supplierBits}\n`);
|
|
205
|
+
process.stdout.write(`${pad}${o.url}\n`);
|
|
206
|
+
if (i < r.offers.length - 1)
|
|
207
|
+
process.stdout.write('\n');
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=image-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-search.js","sourceRoot":"","sources":["../../src/commands/image-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import QRCode from 'qrcode';
|
|
2
|
+
import { withSession } from '../session/context.js';
|
|
3
|
+
import { parseIdentity } from '../auth/cookies.js';
|
|
4
|
+
import { writeState } from '../session/state.js';
|
|
5
|
+
import { emit, info, isJson } from '../io/output.js';
|
|
6
|
+
import { CliError } from '../io/errors.js';
|
|
7
|
+
import { nowIso } from '../util/time.js';
|
|
8
|
+
async function ensureDaemonStarted(opts) {
|
|
9
|
+
if (opts.noDaemon)
|
|
10
|
+
return;
|
|
11
|
+
if (opts.profile)
|
|
12
|
+
return; // daemon only serves the default profile
|
|
13
|
+
try {
|
|
14
|
+
const { status, start } = await import('../daemon/manager.js');
|
|
15
|
+
const st = await status();
|
|
16
|
+
if (st.running) {
|
|
17
|
+
info(`Daemon already running (pid ${st.pid}).`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
info('Starting daemon to keep browser warm (reduces risk control hits)...');
|
|
21
|
+
const { pid } = await start();
|
|
22
|
+
info(`Daemon ready (pid ${pid}) — next commands will reuse this context.`);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
info(`(Daemon auto-start skipped: ${e.message})`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const LOGIN_URL = 'https://login.1688.com/member/signin.htm?tbpm=1';
|
|
29
|
+
const WARMUP_URL = 'https://air.1688.com/app/ctf-page/trade-order-list/buyer-order-list.html';
|
|
30
|
+
export async function run(opts) {
|
|
31
|
+
const timeoutMs = Math.max(30, parseInt(opts.timeout ?? '300', 10)) * 1000;
|
|
32
|
+
const headed = opts.headed === true;
|
|
33
|
+
if (!opts.force) {
|
|
34
|
+
const existing = await peekIdentity(opts.profile);
|
|
35
|
+
if (existing) {
|
|
36
|
+
const name = existing.nick ?? existing.memberId;
|
|
37
|
+
emit({
|
|
38
|
+
human: () => info(`Already logged in as ${name} (memberId: ${existing.memberId}). Use --force to re-login.`),
|
|
39
|
+
data: {
|
|
40
|
+
ok: true,
|
|
41
|
+
alreadyLoggedIn: true,
|
|
42
|
+
memberId: existing.memberId,
|
|
43
|
+
nick: existing.nick,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
await ensureDaemonStarted(opts);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const identity = await withSession({ headless: !headed, profile: opts.profile }, async (ctx) => {
|
|
51
|
+
if (opts.force)
|
|
52
|
+
await clearAlibabaCookies(ctx);
|
|
53
|
+
const page = await ctx.newPage();
|
|
54
|
+
if (headed) {
|
|
55
|
+
info('Opening 1688 login page in a browser window...');
|
|
56
|
+
info('Scan the QR code with your 1688 or Taobao app.');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
printInteractive('Generating QR code...');
|
|
60
|
+
attachQrRenderer(page);
|
|
61
|
+
}
|
|
62
|
+
await page.goto(LOGIN_URL);
|
|
63
|
+
await waitForLogin(ctx, page, timeoutMs, headed);
|
|
64
|
+
printInteractive('Confirmed. Finalizing session...');
|
|
65
|
+
try {
|
|
66
|
+
await page.goto(WARMUP_URL, {
|
|
67
|
+
waitUntil: 'domcontentloaded',
|
|
68
|
+
timeout: 15000,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* ignore warmup failure */
|
|
73
|
+
}
|
|
74
|
+
const id = parseIdentity(await ctx.cookies());
|
|
75
|
+
if (!id) {
|
|
76
|
+
throw new CliError(8, 'LOGIN_INCOMPLETE', 'Login flow finished but identity cookies are missing. Try --headed.');
|
|
77
|
+
}
|
|
78
|
+
return id;
|
|
79
|
+
});
|
|
80
|
+
await writeState({
|
|
81
|
+
version: 1,
|
|
82
|
+
memberId: identity.memberId,
|
|
83
|
+
nick: identity.nick ?? undefined,
|
|
84
|
+
loggedInAt: nowIso(),
|
|
85
|
+
lastVerifiedAt: nowIso(),
|
|
86
|
+
});
|
|
87
|
+
const name = identity.nick ?? identity.memberId;
|
|
88
|
+
emit({
|
|
89
|
+
human: () => process.stdout.write(`Logged in as ${name} (memberId: ${identity.memberId})\n`),
|
|
90
|
+
data: { ok: true, memberId: identity.memberId, nick: identity.nick },
|
|
91
|
+
});
|
|
92
|
+
await ensureDaemonStarted(opts);
|
|
93
|
+
}
|
|
94
|
+
async function peekIdentity(profile) {
|
|
95
|
+
return withSession({ headless: true, profile }, async (ctx) => parseIdentity(await ctx.cookies()));
|
|
96
|
+
}
|
|
97
|
+
async function clearAlibabaCookies(ctx) {
|
|
98
|
+
const all = await ctx.cookies();
|
|
99
|
+
try {
|
|
100
|
+
await ctx.clearCookies({ domain: /\.1688\.com$/ });
|
|
101
|
+
await ctx.clearCookies({ domain: /\.taobao\.com$/ });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
const keep = all.filter((c) => !c.domain.endsWith('.1688.com') && !c.domain.endsWith('.taobao.com'));
|
|
106
|
+
await ctx.clearCookies();
|
|
107
|
+
if (keep.length)
|
|
108
|
+
await ctx.addCookies(keep);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function waitForLogin(ctx, page, timeoutMs, headed) {
|
|
112
|
+
const deadline = Date.now() + timeoutMs;
|
|
113
|
+
while (Date.now() < deadline) {
|
|
114
|
+
if (page.isClosed()) {
|
|
115
|
+
throw new CliError(130, 'CANCELED', headed
|
|
116
|
+
? 'Login canceled (browser closed).'
|
|
117
|
+
: 'Login canceled.');
|
|
118
|
+
}
|
|
119
|
+
let cookies;
|
|
120
|
+
try {
|
|
121
|
+
cookies = await ctx.cookies();
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
throw new CliError(130, 'CANCELED', 'Login canceled.');
|
|
125
|
+
}
|
|
126
|
+
if (cookies.some((c) => c.name === 'unb' && c.domain.endsWith('.1688.com'))) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
130
|
+
}
|
|
131
|
+
throw new CliError(7, 'LOGIN_TIMEOUT', `Login timed out after ${Math.round(timeoutMs / 1000)}s. ` +
|
|
132
|
+
`If the QR never appeared, try \`1688 login --headed\`.`);
|
|
133
|
+
}
|
|
134
|
+
// ── QR rendering ──────────────────────────────────────────────────────────
|
|
135
|
+
function attachQrRenderer(page) {
|
|
136
|
+
let lastContent;
|
|
137
|
+
page.on('response', async (resp) => {
|
|
138
|
+
const url = resp.url();
|
|
139
|
+
if (!/qrcode\/generate/i.test(url))
|
|
140
|
+
return;
|
|
141
|
+
let json;
|
|
142
|
+
try {
|
|
143
|
+
json = await resp.json();
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
try {
|
|
147
|
+
const txt = await resp.text();
|
|
148
|
+
json = JSON.parse(txt);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const content = findValue(json, 'codeContent');
|
|
155
|
+
if (!content || content === lastContent)
|
|
156
|
+
return;
|
|
157
|
+
const refreshing = lastContent !== undefined;
|
|
158
|
+
lastContent = content;
|
|
159
|
+
await renderQrToTerminal(content, refreshing);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async function renderQrToTerminal(content, refreshing) {
|
|
163
|
+
const out = process.stderr;
|
|
164
|
+
out.write('\n');
|
|
165
|
+
if (refreshing) {
|
|
166
|
+
out.write('QR refreshed — scan the new code:\n\n');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
out.write('Scan with your 1688 or Taobao app:\n\n');
|
|
170
|
+
}
|
|
171
|
+
if (out.isTTY) {
|
|
172
|
+
try {
|
|
173
|
+
const ascii = await QRCode.toString(content, {
|
|
174
|
+
type: 'terminal',
|
|
175
|
+
small: true,
|
|
176
|
+
});
|
|
177
|
+
out.write(ascii);
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
out.write(`(QR render failed: ${e.message})\n`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
out.write('(non-TTY — open the URL below on your phone)\n');
|
|
185
|
+
}
|
|
186
|
+
out.write('\nOr open on your phone: ');
|
|
187
|
+
out.write(content);
|
|
188
|
+
out.write('\n\nWaiting for scan + confirmation...\n');
|
|
189
|
+
}
|
|
190
|
+
function printInteractive(msg) {
|
|
191
|
+
// Always write to stderr — keeps stdout JSON clean for pipes/agents.
|
|
192
|
+
if (!isJson()) {
|
|
193
|
+
process.stderr.write(`→ ${msg}\n`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function findValue(obj, key) {
|
|
197
|
+
if (!obj || typeof obj !== 'object')
|
|
198
|
+
return undefined;
|
|
199
|
+
const o = obj;
|
|
200
|
+
if (typeof o[key] === 'string')
|
|
201
|
+
return o[key];
|
|
202
|
+
for (const v of Object.values(o)) {
|
|
203
|
+
const r = findValue(v, key);
|
|
204
|
+
if (r)
|
|
205
|
+
return r;
|
|
206
|
+
}
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { withSession } from '../session/context.js';
|
|
2
|
+
import { parseIdentity } from '../auth/cookies.js';
|
|
3
|
+
import { clearState } from '../session/state.js';
|
|
4
|
+
import { emit, info, isJson } from '../io/output.js';
|
|
5
|
+
import { CliError } from '../io/errors.js';
|
|
6
|
+
import { confirm } from '../io/prompt.js';
|
|
7
|
+
const LOGOUT_URL = 'https://login.1688.com/member/logout.htm';
|
|
8
|
+
export async function run(opts) {
|
|
9
|
+
const pre = await withSession({ headless: true, profile: opts.profile }, async (ctx) => parseIdentity(await ctx.cookies()));
|
|
10
|
+
if (!pre) {
|
|
11
|
+
await clearState();
|
|
12
|
+
emit({
|
|
13
|
+
human: () => info('Not logged in.'),
|
|
14
|
+
data: { ok: true, wasLoggedIn: false },
|
|
15
|
+
});
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!opts.yes) {
|
|
19
|
+
if (isJson() || !process.stdin.isTTY) {
|
|
20
|
+
throw new CliError(2, 'CONFIRM_REQUIRED', 'Pass --yes to confirm logout in non-interactive mode.');
|
|
21
|
+
}
|
|
22
|
+
const name = pre.nick ?? pre.memberId;
|
|
23
|
+
const ok = await confirm(`Logout ${name} (memberId: ${pre.memberId})?`);
|
|
24
|
+
if (!ok) {
|
|
25
|
+
info('Canceled.');
|
|
26
|
+
throw new CliError(130, 'CANCELED', '');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
await withSession({ headless: true, profile: opts.profile }, async (ctx) => {
|
|
30
|
+
const page = await ctx.newPage();
|
|
31
|
+
try {
|
|
32
|
+
await page.goto(LOGOUT_URL, {
|
|
33
|
+
waitUntil: 'domcontentloaded',
|
|
34
|
+
timeout: 15000,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
/* ignore — proceed to local cookie wipe */
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await ctx.clearCookies({ domain: /\.1688\.com$/ });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
/* ignore */
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await ctx.clearCookies({ domain: /\.taobao\.com$/ });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* ignore */
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
await clearState();
|
|
54
|
+
emit({
|
|
55
|
+
human: () => process.stdout.write('Logged out.\n'),
|
|
56
|
+
data: { ok: true, wasLoggedIn: true },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"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"}
|