lenwy-whatsmeow 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 ADDED
@@ -0,0 +1,407 @@
1
+ # ☘️ lenwy-whatsmeow
2
+
3
+ **lenwy-whatsmeow** adalah library WhatsApp API untuk Node.js dengan performa tinggi. Library ini punya gaya pemakaian (developer experience) yang mirip **Baileys** (`makeWASocket`, `ev.on`, `sendMessage`, dll), tapi di balik layar, seluruh koneksi ke WhatsApp ditangani oleh engine **Go (`whatsmeow`)** yang jauh lebih ringan dan cepat.
4
+
5
+ Jadi kamu tetap menulis kode dengan sintaks yang familiar, tapi mendapat keuntungan kecepatan & efisiensi memori dari Go.
6
+
7
+ ---
8
+
9
+ ## Kenapa Pakai lenwy-whatsmeow?
10
+
11
+ - **Sintaks familiar** — kalau kamu pernah pakai Baileys, kamu tidak perlu belajar API baru dari nol.
12
+ - **Ringan & cepat** — koneksi WebSocket ke WhatsApp ditangani oleh Go, bukan JavaScript.
13
+ - **Auto reconnect** — kalau internet putus, koneksi otomatis dipulihkan tanpa perlu scan ulang.
14
+ - **Aman untuk sesi** — proses shutdown (`Ctrl+C`, dsb) ditangani dengan baik supaya database sesi tidak corrupt.
15
+ - **Fitur media siap pakai** — kirim/download media, convert ke voice note, buat stiker (statis & animasi), kompres gambar, sampai ubah stiker balik jadi gambar/video — semua sudah dibungkus jadi satu perintah.
16
+
17
+ ---
18
+
19
+ ## Instalasi
20
+
21
+ Install library langsung via NPM atau Yarn:
22
+
23
+ ```bash
24
+ npm install lenwy-whatsmeow
25
+ ```
26
+
27
+ atau menggunakan Yarn:
28
+
29
+ ```Bash
30
+ yarn add lenwy-whatsmeow
31
+ ```
32
+ ## Zero Go Dependency (Siap Pakai di Pterodactyl)
33
+
34
+ Library ini tidak membutuhkan instalasi Go di server atau komputer kamu!
35
+
36
+ Binary hasil kompilasi Go untuk Linux (main_linux) dan Windows (main_win.exe) sudah dibundel langsung di dalam paket. Kamu bisa langsung menjalankannya di platform hosting berbasis Node.js seperti Pterodactyl (Egg Node.js), VPS, maupun komputer lokal tanpa setup tambahan.
37
+ Prasyarat
38
+
39
+ - Node.js: Versi LTS terbaru (v18+ disarankan).
40
+
41
+ - FFmpeg & Media Suite: Sudah ditangani otomatis lewat ffmpeg-static dan sharp bawaan paket (tidak perlu install FFmpeg secara manual).
42
+
43
+ ---
44
+
45
+ ## Mulai Cepat (Quick Start)
46
+
47
+ Berikut contoh dasar untuk menghubungkan bot ke WhatsApp:
48
+
49
+ ```javascript
50
+ import { makeWASocket } from "lenwy-whatsmeow";
51
+
52
+ const conn = makeWASocket({
53
+ sessionName: "my-session", // Nama sesi, bebas kamu tentukan
54
+ });
55
+
56
+ // Status koneksi
57
+ conn.ev.on("connection.update", (data) => {
58
+ if (data.reason === "connection_lost") {
59
+ console.log("⚠️ Koneksi terputus, mencoba menyambung ulang...");
60
+ }
61
+
62
+ if (data.open) {
63
+ console.log("✅ Berhasil terhubung ke WhatsApp!");
64
+ }
65
+ });
66
+
67
+ // Kode pairing (kalau login pakai nomor HP, bukan QR)
68
+ conn.ev.on("pairing_code", (code) => {
69
+ console.log("Kode Pairing Kamu:", code);
70
+ });
71
+
72
+ // Pesan masuk
73
+ conn.ev.on("messages.upsert", (m) => {
74
+ console.log("Pesan Masuk:", m);
75
+ });
76
+ ```
77
+
78
+ > **Catatan:** Nama fungsi/opsi seperti `sessionName` mengikuti pola umum yang dipakai di seluruh contoh dokumentasi ini.
79
+
80
+ ---
81
+
82
+ ## Mengirim Pesan
83
+
84
+ Semua jenis pesan dikirim lewat `conn.sendMessage(jid, content, options)`.
85
+
86
+ ```javascript
87
+ // Kirim Pesan Teks
88
+ await conn.sendMessage(jid, {
89
+ text: "Halo World",
90
+ });
91
+
92
+ // Kirim Gambar
93
+ await conn.sendMessage(jid, {
94
+ image: "./foto.jpg",
95
+ caption: "Deskripsi Gambar",
96
+ });
97
+
98
+ // Kirim Video
99
+ await conn.sendMessage(jid, {
100
+ video: "./video.mp4",
101
+ caption: "Deskripsi Video",
102
+ });
103
+
104
+ // Kirim Stiker
105
+ await conn.sendMessage(jid, {
106
+ sticker: "./stiker.webp",
107
+ });
108
+
109
+ // Kirim Audio Biasa
110
+ await conn.sendMessage(jid, {
111
+ audio: "./lagu.mp3",
112
+ });
113
+
114
+ // Kirim Voice Note (PTT)
115
+ await conn.sendMessage(jid, {
116
+ ptt: "./vn.ogg",
117
+ });
118
+
119
+ // Kirim Dokumen
120
+ await conn.sendMessage(jid, {
121
+ document: "./file.pdf",
122
+ fileName: "Modul_Belajar.pdf",
123
+ });
124
+
125
+ // Membalas Pesan (Quoted Reply)
126
+ await conn.sendMessage(
127
+ jid,
128
+ { text: "Ini balasan pesan" },
129
+ { quoted: m },
130
+ );
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Reaksi, Hapus, dan Edit Pesan
136
+
137
+ Untuk fitur ini, kamu butuh informasi pesan yang dibalas (`quoted message`). Gunakan helper `getQuotedInfo()` berikut untuk mengekstraknya dengan aman dari berbagai format struktur data:
138
+
139
+ ```javascript
140
+ function getQuotedInfo(m, meta, raw) {
141
+ const id =
142
+ meta?.quotedId ||
143
+ meta?.quotedID ||
144
+ meta?.quotedMessageId ||
145
+ meta?.quoted?.id ||
146
+ raw?.quotedId;
147
+
148
+ const participant =
149
+ meta?.quotedSender ||
150
+ meta?.quotedParticipant ||
151
+ meta?.quoted?.sender ||
152
+ raw?.quotedSender ||
153
+ "";
154
+
155
+ if (id) {
156
+ return { id, participant };
157
+ }
158
+
159
+ const deepSearch = (obj) => {
160
+ if (!obj || typeof obj !== "object") return null;
161
+
162
+ const stanza = obj.stanzaId || obj.stanzaID || obj.StanzaID;
163
+ if (stanza) {
164
+ return {
165
+ id: stanza,
166
+ participant: obj.participant || obj.Participant || "",
167
+ };
168
+ }
169
+
170
+ for (const k of Object.keys(obj)) {
171
+ if (typeof obj[k] === "object" && obj[k] !== null) {
172
+ const res = deepSearch(obj[k]);
173
+ if (res) return res;
174
+ }
175
+ }
176
+ return null;
177
+ };
178
+
179
+ return deepSearch(raw) || deepSearch(m);
180
+ }
181
+ ```
182
+
183
+ Setelah dapat `quoted`, kamu bisa langsung pakai:
184
+
185
+ ```javascript
186
+ const quoted = getQuotedInfo(m, meta, raw);
187
+
188
+ if (quoted) {
189
+ // Kasih reaksi emoji
190
+ await conn.react(jid, { id: quoted.id, participant: quoted.participant }, "☘️");
191
+
192
+ // Hapus pesan
193
+ await conn.deleteMessage(jid, { id: quoted.id, participant: quoted.participant });
194
+
195
+ // Edit pesan
196
+ await conn.editMessage(jid, { id: quoted.id }, "Pesan ini telah diperbarui");
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Manajemen Grup
203
+
204
+ ### Cek Info Grup & Status Admin Bot
205
+
206
+ ```javascript
207
+ const metadata = await conn.groupMetadata(groupJid);
208
+
209
+ console.log(metadata.subject); // Nama grup
210
+ console.log(metadata.isBotAdmin); // true / false
211
+ ```
212
+
213
+ ### Kelola Anggota
214
+
215
+ ```javascript
216
+ // Keluarkan anggota
217
+ await conn.groupParticipantsUpdate(groupJid, ["628xxx@s.whatsapp.net"], "remove");
218
+
219
+ // Jadikan admin
220
+ await conn.groupParticipantsUpdate(groupJid, ["628xxx@s.whatsapp.net"], "promote");
221
+
222
+ // Turunkan dari admin
223
+ await conn.groupParticipantsUpdate(groupJid, ["628xxx@s.whatsapp.net"], "demote");
224
+
225
+ // Tambah anggota
226
+ const res = await conn.groupParticipantsUpdate(groupJid, ["628xxx@s.whatsapp.net"], "add");
227
+
228
+ // Kalau target mengaktifkan privasi "siapa yang bisa menambahkanku ke grup",
229
+ // bot tidak bisa menambahkan secara langsung — kirim link undangan sebagai gantinya
230
+ if (res?.inviteRequired) {
231
+ console.log("Kirimkan link undangan ini:", res.inviteLink);
232
+ }
233
+ ```
234
+
235
+ ### Pengaturan Grup Lainnya
236
+
237
+ ```javascript
238
+ // Kunci grup (hanya admin yang bisa kirim pesan)
239
+ await conn.groupSettingUpdate(groupJid, "announcement");
240
+
241
+ // Buka kunci grup
242
+ await conn.groupSettingUpdate(groupJid, "not_announcement");
243
+
244
+ // Ganti nama grup
245
+ await conn.groupUpdateSubject(groupJid, "Nama Grup Baru");
246
+
247
+ // Ganti deskripsi grup
248
+ await conn.groupUpdateDescription(groupJid, "Deskripsi baru grup ini.");
249
+
250
+ // Ambil link undangan
251
+ const inviteLink = await conn.groupInviteCode(groupJid);
252
+
253
+ // Reset / buat link undangan baru
254
+ const newInviteLink = await conn.groupRevokeInviteCode(groupJid);
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Download Media
260
+
261
+ Gunakan `conn.downloadMedia()` untuk mengunduh gambar, video, stiker, audio, atau dokumen dari pesan yang dibalas.
262
+
263
+ ```javascript
264
+ const quoted = getQuotedInfo(m, meta, raw);
265
+
266
+ const res = await conn.downloadMedia(
267
+ { id: quoted.id },
268
+ "./downloads", // Folder tujuan
269
+ );
270
+
271
+ console.log(res.filePath); // Lokasi file
272
+ console.log(res.fileName); // Nama file
273
+ console.log(res.mediaType); // image / video / audio / document / sticker
274
+ console.log(res.ext); // Ekstensi file
275
+ ```
276
+
277
+ > **Tips:** Kalau kamu menentukan folder tujuan sendiri, gunakan **absolute path** (misalnya lewat `path.resolve("./downloads")`) alih-alih path relatif seperti `"./downloads"` langsung. Ini untuk menghindari file tersimpan di lokasi yang tidak kamu duga, karena proses Go berjalan dengan working directory sendiri.
278
+
279
+ ```javascript
280
+ import path from "path";
281
+ import fs from "fs";
282
+
283
+ const DOWNLOAD_DIR = path.resolve("./downloads");
284
+
285
+ if (!fs.existsSync(DOWNLOAD_DIR)) {
286
+ fs.mkdirSync(DOWNLOAD_DIR, { recursive: true });
287
+ }
288
+
289
+ const res = await conn.downloadMedia({ id: quoted.id }, DOWNLOAD_DIR);
290
+ ```
291
+
292
+ ---
293
+
294
+ ## Ubah Audio Jadi Voice Note (`tovn`)
295
+
296
+ Kirimkan pesan `.tovn` sambil membalas (reply) pesan audio, dan bot akan otomatis mengonversinya jadi Voice Note (PTT) menggunakan FFmpeg (codec Opus, mono, bitrate 32kbps).
297
+
298
+ Contoh alur pemakaian di dalam handler pesan:
299
+
300
+ ```javascript
301
+ if (["tovn"].includes(command)) {
302
+ const quoted = getQuotedInfo(m, meta, raw);
303
+
304
+ if (!quoted) {
305
+ return conn.sendMessage(jid, { text: "Balas pesan audio dulu ya!" });
306
+ }
307
+
308
+ // Library akan menangani proses download -> convert -> kirim -> cleanup secara otomatis
309
+ }
310
+ ```
311
+
312
+ File sementara (input audio & hasil `.ogg`) otomatis dibersihkan setelah voice note terkirim.
313
+
314
+ ---
315
+
316
+ ## Kompres Gambar
317
+
318
+ Balas gambar dengan perintah `.kompres` untuk mengompres ukurannya (kualitas JPEG 70, dioptimalkan dengan MozJPEG).
319
+
320
+ ```javascript
321
+ if (["kompres"].includes(command)) {
322
+ const quoted = getQuotedInfo(m, meta, raw);
323
+
324
+ if (!quoted) {
325
+ return conn.sendMessage(jid, { text: "Balas gambar dulu ya!" });
326
+ }
327
+
328
+ // Library akan mengirim balik gambar hasil kompresi
329
+ // beserta perbandingan ukuran awal & ukuran baru
330
+ }
331
+ ```
332
+
333
+ Contoh caption hasil yang dikirim otomatis:
334
+
335
+ ```
336
+ Berhasil Dikompres!
337
+
338
+ Ukuran Awal: 1024.5 KB
339
+ Ukuran Baru: 245.7 KB
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Buat & Ubah Stiker
345
+
346
+ ### Gambar/GIF/Video → Stiker
347
+
348
+ Balas gambar, GIF, atau video pendek dengan perintah `.sticker`:
349
+
350
+ | Media Input | Hasil |
351
+ | ----------------- | ---------------------- |
352
+ | JPG / PNG / WebP | Stiker WebP statis |
353
+ | GIF / MP4 / MOV / WEBM / MKV | Stiker WebP animasi |
354
+
355
+ Batasan untuk stiker animasi:
356
+ - Durasi maksimal **10 detik**
357
+ - Ukuran file maksimal **~0.99 MB**
358
+ - Resolusi **512x512**
359
+ - **15 FPS**
360
+ - Audio otomatis dihapus
361
+
362
+ ### Stiker: Gambar/Video (`tomedia`)
363
+
364
+ Balas stiker dengan perintah `.tomedia` untuk mengubahnya kembali:
365
+
366
+ | Jenis Stiker | Hasil |
367
+ | --------------- | ------------ |
368
+ | Stiker Statis | Gambar JPEG |
369
+ | Stiker Animasi | Video MP4 |
370
+
371
+ Semua proses (deteksi jenis media, konversi, sampai pengiriman) ditangani otomatis oleh library — kamu cukup memanggil perintahnya.
372
+
373
+ ---
374
+
375
+ ## Daftar Event
376
+
377
+ | Event | Isi Data |
378
+ | :--- | :--- |
379
+ | `connection.update` | Status koneksi (`open`, `isLoggedIn`, `botJid`, dll) |
380
+ | `messages.upsert` | Pesan masuk |
381
+ | `pairing_code` | Kode pairing 8 digit (untuk login via nomor HP) |
382
+ | `error` | Error internal dari engine |
383
+
384
+ ---
385
+
386
+ ## Menghentikan Bot dengan Aman
387
+
388
+ Untuk mematikan bot secara terprogram tanpa merusak sesi:
389
+
390
+ ```javascript
391
+ await conn.stop();
392
+ ```
393
+
394
+ Bot juga sudah menangani sinyal `Ctrl+C` (`SIGINT`/`SIGTERM`) secara otomatis, jadi sesi kamu tetap aman meski proses dihentikan tiba-tiba.
395
+
396
+ ---
397
+
398
+ ## Troubleshooting Umum
399
+
400
+ **Q: Kenapa file yang di-download tidak muncul di folder yang saya harapkan?**
401
+ A: Pastikan kamu memakai absolute path (`path.resolve(...)`) saat menentukan folder tujuan download, bukan path relatif langsung.
402
+
403
+ **Q: Kenapa bot gagal menambahkan anggota ke grup (error 403)?**
404
+ A: Kemungkinan besar target mengaktifkan privasi "siapa yang bisa menambahkanku ke grup". Cek `res.inviteRequired` dan kirimkan `res.inviteLink` sebagai gantinya.
405
+
406
+ **Q: Koneksi WhatsApp saya sering putus, apa perlu scan ulang?**
407
+ A: Tidak. Engine akan otomatis mencoba menyambung ulang di latar belakang. Kamu bisa memantau prosesnya lewat event `connection.update`.
@@ -0,0 +1,33 @@
1
+ module lenwy-whatsmeow/engine
2
+
3
+ go 1.26.0
4
+
5
+ require (
6
+ github.com/mattn/go-sqlite3 v1.14.52
7
+ github.com/mdp/qrterminal/v3 v3.2.1
8
+ go.mau.fi/whatsmeow v0.0.0-20260904121843-28bfe537ea6a
9
+ )
10
+
11
+ require (
12
+ filippo.io/edwards25519 v1.2.0 // indirect
13
+ github.com/beeper/argo-go v1.1.2 // indirect
14
+ github.com/coder/websocket v1.8.15 // indirect
15
+ github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
16
+ github.com/google/uuid v1.6.0 // indirect
17
+ github.com/mattn/go-colorable v0.1.14 // indirect
18
+ github.com/mattn/go-isatty v0.0.20 // indirect
19
+ github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b // indirect
20
+ github.com/rs/zerolog v1.35.1 // indirect
21
+ github.com/vektah/gqlparser/v2 v2.5.27 // indirect
22
+ go.mau.fi/libsignal v0.2.2 // indirect
23
+ go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde // indirect
24
+ golang.org/x/crypto v0.55.0 // indirect
25
+ golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 // indirect
26
+ golang.org/x/net v0.58.0 // indirect
27
+ golang.org/x/sync v0.22.0 // indirect
28
+ golang.org/x/sys v0.47.0 // indirect
29
+ golang.org/x/term v0.45.0 // indirect
30
+ golang.org/x/text v0.41.0 // indirect
31
+ google.golang.org/protobuf v1.36.12 // indirect
32
+ rsc.io/qr v0.2.0 // indirect
33
+ )
@@ -0,0 +1,67 @@
1
+ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
2
+ filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
3
+ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
4
+ github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
5
+ github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
6
+ github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
7
+ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
8
+ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
9
+ github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs=
10
+ github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4=
11
+ github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA=
12
+ github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
13
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
14
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
15
+ github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg=
16
+ github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo=
17
+ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
18
+ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
19
+ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
20
+ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
21
+ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
22
+ github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
23
+ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
24
+ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
25
+ github.com/mattn/go-sqlite3 v1.14.52 h1:wVbm2Qnf4OXkqhBTSPuCRZDRnxfbVrrmiCEroVdog8U=
26
+ github.com/mattn/go-sqlite3 v1.14.52/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
27
+ github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
28
+ github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
29
+ github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b h1:sS7HLzwS+dO+gxATgQfeZDEdUZe2pKAB3nGoUwP5zU0=
30
+ github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
31
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
32
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
33
+ github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI=
34
+ github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
35
+ github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
36
+ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
37
+ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
38
+ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
39
+ github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
40
+ github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
41
+ go.mau.fi/libsignal v0.2.2 h1:QV+XdzQkm3x3aSG7FcqfGSZuFXz83pRZPBFaPygHbOU=
42
+ go.mau.fi/libsignal v0.2.2/go.mod h1:CRlIQg2J8uYTfDFvNoO8/KcZjs5cey0vbc6oj/bssY0=
43
+ go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde h1:eMHY9dMDkNuDMWhfTbMZHbbsxj7G6mfujjKei1HaFQM=
44
+ go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde/go.mod h1:z0ZZNt4hq3FZbUKnunexE/QscCx7VkLvQSvtggc/aE8=
45
+ go.mau.fi/whatsmeow v0.0.0-20260904121843-28bfe537ea6a h1:VQgow0KuoIspGo+sAdl8E5f1j1B7OSra7oquz9A7sgE=
46
+ go.mau.fi/whatsmeow v0.0.0-20260904121843-28bfe537ea6a/go.mod h1:aMd13H2xFFGH9cskcvxo4Aae+TmyFN38yw+HvsrpwVg=
47
+ golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
48
+ golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
49
+ golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 h1:YXnL44eJ77R+ji4/ooy8UsXIhz+lbi2Qgdlc8iRN0gY=
50
+ golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297/go.mod h1:Mkmymgv+uMpSQ/XxJ/7GpdrdYoqm3u72jEbpCLiJmNk=
51
+ golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
52
+ golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
53
+ golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
54
+ golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
55
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
56
+ golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
57
+ golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
58
+ golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
59
+ golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
60
+ golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
61
+ golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
62
+ google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
63
+ google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
64
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
65
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
66
+ rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
67
+ rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=