nothing-qrcpp 1.0.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/README.md +99 -0
- package/index.d.ts +41 -0
- package/index.js +81 -0
- package/package.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# nothing-qrcpp
|
|
2
|
+
|
|
3
|
+
Typed event callbacks and manual control API for the C++ QR detector built into the Nothing Browser binary (`PiggyQRDetector`).
|
|
4
|
+
|
|
5
|
+
The detector runs **automatically** — you do not need this package to receive QR events. It exists for discoverability, typed callbacks, and the `site.qr` control API.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install nothing-qrcpp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
const piggy = require('nothing-browser').default;
|
|
21
|
+
const qrcpp = require('nothing-qrcpp');
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
|
|
24
|
+
await piggy.launch({ mode: 'tab', binary: 'headless' });
|
|
25
|
+
await piggy.register('whatsapp', 'https://web.whatsapp.com', { single: true });
|
|
26
|
+
|
|
27
|
+
await piggy.extend(
|
|
28
|
+
qrcpp({
|
|
29
|
+
onQR: (d) => console.log(`Scan this QR (attempt ${d.attempts}):`, d.qrData),
|
|
30
|
+
onScanned: () => console.log('Authenticated!'),
|
|
31
|
+
onTimeout: () => console.log('QR rotated — new one incoming...'),
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
await piggy.whatsapp.navigate();
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Without this package
|
|
39
|
+
|
|
40
|
+
If you don't want the dependency, you can listen directly — the C++ emits these events regardless:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
piggy.whatsapp.on('qr', (d) => console.log('Scan:', d.qrData));
|
|
44
|
+
piggy.whatsapp.on('qr:scanned', () => console.log('Done!'));
|
|
45
|
+
piggy.whatsapp.on('qr:timeout', () => console.log('Rotated'));
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Options
|
|
51
|
+
|
|
52
|
+
| Option | Type | When called |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `onQR` | `function` | New or rotated QR is ready. `data.qrData` is `"data:image/png;base64,..."` |
|
|
55
|
+
| `onScanned` | `function` | QR scanned, WAWeb authenticated |
|
|
56
|
+
| `onTimeout` | `function` | QR expired and rotated (~every 20s) |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Events
|
|
61
|
+
|
|
62
|
+
| Event | Data | When |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `qr` | `{ tabId, qrData, attempts }` | New QR ready — `qrData` is a base64 PNG data URL |
|
|
65
|
+
| `qr:scanned` | `{ tabId }` | Canvas disappeared — auth succeeded |
|
|
66
|
+
| `qr:timeout` | `{ tabId }` | QR rotated before being scanned |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## API (`site.qr`)
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
// Check current QR state
|
|
74
|
+
const state = await piggy.whatsapp.qr.status();
|
|
75
|
+
// { waiting: true, attempts: 2 }
|
|
76
|
+
|
|
77
|
+
// Force an immediate canvas check (skips the 500ms poll interval)
|
|
78
|
+
await piggy.whatsapp.qr.force();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## How the C++ detector works
|
|
84
|
+
|
|
85
|
+
- Polls the page every 500ms for a `<canvas>` matching known WAWeb QR selectors
|
|
86
|
+
- Extracts the canvas as a base64 PNG via `canvas.toDataURL()`
|
|
87
|
+
- Hashes the image to detect rotation — only emits `qr` when the image actually changes
|
|
88
|
+
- Prints the QR to the terminal automatically using iTerm2/Kitty inline image protocol with a plain data URL fallback
|
|
89
|
+
- When the canvas disappears, emits `qr:scanned` and stops polling
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Notes
|
|
94
|
+
|
|
95
|
+
- To force a fresh QR scan: call `site.storage.clear()` before navigating (requires `nothing-innerstorage`)
|
|
96
|
+
- This plugin was made upon request — report any issues found
|
|
97
|
+
- This plugin is tailored specifically for WhatsApp sessions. You can use it on other sites but there is no guarantee it will work, and that is not a bug. A general-purpose `nothing-storage` plugin will be released in the future to solve that
|
|
98
|
+
- `qrData` is a `data:image/png;base64,...` URL — render it in a browser, pass it to a QR library, or display it in the terminal. The C++ already prints it automatically
|
|
99
|
+
- The QR is canvas-based in WAWeb — there is no `<img>` tag. Do not try to read it with `find.css()` or `provide.text()`
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface QRCppOptions {
|
|
2
|
+
/** Called when a new or rotated QR code is ready to scan. */
|
|
3
|
+
onQR?: (data: { tabId: string; qrData: string; attempts: number }) => void;
|
|
4
|
+
/** Called when the QR is scanned and WhatsApp Web authenticates successfully. */
|
|
5
|
+
onScanned?: (data: { tabId: string }) => void;
|
|
6
|
+
/** Called when the QR expires and rotates before being scanned (~every 20s). */
|
|
7
|
+
onTimeout?: (data: { tabId: string }) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface QRApi {
|
|
11
|
+
/** Check whether C++ is waiting for a QR scan and how many have been shown. */
|
|
12
|
+
status(): Promise<{ waiting: boolean; attempts: number }>;
|
|
13
|
+
/** Force an immediate canvas check without waiting for the next poll interval. */
|
|
14
|
+
force(): Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* nothing-qrcpp plugin factory.
|
|
19
|
+
*
|
|
20
|
+
* The QR detector runs automatically inside the binary — this package adds
|
|
21
|
+
* typed event callbacks and the `site.qr` API for manual control.
|
|
22
|
+
*
|
|
23
|
+
* ```js
|
|
24
|
+
* await piggy.extend(qrcpp({
|
|
25
|
+
* onQR: (d) => console.log('Scan this:', d.qrData),
|
|
26
|
+
* onScanned: () => console.log('Authenticated!'),
|
|
27
|
+
* onTimeout: () => console.log('QR rotated, new one incoming...'),
|
|
28
|
+
* }));
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare function qrcpp(opts?: QRCppOptions): (site: any) => Promise<any>;
|
|
32
|
+
|
|
33
|
+
export default qrcpp;
|
|
34
|
+
export = qrcpp;
|
|
35
|
+
|
|
36
|
+
declare module 'nothing-browser' {
|
|
37
|
+
interface PiggySite {
|
|
38
|
+
/** QR code control API — added by nothing-qrcpp */
|
|
39
|
+
qr: QRApi;
|
|
40
|
+
}
|
|
41
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// nothing-qrcpp
|
|
4
|
+
// Wraps the C++ PiggyQRDetector built into the Nothing Browser binary.
|
|
5
|
+
// The QR detector runs automatically — no activation needed.
|
|
6
|
+
// This package is a thin event/API wrapper for discoverability and convenience.
|
|
7
|
+
//
|
|
8
|
+
// C++ events this listens for:
|
|
9
|
+
// qr { tabId, qrData, attempts } — new or rotated QR ready to scan
|
|
10
|
+
// qr:scanned { tabId } — QR canvas disappeared, auth done
|
|
11
|
+
// qr:timeout { tabId } — QR rotated (~every 20s), new one incoming
|
|
12
|
+
//
|
|
13
|
+
// C++ commands this sends:
|
|
14
|
+
// qr.status {} → { waiting: bool, attempts: int }
|
|
15
|
+
// qr.force {} → "qr check triggered"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} opts
|
|
19
|
+
* @param {function} [opts.onQR] Called when a new QR code is ready. Receives { tabId, qrData, attempts }.
|
|
20
|
+
* @param {function} [opts.onScanned] Called when the QR is scanned and auth succeeds.
|
|
21
|
+
* @param {function} [opts.onTimeout] Called when the QR rotates before being scanned.
|
|
22
|
+
* @returns {function} Plugin installer — pass to piggy.extend() or call manually.
|
|
23
|
+
*/
|
|
24
|
+
module.exports = function qrcpp(opts) {
|
|
25
|
+
opts = opts || {};
|
|
26
|
+
|
|
27
|
+
return async function install(site) {
|
|
28
|
+
if (!site || typeof site.on !== 'function') {
|
|
29
|
+
throw new Error(
|
|
30
|
+
'[nothing-qrcpp] install() received an invalid site object. ' +
|
|
31
|
+
'Make sure you registered the site with { single: true } and called piggy.extend() after piggy.register().'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof site._send !== 'function') {
|
|
36
|
+
throw new Error(
|
|
37
|
+
'[nothing-qrcpp] site._send is not available. ' +
|
|
38
|
+
'Use piggy.extend() to install plugins — it wires _send automatically. ' +
|
|
39
|
+
'If installing manually, attach site._send before calling install().'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── Event listeners ──────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
site.on('qr', function(data) {
|
|
46
|
+
if (typeof opts.onQR === 'function') opts.onQR(data);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
site.on('qr:scanned', function(data) {
|
|
50
|
+
if (typeof opts.onScanned === 'function') opts.onScanned(data);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
site.on('qr:timeout', function(data) {
|
|
54
|
+
if (typeof opts.onTimeout === 'function') opts.onTimeout(data);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ── Attach API to site ───────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
site.qr = {
|
|
60
|
+
/**
|
|
61
|
+
* Check whether the C++ detector is currently waiting for a QR scan
|
|
62
|
+
* and how many QR codes have been shown this session.
|
|
63
|
+
* @returns {Promise<{ waiting: boolean, attempts: number }>}
|
|
64
|
+
*/
|
|
65
|
+
status: function() {
|
|
66
|
+
return site._send('qr.status', {});
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Force the C++ detector to run a canvas check immediately,
|
|
71
|
+
* without waiting for the next poll interval (500ms).
|
|
72
|
+
* @returns {Promise<string>}
|
|
73
|
+
*/
|
|
74
|
+
force: function() {
|
|
75
|
+
return site._send('qr.force', {});
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return site;
|
|
80
|
+
};
|
|
81
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nothing-qrcpp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "nothing-browser plugin — typed event wrapper and control API for the C++ PiggyQRDetector built into the Nothing Browser binary",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": ["nothing-browser", "piggy", "whatsapp", "qr", "qrcode", "plugin"],
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"nothing-browser": "*"
|
|
11
|
+
}
|
|
12
|
+
}
|