@neelegirl/wa-api 1.6.0 → 1.6.2

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.
@@ -11,9 +11,14 @@
11
11
  export declare function sendMessage(
12
12
  sessionId: string,
13
13
  jid: string,
14
- content: import("@neelegirl/baileys/lib").AnyMessageContent,
15
- options?: import("@neelegirl/baileys/lib").MiscMessageGenerationOptions
16
- ): Promise<import("@neelegirl/baileys/lib").proto.WebMessageInfo>;
14
+ content: import("@neelegirl/baileys").AnyMessageContent,
15
+ options?: import("@neelegirl/baileys").MiscMessageGenerationOptions
16
+ ): Promise<import("@neelegirl/baileys").proto.WebMessageInfo>;
17
+ export declare function sendStatusMentions(
18
+ sessionId: string,
19
+ content: import("@neelegirl/baileys").AnyMessageContent,
20
+ options?: import("@neelegirl/baileys").MiscMessageGenerationOptions
21
+ ): Promise<import("@neelegirl/baileys").proto.WebMessageInfo>;
17
22
  /**
18
23
  * Sendet einen rohen WAMessage-Stanza an WhatsApp.
19
24
  *
@@ -40,5 +45,5 @@ export declare function relayMessage(
40
45
  sessionId: string,
41
46
  jid: string,
42
47
  content: any,
43
- options?: import('@neelegirl/baileys/lib').MiscMessageGenerationOptions
48
+ options?: import('@neelegirl/baileys').MiscMessageGenerationOptions
44
49
  ): Promise<string>;
@@ -29,9 +29,7 @@ const Socket_1 = require("../Socket");
29
29
  const Utils_1 = require("../Utils");
30
30
  const create_delay_1 = require("../Utils/create-delay");
31
31
  const is_exist_1 = require("../Utils/is-exist");
32
- const mime_1 = __importDefault(require("mime"));
33
32
  const Error_1 = require("../Error");
34
- const qrcode = require("qrcode")
35
33
 
36
34
  const sessionCache = new Map();
37
35
 
@@ -58,7 +56,7 @@ async function sendMessage(sessionId, jid, content, options) {
58
56
  const session = getCachedSession(sessionId);
59
57
 
60
58
  // Convert phone number to JID if needed
61
- const destJid = jid.includes("@") ? jid : phoneToJid({ to: jid });
59
+ const destJid = jid.includes("@") ? jid : (0, Utils_1.phoneToJid)({ to: jid });
62
60
 
63
61
  try {
64
62
  return await session.sendMessage(destJid, content, options || {});
@@ -108,9 +106,9 @@ exports.sendStatusMentions = sendStatusMentions;
108
106
  */
