Skip to content

Commit 94a99c3

Browse files
committed
feat(release): release v1.2.0 version
2 parents d1bdbf4 + 07a615b commit 94a99c3

26 files changed

Lines changed: 564 additions & 198 deletions

.github/workflows/release.yml

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
name: Release
22

33
on:
4-
push:
5-
branches:
6-
- main
4+
push:
5+
branches:
6+
- main
77

88
permissions:
9-
contents: write
10-
issues: write
11-
pull-requests: write
9+
contents: write
10+
issues: write
11+
pull-requests: write
1212

1313
jobs:
14-
release:
15-
runs-on: ubuntu-latest
16-
steps:
17-
- name: Checkout code
18-
uses: actions/checkout@v2
19-
20-
- name: Set up Node.js
21-
uses: actions/setup-node@v4
22-
with:
23-
node-version: 'lts/*'
24-
25-
- name: Install dependencies
26-
run: npm install
27-
28-
- name: Build package
29-
run: npm run build
30-
31-
- name: Run audit
32-
run: npm audit signatures
33-
34-
- name: Release
35-
env:
36-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
38-
run: npx semantic-release
14+
release:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v2
19+
20+
- name: Set up Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: 'lts/*'
24+
25+
- name: Install dependencies
26+
run: npm install
27+
28+
- name: Build package
29+
run: npm run build
30+
31+
- name: Run audit
32+
run: npm audit signatures
33+
34+
- name: Release
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
38+
run: npx semantic-release

.prettierrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"tabWidth": 4,
5+
"trailingComma": "es5",
6+
"printWidth": 120
7+
}

