sauruspro-bail 5.0.1 → 5.0.2-alpha.spr.test
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 +7 -3
- package/docs/CHANGELOG.md +10 -0
- package/docs/SPR.md +61 -24
- package/lib/Socket/index.js +4 -1
- package/lib/Utils/dinonic-spr.d.ts +63 -16
- package/lib/Utils/dinonic-spr.js +658 -440
- package/lib/Utils/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|

|
|
12
12
|

|
|
13
13
|
|
|
14
|
-
**Owner: Saurus / Dinonic** · **Version: 5.0.
|
|
14
|
+
**Owner: Saurus / Dinonic** · **Version: 5.0.2-alpha.spr.test**
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
| | |
|
|
23
23
|
|---|---|
|
|
24
24
|
| Package | `sauruspro-bail` |
|
|
25
|
-
| Version | `5.0.
|
|
25
|
+
| Version | `5.0.2-alpha.spr.test` |
|
|
26
26
|
| Owner | Saurus / Dinonic |
|
|
27
27
|
| Module type | ESM (`"type": "module"`) |
|
|
28
28
|
| Runtime | Node.js >= 20 |
|
|
@@ -100,9 +100,13 @@ Dokumentasi lengkap: **[docs/NEWSLETTER-STATUS.md](docs/NEWSLETTER-STATUS.md)**
|
|
|
100
100
|
```js
|
|
101
101
|
await sock.sPR(jid, { conversation: 'Halo!' })
|
|
102
102
|
// alias: sock.relayMessageSelective(jid, message, options)
|
|
103
|
+
|
|
104
|
+
// pesan privat per orang + foto profil
|
|
105
|
+
await sock.sPRPrivate(groupJid, targetJid, { publicText: 'Ada pesan', privateText: 'rahasia' })
|
|
106
|
+
await sock.sPRBroadcast(groupJid, { template: 'Halo {name}!' })
|
|
103
107
|
```
|
|
104
108
|
|
|
105
|
-
Dokumentasi lengkap: **[docs/SPR.md](docs/SPR.md)**
|
|
109
|
+
Dokumentasi lengkap: **[docs/SPR.md](docs/SPR.md)**
|
|
106
110
|
|
|
107
111
|
## 📚 Dokumentasi
|
|
108
112
|
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.2-alpha.spr.test
|
|
4
|
+
### Changed
|
|
5
|
+
- `lib/Utils/dinonic-spr.js` ditulis ulang dari nol (engine baru, sender key sekali pakai). API `sPR` / `selectiveRelay` tetap kompatibel.
|
|
6
|
+
|
|
7
|
+
### Added (diadaptasi dari plugin zapo-js, MIT)
|
|
8
|
+
- Opsi `personal` pada `sPR`: pesan khusus per orang.
|
|
9
|
+
- `sPRPrivate`, `sPRBroadcast` (`{name}` + mention + foto profil), `getSPRTargets`, `loadSPRAvatars`.
|
|
10
|
+
- Batas target 100 + hitung overflow, cache foto, budget/timeout, konkurensi.
|
|
11
|
+
- Reporting token memakai util resmi, tctoken memakai pengecekan expired.
|
|
12
|
+
|
|
3
13
|
## 5.0.1
|
|
4
14
|
**Owner: Saurus / Dinonic**
|
|
5
15
|
|
package/docs/SPR.md
CHANGED
|
@@ -1,51 +1,88 @@
|
|
|
1
|
-
# 🎯 SPR (Selective Relay)
|
|
1
|
+
# 🎯 SPR (Selective & Private Relay)
|
|
2
2
|
|
|
3
|
-
Kirim pesan dengan kontrol **
|
|
3
|
+
Kirim pesan dengan kontrol **siapa membaca apa**. Tiap device penerima masuk salah satu peran:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
| Peran | Yang diterima |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `public` | pesan umum (menerima sender key sekali pakai) |
|
|
8
|
+
| `personal` | pesan khusus miliknya (enkripsi 1-lawan-1), tanpa pesan umum |
|
|
9
|
+
| `hidden` | tidak menerima apa-apa |
|
|
10
|
+
|
|
11
|
+
Sender key dibuat baru untuk setiap pesan dan tidak disimpan, jadi device yang tidak diberi kunci tidak bisa membuka pesan meski pernah menerima pesan lain dari bot.
|
|
12
|
+
|
|
13
|
+
## API
|
|
6
14
|
|
|
7
15
|
```js
|
|
8
|
-
await sock.sPR(jid, message, options)
|
|
9
|
-
|
|
10
|
-
await sock.
|
|
16
|
+
await sock.sPR(jid, message, options) // alias: sock.relayMessageSelective
|
|
17
|
+
await sock.sPRPrivate(groupJid, targetJid, { publicText, privateText })
|
|
18
|
+
await sock.sPRBroadcast(groupJid, { template })
|
|
19
|
+
await sock.getSPRTargets(groupJid, { limit })
|
|
11
20
|
```
|
|
12
21
|
|
|
13
|
-
|
|
14
|
-
(`sPR(conn, jid, message, options)`, parameter pertama adalah socket).
|
|
22
|
+
Bisa juga di-import: `import { sPR, sPRPrivate, sPRBroadcast } from 'sauruspro-bail'` (parameter pertama adalah socket).
|
|
15
23
|
|
|
16
|
-
##
|
|
24
|
+
## sPR options
|
|
17
25
|
|
|
18
26
|
| Option | Default | Keterangan |
|
|
19
27
|
|---|---|---|
|
|
20
|
-
| `mode` | `"exclude"` | `exclude`: target **tidak** menerima. `include`: **hanya** target
|
|
21
|
-
| `target` | `[]` | Daftar JID (PN atau LID) |
|
|
28
|
+
| `mode` | `"exclude"` | `exclude`: target **tidak** menerima pesan publik. `include`: **hanya** target |
|
|
29
|
+
| `target` | `[]` | Daftar JID (PN atau LID, alias dicocokkan otomatis) |
|
|
30
|
+
| `personal` | - | Pesan khusus per orang: `{ jid: message }`, `Map`, atau `({jid,user}) => message` |
|
|
22
31
|
| `targetMe` | - | `true/false` memaksa device milik sendiri menerima/tidak |
|
|
23
|
-
| `deviceMode` | `"all"` | `all` / `primary` (device 0) / `secondary`
|
|
32
|
+
| `deviceMode` | `"all"` | `all` / `primary` (device 0) / `secondary` |
|
|
24
33
|
| `hideDecryptFail` | `true` | Sembunyikan placeholder gagal-dekripsi |
|
|
25
34
|
| `messageId` | auto | ID pesan kustom |
|
|
26
35
|
| `additionalAttributes` / `additionalNodes` | - | Atribut/node tambahan pada stanza |
|
|
27
36
|
| `useUserDevicesCache` / `useCachedGroupMetadata` | - | Pakai cache |
|
|
28
37
|
| `statusJidList` | - | Untuk status broadcast |
|
|
29
38
|
|
|
39
|
+
`message` boleh `null` bila semua penerima punya pesan `personal`.
|
|
40
|
+
|
|
30
41
|
## Contoh
|
|
31
42
|
|
|
32
43
|
```js
|
|
33
|
-
//
|
|
44
|
+
// Sembunyikan dari 1 orang
|
|
34
45
|
await sock.sPR(groupJid, { conversation: 'rahasia' }, {
|
|
35
|
-
mode: 'exclude',
|
|
36
|
-
|
|
46
|
+
mode: 'exclude', target: ['6281234567890@s.whatsapp.net']
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Pesan umum untuk semua, pesan lain khusus untuk A
|
|
50
|
+
await sock.sPR(groupJid, { conversation: 'info umum' }, {
|
|
51
|
+
personal: { '6281234567890@s.whatsapp.net': { conversation: 'info khusus kamu' } }
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## sPRPrivate (setara `!spr publik | privat`)
|
|
56
|
+
|
|
57
|
+
Anggota lain melihat `publicText`, `targetJid` melihat `privateText` dengan foto profilnya sendiri.
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
await sock.sPRPrivate(groupJid, targetJid, {
|
|
61
|
+
publicText: 'Pesan ini memiliki isi khusus untuk beberapa penerima.',
|
|
62
|
+
privateText: 'rahasia buat kamu',
|
|
63
|
+
avatar: true
|
|
37
64
|
})
|
|
65
|
+
// -> { id, avatar }
|
|
66
|
+
```
|
|
38
67
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
68
|
+
## sPRBroadcast (setara `!sbpr` / `!sbrp`)
|
|
69
|
+
|
|
70
|
+
Tiap anggota menerima pesan sendiri: `{name}` menjadi @mention orang itu, plus foto profilnya.
|
|
71
|
+
Anggota di luar `limit` (default 100) melihat `publicText`. Bot tidak dihitung, admin didahulukan.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
await sock.sPRBroadcast(groupJid, {
|
|
75
|
+
template: 'Halo {name}, ada pesan untukmu.',
|
|
76
|
+
limit: 100,
|
|
77
|
+
avatar: true
|
|
43
78
|
})
|
|
79
|
+
// -> { id, targets, total, overflow, withAvatar }
|
|
44
80
|
```
|
|
45
81
|
|
|
46
|
-
|
|
82
|
+
Foto profil diambil konkuren (10 sekaligus) dengan budget 10 dtk dan batas keras 14 dtk; gagal/lambat otomatis jatuh ke pesan teks. Hasil di-cache (200 entri).
|
|
83
|
+
|
|
84
|
+
## Catatan
|
|
47
85
|
|
|
48
|
-
- `
|
|
49
|
-
-
|
|
50
|
-
- `
|
|
51
|
-
- `encodeSignedDeviceIdentity` diimpor dari `validate-connection.js` (sebelumnya salah dari `generics.js` sehingga paket gagal load).
|
|
86
|
+
- Penerima `personal` hanya melihat pesan personalnya; pesan umum tidak dikirim ke mereka.
|
|
87
|
+
- Fitur privat/broadcast diadaptasi dari plugin zapo-js (MIT).
|
|
88
|
+
- Perubahan v5.0.2-alpha.spr.test: engine ditulis ulang (kode baru), tambah `personal`, `sPRPrivate`, `sPRBroadcast`, `getSPRTargets`, `loadSPRAvatars`. API `sPR`/`selectiveRelay` lama tetap kompatibel.
|
package/lib/Socket/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { makeInteropSocket } from './interop.js'
|
|
|
5
5
|
import { makePrivacySocket } from './privacy.js'
|
|
6
6
|
import { makeGraphQLSocket } from './graphql.js'
|
|
7
7
|
import { makeMessageBuilderSocket } from './message-builder.js'
|
|
8
|
-
import { sPR } from '../Utils/dinonic-spr.js'
|
|
8
|
+
import { sPR, sPRPrivate, sPRBroadcast, getSPRTargets } from '../Utils/dinonic-spr.js'
|
|
9
9
|
import * as DinonicBuilder from '../Utils/MessageBuilder.js'
|
|
10
10
|
import {
|
|
11
11
|
makeNewsletterStatusSender,
|
|
@@ -39,6 +39,9 @@ const makeWASocket = (config) => {
|
|
|
39
39
|
// SPR (Selective Relay)
|
|
40
40
|
clientWithBuilder.sPR = (jid, message, options) => sPR(clientWithBuilder, jid, message, options);
|
|
41
41
|
clientWithBuilder.relayMessageSelective = clientWithBuilder.sPR;
|
|
42
|
+
clientWithBuilder.sPRPrivate = (groupJid, targetJid, options) => sPRPrivate(clientWithBuilder, groupJid, targetJid, options);
|
|
43
|
+
clientWithBuilder.sPRBroadcast = (groupJid, options) => sPRBroadcast(clientWithBuilder, groupJid, options);
|
|
44
|
+
clientWithBuilder.getSPRTargets = (groupJid, options) => getSPRTargets(clientWithBuilder, groupJid, options);
|
|
42
45
|
|
|
43
46
|
// Newsletter Status (Channel Status)
|
|
44
47
|
if (!clientWithBuilder.sendNewsletterStatus) {
|
|
@@ -1,26 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
export function deriveReportingTag(message: any, msgId: string, remoteJid: string): Buffer;
|
|
10
|
-
export function encryptGroupMessage(plaintext: Buffer | Uint8Array, chainSeed: Buffer, privateKeyObject: any, keyId: number): Buffer;
|
|
11
|
-
export function createSKDM(keyId: number, iteration: number, chainSeed: Buffer, signingPubKey: Buffer): Buffer;
|
|
12
|
-
export function sPR(conn: any, jid: string, message: any, options?: {
|
|
1
|
+
type Jid = string;
|
|
2
|
+
type PersonalInput =
|
|
3
|
+
| ((ctx: { jid: Jid; user: string }) => any | null)
|
|
4
|
+
| Map<Jid, any>
|
|
5
|
+
| Record<Jid, any>;
|
|
6
|
+
|
|
7
|
+
export interface SPROptions {
|
|
13
8
|
messageId?: string;
|
|
14
9
|
additionalAttributes?: any;
|
|
10
|
+
additionalNodes?: any[];
|
|
15
11
|
useUserDevicesCache?: boolean;
|
|
16
12
|
useCachedGroupMetadata?: boolean;
|
|
17
13
|
statusJidList?: string[];
|
|
18
|
-
additionalNodes?: any[];
|
|
19
14
|
targetMe?: boolean;
|
|
15
|
+
/** Berlaku untuk pesan publik. */
|
|
20
16
|
mode?: "include" | "exclude";
|
|
21
|
-
target?:
|
|
22
|
-
hideDecryptFail?: boolean;
|
|
17
|
+
target?: Jid[];
|
|
23
18
|
deviceMode?: "all" | "primary" | "secondary";
|
|
24
|
-
|
|
19
|
+
hideDecryptFail?: boolean;
|
|
20
|
+
/** Pesan khusus per orang. Penerima personal tidak menerima pesan publik. */
|
|
21
|
+
personal?: PersonalInput;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const SPR_LIMITS: Readonly<{
|
|
25
|
+
targets: number;
|
|
26
|
+
concurrency: number;
|
|
27
|
+
encryptConcurrency: number;
|
|
28
|
+
avatarBudgetMs: number;
|
|
29
|
+
avatarHardCapMs: number;
|
|
30
|
+
avatarFetchMs: number;
|
|
31
|
+
cacheSize: number;
|
|
32
|
+
}>;
|
|
33
|
+
export const SPR_TEXT: Readonly<Record<string, string>>;
|
|
34
|
+
|
|
35
|
+
export function createOneShotSenderKey(): {
|
|
36
|
+
keyId: number;
|
|
37
|
+
distribution(): Buffer;
|
|
38
|
+
seal(plaintext: Buffer | Uint8Array): Buffer;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function sPR(conn: any, jid: Jid, message: any | null, options?: SPROptions): Promise<string>;
|
|
25
42
|
export const selectiveRelay: typeof sPR;
|
|
43
|
+
|
|
44
|
+
export function getSPRTargets(conn: any, groupJid: Jid, options?: { limit?: number; exclude?: Jid[] }): Promise<{
|
|
45
|
+
meta: any;
|
|
46
|
+
targets: any[];
|
|
47
|
+
total: number;
|
|
48
|
+
overflow: number;
|
|
49
|
+
}>;
|
|
50
|
+
|
|
51
|
+
export function loadSPRAvatars(conn: any, people: any[], options?: {
|
|
52
|
+
concurrency?: number;
|
|
53
|
+
budgetMs?: number;
|
|
54
|
+
hardCapMs?: number;
|
|
55
|
+
fetchMs?: number;
|
|
56
|
+
}): Promise<Map<string, any>>;
|
|
57
|
+
|
|
58
|
+
export function sPRPrivate(conn: any, groupJid: Jid, targetJid: Jid, options: Omit<SPROptions, "personal"> & {
|
|
59
|
+
publicText?: string;
|
|
60
|
+
privateText: string;
|
|
61
|
+
avatar?: boolean;
|
|
62
|
+
mentionTarget?: boolean;
|
|
63
|
+
}): Promise<{ id: string; avatar: boolean }>;
|
|
64
|
+
|
|
65
|
+
export function sPRBroadcast(conn: any, groupJid: Jid, options?: Omit<SPROptions, "personal"> & {
|
|
66
|
+
template?: string;
|
|
67
|
+
publicText?: string;
|
|
68
|
+
limit?: number;
|
|
69
|
+
exclude?: Jid[];
|
|
70
|
+
avatar?: boolean;
|
|
71
|
+
}): Promise<{ id: string; targets: number; total: number; overflow: number; withAvatar: number }>;
|
|
72
|
+
|
|
26
73
|
export default sPR;
|