109
107
  async function relayMessage(sessionId, jid, content, options = {}) {
110
108
  const session = getCachedSession(sessionId);
111
- if (!session) throw new WhatsappError(`Session ${sessionId} nicht gefunden`);
109
+ if (!session) throw new Error_1.WhatsappError(`Session ${sessionId} nicht gefunden`);
112
110
 
113
- const destJid = jid.includes("@") ? jid : phoneToJid({ to: jid });
111
+ const destJid = jid.includes("@") ? jid : (0, Utils_1.phoneToJid)({ to: jid });
114
112
  try {
115
113
  // Baileys-intern sendet hier direkt das XML-Stanza
116
114
  return await session.relayMessage(destJid, content, options);
@@ -118,4 +116,4 @@ async function relayMessage(sessionId, jid, content, options = {}) {
118
116
  throw new Error_1.WhatsappError(`Relay an ${destJid} fehlgeschlagen: ${err.message}`, { cause: err });
119
117
  }
120
118
  }
121
- exports.relayMessage = relayMessage;
119
+ exports.relayMessage = relayMessage;
@@ -1,15 +1,17 @@
1
- import { WASocket } from "@neelegirl/baileys/lib";
1
+ import { WASocket } from "@neelegirl/baileys";
2
2
  import type { MessageReceived, MessageUpdated, StartSessionParams } from "../Types";
3
3
  export declare const startSession: (sessionId?: string, options?: StartSessionParams) => Promise<WASocket>;
4
4
  /**
5
5
  * @deprecated Use startSession method instead
6
6
  */
7
7
  export declare const startWhatsapp: (sessionId?: string, options?: StartSessionParams) => Promise<WASocket>;
8
- export declare const startSessionWithPairingCode: (sessionId?: string, options?: {phoneNumber}) => Promise<WASocket>;
8
+ export declare const startSessionWithPairingCode: (sessionId?: string, options?: {
9
+ phoneNumber: string;
10
+ }, key?: string) => Promise<WASocket>;
9
11
  export declare const deleteSession: (sessionId: string) => Promise<void>;
10
12
  export declare const getAllSession: () => string[];
11
13
  export declare const getSession: (key: string) => WASocket | undefined;
12
- export declare const loadSessionsFromStorage: () => void;
14
+ export declare const loadSessionsFromStorage: () => Promise<string[]>;
13
15
  export declare const onMessageReceived: (listener: (msg: MessageReceived) => any) => void;
14
16
  export declare const onQRUpdated: (listener: ({ sessionId, qr }: {
15
17
  sessionId: string;
@@ -19,4 +21,4 @@ export declare const onConnected: (listener: (sessionId: string) => any) => void
19
21
  export declare const onDisconnected: (listener: (sessionId: string) => any) => void;
20
22
  export declare const onConnecting: (listener: (sessionId: string) => any) => void;
21
23
  export declare const onMessageUpdate: (listener: (data: MessageUpdated) => any) => void;
22
- //# sourceMappingURL=index.d.ts.map
24
+ export declare const onPairingCode: (listener: (sessionId: string, code: string) => any) => void;
@@ -49,39 +49,9 @@ const sessions = new Map();
49
49
  const callback = new Map();
50
50
  const retryCount = new Map();
51
51
  let stock;
52
- let CURRENT_WA_API_VERSION = "1.5.1";
53
- try {
54
- // Prefer package.json version when available
55
- // dist/Socket/index.js -> ../../package.json
56
- // eslint-disable-next-line @typescript-eslint/no-var-requires
57
- const pkg = require("../../package.json");
58
- if (pkg && typeof pkg.version === "string") {
59
- CURRENT_WA_API_VERSION = pkg.version;
60
- }
61
- }
62
- catch (_a) {
63
- // fallback keeps bundled version
64
- }
65
- let waApiUpdateCheckDone = false;
66
-
67
- function isNewerVersion(latest, current) {
68
- if (!latest || !current) return false;
69
- const a = current.split('.').map((n) => parseInt(n, 10) || 0);
70
- const b = latest.split('.').map((n) => parseInt(n, 10) || 0);
71
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
72
- const x = a[i] || 0, y = b[i] || 0;
73
- if (y > x) return true;
74
- if (y < x) return false;
75
- }
76
- return false;
77
- }
78
-
79
- // Liest von der offiziellen npm-Registry (registry.npmjs.org), ob ein Update existiert – nur 1x pro Prozess
52
+ const CURRENT_WA_API_VERSION = require("../../package.json").version || "1.6.2";
53
+ // Update-Check-Funktion für WA-API
80
54
  const checkWaApiUpdate = () => {
81
- if (waApiUpdateCheckDone) {
82
- return Promise.resolve(null);
83
- }
84
- waApiUpdateCheckDone = true;
85
55
  return new Promise((resolve) => {
86
56
  const url = `https://registry.npmjs.org/@neelegirl/wa-api/latest`;
87
57
  https_1.default.get(url, { timeout: 5000 }, (res) => {
@@ -93,8 +63,8 @@ const checkWaApiUpdate = () => {
93
63
  try {
94
64
  const packageInfo = JSON.parse(data);
95
65
  const latestVersion = packageInfo.version;
96
- if (latestVersion && isNewerVersion(latestVersion, CURRENT_WA_API_VERSION)) {
97
- const updateMessage = `\n╔════════════════════════════════════════╗\n║ 🔔 NEUES UPDATE VERFÜGBAR! 🔔 ║\n╠════════════════════════════════════════╣\n║ @neelegirl/wa-api ║\n║ Aktuelle Version: ${(CURRENT_WA_API_VERSION || '').padEnd(20)} ║\n║ Neue Version: ${(latestVersion || '').padEnd(20)} ║\n║ ║\n║ Bitte aktualisiere: ║\n║ npm install @neelegirl/wa-api@latest ║\n╚════════════════════════════════════════╝\n`;
66
+ if (latestVersion && latestVersion !== CURRENT_WA_API_VERSION) {
67
+ const updateMessage = `\n╔════════════════════════════════════════╗\n║ 🔔 NEUES UPDATE VERFÜGBAR! 🔔 ║\n╠════════════════════════════════════════╣\n║ @neelegirl/wa-api ║\n║ Aktuelle Version: ${CURRENT_WA_API_VERSION.padEnd(20)} ║\n║ Neue Version: ${latestVersion.padEnd(20)} ║\n║ ║\n║ Bitte aktualisiere: ║\n║ npm install @neelegirl/wa-api@latest ║\n╚════════════════════════════════════════╝\n`;
98
68
  console.log(updateMessage);
99
69
  resolve({
100
70
  current: CURRENT_WA_API_VERSION,
@@ -103,11 +73,11 @@ const checkWaApiUpdate = () => {
103
73
  });
104
74
  }
105
75
  else {
106
- const currentVersionMessage = `\n╔════════════════════════════════════════╗\n║ ✅ Du nutzt die aktuelle Version ║\n║ von @neelegirl/wa-api ║\n╚════════════════════════════════════════╝\n`;
76
+ const currentVersionMessage = `\n╔════════════════════════════════════════╗\n║ ✅ Du nutzt gerade die aktuelle ║\n║ Version von @neelegirl/wa-api ║\n║ ║\n║ Wir informieren dich, wenn es ein ║\n║ Update gibt. ║\n╚════════════════════════════════════════╝\n`;
107
77
  console.log(currentVersionMessage);
108
78
  resolve({
109
79
  current: CURRENT_WA_API_VERSION,
110
- latest: latestVersion || CURRENT_WA_API_VERSION,
80
+ latest: latestVersion,
111
81
  hasUpdate: false
112
82
  });
113
83
  }
@@ -142,7 +112,7 @@ const startSession = (sessionId = "mysession", options = { printQR: true }) => _
142
112
  markOnlineOnConnect: false,
143
113
  browser: baileys_1.Browsers.ubuntu("Chrome"),
144
114
  });
145
- sessions.set(sessionId, Object.assign({}, sock));
115
+ sessions.set(sessionId, sock);
146
116
  try {
147
117
 
148
118
  sock.ev.process((events) => __awaiter(void 0, void 0, void 0, function* () {
@@ -228,8 +198,11 @@ const onimaii = (sessionId = "mysession", connect) => __awaiter(void 0, void 0,
228
198
  })
229
199
  exports.onimaii = onimaii;
230
200
  exports.startSession = startSession;
231
- const startSessionWithPairingCode = (sessionId = "mysession", options = { phoneNumber },key) => __awaiter(void 0, void 0, void 0, function* () {
232
- if (isSessionExistAndRunning(sessionId))throw new WhatsappError(Messages.sessionAlreadyExist(sessionId));
201
+ const startSessionWithPairingCode = (sessionId = "mysession", options = {}, key) => __awaiter(void 0, void 0, void 0, function* () {
202
+ if (!options.phoneNumber)
203
+ throw new Error_1.WhatsappError(Defaults_1.Messages.paremetersRequired("phoneNumber"));
204
+ if (isSessionExistAndRunning(sessionId))
205
+ throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
233
206
  const logger = (0, pino_1.default)({ level: "silent" });
234
207
  const { version } = yield (0, baileys_1.fetchLatestBaileysVersion)();
235
208
  const startSocket = () => __awaiter(void 0, void 0, void 0, function* () {
@@ -244,7 +217,7 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
244
217
  markOnlineOnConnect: false,
245
218
  browser: baileys_1.Browsers.ubuntu("Chrome"),
246
219
  });
247
- sessions.set(sessionId, { ...sock });
220
+ sessions.set(sessionId, sock);
248
221
  try {
249
222
  if (!sock.authState.creds.registered) {
250
223
  console.log("first time pairing");
@@ -371,22 +344,22 @@ const getAllSessionData = () => {
371
344
  exports.getAllSessionData = getAllSessionData;
372
345
 
373
346
  async function loadSessionsFromStorage() {
374
- const dirPath = path.resolve(CREDENTIALS.DIR_NAME);
347
+ const dirPath = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME);
375
348
  const loadedSessions = [];
376
349
 
377
350
  // Ordner anlegen, falls nicht existiert
378
- if (!fs.existsSync(dirPath)) {
379
- fs.mkdirSync(dirPath, { recursive: true });
351
+ if (!fs_1.default.existsSync(dirPath)) {
352
+ fs_1.default.mkdirSync(dirPath, { recursive: true });
380
353
  }
381
354
 
382
355
  try {
383
- const entries = await fs.promises.readdir(dirPath);
356
+ const entries = await fs_1.default.promises.readdir(dirPath);
384
357
 
385
358
  for (const entry of entries) {
386
- const fullPath = path.join(dirPath, entry);
359
+ const fullPath = path_1.default.join(dirPath, entry);
387
360
  let stat;
388
361
  try {
389
- stat = await fs.promises.stat(fullPath);
362
+ stat = await fs_1.default.promises.stat(fullPath);
390
363
  } catch {
391
364
  // Wenn sich die Datei zwischenzeitlich entfernt hat o.Ä., überspringen
392
365
  continue;
@@ -400,7 +373,7 @@ async function loadSessionsFromStorage() {
400
373
  : entry; // oder continue, wenn du ohne _ nicht laden willst
401
374
 
402
375
  try {
403
- await startSession(sessionId);
376
+ await (0, exports.startSession)(sessionId);
404
377
  loadedSessions.push(sessionId);
405
378
  } catch (err) {
406
379
  console.error(`Fehler beim Starten der Session "${sessionId}":`, err);
@@ -422,7 +395,7 @@ const onMessageReceived = (listener) => {
422
395
  const sock = (conn) => {
423
396
  onMessageReceived(async(msg) =>{
424
397
  let {sessionId} = msg;
425
- let sock1 = getSesseion(sessionId)
398
+ let sock1 = (0, exports.getSession)(sessionId)
426
399
  conn = sock1
427
400
  })
428
401
  };
@@ -449,6 +422,6 @@ const onMessageUpdate = (listener) => {
449
422
  };
450
423
  exports.onMessageUpdate = onMessageUpdate;
451
424
  const onPairingCode = (listener) => {
452
- callback.set(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED, listener);
425
+ callback.set(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE, listener);
453
426
  };
454
427
  exports.onPairingCode = onPairingCode;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { WAMessageUpdate, proto } from "@neelegirl/baileys/lib";
2
+ import { WAMessageUpdate, proto } from "@neelegirl/baileys";
3
3
  export interface SendMessageTypes {
4
4
  to: string | number;
5
5
  text?: string;
@@ -195,12 +195,5 @@ class Whatsapp {
195
195
  }));
196
196
  });
197
197
  }
198
- }
199
- exports.Whatsapp = Whatsapp;
200
- const wa = new Whatsapp();
201
- // wa.load();
202
- const mySocket = new Socket_1.Socket({ id: "mysocket", phoneNumber: "6281524538841" });
203
- mySocket.onPairing = (code) => {
204
- console.log(code);
205
- };
206
- wa.startSession(mySocket);
198
+ }
199
+ exports.Whatsapp = Whatsapp;
package/package.json CHANGED
@@ -1,25 +1,7 @@
1
1
  {
2
2
  "name": "@neelegirl/wa-api",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "Multi-session WhatsApp wrapper built on @neelegirl/baileys for QR, pairing and message automation.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "require": "./dist/index.js",
11
- "default": "./dist/index.js"
12
- },
13
- "./package.json": "./package.json"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/neelegirly/neelegirl-wa-api.git"
18
- },
19
- "homepage": "https://github.com/neelegirly/neelegirl-wa-api#readme",
20
- "bugs": {
21
- "url": "https://github.com/neelegirly/neelegirl-wa-api/issues"
22
- },
23
5
  "keywords": [
24
6
  "whatsapp",
25
7
  "wa-api",
@@ -29,28 +11,29 @@
29
11
  "automation",
30
12
  "neelegirl"
31
13
  ],
14
+ "homepage": "https://github.com/neelegirly/neelegirl-wa-api#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/neelegirly/neelegirl-wa-api.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/neelegirly/neelegirl-wa-api/issues"
21
+ },
22
+ "license": "ISC",
23
+ "author": "Neele",
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
32
26
  "files": [
33
27
  "dist/**/*",
34
28
  "readme.md",
35
29
  "LICENSE"
36
30
  ],
37
31
  "scripts": {
38
- "start": "node ./dist/index.js",
39
- "run-script": "node ./dist/index.js"
32
+ "test": "node -e \"require('./dist')\""
40
33
  },
41
- "author": "Neele",
42
- "license": "ISC",
43
34
  "dependencies": {
44
- "@adiwajshing/keyed-db": "^0.2.4",
45
- "@hapi/boom": "^10.0.1",
46
- "@neelegirl/baileys": "^2.1.0",
47
- "jest": "^29.0.0",
48
- "mime": "^3.0.0",
49
- "pino": "^8.11.0",
50
- "qrcode-terminal": "^0.12.0"
51
- },
52
- "devDependencies": {
53
- "@types/mime": "^3.0.1"
35
+ "@neelegirl/baileys": "^2.1.2",
36
+ "pino": "^9.6.0"
54
37
  },
55
38
  "engines": {
56
39
  "node": ">=20.0.0"
package/readme.md CHANGED
@@ -1,676 +1,140 @@
1
- <div align="center">
2
-
3
- # @neelegirl/wa-api
4
-
5
- **Mehrfach-Sessions, QR-Login, Pairing-Code und vereinfachtes Messaging**
6
- **aufbauend auf dem gepflegten `@neelegirl/baileys`-Fork.**
7
-
8
- [![npm](https://img.shields.io/npm/v/@neelegirl/wa-api?style=for-the-badge&color=ff69b4&logo=npm)](https://www.npmjs.com/package/@neelegirl/wa-api)
9
- [![Dependency](https://img.shields.io/badge/@neelegirl%2Fbaileys-2.1.x-6f42c1?style=for-the-badge)](https://www.npmjs.com/package/@neelegirl/baileys)
10
- [![Node](https://img.shields.io/badge/Node-20+-2ea043?style=for-the-badge&logo=node.js)](https://nodejs.org)
11
-
12
1
  <p align="center">
13
- <img src="https://files.catbox.moe/6np1ii.JPG" width="920" alt="Neelegirl wa-api Hero" />
2
+ <img src="https://files.catbox.moe/6np1ii.JPG" alt="@neelegirl/wa-api" width="900" />
14
3
  </p>
15
4
 
16
- </div>
5
+ # @neelegirl/wa-api
17
6
 
18
- ## Überblick
7
+ Mehrfach-Session-Wrapper fuer WhatsApp auf Basis von `@neelegirl/baileys`.
8
+ Das Paket kapselt Session-Start, Pairing, Listener und einfache Message-Helper,
9
+ ohne selbst ein eigenes REST- oder Queue-System mitzubringen.
19
10
 
20
- `@neelegirl/wa-api` ist die bequemere Multi-Session-Schicht für Projekte, die nicht direkt auf der vollständigen Baileys-Oberfläche arbeiten wollen. Das Paket nutzt `@neelegirl/baileys` als eigentliche WhatsApp-Web-Basis und stellt darauf ein kompakteres API-Set für Sessions, Event-Hooks und das Senden von Nachrichten bereit.
11
+ **Version 1.6.2** · **Node.js 20+** · **basiert auf `@neelegirl/baileys` 2.1.2**
21
12
 
22
- ## Update-Stand
13
+ ## Stand
23
14
 
24
- - abgestimmt auf `@neelegirl/baileys@2.1.x`
25
- - Dokumentation auf den realen Dist-Exports bereinigt
26
- - Bild/Branding modernisiert
27
- - Hinweise ergänzt, was lokal funktioniert und was bewusst nicht behauptet wird
15
+ - basiert auf `@neelegirl/baileys` `2.1.2`
16
+ - Multi-Session-Management ueber Dateispeicher
17
+ - QR-Login und Pairing-Code-Login
18
+ - Helper fuer `sendMessage`, `sendStatusMentions` und `relayMessage`
19
+ - Listener fuer Verbindung, QR, Pairing-Code und Nachrichten
28
20
 
29
- **Wichtig:** `wa-api` baut auf dem aktualisierten Neelegirl-Baileys-Fork auf. Es ist keine eigenständige Neuimplementierung von WhiskeySockets/Baileys, sondern eine Wrapper-Schicht darüber.
21
+ ## Voraussetzungen
22
+
23
+ - Node.js `>= 20`
24
+ - installierte `@neelegirl/baileys`-Abhaengigkeit
25
+ - optional `qrcode-terminal`, wenn `printQR: true` fuer Terminal-QR genutzt wird
30
26
 
31
27
  ## Installation
32
28
 
33
29
  ```bash
34
- npm install @neelegirl/wa-api @neelegirl/baileys
30
+ npm install @neelegirl/wa-api
35
31
  ```
36
32
 
37
- oder:
33
+ Optional fuer Terminal-QR:
38
34
 
39
35
  ```bash
40
- yarn add @neelegirl/wa-api @neelegirl/baileys
36
+ npm install qrcode-terminal
41
37
  ```
42
38
 
43
- ## Voraussetzungen
44
-
45
- - Node.js `20+`
46
- - WhatsApp Multi-Device-Konto
47
- - persistenter Speicherort für Sessiondaten
48
-
49
39
  ## Schnellstart
50
40
 
51
41
  ```js
52
42
  const wa = require('@neelegirl/wa-api')
53
43
 
54
- async function bootstrap() {
55
- await wa.startSession('main-session', {
56
- printQR: true
57
- })
58
-
59
- console.log('Session gestartet')
60
- }
61
-
62
- wa.onConnected((sessionId) => {
63
- console.log(`[${sessionId}] verbunden`)
44
+ wa.onQRUpdated(({ sessionId, qr }) => {
45
+ console.log('QR aktualisiert:', sessionId, qr)
64
46
  })
65
47
 
66
- wa.onDisconnected((sessionId) => {
67
- console.log(`[${sessionId}] getrennt`)
48
+ wa.onConnected((sessionId) => {
49
+ console.log('Verbunden:', sessionId)
68
50
  })
69
51
 
70
- wa.onMessageReceived(async ({ sessionId, key, message }) => {
71
- const jid = key.remoteJid
72
- const text = message?.conversation || message?.extendedTextMessage?.text || ''
73
-
74
- if (text.toLowerCase() === 'ping') {
75
- await wa.sendMessage(sessionId, jid, { text: 'pong' })
76
- }
52
+ wa.onMessageReceived((msg) => {
53
+ console.log('Nachricht in Session', msg.sessionId)
77
54
  })
78
55
 
79
- bootstrap().catch(console.error)
80
- ```
81
-
82
- ## Session-API
83
-
84
- ### Starten
85
-
86
- ```js
87
- await wa.startSession('session-a', { printQR: true })
56
+ async function main() {
57
+ await wa.startSession('session1', { printQR: true })
58
+ }
88
59
 
89
- await wa.startSessionWithPairingCode('session-b', {
90
- phoneNumber: '491234567890'
91
- })
60
+ main().catch(console.error)
92
61
  ```
93
62
 
94
- ### Verwalten
63
+ ## Pairing-Code-Login
95
64
 
96
65
  ```js
97
- const all = wa.getAllSession()
98
- const one = wa.getSession('session-a')
99
-
100
- await wa.deleteSession('session-a')
101
- await wa.loadSessionsFromStorage()
102
- ```
103
-
104
- ## Messaging
66
+ const wa = require('@neelegirl/wa-api')
105
67
 
106
- Die Dist-API bietet einen universellen `sendMessage`-Wrapper über die aktive Session:
68
+ async function main() {
69
+ await wa.startSessionWithPairingCode(
70
+ 'session2',
71
+ { phoneNumber: '491234567890' },
72
+ 'ONIMAIII'
73
+ )
74
+ }
107
75
 
108
- ```js
109
- await wa.sendMessage('session-a', '491234567890@s.whatsapp.net', {
110
- text: 'Hallo aus wa-api'
76
+ wa.onPairingCode((sessionId, code) => {
77
+ console.log('Pairing-Code fuer', sessionId, code)
111
78
  })
112
- ```
113
-
114
- Zusätzlich gibt es `relayMessage`, wenn du gezielt weiterleiten bzw. rohe Baileys-Pfade der Session nutzen willst.
115
-
116
- ## Event-Hooks
117
-
118
- Vorhandene Event-Helper im Dist-Build:
119
-
120
- - `onMessageReceived(listener)`
121
- - `onQRUpdated(listener)`
122
- - `onConnected(listener)`
123
- - `onDisconnected(listener)`
124
- - `onConnecting(listener)`
125
- - `onMessageUpdate(listener)`
126
- - `onPairingCode(listener)`
127
-
128
- ## Konsole beim Start
129
-
130
- Diese Zustände sind beim echten Start normal:
131
-
132
- - QR wird im Terminal angezeigt, wenn noch keine Session gespeichert ist
133
- - Pairing-Code wird ausgegeben, wenn du die Pairing-Variante nutzt
134
- - `connected`/`disconnected` wechseln bei Reconnects sauber
135
- - nach `creds.update` bleibt die Session für Folgestarts erhalten
136
-
137
- ## Was wirklich funktioniert
138
-
139
- - mehrere parallele Sessions
140
- - Sessionstart per QR
141
- - Sessionstart per Pairing-Code
142
- - Nachrichtenversand über aktive Sessions
143
- - Sessionzugriff über `getSession()` für tiefergehende eigene Arbeit
144
- - Event-Listener für eingehende Nachrichten und Verbindungsstatus
145
-
146
- ## Was bewusst **nicht** behauptet wird
147
-
148
- - kein separater, vollständig dokumentierter Source-Build im Paket selbst
149
- - kein vollständiger Ersatz für das volle Baileys-API-Surface
150
- - kein Anspruch auf vollständigen Upstream-Gleichstand in jeder internen Implementierungsdetailschicht
151
79
 
152
- ## Empfehlung für produktive Nutzung
153
-
154
- - `@neelegirl/baileys` und `@neelegirl/wa-api` immer gemeinsam aktualisieren
155
- - Sessionordner außerhalb flüchtiger Deploy-Ordner speichern
156
- - bei Multi-Session-Projekten eigene Health-/Reconnect-Logs ergänzen
157
-
158
- ## Lizenz
159
-
160
- `wa-api` bleibt die einfache Bedienebene. Die technische WhatsApp-Web-Basis stammt aus `@neelegirl/baileys`, das selektiv auf aktuellem WhiskeySockets/Baileys-Wissen aufsetzt.
161
- image: { url: './bild.jpg' },
162
- caption: 'Schönes Bild! ✨'
163
- });
80
+ main().catch(console.error)
164
81
  ```
165
82
 
166
- #### 3. **Video**
167
-
168
- ```javascript
169
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
170
- video: { url: './video.mp4' },
171
- caption: 'Mein Video! 🎬'
172
- });
173
- ```
174
-
175
- #### 4. **GIF (als Video)**
176
-
177
- ```javascript
178
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
179
- video: { url: './animation.mp4' },
180
- gifPlayback: true, // Wichtig für GIFs!
181
- caption: 'Kawaii GIF! ✨'
182
- });
183
- ```
184
-
185
- #### 5. **Audio/Sprachnachricht**
186
-
187
- ```javascript
188
- const fs = require('fs');
83
+ Der dritte Parameter ist optional. Wenn ein eigener Code gesetzt wird, muss er
84
+ 8 Zeichen lang sein.
189
85
 
190
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
191
- audio: fs.createReadStream('./audio.ogg'),
192
- mimetype: 'audio/ogg',
193
- ptt: true // Push-to-Talk (Sprachnachricht)
194
- });
195
- ```
196
-
197
- #### 6. **Dokument**
198
-
199
- ```javascript
200
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
201
- document: {
202
- url: './dokument.pdf',
203
- filename: 'Wichtiges Dokument.pdf'
204
- },
205
- mimetype: 'application/pdf'
206
- });
207
- ```
208
-
209
- #### 7. **Umfrage (Poll)**
210
-
211
- ```javascript
212
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
213
- poll: {
214
- name: 'Was ist deine Lieblingsfarbe?',
215
- values: ['Rot', 'Blau', 'Grün', 'Gelb'],
216
- selectableCount: 1 // Anzahl der auswählbaren Optionen
217
- }
218
- });
219
- ```
220
-
221
- #### 8. **Reaktion**
222
-
223
- ```javascript
224
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
225
- react: {
226
- text: '❤️', // Emoji
227
- key: message.key // Key der Nachricht
228
- }
229
- });
230
-
231
- // Reaktion entfernen
232
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
233
- react: {
234
- text: '', // Leerer String entfernt Reaktion
235
- key: message.key
236
- }
237
- });
238
- ```
86
+ ## Nachrichten senden
239
87
 
240
- #### 9. **Nachricht löschen**
241
-
242
- ```javascript
243
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
244
- delete: message.key // Für alle löschen
245
- });
246
- ```
247
-
248
- #### 10. **Nachricht anpinnen**
249
-
250
- ```javascript
251
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
252
- pin: {
253
- type: 1, // 0 = entfernen, 1 = anpinnen
254
- time: 86400, // Sekunden (24h = 86400)
255
- key: message.key
256
- }
257
- });
258
- ```
259
-
260
- #### 11. **Kontakt teilen**
261
-
262
- ```javascript
263
- const vcard = `BEGIN:VCARD
264
- VERSION:3.0
265
- FN:Max Mustermann
266
- TEL;type=CELL;type=VOICE;waid=491234567890:+49 123 4567890
267
- END:VCARD`;
268
-
269
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
270
- contacts: {
271
- displayName: 'Max Mustermann',
272
- contacts: [{ vcard }]
273
- }
274
- });
275
- ```
276
-
277
- #### 12. **Standort**
278
-
279
- ```javascript
280
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
281
- location: {
282
- degreesLatitude: 52.520008,
283
- degreesLongitude: 13.404954
284
- }
285
- });
286
- ```
88
+ ```js
89
+ const wa = require('@neelegirl/wa-api')
287
90
 
288
- #### 13. **Nachricht weiterleiten**
91
+ await wa.sendMessage('session1', '491234567890', { text: 'Hallo' })
289
92
 
290
- ```javascript
291
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
292
- forward: originalMessage // Originale Nachricht
293
- });
294
- ```
295
-
296
- #### 14. **Mit Quote (Antwort)**
93
+ await wa.sendStatusMentions('session1', {
94
+ text: 'Status mit Mentions'
95
+ })
297
96
 
298
- ```javascript
299
- await onimai.sendMessage(
300
- 'session1',
301
- '491234567890@s.whatsapp.net',
97
+ await wa.relayMessage(
98
+ 'session1',
99
+ 'status@broadcast',
302
100
  {
303
- text: 'Das ist eine Antwort!'
101
+ protocolMessage: {
102
+ type: 14
103
+ }
304
104
  },
305
- {
306
- quoted: originalMessage // Originale Nachricht
307
- }
308
- );
309
- ```
310
-
311
- #### 15. **Mit Erwähnung**
312
-
313
- ```javascript
314
- await onimai.sendMessage('session1', '491234567890@s.whatsapp.net', {
315
- text: '@491111111111 Hallo!',
316
- mentions: ['491111111111@s.whatsapp.net']
317
- });
318
- ```
319
-
320
- ---
321
-
322
- ## 🎧 Event Listener
323
-
324
- ### 📥 **Nachrichten empfangen**
325
-
326
- ```javascript
327
- onimai.onMessageReceived(async (msg) => {
328
- const {
329
- sessionId, // Session-ID
330
- key, // Message-Key (id, remoteJid, fromMe)
331
- message, // Nachrichteninhalt
332
- messageTimestamp // Zeitstempel
333
- } = msg;
334
-
335
- const from = key.remoteJid;
336
- const text = message?.conversation || message?.extendedTextMessage?.text || '';
337
-
338
- console.log(`📥 Neue Nachricht von ${from}: ${text}`);
339
-
340
- // Medien speichern (wenn vorhanden)
341
- if (message?.imageMessage) {
342
- await msg.saveImage('./downloads/');
343
- }
344
- if (message?.videoMessage) {
345
- await msg.saveVideo('./downloads/');
346
- }
347
- if (message?.documentMessage) {
348
- await msg.saveDocument('./downloads/');
349
- }
350
- });
351
- ```
352
-
353
- ### 🔄 **Nachrichten-Updates**
354
-
355
- ```javascript
356
- onimai.onMessageUpdate((sessionId, data) => {
357
- const {
358
- update, // Update-Objekt
359
- messageStatus // Lesbarer Status
360
- } = data;
361
-
362
- console.log(`📊 Status Update: ${messageStatus}`);
363
- // Mögliche Status: 'sent', 'delivered', 'read', 'failed'
364
- });
365
- ```
366
-
367
- ### 🔌 **Verbindungs-Events**
368
-
369
- ```javascript
370
- // Verbunden
371
- onimai.onConnected((sessionId) => {
372
- console.log(`✅ Session ${sessionId} ist jetzt verbunden!`);
373
- });
374
-
375
- // Verbindung wird hergestellt
376
- onimai.onConnecting((sessionId) => {
377
- console.log(`🔄 Session ${sessionId} verbindet...`);
378
- });
379
-
380
- // Getrennt
381
- onimai.onDisconnected((sessionId) => {
382
- console.log(`❌ Session ${sessionId} wurde getrennt`);
383
- });
384
- ```
385
-
386
- ### 📱 **QR-Code Updates**
387
-
388
- ```javascript
389
- onimai.onQRUpdated((info) => {
390
- const { sessionId, qr } = info;
391
- console.log(`📱 Neuer QR-Code für Session ${sessionId}:`);
392
- console.log(qr);
393
-
394
- // Du kannst den QR-Code auch in eine Datei speichern oder auf einer Webseite anzeigen
395
- });
105
+ {}
106
+ )
396
107
  ```
397
108
 
398
- ### 🔑 **Pairing-Code**
109
+ ## Sessions aus dem Speicher laden
399
110
 
400
- ```javascript
401
- onimai.onPairingCode((sessionId, code) => {
402
- console.log(`🔑 Pairing-Code für Session ${sessionId}: ${code}`);
403
- });
404
- ```
405
-
406
- ---
407
-
408
- ## 🔧 Erweiterte Funktionen
409
-
410
- ### 💾 **Medien speichern**
411
-
412
- ```javascript
413
- onimai.onMessageReceived(async (msg) => {
414
- // Bild speichern
415
- if (msg.message?.imageMessage) {
416
- const path = await msg.saveImage('./downloads/');
417
- console.log('✅ Bild gespeichert:', path);
418
- }
419
-
420
- // Video speichern
421
- if (msg.message?.videoMessage) {
422
- const path = await msg.saveVideo('./downloads/');
423
- console.log('✅ Video gespeichert:', path);
424
- }
425
-
426
- // Dokument speichern
427
- if (msg.message?.documentMessage) {
428
- const path = await msg.saveDocument('./downloads/');
429
- console.log('✅ Dokument gespeichert:', path);
430
- }
431
- });
432
- ```
433
-
434
- ### 🔄 **Multi-Session Beispiel**
435
-
436
- ```javascript
437
- // Mehrere Sessions gleichzeitig starten
438
- const sessions = ['session1', 'session2', 'session3'];
439
-
440
- for (const sessionId of sessions) {
441
- await onimai.startSession(sessionId, { printQR: true });
442
- }
443
-
444
- // Nachricht an alle Sessions senden
445
- const message = { text: 'Broadcast-Nachricht! 📢' };
446
- const recipients = ['491234567890@s.whatsapp.net'];
447
-
448
- for (const sessionId of sessions) {
449
- for (const recipient of recipients) {
450
- await onimai.sendMessage(sessionId, recipient, message);
451
- }
452
- }
453
- ```
111
+ ```js
112
+ const wa = require('@neelegirl/wa-api')
454
113
 
455
- ### 🚀 **Smart Queue Integration**
456
-
457
- ```javascript
458
- // Nutze die Smart Message Queue von Baileys für zuverlässiges Bulk-Messaging
459
- const baileys = require('@neelegirl/baileys');
460
- const session = onimai.getSession('session1');
461
-
462
- if (session) {
463
- const queue = baileys.createSmartMessageQueue(session, {
464
- maxRetries: 5,
465
- retryDelay: 2000,
466
- maxConcurrent: 3
467
- });
468
-
469
- // Viele Nachrichten zur Queue hinzufügen
470
- const recipients = ['491234567890@s.whatsapp.net', '499876543210@s.whatsapp.net'];
471
-
472
- for (const jid of recipients) {
473
- await queue.add({
474
- jid,
475
- message: { text: 'Wichtige Ankündigung! 📢' },
476
- priority: 'high'
477
- });
478
- }
479
- }
114
+ const loaded = await wa.loadSessionsFromStorage()
115
+ console.log('Geladene Sessions:', loaded)
480
116
  ```
481
117
 
482
- ---
483
-
484
- ## 📚 Vollständige API-Referenz
485
-
486
- ### 🔌 **Session-Funktionen**
487
-
488
- | Funktion | Beschreibung | Beispiel |
489
- |----------|-------------|----------|
490
- | `startSession(id, options)` | Startet eine Session mit QR-Code | `await onimai.startSession('session1')` |
491
- | `startSessionWithPairingCode(id, options)` | Startet mit Pairing-Code | `await onimai.startSessionWithPairingCode('session2', { phoneNumber: '491234567890' })` |
492
- | `getAllSession()` | Gibt alle aktiven Sessions zurück | `const sessions = onimai.getAllSession()` |
493
- | `getSession(id)` | Gibt eine spezifische Session zurück | `const session = onimai.getSession('session1')` |
494
- | `deleteSession(id)` | Löscht eine Session | `await onimai.deleteSession('session1')` |
495
- | `loadSessionsFromStorage()` | Lädt alle Sessions aus Storage | `const loaded = await onimai.loadSessionsFromStorage()` |
496
-
497
- ### 💬 **Nachrichten-Funktionen**
498
-
499
- | Funktion | Beschreibung |
500
- |----------|-------------|
501
- | `sendMessage(sessionId, jid, content, options)` | Sendet eine Nachricht |
502
-
503
- **Content-Typen:**
504
- - `{ text: string }` - Text
505
- - `{ image: { url: string }, caption?: string }` - Bild
506
- - `{ video: { url: string }, caption?: string, gifPlayback?: boolean }` - Video/GIF
507
- - `{ audio: Stream, mimetype: string, ptt?: boolean }` - Audio
508
- - `{ document: { url: string, filename?: string }, mimetype: string }` - Dokument
509
- - `{ poll: { name: string, values: string[], selectableCount: number } }` - Umfrage
510
- - `{ react: { text: string, key: MessageKey } }` - Reaktion
511
- - `{ delete: MessageKey }` - Löschen
512
- - `{ pin: { type: number, time: number, key: MessageKey } }` - Anpinnen
513
- - `{ contacts: { displayName: string, contacts: Array } }` - Kontakt
514
- - `{ location: { degreesLatitude: number, degreesLongitude: number } }` - Standort
515
- - `{ forward: Message }` - Weiterleiten
516
-
517
- ### 🎧 **Event-Listener**
518
-
519
- | Event | Beschreibung | Callback-Parameter |
520
- |-------|-------------|-------------------|
521
- | `onMessageReceived` | Neue Nachricht empfangen | `(msg: Message)` |
522
- | `onMessageUpdate` | Nachrichten-Update | `(sessionId: string, data: UpdateData)` |
523
- | `onConnected` | Session verbunden | `(sessionId: string)` |
524
- | `onConnecting` | Session verbindet | `(sessionId: string)` |
525
- | `onDisconnected` | Session getrennt | `(sessionId: string)` |
526
- | `onQRUpdated` | QR-Code aktualisiert | `(info: { sessionId: string, qr: string })` |
527
- | `onPairingCode` | Pairing-Code erhalten | `(sessionId: string, code: string)` |
528
-
529
- ---
530
-
531
- ## ⚠️ Wichtige Hinweise
532
-
533
- ### 🚨 **Disclaimer**
534
-
535
- > ⚠️ **WICHTIG**: Diese Library funktioniert **ausschließlich** mit **@neelegirl/baileys**!
536
- >
537
- > - ✖️ **Kein Spam** oder Massennachrichten
538
- > - ✖️ **Kein Missbrauch** für unethische Zwecke
539
- > - ✖️ **Keine Stalkerware** oder automatisierte Überwachung
540
- > - ✔️ **Verantwortungsvoller Gebrauch** wird erwartet
541
-
542
- ### 🔒 **Sicherheit**
543
-
544
- - **Nie** deine Session-Daten öffentlich teilen
545
- - **Immer** `.gitignore` für Credentials-Ordner verwenden
546
- - **Regelmäßig** Backups erstellen
547
- - **Sichere** Passwörter für deine Server verwenden
548
-
549
- ### 💡 **Best Practices**
550
-
551
- 1. **Error-Handling**: Immer try-catch für wichtige Operationen
552
- 2. **Rate-Limiting**: Nutze Smart Message Queue für Bulk-Messaging
553
- 3. **Session-Management**: Sessions ordentlich verwalten und löschen wenn nicht mehr benötigt
554
- 4. **Updates**: Regelmäßig auf Updates prüfen (automatisch aktiviert, nur einmal angezeigt)
555
-
556
- ---
118
+ `loadSessionsFromStorage()` liefert die erfolgreich geladenen Session-IDs zurueck.
557
119
 
558
- ## 🆕 Was ist neu in Version 1.5.1?
120
+ ## Verfuegbare Listener
559
121
 
560
- ### ✨ **Neue Features & Glow-Up**
122
+ - `onQRUpdated`
123
+ - `onConnected`
124
+ - `onDisconnected`
125
+ - `onConnecting`
126
+ - `onMessageReceived`
127
+ - `onMessageUpdate`
128
+ - `onPairingCode`
561
129
 
562
- - 📖 **README Glow-Up** – Version 1.5.1, Badges & Changelog
563
- - ✅ **Kompatibilität** mit **@neelegirl/baileys 2.0.4** & **Baileys API 1.7.2**
564
- - 🔔 **Update-Check** – Liest Version von **npm-Registry** (registry.npmjs.org), nur 1× pro Prozess
565
- - 📦 **Abhängigkeit** auf `@neelegirl/baileys@^2.0.4` (empfohlen 2.0.4)
566
- - 🚀 **Smart Queue Ready** · QR · Pairing · Auto-Reconnect
567
- - 💎 **Multi-Device** & Session-Management optimiert
130
+ ## Grenzen
568
131
 
569
- ### 🔄 **Verbesserungen**
132
+ - kein eingebauter HTTP-Server
133
+ - kein Queue-System
134
+ - keine Word2Web-spezifischen Features im Paket
135
+ - veroeffentlicht als vorgebaute `dist/`-Distribution
136
+ - das Low-Level-Verhalten kommt direkt aus `@neelegirl/baileys`
570
137
 
571
- - Semver-Vergleich für „Update verfügbar“ nur bei wirklich neuerer Version
572
- - Verbesserte Fehlerbehandlung & Stabilität
573
- - Schnellerer Verbindungsaufbau · Bessere LID-Unterstützung
574
-
575
- ---
576
-
577
- ## 💬 Support & Community
578
-
579
- <div align="center">
580
-
581
- ### 🌸 **Made with Love by @neelegirl** 🌸
582
-
583
- [![GitHub](https://img.shields.io/badge/GitHub-@neelegirl-pink?style=for-the-badge&logo=github)](https://github.com/neelegirl)
584
- [![Email](https://img.shields.io/badge/Email-Support-pink?style=for-the-badge&logo=gmail)](mailto:neelehoven@gmail.com)
585
- [![Docs](https://img.shields.io/badge/Docs-wa--api.org-pink?style=for-the-badge)](https://wa-api.org)
586
-
587
- **⭐ Wenn dir dieses Projekt gefällt, gib ihm ein Star auf GitHub! ⭐**
588
-
589
- </div>
590
-
591
- ---
592
-
593
- ## 📝 Changelog
594
-
595
- ### Version 1.5.1 (Aktuell) 🎉
596
-
597
- - 📖 **README Glow-Up** – Version 1.5.1, Baileys 2.0.5 Badges
598
- - 🔔 Update-Check von **npm-Registry** (registry.npmjs.org), nur 1× pro Prozess
599
- - ✨ Kompatibilität mit **@neelegirl/baileys 2.0.4** & **Baileys API 1.7.2**
600
- - 📦 Abhängigkeit `@neelegirl/baileys@^2.0.4`
601
-
602
- ### Version 1.3.2
603
-
604
- - 📖 **README Glow-Up** – Version 1.3.2, Baileys 2.0.2 Badges
605
- - 🔔 Update-Check von **npm-Registry** (registry.npmjs.org), nur 1× pro Prozess
606
- - ✨ Kompatibilität mit **@neelegirl/baileys 2.0.2** & **Baileys API 1.7.2**
607
- - 📦 Abhängigkeit `@neelegirl/baileys@^2.0.0`
608
- - 🚀 Smart Queue Ready · Semver-Vergleich für Update-Hinweis
609
- - 💎 Multi-Device & Session-Management optimiert
610
- - 🚀 Smart Queue Ready · Semver-Vergleich für Update-Hinweis
611
- - 💎 Multi-Device & Session-Management optimiert
612
-
613
- ### Version 1.3.1
614
-
615
- - 📖 README Glow-Up · Changelog · Baileys 2.0.2
616
-
617
- ### Version 1.2.5
618
-
619
- - 📖 README Glow-Up · Changelog
620
-
621
- ### Version 1.2.4
622
-
623
- - 📖 README Glow-Up · Changelog
624
-
625
- ### Version 1.2.3
626
-
627
- - 📖 README Glow-Up · Changelog
628
-
629
- ### Version 1.2.2
630
-
631
- - 📖 README Glow-Up · Changelog ergänzt
632
-
633
- ### Version 1.2.1
634
-
635
- - 📖 README Glow-Up · Update-Check von npm-Registry · Baileys 2.0.2 Badges
636
-
637
- ### Version 1.2.0
638
-
639
- - 📖 README Glow-Up · Baileys 2.0.0 Badges
640
- - ✨ Kompatibilität mit @neelegirl/baileys 2.0.0 & Baileys API 1.7.2
641
- - 🚀 Smart Queue Ready · Auto-Update-Check (1x pro Prozess)
642
-
643
- ### Version 1.1.1
644
-
645
- - 📖 README Glow-Up · Kompatibilität mit @neelegirl/baileys 1.7.1
646
- - 🚀 Smart Queue Ready, Auto-Update-Check
647
-
648
- ### Version 1.1.0
649
-
650
- - ✨ Kompatibilität mit @neelegirl/baileys 1.7.0
651
- - 🚀 Smart Queue Ready, Auto-Update-Check
652
-
653
- ### Version 1.0.10
654
-
655
- - ✨ Automatische Update-Prüfung hinzugefügt
656
- - 🎨 Verbesserte QR-Code-Anzeige
657
- - 🔄 Kompatibilität mit @neelegirl/baileys 1.6.6
658
- - 🚀 Verbesserte Stabilität
659
- - 🐛 Bugfixes für Session-Management
660
-
661
- ### Version 1.0.9
662
-
663
- - 🔔 Update-Benachrichtigung hinzugefügt
664
- - 💎 Optimierungen für Multi-Device
665
-
666
- ---
667
-
668
- <div align="center">
669
-
670
- ### ✨ *Stay kawaii, stay connected – Onimai forever!* ✨
671
-
672
- **🌸 Made with Love & Glitter 🌸**
673
-
674
- [⬆️ Nach oben](#-neelegirlwa-api)
138
+ ## Lizenz
675
139
 
676
- </div>
140
+ ISC