Example/example.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import WhatsMulti from '../src';
2+
3+
// Start the WhatsMulti example
4+
const start = async () => {
5+
const client = new WhatsMulti({
6+
mongoUri: 'mongodb://localhost:27017/whatsmulti',
7+
});
8+
9+
// Create the first session with local storage
10+
await client.createSession('session-1', 'mongodb');
11+
12+
// Event listeners for session status changes
13+
client.on('disconnected', (_, sessionId) => console.log(sessionId, 'is Disconnected.'));
14+
client.on('connecting', (_, sessionId) => console.log(sessionId, 'is Connecting...'));
15+
client.on('connected', (_, sessionId) => console.log(sessionId, 'is Connected.'));
16+
17+
// Listen for QR Code event and log it
18+
client.on('qr', (data) => console.log(data));
19+
20+
// Listen for incoming messages
21+
client.on('messages.upsert', (data, sessionId) => {
22+
const msg = data.messages[0];
23+
if (msg.key.fromMe) return; // Ignore messages sent by the bot
24+
25+
const text = msg.message?.conversation || '';
26+
const command = text.split(' ')[0]; // Extract command from message
27+
28+
switch (command) {
29+
case 'status':
30+
// Get and send the session status
31+
const status = client.getSessionStatus(sessionId);
32+
client.sendMessage(sessionId, msg, {
33+
text: `Status: ${sessionId} is ${status}`,
34+
});
35+
break;
36+
37+
case 'allsessions':
38+
// List all active sessions
39+
const sessions = client.getSessions();
40+
client.sendMessage(sessionId, msg, {
41+
text: `Total Sessions: ${sessions.length}\n${sessions.join('\n')}`,
42+
});
43+
break;
44+
45+
case 'create':
46+
// Create a new session dynamically
47+
let newSessionIdVar = text.split(' ')[1] || 'session-2';
48+
client.createSession(newSessionIdVar, 'local', {
49+
printQRInTerminal: false,
50+
});
51+
52+
// Send QR code when it's generated
53+
client.on('qr', (data, newSessionId) => {
54+
if (newSessionId === newSessionIdVar) {
55+
const base64Data = data.image.replace(/^data:image\/png;base64,/, '');
56+
const buffer = Buffer.from(base64Data, 'base64');
57+
client.sendMessage(sessionId, msg, {
58+
image: buffer,
59+
caption: 'Scan QR Code.',
60+
});
61+
}
62+
});
63+
64+
// Notify when the session is connected
65+
client.on('connected', (_, newSessionId) => {
66+
if (newSessionId === newSessionIdVar) {
67+
client.sendMessage(sessionId, msg, {
68+
text: `Session ${newSessionIdVar} is Connected.`,
69+
});
70+
}
71+
});
72+
break;
73+
74+
case 'delete':
75+
// Delete an existing session
76+
sessionId = text.split(' ')[1] || 'session-1';
77+
client.deleteSession(sessionId);
78+
client.sendMessage(sessionId, msg, {
79+
text: `Session ${sessionId} has been deleted.`,
80+
});
81+
break;
82+
83+
case 'send':
84+
// Send a message to a specific session
85+
sessionId = text.split(' ')[1] || 'session-1';
86+
const message = text.split(' ').slice(2).join(' ');
87+
client.sendMessage(sessionId, msg, {
88+
text: message,
89+
});
90+
break;
91+
}
92+
});
93+
};
94+
95+
// Start the example
96+
start();

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# @Dutakey/WhatsMulti
2+
3+
## 📌 Overview
4+
5+
@Dutakey/WhatsMulti is a wrapper for [@whiskeysockets/baileys](https://github.com/WhiskeySockets/Baileys), designed to efficiently manage multiple WhatsApp Web sessions. It offers advanced session handling, flexible event listeners, and various storage options, making it ideal for developers integrating WhatsApp into their applications.
6+
7+
## 🚀 Installation
8+
9+
Install via npm:
10+
11+
```sh
12+
npm install @dutakey/whatsmulti
13+
```
14+
15+
Or using yarn:
16+
17+
```sh
18+
yarn add @dutakey/whatsmulti
19+
```
20+
21+
## ✨ Key Features
22+
23+
- **Seamless Multi-Session Management**: Effortlessly create, manage, and maintain multiple WhatsApp sessions.
24+
- **Flexible Storage Options**: Store sessions locally or integrate with databases like MongoDB and Supabase.
25+
- **Robust Event Handling**: Easily handle events across multiple sessions for real-time monitoring.
26+
27+
## 📂 Examples
28+
29+
Check the [`example`](./Example/example.ts) folder for usage examples.
30+
31+
## 🎯 Contributing
32+
33+
Contributions are welcome! If you find a bug, have feature suggestions, or want to improve the project, feel free to open an issue or submit a pull request.
34+
35+
## 📄 License
36+
37+
This project is licensed under **MIT**, allowing free use, modification, and distribution.

package.json

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,38 @@
66
"main": "lib/index.js",
77
"types": "lib/index.d.ts",
88
"files": [
9-
"lib/*",
10-
"README.md"
9+
"lib/*",
10+
"README.md"
1111
],
1212
"publishConfig": {
13-
"access": "public"
13+
"access": "public"
1414
},
1515
"dependencies": {
16-
"@whiskeysockets/baileys": "^6.7.9",
17-
"pino": "^7.0.0",
18-
"pino-pretty": "^13.0.0",
19-
"qrcode-terminal": "^0.12.0"
16+
"@whiskeysockets/baileys": "^6.7.16",
17+
"mongoose": "^8.13.2",
18+
"pino": "^7.11.0",
19+
"pino-pretty": "^13.0.0",
20+
"qrcode": "^1.5.4",
21+
"qrcode-terminal": "^0.12.0"
2022
},
2123
"devDependencies": {
22-
"semantic-release": "^24.2.1",
23-
"typescript": "^5.7.2"
24+
"semantic-release": "^24.2.3",
25+
"typescript": "^5.8.3"
2426
},
2527
"scripts": {
26-
"build": "tsc",
27-
"semantic-release": "semantic-release"
28+
"build": "tsc",
29+
"semantic-release": "semantic-release"
2830
},
2931
"repository": {
30-
"type": "git",
31-
"url": "git+https://github.com/DutaKey/WhatsMulti.git"
32+
"type": "git",
33+
"url": "git+https://github.com/DutaKey/WhatsMulti.git"
3234
},
3335
"keywords": [
34-
"whatsapp"
36+
"whatsapp"
3537
],
3638
"license": "MIT",
3739
"bugs": {
38-
"url": "https://github.com/DutaKey/WhatsMulti/issues"
40+
"url": "https://github.com/DutaKey/WhatsMulti/issues"
3941
},
4042
"homepage": "https://github.com/DutaKey/WhatsMulti#readme"
41-
}
43+
}

release.config.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module.exports = {
2-
branches: ["main"],
3-
}
2+
branches: ['main'],
3+
};

src/Defaults/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export const LOCAL_CONNECTION_PATH = "whatsmulti_session";
1+
export const LOCAL_CONNECTION_PATH = 'whatsmulti_session';
22

3-
export const DEFAULT_CONNECTION_TYPE = "local";
3+
export const DEFAULT_CONNECTION_TYPE = 'local';

