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.
Files changed (80) hide show
  1. package/AGENTS.md +118 -0
  2. package/README.md +48 -0
  3. package/dist/auth/cookies.js +31 -0
  4. package/dist/auth/cookies.js.map +1 -0
  5. package/dist/auth/verify.js +25 -0
  6. package/dist/auth/verify.js.map +1 -0
  7. package/dist/cli.js +373 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/cart-add.js +199 -0
  10. package/dist/commands/cart-add.js.map +1 -0
  11. package/dist/commands/cart-list.js +168 -0
  12. package/dist/commands/cart-list.js.map +1 -0
  13. package/dist/commands/cart-remove.js +119 -0
  14. package/dist/commands/cart-remove.js.map +1 -0
  15. package/dist/commands/checkout-confirm.js +407 -0
  16. package/dist/commands/checkout-confirm.js.map +1 -0
  17. package/dist/commands/checkout-prepare.js +244 -0
  18. package/dist/commands/checkout-prepare.js.map +1 -0
  19. package/dist/commands/doctor.js +246 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/image-search.js +210 -0
  22. package/dist/commands/image-search.js.map +1 -0
  23. package/dist/commands/login.js +209 -0
  24. package/dist/commands/login.js.map +1 -0
  25. package/dist/commands/logout.js +59 -0
  26. package/dist/commands/logout.js.map +1 -0
  27. package/dist/commands/offer.js +185 -0
  28. package/dist/commands/offer.js.map +1 -0
  29. package/dist/commands/order-get.js +76 -0
  30. package/dist/commands/order-get.js.map +1 -0
  31. package/dist/commands/order-list.js +176 -0
  32. package/dist/commands/order-list.js.map +1 -0
  33. package/dist/commands/order-logistics.js +152 -0
  34. package/dist/commands/order-logistics.js.map +1 -0
  35. package/dist/commands/search.js +250 -0
  36. package/dist/commands/search.js.map +1 -0
  37. package/dist/commands/seller-chat.js +213 -0
  38. package/dist/commands/seller-chat.js.map +1 -0
  39. package/dist/commands/seller-inquire.js +110 -0
  40. package/dist/commands/seller-inquire.js.map +1 -0
  41. package/dist/commands/seller-lookup-ww.js +6 -0
  42. package/dist/commands/seller-lookup-ww.js.map +1 -0
  43. package/dist/commands/seller-messages.js +181 -0
  44. package/dist/commands/seller-messages.js.map +1 -0
  45. package/dist/commands/whoami.js +53 -0
  46. package/dist/commands/whoami.js.map +1 -0
  47. package/dist/commands/workflows.js +264 -0
  48. package/dist/commands/workflows.js.map +1 -0
  49. package/dist/daemon/client.js +75 -0
  50. package/dist/daemon/client.js.map +1 -0
  51. package/dist/daemon/manager.js +128 -0
  52. package/dist/daemon/manager.js.map +1 -0
  53. package/dist/daemon/protocol.js +5 -0
  54. package/dist/daemon/protocol.js.map +1 -0
  55. package/dist/daemon/server.js +197 -0
  56. package/dist/daemon/server.js.map +1 -0
  57. package/dist/daemon/throttle.js +17 -0
  58. package/dist/daemon/throttle.js.map +1 -0
  59. package/dist/io/errors.js +10 -0
  60. package/dist/io/errors.js.map +1 -0
  61. package/dist/io/output.js +17 -0
  62. package/dist/io/output.js.map +1 -0
  63. package/dist/io/prompt.js +17 -0
  64. package/dist/io/prompt.js.map +1 -0
  65. package/dist/session/context.js +91 -0
  66. package/dist/session/context.js.map +1 -0
  67. package/dist/session/dispatch.js +50 -0
  68. package/dist/session/dispatch.js.map +1 -0
  69. package/dist/session/lock.js +23 -0
  70. package/dist/session/lock.js.map +1 -0
  71. package/dist/session/paths.js +31 -0
  72. package/dist/session/paths.js.map +1 -0
  73. package/dist/session/shared.js +104 -0
  74. package/dist/session/shared.js.map +1 -0
  75. package/dist/session/state.js +27 -0
  76. package/dist/session/state.js.map +1 -0
  77. package/dist/util/time.js +17 -0
  78. package/dist/util/time.js.map +1 -0
  79. package/package.json +44 -0
  80. package/scripts/postinstall.mjs +49 -0
