@roidev/kachina-md 2.1.0 → 2.1.1
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/lib/client/Client.js +283 -7
- package/lib/handlers/PluginHandler.js +110 -0
- package/lib/helpers/database.js +140 -0
- package/lib/helpers/index.js +85 -0
- package/lib/helpers/logger.js +69 -0
- package/lib/helpers/serialize.js +43 -0
- package/lib/helpers/sticker.js +52 -7
- package/lib/index.d.ts +265 -0
- package/package.json +4 -2
package/lib/helpers/database.js
CHANGED
|
@@ -3,7 +3,27 @@ import { JSONFile } from 'lowdb/node';
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} DatabaseOptions
|
|
8
|
+
* @property {string} [path='./database'] - Path to database directory
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Simple JSON-based database wrapper using LowDB
|
|
13
|
+
* Provides key-value storage organized by collections
|
|
14
|
+
* Each collection is stored as a separate JSON file
|
|
15
|
+
*
|
|
16
|
+
* @class Database
|
|
17
|
+
* @example
|
|
18
|
+
* const db = new Database({ path: './data' });
|
|
19
|
+
* await db.set('users', 'john', { name: 'John', age: 30 });
|
|
20
|
+
* const user = await db.get('users', 'john');
|
|
21
|
+
*/
|
|
6
22
|
export class Database {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new Database instance
|
|
25
|
+
* @param {DatabaseOptions} [options={}] - Database configuration
|
|
26
|
+
*/
|
|
7
27
|
constructor(options = {}) {
|
|
8
28
|
this.path = options.path || './database';
|
|
9
29
|
this.collections = new Map();
|
|
@@ -14,6 +34,17 @@ export class Database {
|
|
|
14
34
|
}
|
|
15
35
|
}
|
|
16
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Get or create a collection (LowDB instance)
|
|
39
|
+
* @async
|
|
40
|
+
* @param {string} name - Collection name (becomes filename)
|
|
41
|
+
* @param {Object} [defaultData={}] - Default data if collection doesn't exist
|
|
42
|
+
* @returns {Promise<Low>} LowDB instance
|
|
43
|
+
* @example
|
|
44
|
+
* const usersDb = await db.collection('users');
|
|
45
|
+
* usersDb.data.john = { name: 'John' };
|
|
46
|
+
* await usersDb.write();
|
|
47
|
+
*/
|
|
17
48
|
async collection(name, defaultData = {}) {
|
|
18
49
|
if (this.collections.has(name)) {
|
|
19
50
|
return this.collections.get(name);
|
|
@@ -31,12 +62,34 @@ export class Database {
|
|
|
31
62
|
return db;
|
|
32
63
|
}
|
|
33
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Get a value from collection
|
|
67
|
+
* @async
|
|
68
|
+
* @template T
|
|
69
|
+
* @param {string} collection - Collection name
|
|
70
|
+
* @param {string} key - Key to retrieve
|
|
71
|
+
* @param {T} [defaultValue=null] - Default value if key doesn't exist
|
|
72
|
+
* @returns {Promise<T>} Value or default value
|
|
73
|
+
* @example
|
|
74
|
+
* const user = await db.get('users', 'john', { name: 'Unknown' });
|
|
75
|
+
*/
|
|
34
76
|
async get(collection, key, defaultValue = null) {
|
|
35
77
|
const db = await this.collection(collection, {});
|
|
36
78
|
await db.read();
|
|
37
79
|
return db.data[key] ?? defaultValue;
|
|
38
80
|
}
|
|
39
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Set a value in collection
|
|
84
|
+
* @async
|
|
85
|
+
* @template T
|
|
86
|
+
* @param {string} collection - Collection name
|
|
87
|
+
* @param {string} key - Key to set
|
|
88
|
+
* @param {T} value - Value to store
|
|
89
|
+
* @returns {Promise<T>} The value that was set
|
|
90
|
+
* @example
|
|
91
|
+
* await db.set('users', 'john', { name: 'John', age: 30 });
|
|
92
|
+
*/
|
|
40
93
|
async set(collection, key, value) {
|
|
41
94
|
const db = await this.collection(collection, {});
|
|
42
95
|
await db.read();
|
|
@@ -45,12 +98,32 @@ export class Database {
|
|
|
45
98
|
return value;
|
|
46
99
|
}
|
|
47
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Check if key exists in collection
|
|
103
|
+
* @async
|
|
104
|
+
* @param {string} collection - Collection name
|
|
105
|
+
* @param {string} key - Key to check
|
|
106
|
+
* @returns {Promise<boolean>} True if key exists
|
|
107
|
+
* @example
|
|
108
|
+
* if (await db.has('users', 'john')) {
|
|
109
|
+
* console.log('User exists');
|
|
110
|
+
* }
|
|
111
|
+
*/
|
|
48
112
|
async has(collection, key) {
|
|
49
113
|
const db = await this.collection(collection, {});
|
|
50
114
|
await db.read();
|
|
51
115
|
return key in db.data;
|
|
52
116
|
}
|
|
53
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Delete a key from collection
|
|
120
|
+
* @async
|
|
121
|
+
* @param {string} collection - Collection name
|
|
122
|
+
* @param {string} key - Key to delete
|
|
123
|
+
* @returns {Promise<boolean>} True if successful
|
|
124
|
+
* @example
|
|
125
|
+
* await db.delete('users', 'john');
|
|
126
|
+
*/
|
|
54
127
|
async delete(collection, key) {
|
|
55
128
|
const db = await this.collection(collection, {});
|
|
56
129
|
await db.read();
|
|
@@ -59,12 +132,29 @@ export class Database {
|
|
|
59
132
|
return true;
|
|
60
133
|
}
|
|
61
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Get all data from collection
|
|
137
|
+
* @async
|
|
138
|
+
* @param {string} collection - Collection name
|
|
139
|
+
* @returns {Promise<Object>} All collection data
|
|
140
|
+
* @example
|
|
141
|
+
* const allUsers = await db.all('users');
|
|
142
|
+
* console.log(Object.keys(allUsers)); // ['john', 'jane', ...]
|
|
143
|
+
*/
|
|
62
144
|
async all(collection) {
|
|
63
145
|
const db = await this.collection(collection, {});
|
|
64
146
|
await db.read();
|
|
65
147
|
return db.data;
|
|
66
148
|
}
|
|
67
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Clear all data from collection
|
|
152
|
+
* @async
|
|
153
|
+
* @param {string} collection - Collection name
|
|
154
|
+
* @returns {Promise<boolean>} True if successful
|
|
155
|
+
* @example
|
|
156
|
+
* await db.clear('users'); // Removes all users
|
|
157
|
+
*/
|
|
68
158
|
async clear(collection) {
|
|
69
159
|
const db = await this.collection(collection, {});
|
|
70
160
|
db.data = {};
|
|
@@ -72,6 +162,19 @@ export class Database {
|
|
|
72
162
|
return true;
|
|
73
163
|
}
|
|
74
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Update a value in collection
|
|
167
|
+
* @async
|
|
168
|
+
* @param {string} collection - Collection name
|
|
169
|
+
* @param {string} key - Key to update
|
|
170
|
+
* @param {Function|Object} updater - Function that receives old value and returns new value, or object to merge
|
|
171
|
+
* @returns {Promise<*>} Updated value
|
|
172
|
+
* @example
|
|
173
|
+
* // Using function
|
|
174
|
+
* await db.update('users', 'john', (user) => ({ ...user, age: 31 }));
|
|
175
|
+
* // Using object merge
|
|
176
|
+
* await db.update('users', 'john', { age: 31 });
|
|
177
|
+
*/
|
|
75
178
|
async update(collection, key, updater) {
|
|
76
179
|
const db = await this.collection(collection, {});
|
|
77
180
|
await db.read();
|
|
@@ -86,6 +189,20 @@ export class Database {
|
|
|
86
189
|
return db.data[key];
|
|
87
190
|
}
|
|
88
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Increment a numeric field in a stored object
|
|
194
|
+
* @async
|
|
195
|
+
* @param {string} collection - Collection name
|
|
196
|
+
* @param {string} key - Key of object to update
|
|
197
|
+
* @param {string} field - Field name to increment
|
|
198
|
+
* @param {number} [amount=1] - Amount to increment by
|
|
199
|
+
* @returns {Promise<Object>} Updated object
|
|
200
|
+
* @example
|
|
201
|
+
* // Increment user score by 10
|
|
202
|
+
* await db.increment('users', 'john', 'score', 10);
|
|
203
|
+
* // Increment by 1 (default)
|
|
204
|
+
* await db.increment('users', 'john', 'loginCount');
|
|
205
|
+
*/
|
|
89
206
|
async increment(collection, key, field, amount = 1) {
|
|
90
207
|
return await this.update(collection, key, (data) => {
|
|
91
208
|
data = data || {};
|
|
@@ -94,6 +211,18 @@ export class Database {
|
|
|
94
211
|
});
|
|
95
212
|
}
|
|
96
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Push a value to an array
|
|
216
|
+
* @async
|
|
217
|
+
* @param {string} collection - Collection name
|
|
218
|
+
* @param {string} key - Key of array to update
|
|
219
|
+
* @param {*} value - Value to push
|
|
220
|
+
* @returns {Promise<Array>} Updated array
|
|
221
|
+
* @example
|
|
222
|
+
* await db.push('chats', 'john', 'Hello');
|
|
223
|
+
* await db.push('chats', 'john', 'How are you?');
|
|
224
|
+
* // chats.john = ['Hello', 'How are you?']
|
|
225
|
+
*/
|
|
97
226
|
async push(collection, key, value) {
|
|
98
227
|
return await this.update(collection, key, (data) => {
|
|
99
228
|
data = data || [];
|
|
@@ -104,6 +233,17 @@ export class Database {
|
|
|
104
233
|
});
|
|
105
234
|
}
|
|
106
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Remove a value from an array
|
|
238
|
+
* @async
|
|
239
|
+
* @param {string} collection - Collection name
|
|
240
|
+
* @param {string} key - Key of array to update
|
|
241
|
+
* @param {*} value - Value to remove
|
|
242
|
+
* @returns {Promise<Array>} Updated array
|
|
243
|
+
* @example
|
|
244
|
+
* await db.pull('chats', 'john', 'Hello');
|
|
245
|
+
* // Removes 'Hello' from the array
|
|
246
|
+
*/
|
|
107
247
|
async pull(collection, key, value) {
|
|
108
248
|
return await this.update(collection, key, (data) => {
|
|
109
249
|
if (Array.isArray(data)) {
|
package/lib/helpers/index.js
CHANGED
|
@@ -4,10 +4,27 @@ export { Logger } from './logger.js';
|
|
|
4
4
|
export * from './sticker.js';
|
|
5
5
|
|
|
6
6
|
// Utility functions
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sleep for specified milliseconds
|
|
10
|
+
* @param {number} ms - Milliseconds to sleep
|
|
11
|
+
* @returns {Promise<void>}
|
|
12
|
+
* @example
|
|
13
|
+
* await sleep(1000); // Sleep for 1 second
|
|
14
|
+
*/
|
|
7
15
|
export function sleep(ms) {
|
|
8
16
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
9
17
|
}
|
|
10
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Format seconds into human-readable time string
|
|
21
|
+
* @param {number} seconds - Seconds to format
|
|
22
|
+
* @returns {string} Formatted time string (e.g., "1d 2h 30m" or "5m 30s")
|
|
23
|
+
* @example
|
|
24
|
+
* formatTime(90); // "1m 30s"
|
|
25
|
+
* formatTime(3661); // "1h 1m 1s"
|
|
26
|
+
* formatTime(90000); // "1d 1h 0m"
|
|
27
|
+
*/
|
|
11
28
|
export function formatTime(seconds) {
|
|
12
29
|
const days = Math.floor(seconds / 86400);
|
|
13
30
|
const hours = Math.floor((seconds % 86400) / 3600);
|
|
@@ -20,6 +37,15 @@ export function formatTime(seconds) {
|
|
|
20
37
|
return `${secs}s`;
|
|
21
38
|
}
|
|
22
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Format bytes into human-readable size string
|
|
42
|
+
* @param {number} bytes - Bytes to format
|
|
43
|
+
* @returns {string} Formatted size string (e.g., "1.5 MB", "500 KB")
|
|
44
|
+
* @example
|
|
45
|
+
* formatBytes(1024); // "1 KB"
|
|
46
|
+
* formatBytes(1536000); // "1.46 MB"
|
|
47
|
+
* formatBytes(0); // "0 B"
|
|
48
|
+
*/
|
|
23
49
|
export function formatBytes(bytes) {
|
|
24
50
|
if (bytes === 0) return '0 B';
|
|
25
51
|
const k = 1024;
|
|
@@ -28,6 +54,16 @@ export function formatBytes(bytes) {
|
|
|
28
54
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
29
55
|
}
|
|
30
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Parse command from text message
|
|
59
|
+
* @param {string} text - Text to parse
|
|
60
|
+
* @param {string} [prefix='!'] - Command prefix
|
|
61
|
+
* @returns {{command: string, args: Array<string>, text: string}|null} Parsed command object or null if no command
|
|
62
|
+
* @example
|
|
63
|
+
* parseCommand('!help me', '!');
|
|
64
|
+
* // { command: 'help', args: ['me'], text: 'me' }
|
|
65
|
+
* parseCommand('hello'); // null
|
|
66
|
+
*/
|
|
31
67
|
export function parseCommand(text, prefix = '!') {
|
|
32
68
|
if (!text.startsWith(prefix)) return null;
|
|
33
69
|
|
|
@@ -39,15 +75,39 @@ export function parseCommand(text, prefix = '!') {
|
|
|
39
75
|
};
|
|
40
76
|
}
|
|
41
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Check if text is a URL
|
|
80
|
+
* @param {string} text - Text to check
|
|
81
|
+
* @returns {boolean} True if text is a URL
|
|
82
|
+
* @example
|
|
83
|
+
* isUrl('https://example.com'); // true
|
|
84
|
+
* isUrl('hello world'); // false
|
|
85
|
+
*/
|
|
42
86
|
export function isUrl(text) {
|
|
43
87
|
return /^https?:\/\//i.test(text);
|
|
44
88
|
}
|
|
45
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Extract all URLs from text
|
|
92
|
+
* @param {string} text - Text to extract URLs from
|
|
93
|
+
* @returns {Array<string>} Array of URLs found
|
|
94
|
+
* @example
|
|
95
|
+
* extractUrls('Visit https://example.com and http://test.com');
|
|
96
|
+
* // ['https://example.com', 'http://test.com']
|
|
97
|
+
*/
|
|
46
98
|
export function extractUrls(text) {
|
|
47
99
|
const urlRegex = /https?:\/\/[^\s]+/gi;
|
|
48
100
|
return text.match(urlRegex) || [];
|
|
49
101
|
}
|
|
50
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Generate random alphanumeric string
|
|
105
|
+
* @param {number} [length=10] - Length of string
|
|
106
|
+
* @returns {string} Random string
|
|
107
|
+
* @example
|
|
108
|
+
* randomString(5); // "aB3xZ"
|
|
109
|
+
* randomString(); // "a1B2c3D4e5" (10 chars)
|
|
110
|
+
*/
|
|
51
111
|
export function randomString(length = 10) {
|
|
52
112
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
53
113
|
let result = '';
|
|
@@ -57,14 +117,39 @@ export function randomString(length = 10) {
|
|
|
57
117
|
return result;
|
|
58
118
|
}
|
|
59
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Generate random number in range
|
|
122
|
+
* @param {number} min - Minimum value (inclusive)
|
|
123
|
+
* @param {number} max - Maximum value (inclusive)
|
|
124
|
+
* @returns {number} Random number
|
|
125
|
+
* @example
|
|
126
|
+
* randomNumber(1, 10); // Random number between 1 and 10
|
|
127
|
+
*/
|
|
60
128
|
export function randomNumber(min, max) {
|
|
61
129
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
62
130
|
}
|
|
63
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Pick random element from array
|
|
134
|
+
* @template T
|
|
135
|
+
* @param {Array<T>} array - Array to pick from
|
|
136
|
+
* @returns {T} Random element
|
|
137
|
+
* @example
|
|
138
|
+
* pickRandom(['red', 'blue', 'green']); // One of the colors
|
|
139
|
+
*/
|
|
64
140
|
export function pickRandom(array) {
|
|
65
141
|
return array[Math.floor(Math.random() * array.length)];
|
|
66
142
|
}
|
|
67
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Split array into chunks of specified size
|
|
146
|
+
* @template T
|
|
147
|
+
* @param {Array<T>} array - Array to chunk
|
|
148
|
+
* @param {number} size - Chunk size
|
|
149
|
+
* @returns {Array<Array<T>>} Array of chunks
|
|
150
|
+
* @example
|
|
151
|
+
* chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
|
|
152
|
+
*/
|
|
68
153
|
export function chunk(array, size) {
|
|
69
154
|
const chunks = [];
|
|
70
155
|
for (let i = 0; i < array.length; i += size) {
|
package/lib/helpers/logger.js
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} LoggerOptions
|
|
5
|
+
* @property {'debug'|'info'|'success'|'warn'|'error'} [level='info'] - Minimum log level to display
|
|
6
|
+
* @property {string} [prefix=''] - Prefix for all log messages
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Colored console logger with different log levels
|
|
11
|
+
* @class Logger
|
|
12
|
+
* @example
|
|
13
|
+
* const logger = new Logger({ prefix: 'MyBot', level: 'debug' });
|
|
14
|
+
* logger.info('Bot started');
|
|
15
|
+
* logger.success('Connected successfully');
|
|
16
|
+
* logger.error('Connection failed');
|
|
17
|
+
*/
|
|
3
18
|
export class Logger {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new Logger instance
|
|
21
|
+
* @param {LoggerOptions} [options={}] - Logger configuration
|
|
22
|
+
*/
|
|
4
23
|
constructor(options = {}) {
|
|
5
24
|
this.level = options.level || 'info';
|
|
6
25
|
this.prefix = options.prefix || '';
|
|
@@ -13,46 +32,96 @@ export class Logger {
|
|
|
13
32
|
};
|
|
14
33
|
}
|
|
15
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Check if message should be logged based on log level
|
|
37
|
+
* @private
|
|
38
|
+
* @param {string} level - Log level to check
|
|
39
|
+
* @returns {boolean} True if should log
|
|
40
|
+
*/
|
|
16
41
|
shouldLog(level) {
|
|
17
42
|
return this.levels[level] >= this.levels[this.level];
|
|
18
43
|
}
|
|
19
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Format log message with timestamp and prefix
|
|
47
|
+
* @private
|
|
48
|
+
* @param {string} level - Log level
|
|
49
|
+
* @param {...*} args - Arguments to format
|
|
50
|
+
* @returns {string} Formatted message
|
|
51
|
+
*/
|
|
20
52
|
format(level, ...args) {
|
|
21
53
|
const timestamp = new Date().toLocaleTimeString();
|
|
22
54
|
const prefix = this.prefix ? `[${this.prefix}] ` : '';
|
|
23
55
|
return `${chalk.gray(timestamp)} ${prefix}${args.join(' ')}`;
|
|
24
56
|
}
|
|
25
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Log debug message (gray)
|
|
60
|
+
* @param {...*} args - Values to log
|
|
61
|
+
* @example
|
|
62
|
+
* logger.debug('Debugging info', { data: 'value' });
|
|
63
|
+
*/
|
|
26
64
|
debug(...args) {
|
|
27
65
|
if (this.shouldLog('debug')) {
|
|
28
66
|
console.log(chalk.gray('[DEBUG]'), this.format('debug', ...args));
|
|
29
67
|
}
|
|
30
68
|
}
|
|
31
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Log info message (blue)
|
|
72
|
+
* @param {...*} args - Values to log
|
|
73
|
+
* @example
|
|
74
|
+
* logger.info('Bot started successfully');
|
|
75
|
+
*/
|
|
32
76
|
info(...args) {
|
|
33
77
|
if (this.shouldLog('info')) {
|
|
34
78
|
console.log(chalk.blue('[INFO]'), this.format('info', ...args));
|
|
35
79
|
}
|
|
36
80
|
}
|
|
37
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Log success message (green)
|
|
84
|
+
* @param {...*} args - Values to log
|
|
85
|
+
* @example
|
|
86
|
+
* logger.success('Connected to WhatsApp');
|
|
87
|
+
*/
|
|
38
88
|
success(...args) {
|
|
39
89
|
if (this.shouldLog('success')) {
|
|
40
90
|
console.log(chalk.green('[SUCCESS]'), this.format('success', ...args));
|
|
41
91
|
}
|
|
42
92
|
}
|
|
43
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Log warning message (yellow)
|
|
96
|
+
* @param {...*} args - Values to log
|
|
97
|
+
* @example
|
|
98
|
+
* logger.warn('Rate limit approaching');
|
|
99
|
+
*/
|
|
44
100
|
warn(...args) {
|
|
45
101
|
if (this.shouldLog('warn')) {
|
|
46
102
|
console.log(chalk.yellow('[WARN]'), this.format('warn', ...args));
|
|
47
103
|
}
|
|
48
104
|
}
|
|
49
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Log error message (red)
|
|
108
|
+
* @param {...*} args - Values to log
|
|
109
|
+
* @example
|
|
110
|
+
* logger.error('Connection failed:', error);
|
|
111
|
+
*/
|
|
50
112
|
error(...args) {
|
|
51
113
|
if (this.shouldLog('error')) {
|
|
52
114
|
console.error(chalk.red('[ERROR]'), this.format('error', ...args));
|
|
53
115
|
}
|
|
54
116
|
}
|
|
55
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Log command execution (cyan)
|
|
120
|
+
* @param {string} command - Command name
|
|
121
|
+
* @param {string} from - Sender information
|
|
122
|
+
* @example
|
|
123
|
+
* logger.command('!ping', 'User@s.whatsapp.net');
|
|
124
|
+
*/
|
|
56
125
|
command(command, from) {
|
|
57
126
|
console.log(
|
|
58
127
|
chalk.cyan('[CMD]'),
|
package/lib/helpers/serialize.js
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
import { downloadMediaMessage, getContentType } from 'baileys';
|
|
2
2
|
import { fileTypeFromBuffer } from 'file-type';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} SerializedMessage
|
|
6
|
+
* @property {Object} key - Message key
|
|
7
|
+
* @property {string} chat - Chat JID (remoteJid)
|
|
8
|
+
* @property {boolean} fromMe - Whether message is from bot
|
|
9
|
+
* @property {string} id - Message ID
|
|
10
|
+
* @property {boolean} isGroup - Whether chat is a group
|
|
11
|
+
* @property {string} sender - Sender JID
|
|
12
|
+
* @property {string} pushName - Sender push name
|
|
13
|
+
* @property {string} type - Message type (e.g., 'conversation', 'imageMessage')
|
|
14
|
+
* @property {Object} message - Raw message object
|
|
15
|
+
* @property {string} body - Message text content
|
|
16
|
+
* @property {SerializedMessage} [quoted] - Quoted/replied message
|
|
17
|
+
* @property {string} caption - Media caption
|
|
18
|
+
* @property {string} mimetype - Media mime type
|
|
19
|
+
* @property {number} fileSize - Media file size
|
|
20
|
+
* @property {Array<string>} mentions - Mentioned JIDs
|
|
21
|
+
* @property {Function} reply - Reply to message
|
|
22
|
+
* @property {Function} react - React to message with emoji
|
|
23
|
+
* @property {Function} download - Download media from message
|
|
24
|
+
* @property {Function} delete - Delete message
|
|
25
|
+
* @property {Function} forward - Forward message
|
|
26
|
+
* @property {Function} copyNForward - Copy and forward message
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Serialize raw Baileys message into standardized format with helper methods
|
|
31
|
+
* @async
|
|
32
|
+
* @param {Object} msg - Raw Baileys message object
|
|
33
|
+
* @param {Object} sock - WhatsApp socket instance
|
|
34
|
+
* @returns {Promise<SerializedMessage>} Serialized message object
|
|
35
|
+
* @example
|
|
36
|
+
* const m = await serialize(rawMessage, sock);
|
|
37
|
+
* console.log(m.body); // Message text
|
|
38
|
+
* await m.reply('Hello!'); // Reply to message
|
|
39
|
+
* await m.react('👍'); // React with emoji
|
|
40
|
+
*/
|
|
4
41
|
export async function serialize(msg, sock) {
|
|
5
42
|
if (!msg) return msg;
|
|
6
43
|
|
|
@@ -86,6 +123,12 @@ export async function serialize(msg, sock) {
|
|
|
86
123
|
return m;
|
|
87
124
|
}
|
|
88
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Extract text body from various message types
|
|
128
|
+
* @private
|
|
129
|
+
* @param {Object} message - Message object
|
|
130
|
+
* @returns {string} Extracted text content
|
|
131
|
+
*/
|
|
89
132
|
function getBody(message) {
|
|
90
133
|
if (!message) return '';
|
|
91
134
|
|
package/lib/helpers/sticker.js
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import { Sticker, StickerTypes } from 'wa-sticker-formatter';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} StickerOptions
|
|
5
|
+
* @property {string} [pack='Sticker'] - Sticker pack name
|
|
6
|
+
* @property {string} [author='Kachina Bot'] - Sticker author name
|
|
7
|
+
* @property {string} [type] - Sticker type (DEFAULT, FULL, CROPPED, CIRCLE, ROUNDED)
|
|
8
|
+
* @property {Array<string>} [categories=[]] - Sticker categories
|
|
9
|
+
* @property {string} [id=''] - Sticker ID
|
|
10
|
+
* @property {number} [quality=50] - Image quality (1-100)
|
|
11
|
+
* @property {string} [background='transparent'] - Background color
|
|
12
|
+
*/
|
|
13
|
+
|
|
3
14
|
/**
|
|
4
15
|
* Create sticker from image/video buffer
|
|
5
|
-
* @
|
|
6
|
-
* @param {
|
|
7
|
-
* @
|
|
16
|
+
* @async
|
|
17
|
+
* @param {Buffer|string} buffer - Image or video buffer, or file path/URL
|
|
18
|
+
* @param {StickerOptions} [options={}] - Sticker configuration options
|
|
19
|
+
* @returns {Promise<Buffer>} Sticker buffer ready to send
|
|
20
|
+
* @example
|
|
21
|
+
* const stickerBuffer = await createSticker(imageBuffer, {
|
|
22
|
+
* pack: 'My Stickers',
|
|
23
|
+
* author: 'My Bot',
|
|
24
|
+
* type: StickerTypes.FULL
|
|
25
|
+
* });
|
|
8
26
|
*/
|
|
9
27
|
export async function createSticker(buffer, options = {}) {
|
|
10
28
|
const sticker = new Sticker(buffer, {
|
|
@@ -21,7 +39,16 @@ export async function createSticker(buffer, options = {}) {
|
|
|
21
39
|
}
|
|
22
40
|
|
|
23
41
|
/**
|
|
24
|
-
* Create full sticker (
|
|
42
|
+
* Create full sticker without cropping (preserves original aspect ratio)
|
|
43
|
+
* @async
|
|
44
|
+
* @param {Buffer|string} buffer - Image or video buffer, or file path/URL
|
|
45
|
+
* @param {StickerOptions} [options={}] - Sticker configuration options
|
|
46
|
+
* @returns {Promise<Buffer>} Full sticker buffer
|
|
47
|
+
* @example
|
|
48
|
+
* const sticker = await createFullSticker(imageBuffer, {
|
|
49
|
+
* pack: 'My Pack',
|
|
50
|
+
* author: 'Bot'
|
|
51
|
+
* });
|
|
25
52
|
*/
|
|
26
53
|
export async function createFullSticker(buffer, options = {}) {
|
|
27
54
|
return await createSticker(buffer, {
|
|
@@ -31,7 +58,13 @@ export async function createFullSticker(buffer, options = {}) {
|
|
|
31
58
|
}
|
|
32
59
|
|
|
33
60
|
/**
|
|
34
|
-
* Create cropped sticker
|
|
61
|
+
* Create cropped sticker (1:1 aspect ratio, center-cropped)
|
|
62
|
+
* @async
|
|
63
|
+
* @param {Buffer|string} buffer - Image or video buffer, or file path/URL
|
|
64
|
+
* @param {StickerOptions} [options={}] - Sticker configuration options
|
|
65
|
+
* @returns {Promise<Buffer>} Cropped sticker buffer
|
|
66
|
+
* @example
|
|
67
|
+
* const sticker = await createCroppedSticker(imageBuffer);
|
|
35
68
|
*/
|
|
36
69
|
export async function createCroppedSticker(buffer, options = {}) {
|
|
37
70
|
return await createSticker(buffer, {
|
|
@@ -41,7 +74,13 @@ export async function createCroppedSticker(buffer, options = {}) {
|
|
|
41
74
|
}
|
|
42
75
|
|
|
43
76
|
/**
|
|
44
|
-
* Create circle sticker
|
|
77
|
+
* Create circle-shaped sticker
|
|
78
|
+
* @async
|
|
79
|
+
* @param {Buffer|string} buffer - Image or video buffer, or file path/URL
|
|
80
|
+
* @param {StickerOptions} [options={}] - Sticker configuration options
|
|
81
|
+
* @returns {Promise<Buffer>} Circle sticker buffer
|
|
82
|
+
* @example
|
|
83
|
+
* const sticker = await createCircleSticker(profilePicBuffer);
|
|
45
84
|
*/
|
|
46
85
|
export async function createCircleSticker(buffer, options = {}) {
|
|
47
86
|
return await createSticker(buffer, {
|
|
@@ -51,7 +90,13 @@ export async function createCircleSticker(buffer, options = {}) {
|
|
|
51
90
|
}
|
|
52
91
|
|
|
53
92
|
/**
|
|
54
|
-
* Create rounded
|
|
93
|
+
* Create sticker with rounded corners
|
|
94
|
+
* @async
|
|
95
|
+
* @param {Buffer|string} buffer - Image or video buffer, or file path/URL
|
|
96
|
+
* @param {StickerOptions} [options={}] - Sticker configuration options
|
|
97
|
+
* @returns {Promise<Buffer>} Rounded sticker buffer
|
|
98
|
+
* @example
|
|
99
|
+
* const sticker = await createRoundedSticker(imageBuffer);
|
|
55
100
|
*/
|
|
56
101
|
export async function createRoundedSticker(buffer, options = {}) {
|
|
57
102
|
return await createSticker(buffer, {
|