src/Handlers/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import { WASocket } from '@whiskeysockets/baileys';
22
import { events } from '../Stores';
33
import { EventMap, EventMapKey } from '../Types/Event';
44

5-
export const on = <K extends EventMapKey>(eventKey: K, e: (data: EventMap[K], sessionId: string, sock: WASocket) => any) => {
5+
export const on = <K extends EventMapKey>(
6+
eventKey: K,
7+
e: (data: EventMap[K], sessionId: string, sock: WASocket) => any
8+
) => {
69
events.set(eventKey, e);
7-
}
10+
};
811

912
// export const process = (
1013
// e: (data: EventMap[EventMapKey], sessionId: string, sock: WASocket) => any

src/Handlers/socket.ts

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,57 @@
1-
import { DisconnectReason } from "@whiskeysockets/baileys";
1+
import QRCode from 'qrcode';
2+
import { DisconnectReason } from '@whiskeysockets/baileys';
23
import { Boom } from '@hapi/boom';
3-
import { EventHandlerType, EventMapKey } from "../Types/Event";
4-
import { events, sessions } from "../Stores";
5-
import { createSession, deleteSession } from "../Services";
6-
import { SessionStatusType } from "../Types/Session";
4+
import { EventHandlerType, EventMapKey } from '../Types/Event';
5+
import { events, sessions } from '../Stores';
6+
import { createSession, deleteSession } from '../Services/sessions';
7+
import { SessionStatusType } from '../Types/Session';
78

89
export const handleSocketEvents = ({ sessionId, eventMap, sock, saveCreds }: EventHandlerType) => {
9-
Object.entries(eventMap).forEach(([key, value]) => {
10-
events.get(key as EventMapKey)?.(value, sessionId, sock);
11-
eventHandlers[key]?.({ eventValue: value, sessionId, sock, saveCreds });
10+
Object.entries(eventMap).forEach(([key, data]) => {
11+
events.get(key as EventMapKey)?.(data, sessionId, sock);
12+
eventHandlers[key]?.({ eventValue: data, sessionId, sock, saveCreds });
1213
});
1314
};
1415

15-
1616
const handleConnectionUpdate = ({ eventValue, sessionId }): void => {
1717
const { connection, lastDisconnect, qr } = eventValue;
18-
const sessionData = sessions.get(sessionId);
18+
const session = sessions.get(sessionId);
1919

2020
if (qr) {
21-
events.get("qr")?.(qr, sessionId);
22-
} else if(connection) {
21+
QRCode.toDataURL(qr).then((qrUrl: String) => {
22+
events.get('qr')?.({ image: qrUrl, qr }, sessionId);
23+
});
24+
} else if (connection) {
2325
updateSessionStatus(sessionId, connection as SessionStatusType);
26+
27+
const isLoggedOut = (lastDisconnect?.error as Boom)?.output?.statusCode === DisconnectReason.loggedOut;
2428
if (connection === 'close') {
25-
const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut;
26-
if (shouldReconnect && sessionData) {
27-
const args = { sessionId, connectionType: sessionData.connectionType, options: sessionData.options }
28-
createSession(args)
29+
if (!isLoggedOut && session) {
30+
createSession(sessionId, session.connectionType, session.meta.socketConfig, session.meta.options);
2931
} else {
3032
deleteSession(sessionId);
3133
events.get('disconnected')?.({}, sessionId);
3234
}
33-
} else if(connection === 'connecting') {
35+
} else if (connection === 'connecting') {
3436
events.get('connecting')?.({}, sessionId);
35-
}
36-
else if (connection === 'open') {
37+
} else if (connection === 'open') {
3738
events.get('connected')?.({}, sessionId);
3839
}
3940
}
40-
}
41+
};
4142

4243
const handleCredsUpdate = ({ saveCreds }) => {
4344
saveCreds();
44-
}
45+
};
4546

4647
const eventHandlers: { [key: string]: Function } = {
47-
"creds.update": handleCredsUpdate,
48-
"connection.update": handleConnectionUpdate,
48+
'creds.update': handleCredsUpdate,
49+
'connection.update': handleConnectionUpdate,
4950
};
5051

5152
const updateSessionStatus = (sessionId: string, status: SessionStatusType): void => {
5253
const session = sessions.get(sessionId);
5354
if (session) {
5455
session.status = status;
5556
}
56-
}
57+
};

0 commit comments

Comments
 (0)