@@ -0,0 +1,250 @@
1
+ import iconv from 'iconv-lite';
2
+ import { dispatch } from '../session/dispatch.js';
3
+ import { emit, info } from '../io/output.js';
4
+ import { CliError } from '../io/errors.js';
5
+ export async function execute(ctx, args) {
6
+ const offers = await fetchSearch(ctx, args.keyword, args.headed === true);
7
+ const slice = offers.slice(0, args.max);
8
+ return { keyword: args.keyword, total: slice.length, offers: slice };
9
+ }
10
+ export async function run(keyword, opts) {
11
+ const kw = (keyword ?? '').trim();
12
+ if (!kw) {
13
+ throw new CliError(2, 'BAD_INPUT', 'Search keyword is required.');
14
+ }
15
+ const max = Math.max(1, parseInt(opts.max ?? '20', 10));
16
+ const data = await dispatch('search', { keyword: kw, max, headed: opts.headed }, { headed: opts.headed, profile: opts.profile });
17
+ emit({
18
+ human: () => printOffers(data.offers, data.keyword),
19
+ data,
20
+ });
21
+ }
22
+ async function fetchSearch(ctx, keyword, headed) {
23
+ const page = await ctx.newPage();
24
+ // s.1688.com is GBK-encoded — UTF-8 percent-encoding makes the server
25
+ // search for mojibake. Encode the keyword as GBK bytes first.
26
+ const gbkBytes = iconv.encode(keyword, 'gbk');
27
+ const gbkQs = Array.from(gbkBytes)
28
+ .map((b) => '%' + b.toString(16).padStart(2, '0').toUpperCase())
29
+ .join('');
30
+ const url = `https://s.1688.com/selloffer/offer_search.htm?keywords=${gbkQs}`;
31
+ info(`Searching 1688 for "${keyword}"...`);
32
+ if (headed) {
33
+ info('A Chrome window has opened — switch focus to it now.');
34
+ }
35
+ try {
36
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
37
+ }
38
+ catch (e) {
39
+ throw new CliError(9, 'NETWORK_ERROR', `Failed to load search page: ${e.message}`);
40
+ }
41
+ // Risk-control gate with retry. Headed: let user solve.
42
+ if (await waitPastBlocking(page, headed)) {
43
+ /* passed */
44
+ }
45
+ else {
46
+ throw riskControlError(headed);
47
+ }
48
+ await detectLoginRedirect(page);
49
+ try {
50
+ await page.waitForSelector('.search-offer-item a[href*="detail.m.1688.com"]', { timeout: headed ? 180000 : 15000 });
51
+ }
52
+ catch {
53
+ if (await isBlocked(page))
54
+ throw riskControlError(headed);
55
+ }
56
+ // Scroll to trigger lazy-loaded cards.
57
+ await page.evaluate(() => window.scrollBy(0, 2000));
58
+ await new Promise((r) => setTimeout(r, 1500));
59
+ await page.evaluate(() => window.scrollBy(0, 2000));
60
+ await new Promise((r) => setTimeout(r, 1500));
61
+ const offers = await extractOffers(page);
62
+ if (process.env.BB1688_DEBUG === '1') {
63
+ const stats = await page.evaluate(() => ({
64
+ cards: document.querySelectorAll('.search-offer-item').length,
65
+ linksToDetail: document.querySelectorAll('.search-offer-item a[href*="detail.m.1688.com"]').length,
66
+ totalDetailLinks: document.querySelectorAll('a[href*="detail.m.1688.com"], a[href*="detail.1688.com"]').length,
67
+ title: document.title,
68
+ bodyHead: (document.body?.innerText ?? '').slice(0, 120),
69
+ }));
70
+ process.stderr.write(`[debug] url=${page.url()}\n` +
71
+ `[debug] title=${stats.title}\n` +
72
+ `[debug] cards=${stats.cards} linksToDetail=${stats.linksToDetail} totalDetailLinks=${stats.totalDetailLinks} extracted=${offers.length}\n` +
73
+ `[debug] body=${stats.bodyHead}\n`);
74
+ }
75
+ return offers;
76
+ }
77
+ async function isBlocked(page, retries = 3) {
78
+ for (let i = 0; i < retries; i++) {
79
+ try {
80
+ if (/\/punish|x5secdata=/.test(page.url()))
81
+ return true;
82
+ const sig = await page.evaluate(() => ({
83
+ title: document.title ?? '',
84
+ body: (document.body?.innerText ?? '').slice(0, 500),
85
+ }));
86
+ if (/验证码拦截|拖动.*滑块|滑动.*验证/.test(sig.title + ' ' + sig.body)) {
87
+ return true;
88
+ }
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ if (i < retries - 1)
94
+ await new Promise((r) => setTimeout(r, 800));
95
+ }
96
+ return false;
97
+ }
98
+ /**
99
+ * Returns true once the page is past any risk-control gate.
100
+ * Primary success signal: search result cards have rendered.
101
+ * Headless: short timeout, fail fast. Headed: long timeout, user solves.
102
+ */
103
+ async function waitPastBlocking(page, headed) {
104
+ const timeoutMs = headed ? 180000 : 5000;
105
+ const deadline = Date.now() + timeoutMs;
106
+ let announced = false;
107
+ let lastProgressAt = Date.now();
108
+ while (Date.now() < deadline) {
109
+ if (page.isClosed()) {
110
+ throw new CliError(130, 'CANCELED', 'Browser closed.');
111
+ }
112
+ // Strongest success signal: results are rendered.
113
+ const hasCards = await page
114
+ .evaluate(() => document.querySelectorAll('.search-offer-item').length > 0)
115
+ .catch(() => false);
116
+ if (hasCards)
117
+ return true;
118
+ if (process.env.BB1688_DEBUG === '1') {
119
+ const sig = await page
120
+ .evaluate(() => ({
121
+ url: location.href,
122
+ title: document.title ?? '',
123
+ body: (document.body?.innerText ?? '').slice(0, 80),
124
+ }))
125
+ .catch(() => null);
126
+ if (sig) {
127
+ process.stderr.write(`[debug] url=${sig.url}\n[debug] title=${sig.title} body=${sig.body}\n`);
128
+ }
129
+ }
130
+ const blocked = await isBlocked(page, 1);
131
+ if (!blocked) {
132
+ // Not blocked, no cards yet — page is loading/transitioning. Keep polling.
133
+ }
134
+ else {
135
+ if (!headed)
136
+ return false;
137
+ if (!announced) {
138
+ info('Verification page detected — drag the slider in the window.');
139
+ announced = true;
140
+ }
141
+ }
142
+ if (Date.now() - lastProgressAt > 10000) {
143
+ info(`Still waiting (${Math.round((deadline - Date.now()) / 1000)}s left)...`);
144
+ lastProgressAt = Date.now();
145
+ }
146
+ await new Promise((r) => setTimeout(r, 1500));
147
+ }
148
+ return false;
149
+ }
150
+ function riskControlError(triedHeaded) {
151
+ const msg = triedHeaded
152
+ ? 'Slider verification not solved in time. Try again:\n' +
153
+ ' 1688 search "<keyword>" --headed'
154
+ : 'Aliyun risk control triggered (slider verification). ' +
155
+ 'Run once with --headed to solve it manually; subsequent headless calls work for hours:\n' +
156
+ ' 1688 search "<keyword>" --headed';
157
+ return new CliError(4, 'RISK_CONTROL', msg);
158
+ }
159
+ async function detectLoginRedirect(page) {
160
+ if (/login\.1688\.com|login\.taobao\.com/.test(page.url())) {
161
+ throw new CliError(3, 'NOT_LOGGED_IN', 'Session expired. Run `1688 login`.');
162
+ }
163
+ }
164
+ export async function extractOffers(page) {
165
+ return page.evaluate(() => {
166
+ const cards = document.querySelectorAll('.search-offer-item');
167
+ const seen = new Set();
168
+ const out = [];
169
+ for (const card of Array.from(cards)) {
170
+ let link = card.closest('a[href*="detail.m.1688.com"]') ??
171
+ card.querySelector('a[href*="detail.m.1688.com"]');
172
+ if (!link)
173
+ continue;
174
+ const m = link.href.match(/[?&]offerId=(\d+)/);
175
+ if (!m)
176
+ continue;
177
+ const offerId = m[1];
178
+ if (seen.has(offerId))
179
+ continue;
180
+ seen.add(offerId);
181
+ const titleEl = card.querySelector('.offer-title-row .title-text') ??
182
+ card.querySelector('.offer-title-row');
183
+ const title = (titleEl?.textContent ?? '').replace(/\s+/g, ' ').trim();
184
+ const priceItem = card.querySelector('.price-item');
185
+ const priceText = priceItem
186
+ ? (priceItem.textContent ?? '').replace(/\s+/g, '')
187
+ : '';
188
+ const pm = priceText.match(/([¥¥])?\s*([\d.]+)(?:\s*[~\-–]\s*([\d.]+))?/);
189
+ const priceMin = pm ? parseFloat(pm[2]) : null;
190
+ const priceMax = pm && pm[3] ? parseFloat(pm[3]) : priceMin;
191
+ const img = card.querySelector('img.main-img') ??
192
+ card.querySelector('img');
193
+ const image = img?.getAttribute('src') ??
194
+ img?.getAttribute('data-src') ??
195
+ null;
196
+ const shopRow = card.querySelector('.offer-shop-row');
197
+ const supplierLink = shopRow?.querySelector('a[href*=".1688.com"]');
198
+ const supplierName = shopRow?.querySelector('.desc-text')?.textContent?.trim() ?? null;
199
+ const shopUrl = supplierLink?.href ?? null;
200
+ const cardText = (card.textContent ?? '').replace(/\s+/g, ' ');
201
+ const yearMatch = cardText.match(/(\d{1,2})\s*年/);
202
+ const years = yearMatch ? parseInt(yearMatch[1], 10) : null;
203
+ const turnover = card.querySelector('.col-desc_after .desc-text')?.textContent?.trim() ??
204
+ null;
205
+ out.push({
206
+ offerId,
207
+ title,
208
+ price: {
209
+ text: priceText.replace(/[¥¥]/g, '¥'),
210
+ min: priceMin,
211
+ max: priceMax,
212
+ },
213
+ supplier: { name: supplierName, shopUrl, years },
214
+ turnover,
215
+ url: `https://detail.m.1688.com/page/index.html?offerId=${offerId}`,
216
+ image,
217
+ });
218
+ }
219
+ return out;
220
+ });
221
+ }
222
+ function printOffers(offers, keyword) {
223
+ if (offers.length === 0) {
224
+ process.stdout.write(`No offers found for "${keyword}".\n`);
225
+ return;
226
+ }
227
+ const w = String(offers.length).length;
228
+ offers.forEach((o, i) => {
229
+ const idx = String(i + 1).padStart(w, ' ');
230
+ const price = o.price.text || '(n/a)';
231
+ process.stdout.write(`${idx}. ${o.title}\n`);
232
+ const pad = ' '.repeat(w + 2);
233
+ process.stdout.write(`${pad}${price}`);
234
+ if (o.turnover)
235
+ process.stdout.write(` · ${o.turnover}`);
236
+ process.stdout.write('\n');
237
+ const supBits = [
238
+ o.supplier.name,
239
+ o.supplier.years ? `${o.supplier.years}年` : null,
240
+ ]
241
+ .filter(Boolean)
242
+ .join(' · ');
243
+ if (supBits)
244
+ process.stdout.write(`${pad}${supBits}\n`);
245
+ process.stdout.write(`${pad}${o.url}\n`);
246
+ if (i < offers.length - 1)
247
+ process.stdout.write('\n');
248
+ });
249
+ }
250
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,213 @@
1
+ import { dispatch } from '../session/dispatch.js';
2
+ import { emit, info } from '../io/output.js';
3
+ import { CliError } from '../io/errors.js';
4
+ import { readState } from '../session/state.js';
5
+ const IM_BASE = 'https://air.1688.com/app/ocms-fusion-components-1688/def_cbu_web_im/index.html';
6
+ export async function execute(ctx, args) {
7
+ if (!args.message || !args.myLoginId || !args.searchNames?.length) {
8
+ throw new CliError(2, 'BAD_INPUT', 'myLoginId, searchNames, and message are required.');
9
+ }
10
+ if (args.message.length > 500) {
11
+ throw new CliError(2, 'BAD_INPUT', 'Message too long (max 500 chars).');
12
+ }
13
+ const page = await ctx.newPage();
14
+ try {
15
+ // Build URL using 1688's "联系卖家" pattern:
16
+ // touid=cnalichn<loginId> (cnalichn prefix is required)
17
+ // siteid=cnalichn
18
+ // status=1
19
+ // orderId / offerId (server uses these to scope/create conversation)
20
+ // #/
21
+ //
22
+ // Without proper scope params, 1688 won't create the conversation
23
+ // server-side and the chat shows "您尚未选择联系人".
24
+ let url;
25
+ if (args.sellerLoginId && (args.orderId || args.offerId)) {
26
+ url =
27
+ `${IM_BASE}?` +
28
+ `touid=cnalichn${encodeURIComponent(args.sellerLoginId)}` +
29
+ `&siteid=cnalichn` +
30
+ `&status=1` +
31
+ `&portalId=` +
32
+ `&gid=` +
33
+ `&offerId=${args.offerId ? encodeURIComponent(args.offerId) : ''}` +
34
+ `&itemsId=` +
35
+ `&orderId=${args.orderId ? encodeURIComponent(args.orderId) : ''}` +
36
+ `#/`;
37
+ const scope = args.orderId
38
+ ? `orderId=${args.orderId}`
39
+ : `offerId=${args.offerId}`;
40
+ info(`Opening 旺旺 (scoped: ${scope})...`);
41
+ }
42
+ else {
43
+ url = `${IM_BASE}?fromid=cnalichn${encodeURIComponent(args.myLoginId)}`;
44
+ info('Opening 旺旺 IM (sidebar mode)...');
45
+ }
46
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
47
+ if (/login\.1688\.com|login\.taobao\.com/.test(page.url())) {
48
+ throw new CliError(3, 'NOT_LOGGED_IN', 'Session expired. Run `1688 login`.');
49
+ }
50
+ const imFrame = page.frameLocator('iframe[src*="def_cbu_web_im_core"]');
51
+ const input = imFrame.locator('pre.edit[contenteditable="true"]').first();
52
+ try {
53
+ await input.waitFor({ state: 'visible', timeout: 20000 });
54
+ }
55
+ catch {
56
+ throw new CliError(22, 'CHAT_NOT_LOADED', 'Failed to open 旺旺 IM (page never loaded chat input).');
57
+ }
58
+ await new Promise((r) => setTimeout(r, 3000));
59
+ // If scoped URL (order/offer) was used, conversation should auto-activate.
60
+ // Otherwise (sidebar mode), find + click the seller in sidebar.
61
+ let matchedName = null;
62
+ if (args.sellerLoginId && (args.orderId || args.offerId)) {
63
+ // Scoped — wait for auto-activation
64
+ matchedName = args.searchNames[0] ?? args.sellerLoginId;
65
+ }
66
+ else {
67
+ info(`Searching sidebar for: ${args.searchNames.join(' / ')}`);
68
+ for (const name of args.searchNames) {
69
+ if (!name)
70
+ continue;
71
+ const item = imFrame.locator(`text=${name}`).first();
72
+ const visible = await item
73
+ .isVisible({ timeout: 2000 })
74
+ .catch(() => false);
75
+ if (visible) {
76
+ info(`Found "${name}" in sidebar; clicking...`);
77
+ await item.click({ force: true });
78
+ matchedName = name;
79
+ break;
80
+ }
81
+ }
82
+ if (!matchedName) {
83
+ throw new CliError(29, 'SELLER_NOT_IN_SIDEBAR', `Seller not found in 旺旺 conversation list (tried: ${args.searchNames
84
+ .filter(Boolean)
85
+ .join(', ')}). Use an orderId-based call so we can pass orderId to ` +
86
+ 'auto-activate the conversation.');
87
+ }
88
+ }
89
+ // Wait for the conversation to actually activate (right pane no longer empty).
90
+ const activated = await page
91
+ .waitForFunction(() => {
92
+ const iframe = document.querySelector('iframe[src*="def_cbu_web_im_core"]');
93
+ const body = iframe?.contentDocument?.body?.innerText ?? '';
94
+ return !/您尚未选择联系人/.test(body) && body.length > 50;
95
+ }, { timeout: 25000 })
96
+ .then(() => true)
97
+ .catch(() => false);
98
+ if (!activated) {
99
+ throw new CliError(26, 'CONVERSATION_NOT_SELECTED', `Conversation panel did not activate for ${matchedName}. ` +
100
+ (args.orderId
101
+ ? `OrderId ${args.orderId} was passed but conversation never opened.`
102
+ : 'Sidebar click did not switch to conversation.'));
103
+ }
104
+ await new Promise((r) => setTimeout(r, 1500));
105
+ // 4. Type the message and send.
106
+ info(`Typing message (${args.message.length} chars)...`);
107
+ await input.click({ force: true });
108
+ await input.fill('');
109
+ await page.keyboard.type(args.message, { delay: 20 });
110
+ await new Promise((r) => setTimeout(r, 500));
111
+ info('Sending...');
112
+ await imFrame
113
+ .locator('button.send-btn:has-text("发送")')
114
+ .first()
115
+ .click({ force: true });
116
+ // 5. Verify: input clears OR message appears in chat body
117
+ const sentAt = new Date().toISOString();
118
+ const sent = await page
119
+ .waitForFunction((msg) => {
120
+ const iframe = document.querySelector('iframe[src*="def_cbu_web_im_core"]');
121
+ const doc = iframe?.contentDocument;
122
+ if (!doc)
123
+ return false;
124
+ const edit = doc.querySelector('pre.edit[contenteditable="true"]');
125
+ const editText = (edit?.innerText ?? '').replace(/\s+/g, '');
126
+ if (editText.length === 0)
127
+ return true;
128
+ const body = doc.body?.innerText ?? '';
129
+ return body.includes(msg);
130
+ }, args.message, { timeout: 10000 })
131
+ .then(() => true)
132
+ .catch(() => false);
133
+ if (!sent) {
134
+ throw new CliError(24, 'SEND_UNCONFIRMED', 'Send clicked but neither input cleared nor message appeared in scrollback.');
135
+ }
136
+ return {
137
+ ok: true,
138
+ sentTo: matchedName,
139
+ message: args.message,
140
+ sentAt,
141
+ };
142
+ }
143
+ finally {
144
+ await page.close().catch(() => { });
145
+ }
146
+ }
147
+ export async function run(opts) {
148
+ if (!opts.message) {
149
+ throw new CliError(2, 'BAD_INPUT', 'Message is required.');
150
+ }
151
+ if (!opts.message.trim()) {
152
+ throw new CliError(2, 'BAD_INPUT', 'Message cannot be empty.');
153
+ }
154
+ if (!opts.target) {
155
+ throw new CliError(2, 'BAD_INPUT', 'Provide an orderId or seller name as target.');
156
+ }
157
+ const state = await readState();
158
+ if (!state.nick) {
159
+ throw new CliError(3, 'NOT_LOGGED_IN', 'Cannot determine your loginId. Run `1688 whoami` first.');
160
+ }
161
+ const myLoginId = state.nick;
162
+ // For orderId target: look up seller; by default also send the order detail
163
+ // URL as a first message (1688 IM auto-renders it as an order card).
164
+ // --no-card skips the card (use for follow-up replies).
165
+ // For loginId target: just send the text (sidebar mode).
166
+ let baseArgs;
167
+ let sendCard = false;
168
+ let finalMessage = opts.message;
169
+ if (/^\d+$/.test(opts.target)) {
170
+ info(`Looking up seller for order ${opts.target}...`);
171
+ const order = await dispatch('order-get', { orderId: opts.target, maxScanPages: 5 }, { headed: opts.headed, profile: opts.profile });
172
+ if (!order.seller.loginId) {
173
+ throw new CliError(12, 'SELLER_NOT_FOUND', `Order ${opts.target} has no seller loginId.`);
174
+ }
175
+ baseArgs = {
176
+ searchNames: [order.seller.loginId, order.seller.name].filter(Boolean),
177
+ sellerLoginId: order.seller.loginId,
178
+ orderId: opts.target,
179
+ myLoginId,
180
+ };
181
+ sendCard = !opts.noCard;
182
+ // Optional: --prefix adds 【订单 XXX】 in text (redundant if card sent)
183
+ if (opts.prefix && !finalMessage.includes(opts.target)) {
184
+ finalMessage = `【订单 ${opts.target}】${finalMessage}`;
185
+ }
186
+ info(`Will message: ${order.seller.name ?? order.seller.loginId}`);
187
+ }
188
+ else {
189
+ baseArgs = {
190
+ searchNames: [opts.target],
191
+ myLoginId,
192
+ };
193
+ info(`Will message: ${opts.target} (sidebar mode — requires existing chat)`);
194
+ }
195
+ // First, send the order URL as a separate message (auto-rendered as card).
196
+ if (sendCard) {
197
+ const orderUrl = `https://trade.1688.com/order/new_step_order_detail.htm?orderId=${opts.target}`;
198
+ info(`Sending message 1/2: order link card`);
199
+ await dispatch('seller-chat', { ...baseArgs, message: orderUrl }, { headed: opts.headed, profile: opts.profile });
200
+ await new Promise((r) => setTimeout(r, 1500));
201
+ info(`Sending message 2/2: question`);
202
+ }
203
+ const data = await dispatch('seller-chat', { ...baseArgs, message: finalMessage }, { headed: opts.headed, profile: opts.profile });
204
+ emit({
205
+ human: () => {
206
+ process.stdout.write(`✓ Message sent to ${data.sentTo}\n`);
207
+ process.stdout.write(` at: ${data.sentAt}\n`);
208
+ process.stdout.write(` >> ${data.message}\n`);
209
+ },
210
+ data,
211
+ });
212
+ }
213
+ //# sourceMappingURL=seller-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seller-chat.js","sourceRoot":"","sources":["../../src/commands/seller-chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ import { dispatch } from '../session/dispatch.js';
2
+ import { emit, info } from '../io/output.js';
3
+ import { CliError } from '../io/errors.js';
4
+ import { readState } from '../session/state.js';
5
+ const PRODUCT_URL = (id) => `https://detail.1688.com/offer/${id}.html`;
6
+ export async function run(opts) {
7
+ if (!opts.offerId || !/^\d+$/.test(opts.offerId)) {
8
+ throw new CliError(2, 'BAD_INPUT', 'Valid offerId required.');
9
+ }
10
+ if (!opts.message?.trim()) {
11
+ throw new CliError(2, 'BAD_INPUT', 'Message cannot be empty.');
12
+ }
13
+ const state = await readState();
14
+ if (!state.nick) {
15
+ throw new CliError(3, 'NOT_LOGGED_IN', 'Cannot determine your loginId. Run `1688 whoami` first.');
16
+ }
17
+ // 1. Resolve seller loginId
18
+ let sellerLoginId = opts.to ?? null;
19
+ let sellerName = null;
20
+ if (!sellerLoginId) {
21
+ sellerLoginId = await tryFindSeller(opts.offerId, opts);
22
+ if (!sellerLoginId) {
23
+ throw new CliError(30, 'SELLER_UNKNOWN', `Cannot find seller for offer ${opts.offerId}. ` +
24
+ 'Pass --to <sellerLoginId> explicitly, OR add the item to cart first ' +
25
+ `(1688 cart add ${opts.offerId} --sku ... --qty 1) so 1688 can ` +
26
+ 'identify the seller.');
27
+ }
28
+ }
29
+ info(`Seller: ${sellerLoginId}${sellerName ? ` (${sellerName})` : ''}`);
30
+ // 2. Send TWO messages — URL first (so 1688 IM can auto-render product card
31
+ // if it supports that for standalone links), then the question text.
32
+ // Pass sellerLoginId + offerId so seller-chat uses offer-scoped URL that
33
+ // creates the conversation server-side (works for never-chatted sellers).
34
+ const productUrl = PRODUCT_URL(opts.offerId);
35
+ const searchNames = [sellerLoginId, sellerName].filter(Boolean);
36
+ const chatBaseArgs = {
37
+ searchNames,
38
+ sellerLoginId,
39
+ offerId: opts.offerId,
40
+ myLoginId: state.nick,
41
+ };
42
+ info(`Sending message 1/2: product link`);
43
+ await dispatch('seller-chat', { ...chatBaseArgs, message: productUrl }, { headed: opts.headed, profile: opts.profile });
44
+ // Small pause so the 2 sends look natural (and avoid hammering)
45
+ await new Promise((r) => setTimeout(r, 1500));
46
+ info(`Sending message 2/2: question`);
47
+ const data = await dispatch('seller-chat', { ...chatBaseArgs, message: opts.message }, { headed: opts.headed, profile: opts.profile });
48
+ emit({
49
+ human: () => {
50
+ process.stdout.write(`✓ Inquiry sent to ${data.sentTo}\n`);
51
+ process.stdout.write(` msg 1 (link): ${productUrl}\n`);
52
+ process.stdout.write(` msg 2 (question): ${opts.message}\n`);
53
+ process.stdout.write(` at: ${data.sentAt}\n`);
54
+ },
55
+ data: { ok: true, sentTo: data.sentTo, productUrl, question: opts.message, sentAt: data.sentAt },
56
+ });
57
+ }
58
+ /**
59
+ * Find seller's loginId for an offerId. Strategy:
60
+ * 1) Read window.FE_GLOBALS.offerLoginId from the product detail page (works
61
+ * for ALL offers — best path)
62
+ * 2) Fallback: cart match (if for some reason the page lookup fails)
63
+ */
64
+ async function tryFindSeller(offerId, opts) {
65
+ // Primary: scrape window.FE_GLOBALS.offerLoginId from detail page
66
+ info(`Reading seller loginId from detail page...`);
67
+ try {
68
+ const loginId = await dispatch('detail-feglobals', { offerId }, { headed: opts.headed, profile: opts.profile });
69
+ if (loginId.offerLoginId) {
70
+ info(`Found from FE_GLOBALS: seller=${loginId.offerLoginId}`);
71
+ return loginId.offerLoginId;
72
+ }
73
+ }
74
+ catch {
75
+ /* fall through */
76
+ }
77
+ // Fallback: check cart
78
+ info(`Looking up offer ${offerId} in cart...`);
79
+ try {
80
+ const cart = await dispatch('cart-list', {}, { headed: opts.headed, profile: opts.profile });
81
+ const item = cart.items.find((i) => i.offerId === offerId);
82
+ if (item?.seller.loginId) {
83
+ info(`Found in cart: seller=${item.seller.loginId}`);
84
+ return item.seller.loginId;
85
+ }
86
+ }
87
+ catch {
88
+ /* ignore */
89
+ }
90
+ return null;
91
+ }
92
+ // Standalone executor: scrape FE_GLOBALS from offer detail page
93
+ export async function scrapeFeGlobals(ctx, args) {
94
+ const page = await ctx.newPage();
95
+ try {
96
+ await page.goto(`https://detail.1688.com/offer/${args.offerId}.html`, { waitUntil: 'domcontentloaded', timeout: 25000 });
97
+ // The script tag containing FE_GLOBALS is in the initial HTML, so we don't
98
+ // need to wait for JS to run — but a small delay helps if redirects happen.
99
+ await new Promise((r) => setTimeout(r, 1500));
100
+ const result = await page.evaluate(() => {
101
+ const w = window;
102
+ return { offerLoginId: w.FE_GLOBALS?.offerLoginId ?? null };
103
+ });
104
+ return result;
105
+ }
106
+ finally {
107
+ await page.close().catch(() => { });
108
+ }
109
+ }
110
+ //# sourceMappingURL=seller-inquire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seller-inquire.js","sourceRoot":"","sources":["../../src/commands/seller-inquire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { lookupWangwangNick } from './seller-chat.js';
2
+ export async function execute(ctx, args) {
3
+ const nick = await lookupWangwangNick(ctx, args.shopUrl);
4
+ return { nick };
5
+ }
6
+ //# sourceMappingURL=seller-lookup-ww.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seller-lookup-ww.js","sourceRoot":"","sources":["../../src/commands/seller-lookup-ww.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAUtD,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAmB,EACnB,IAAwB;IAExB,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}