fluxy-bot 0.15.5 → 0.15.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxy-bot",
3
- "version": "0.15.5",
3
+ "version": "0.15.6",
4
4
  "releaseNotes": [
5
5
  "1. react router implemented",
6
6
  "2. new workspace design",
@@ -120,18 +120,11 @@ export class WhatsAppChannel implements ChannelProvider {
120
120
  // If it's already a phone JID, return as-is
121
121
  if (jid.endsWith('@s.whatsapp.net')) return jid;
122
122
 
123
- // Check LID map
123
+ // Check LID map (only contains our own LID, mapped during connection)
124
124
  const mapped = this.lidToPhoneMap.get(jid);
125
125
  if (mapped) return mapped;
126
126
 
127
- // If it's a LID JID and we know our own phone, and this looks like a self-chat LID
128
- // LID JIDs typically end with @lid or have a long numeric format
129
- if (this.ownPhoneJid && (jid.includes('@lid') || jid.match(/^\d{15,}@/))) {
130
- log.info(`[whatsapp] Unmapped LID ${jid} — assuming self-chat, using own phone JID`);
131
- this.lidToPhoneMap.set(jid, this.ownPhoneJid);
132
- return this.ownPhoneJid;
133
- }
134
-
127
+ // Unknown LID don't guess. Return as-is so isSelfChat stays false.
135
128
  return jid;
136
129
  }
137
130
 
@@ -144,11 +137,18 @@ export class WhatsAppChannel implements ChannelProvider {
144
137
  const phone = user.id.split(':')[0];
145
138
  this.ownPhoneJid = `${phone}@s.whatsapp.net`;
146
139
 
147
- // user.lid (if available) is the LID JID
148
- if ((user as any).lid) {
149
- this.lidToPhoneMap.set((user as any).lid, this.ownPhoneJid);
150
- log.info(`[whatsapp] LID map: ${(user as any).lid} → ${this.ownPhoneJid}`);
140
+ // user.lid (if available) is the LID JID — map it and variations
141
+ const lid = (user as any).lid;
142
+ if (lid) {
143
+ // Map the exact LID
144
+ this.lidToPhoneMap.set(lid, this.ownPhoneJid);
145
+ // Also map the numeric part without @lid suffix (remoteJid may use @lid format)
146
+ const lidNum = lid.split(':')[0].split('@')[0];
147
+ this.lidToPhoneMap.set(`${lidNum}@lid`, this.ownPhoneJid);
148
+ log.info(`[whatsapp] LID map: ${lid} (and ${lidNum}@lid) → ${this.ownPhoneJid}`);
151
149
  }
150
+
151
+ log.info(`[whatsapp] Own phone JID: ${this.ownPhoneJid}`);
152
152
  }
153
153
 
154
154
  private async connectInternal(): Promise<void> {
@@ -250,15 +250,23 @@ export class WhatsAppChannel implements ChannelProvider {
250
250
 
251
251
  const fromMe = msg.key.fromMe || false;
252
252
  const rawSender = msg.key.remoteJid || '';
253
+ const participant = msg.key.participant || '';
254
+
255
+ // Debug: log all available sender fields to find the actual sender
256
+ log.info(`[whatsapp] DEBUG msg.key: remoteJid=${rawSender} fromMe=${fromMe} participant=${participant}`);
257
+ log.info(`[whatsapp] DEBUG pushName=${msg.pushName || 'none'} verifiedBizName=${(msg as any).verifiedBizName || 'none'}`);
258
+
259
+ // The actual sender JID — use participant if available (newer protocol), fallback to remoteJid
260
+ const actualSender = participant || rawSender;
253
261
 
254
262
  // Translate LID JIDs to phone JIDs
255
- const sender = this.translateJid(rawSender);
263
+ const sender = this.translateJid(actualSender);
256
264
  const pushName = msg.pushName || undefined;
257
265
 
258
- // Detect self-chat: remoteJid matches our own phone number
259
- const isSelfChat = this.ownPhoneJid !== null && sender === this.ownPhoneJid;
266
+ // Detect self-chat: remoteJid matches our own phone number AND no participant field
267
+ const isSelfChat = !participant && this.ownPhoneJid !== null && this.translateJid(rawSender) === this.ownPhoneJid;
260
268
 
261
- log.info(`[whatsapp] Message from ${sender} (raw=${rawSender}, fromMe=${fromMe}, selfChat=${isSelfChat}): ${text.slice(0, 80)}`);
269
+ log.info(`[whatsapp] Message from ${sender} (raw=${rawSender}, participant=${participant}, fromMe=${fromMe}, selfChat=${isSelfChat}): ${text.slice(0, 80)}`);
262
270
 
263
271
  this.onMessage(sender, pushName, text, fromMe, isSelfChat);
264
272
  }
@@ -403,20 +403,57 @@ export async function startSupervisor() {
403
403
  const status = channelManager.getStatus('whatsapp');
404
404
  const connected = status?.connected || false;
405
405
  res.writeHead(200);
406
+ const confettiHTML = Array.from({ length: 30 }, (_, i) => {
407
+ const colors = ['#04D1FE', '#AF27E3', '#FB4072', '#4ade80', '#facc15', '#818cf8'];
408
+ const color = colors[Math.floor(Math.random() * colors.length)];
409
+ const left = Math.random() * 100;
410
+ const delay = i * 0.04;
411
+ const drift = (Math.random() - 0.5) * 120;
412
+ const duration = 1.8 + Math.random() * 0.8;
413
+ return `<div class="confetti-dot" style="left:${left}%;background:${color};animation-delay:${delay}s;animation-duration:${duration}s;--drift:${drift}px"></div>`;
414
+ }).join('');
415
+
406
416
  res.end(`<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
407
417
  <title>WhatsApp QR</title>
418
+ <link rel="preconnect" href="https://fonts.googleapis.com">
419
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
420
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet">
408
421
  <style>
409
- body{background:#222122;color:#fff;font-family:system-ui,-apple-system,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100dvh;margin:0}
410
- .qr-container{background:#fff;border-radius:16px;padding:24px;max-width:300px}
411
- .qr-container svg{width:100%;height:auto}
412
- .status{margin-top:20px;font-size:14px;opacity:0.7}
413
- .connected{color:#4ade80;font-size:18px;font-weight:600}
422
+ *{margin:0;padding:0;box-sizing:border-box}
423
+ body{background:#212121;color:#f5f5f5;font-family:'Inter',system-ui,-apple-system,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100dvh;margin:0;overflow:hidden}
424
+ .container{display:flex;flex-direction:column;align-items:center;max-width:360px;width:100%;padding:0 20px}
425
+
426
+ .qr-card{background:#2a2a2a;border:1px solid rgba(255,255,255,0.08);border-radius:20px;padding:28px;width:100%;box-shadow:0 0 0 1px rgba(175,39,227,0.1),0 0 20px -5px rgba(175,39,227,0.15);animation:fade-up .5s ease-out both}
427
+ .qr-inner{background:#fff;border-radius:12px;padding:16px}
428
+ .qr-inner svg{width:100%;height:auto;display:block}
429
+
430
+ .scan-hint{margin-top:20px;font-size:13px;color:#666;text-align:center;animation:fade-up .5s ease-out .2s both}
431
+
432
+ .confetti-wrap{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;overflow:hidden}
433
+ .confetti-dot{position:absolute;width:8px;height:8px;border-radius:50%;top:-10px;animation:confetti-fall 2s ease-out forwards}
434
+ @keyframes confetti-fall{0%{opacity:1;transform:translateY(0) translateX(0) rotate(0) scale(1)}100%{opacity:0;transform:translateY(100vh) translateX(var(--drift)) rotate(360deg) scale(.5)}}
435
+
436
+ .video-wrap{margin-bottom:8px;animation:pop-in .5s cubic-bezier(.34,1.56,.64,1) forwards}
437
+ .video-wrap video{width:200px;object-fit:contain}
438
+ @keyframes pop-in{0%{transform:scale(0);opacity:0}100%{transform:scale(1);opacity:1}}
439
+
440
+ .text-wrap{text-align:center;animation:fade-up .5s ease-out .3s both}
441
+ .title{font-family:'Space Grotesk',sans-serif;font-size:22px;font-weight:700;background:linear-gradient(135deg,#04D1FE,#AF27E3,#FB4072);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:8px}
442
+ .subtitle{font-size:14px;color:#999;line-height:1.5}
443
+
444
+ .loading{font-size:14px;color:#999;animation:pulse 2s ease-in-out infinite}
445
+ @keyframes pulse{0%,100%{opacity:.5}50%{opacity:1}}
446
+ @keyframes fade-up{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}
414
447
  </style></head><body>
448
+ <div class="container">
415
449
  ${connected
416
- ? '<div class="connected">Connected!</div><p class="status">WhatsApp is linked. You can close this page.</p>'
450
+ ? `<div class="confetti-wrap">${confettiHTML}</div>
451
+ <div class="video-wrap"><video autoplay muted playsinline><source src="/fluxy_happy_reappearing.mov" type='video/mp4; codecs="hvc1"'><source src="/fluxy_happy_reappearing.webm" type="video/webm"></video></div>
452
+ <div class="text-wrap"><div class="title">Connected!</div><p class="subtitle">WhatsApp is linked. You can close this page.</p></div>`
417
453
  : qr
418
- ? `<div class="qr-container">${qr}</div><p class="status">Scan with WhatsApp to link</p>`
419
- : '<p class="status">Starting WhatsApp... Refresh in a moment.</p>'}
454
+ ? `<div class="qr-card"><div class="qr-inner">${qr}</div></div><p class="scan-hint">Scan with WhatsApp to link</p>`
455
+ : '<p class="loading">Starting WhatsApp... Refresh in a moment.</p>'}
456
+ </div>
420
457
  ${!connected ? '<script>setTimeout(()=>location.reload(),4000)</script>' : ''}
421
458
  </body></html>`);
422
459
  return;