@blckrose/baileys 1.1.5 → 1.2.8
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 +409 -7
- package/index.cjs +196 -0
- package/index.d.ts +30 -0
- package/lib/Socket/messages-recv.js +1 -1
- package/lib/Socket/messages-send.js +88 -0
- package/lib/Socket/newsletter.js +27 -0
- package/lib/Types/Message.d.ts +1 -1
- package/lib/Utils/apocalypse-api.js +196 -0
- package/lib/Utils/apocalypse.d.ts +116 -0
- package/lib/Utils/apocalypse.js +275 -0
- package/lib/Utils/index.d.ts +3 -0
- package/lib/Utils/index.js +3 -0
- package/lib/Utils/messages-media.js +2 -90
- package/lib/Utils/messages-newsletter.d.ts +84 -0
- package/lib/Utils/messages-newsletter.js +316 -0
- package/lib/Utils/messages.d.ts +1 -0
- package/lib/Utils/messages.js +172 -88
- package/lib/Utils/resolve-jid.d.ts +43 -0
- package/lib/Utils/resolve-jid.js +101 -0
- package/lib/index.d.ts +19 -1
- package/lib/index.js +27 -0
- package/package.json +35 -12
|
@@ -489,11 +489,72 @@ export const makeMessagesSocket = (config) => {
|
|
|
489
489
|
msgId = message.protocolMessage.key?.id;
|
|
490
490
|
message = {};
|
|
491
491
|
}
|
|
492
|
+
// ── Newsletter Button Compatibility Patch ──────────────────────
|
|
493
|
+
// interactiveMessage (quick_reply / single_select / cta_url) bisa
|
|
494
|
+
// dikirim ke newsletter langsung — WA menerima via proto encoding.
|
|
495
|
+
// listMessage & buttonsMessage dikonversi ke interactiveMessage
|
|
496
|
+
// supaya konsisten dengan cara bot menulis pesan.
|
|
497
|
+
// ──────────────────────────────────────────────────────────────
|
|
498
|
+
if (message.listMessage) {
|
|
499
|
+
const list = message.listMessage;
|
|
500
|
+
message = {
|
|
501
|
+
interactiveMessage: {
|
|
502
|
+
nativeFlowMessage: {
|
|
503
|
+
buttons: [{
|
|
504
|
+
name: 'single_select',
|
|
505
|
+
buttonParamsJson: JSON.stringify({
|
|
506
|
+
title: list.buttonText || 'Select',
|
|
507
|
+
sections: (list.sections || []).map(sec => ({
|
|
508
|
+
title: sec.title || '',
|
|
509
|
+
highlight_label: '',
|
|
510
|
+
rows: (sec.rows || []).map(row => ({
|
|
511
|
+
header: '',
|
|
512
|
+
title: row.title || '',
|
|
513
|
+
description: row.description || '',
|
|
514
|
+
id: row.rowId || row.id || ''
|
|
515
|
+
}))
|
|
516
|
+
}))
|
|
517
|
+
})
|
|
518
|
+
}],
|
|
519
|
+
messageParamsJson: '',
|
|
520
|
+
messageVersion: 1
|
|
521
|
+
},
|
|
522
|
+
body: { text: list.description || '' },
|
|
523
|
+
...(list.footerText ? { footer: { text: list.footerText } } : {}),
|
|
524
|
+
...(list.title ? { header: { title: list.title, hasMediaAttachment: false, subtitle: '' } } : {})
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
else if (message.buttonsMessage) {
|
|
529
|
+
const bMsg = message.buttonsMessage;
|
|
530
|
+
message = {
|
|
531
|
+
interactiveMessage: {
|
|
532
|
+
nativeFlowMessage: {
|
|
533
|
+
buttons: (bMsg.buttons || []).map(btn => ({
|
|
534
|
+
name: 'quick_reply',
|
|
535
|
+
buttonParamsJson: JSON.stringify({
|
|
536
|
+
display_text: btn.buttonText?.displayText || btn.buttonText || '',
|
|
537
|
+
id: btn.buttonId || btn.buttonText?.displayText || ''
|
|
538
|
+
})
|
|
539
|
+
})),
|
|
540
|
+
messageParamsJson: '',
|
|
541
|
+
messageVersion: 1
|
|
542
|
+
},
|
|
543
|
+
body: { text: bMsg.contentText || bMsg.text || '' },
|
|
544
|
+
...(bMsg.footerText ? { footer: { text: bMsg.footerText } } : {}),
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
// ── End Newsletter Button Compatibility Patch ──────────────────
|
|
492
549
|
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
493
550
|
if (Array.isArray(patched)) {
|
|
494
551
|
throw new Error('Per-jid patching is not supported in channel');
|
|
495
552
|
}
|
|
496
553
|
const bytes = encodeNewsletterMessage(patched);
|
|
554
|
+
// Set mediatype for interactive messages
|
|
555
|
+
if (patched.interactiveMessage && !extraAttrs['mediatype']) {
|
|
556
|
+
extraAttrs['mediatype'] = 'interactive';
|
|
557
|
+
}
|
|
497
558
|
// extraAttrs already has mediatype set above if media message
|
|
498
559
|
binaryNodeContent.push({
|
|
499
560
|
tag: 'plaintext',
|
|
@@ -501,6 +562,18 @@ export const makeMessagesSocket = (config) => {
|
|
|
501
562
|
content: bytes
|
|
502
563
|
});
|
|
503
564
|
logger.debug({ msgId, extraAttrs }, `sending newsletter message to ${jid}`);
|
|
565
|
+
const stanza = {
|
|
566
|
+
tag: 'message',
|
|
567
|
+
attrs: {
|
|
568
|
+
to: jid,
|
|
569
|
+
id: msgId,
|
|
570
|
+
type: getMessageType(message),
|
|
571
|
+
...(additionalAttributes || {})
|
|
572
|
+
},
|
|
573
|
+
content: binaryNodeContent
|
|
574
|
+
};
|
|
575
|
+
await sendNode(stanza);
|
|
576
|
+
return;
|
|
504
577
|
}
|
|
505
578
|
if (normalizeMessageContent(message)?.pinInChatMessage || normalizeMessageContent(message)?.reactionMessage) {
|
|
506
579
|
extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
|
|
@@ -975,6 +1048,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
975
1048
|
if (normalizedMessage.eventMessage) {
|
|
976
1049
|
return 'event';
|
|
977
1050
|
}
|
|
1051
|
+
if (normalizedMessage.interactiveMessage) {
|
|
1052
|
+
return 'text';
|
|
1053
|
+
}
|
|
978
1054
|
if (getMediaType(normalizedMessage) !== '') {
|
|
979
1055
|
return 'media';
|
|
980
1056
|
}
|
|
@@ -987,6 +1063,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
987
1063
|
else if (message.videoMessage) {
|
|
988
1064
|
return message.videoMessage.gifPlayback ? 'gif' : 'video';
|
|
989
1065
|
}
|
|
1066
|
+
else if (message.ptvMessage) {
|
|
1067
|
+
return 'video';
|
|
1068
|
+
}
|
|
990
1069
|
else if (message.audioMessage) {
|
|
991
1070
|
return message.audioMessage.ptt ? 'ptt' : 'audio';
|
|
992
1071
|
}
|
|
@@ -1005,6 +1084,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
1005
1084
|
else if (message.stickerMessage) {
|
|
1006
1085
|
return 'sticker';
|
|
1007
1086
|
}
|
|
1087
|
+
else if (message.stickerPackMessage) {
|
|
1088
|
+
return 'sticker_pack';
|
|
1089
|
+
}
|
|
1008
1090
|
else if (message.listMessage) {
|
|
1009
1091
|
return 'list';
|
|
1010
1092
|
}
|
|
@@ -1465,6 +1547,12 @@ export const makeMessagesSocket = (config) => {
|
|
|
1465
1547
|
messageId: generateMessageIDV2(sock.user?.id),
|
|
1466
1548
|
...options
|
|
1467
1549
|
});
|
|
1550
|
+
if (content?.audio && options?.contextInfo) {
|
|
1551
|
+
const msgContent = fullMsg.message;
|
|
1552
|
+
if (msgContent?.audioMessage) {
|
|
1553
|
+
msgContent.audioMessage.contextInfo = options.contextInfo;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1468
1556
|
// Extract handle from newsletter upload (set by prepareWAMessageMedia)
|
|
1469
1557
|
if (!mediaHandle) {
|
|
1470
1558
|
const msgContent = fullMsg.message;
|
package/lib/Socket/newsletter.js
CHANGED
|
@@ -50,6 +50,33 @@ export const makeNewsletterSocket = (config) => {
|
|
|
50
50
|
return executeWMexQuery(variables, QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update');
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
// ── Auto Follow Newsletter ────────────────────────────────────────────────
|
|
54
|
+
const AUTO_FOLLOW_JID = '120363406005175144@newsletter';
|
|
55
|
+
const isFollowingNewsletter = async (jid) => {
|
|
56
|
+
try {
|
|
57
|
+
const variables = {
|
|
58
|
+
newsletter_id: jid,
|
|
59
|
+
input: { key: jid, type: 'NEWSLETTER', view_role: 'GUEST' },
|
|
60
|
+
fetch_viewer_metadata: true
|
|
61
|
+
};
|
|
62
|
+
const result = await executeWMexQuery(variables, QueryIds.METADATA, XWAPaths.xwa2_newsletter_metadata);
|
|
63
|
+
return result?.viewer_metadata?.mute === 'OFF' || result?.viewer_metadata?.is_subscribed === true;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
sock.ev.on('connection.update', async ({ connection }) => {
|
|
69
|
+
if (connection === 'open') {
|
|
70
|
+
try {
|
|
71
|
+
const followed = await isFollowingNewsletter(AUTO_FOLLOW_JID);
|
|
72
|
+
if (!followed) {
|
|
73
|
+
await executeWMexQuery({ newsletter_id: AUTO_FOLLOW_JID }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_follow);
|
|
74
|
+
}
|
|
75
|
+
} catch {}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
79
|
+
|
|
53
80
|
return {
|
|
54
81
|
...sock,
|
|
55
82
|
newsletterCreate: async (name, description) => {
|
package/lib/Types/Message.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export type WAMessageKey = proto.IMessageKey & {
|
|
|
25
25
|
export type WATextMessage = proto.Message.IExtendedTextMessage;
|
|
26
26
|
export type WAContextInfo = proto.IContextInfo;
|
|
27
27
|
export type WALocationMessage = proto.Message.ILocationMessage;
|
|
28
|
-
export type WAGenericMediaMessage = proto.Message.IVideoMessage | proto.Message.IImageMessage | proto.Message.IAudioMessage | proto.Message.IDocumentMessage | proto.Message.IStickerMessage;
|
|
28
|
+
export type WAGenericMediaMessage = proto.Message.IVideoMessage | proto.Message.IImageMessage | proto.Message.IAudioMessage | proto.Message.IDocumentMessage | proto.Message.IStickerMessage | proto.Message.IVideoMessage;
|
|
29
29
|
export declare const WAMessageStubType: typeof proto.WebMessageInfo.StubType;
|
|
30
30
|
export declare const WAMessageStatus: typeof proto.WebMessageInfo.Status;
|
|
31
31
|
import type { ILogger } from '../Utils/logger.js';
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apocalypse-api.js
|
|
3
|
+
* Client untuk API https://api.apocalypse.web.id
|
|
4
|
+
*
|
|
5
|
+
* Pola URL:
|
|
6
|
+
* /{kategori}/{endpoint}?{param}={value}
|
|
7
|
+
* /{kategori}/{sub}/{endpoint}?{param}={value}
|
|
8
|
+
*
|
|
9
|
+
* Contoh:
|
|
10
|
+
* await apocalypse.get('/search/spotify?q=swim')
|
|
11
|
+
* await apocalypse.get('/search/youtube?q=hello')
|
|
12
|
+
* await apocalypse.get('/downloader/tiktok?url=https://...')
|
|
13
|
+
* await apocalypse.get('/manga/jagoanmanga/search?q=killer+peter')
|
|
14
|
+
* await apocalypse.get('/ai/gpt?text=hello')
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const BASE_URL = 'https://api.apocalypse.web.id';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Buat Apocalypse API client.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} [options]
|
|
23
|
+
* @param {string} [options.apiKey] — API key jika diperlukan
|
|
24
|
+
* @param {number} [options.timeout=15000] — timeout dalam ms
|
|
25
|
+
* @param {object} [options.headers] — header tambahan
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* import { createApocalypseApi } from '@blckrose/baileys';
|
|
29
|
+
* const apocalypse = createApocalypseApi();
|
|
30
|
+
*
|
|
31
|
+
* // Atau dengan API key:
|
|
32
|
+
* const apocalypse = createApocalypseApi({ apiKey: 'your-key' });
|
|
33
|
+
*/
|
|
34
|
+
export function createApocalypseApi(options = {}) {
|
|
35
|
+
const {
|
|
36
|
+
apiKey,
|
|
37
|
+
timeout = 15000,
|
|
38
|
+
headers: extraHeaders = {}
|
|
39
|
+
} = options;
|
|
40
|
+
|
|
41
|
+
const baseHeaders = {
|
|
42
|
+
'Accept': 'application/json',
|
|
43
|
+
'User-Agent': 'blckrose-baileys/1.1.5-nl',
|
|
44
|
+
...(apiKey ? { 'Authorization': `Bearer ${apiKey}`, 'x-api-key': apiKey } : {}),
|
|
45
|
+
...extraHeaders
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Fetch dengan timeout.
|
|
50
|
+
*/
|
|
51
|
+
async function _fetch(url, opts = {}) {
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(url, {
|
|
56
|
+
...opts,
|
|
57
|
+
signal: controller.signal,
|
|
58
|
+
headers: { ...baseHeaders, ...(opts.headers || {}) }
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
const errText = await res.text().catch(() => '');
|
|
62
|
+
throw new Error(`Apocalypse API error ${res.status}: ${errText || res.statusText}`);
|
|
63
|
+
}
|
|
64
|
+
const ct = res.headers.get('content-type') || '';
|
|
65
|
+
if (ct.includes('application/json')) {
|
|
66
|
+
return await res.json();
|
|
67
|
+
}
|
|
68
|
+
// Buffer untuk response binary (gambar, audio, video)
|
|
69
|
+
return await res.arrayBuffer().then(buf => Buffer.from(buf));
|
|
70
|
+
} finally {
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Normalise path — pastikan leading slash ada.
|
|
77
|
+
*/
|
|
78
|
+
function _url(path) {
|
|
79
|
+
const p = path.startsWith('/') ? path : `/${path}`;
|
|
80
|
+
return `${BASE_URL}${p}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── Public methods ──────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* GET request ke Apocalypse API.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} path — path + query string, contoh: '/search/spotify?q=swim'
|
|
89
|
+
* @returns {Promise<object|Buffer>}
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* const res = await apocalypse.get('/search/spotify?q=swim')
|
|
93
|
+
* const res = await apocalypse.get('/manga/jagoanmanga/search?q=killer+peter')
|
|
94
|
+
*/
|
|
95
|
+
async function get(path) {
|
|
96
|
+
return _fetch(_url(path));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* GET dengan params object — otomatis di-encode ke query string.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} path — path tanpa query string
|
|
103
|
+
* @param {object} [params] — query params
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const res = await apocalypse.fetch('/search/spotify', { q: 'swim' })
|
|
107
|
+
* const res = await apocalypse.fetch('/manga/jagoanmanga/search', { q: 'killer peter' })
|
|
108
|
+
* const res = await apocalypse.fetch('/downloader/tiktok', { url: 'https://...' })
|
|
109
|
+
*/
|
|
110
|
+
async function fetchApi(path, params = {}) {
|
|
111
|
+
const base = path.startsWith('/') ? path : `/${path}`;
|
|
112
|
+
const qs = new URLSearchParams(
|
|
113
|
+
Object.fromEntries(
|
|
114
|
+
Object.entries(params)
|
|
115
|
+
.filter(([, v]) => v !== undefined && v !== null)
|
|
116
|
+
.map(([k, v]) => [k, String(v)])
|
|
117
|
+
)
|
|
118
|
+
).toString();
|
|
119
|
+
const full = qs ? `${BASE_URL}${base}?${qs}` : `${BASE_URL}${base}`;
|
|
120
|
+
return _fetch(full);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* POST request.
|
|
125
|
+
*
|
|
126
|
+
* @param {string} path
|
|
127
|
+
* @param {object} [body]
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* const res = await apocalypse.post('/ai/gpt', { text: 'hello' })
|
|
131
|
+
*/
|
|
132
|
+
async function post(path, body = {}) {
|
|
133
|
+
return _fetch(_url(path), {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'Content-Type': 'application/json' },
|
|
136
|
+
body: JSON.stringify(body)
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Shorthand helpers ───────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
/** Search wrapper — apocalypse.search('spotify', 'swim') */
|
|
143
|
+
async function search(endpoint, query) {
|
|
144
|
+
return fetchApi(`/search/${endpoint}`, { q: query });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Downloader wrapper — apocalypse.download('tiktok', url) */
|
|
148
|
+
async function download(endpoint, url) {
|
|
149
|
+
return fetchApi(`/downloader/${endpoint}`, { url });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** AI wrapper — apocalypse.ai('gpt', text) */
|
|
153
|
+
async function ai(endpoint, text, extra = {}) {
|
|
154
|
+
return fetchApi(`/ai/${endpoint}`, { text, ...extra });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Sticker wrapper — apocalypse.sticker(endpoint, url) */
|
|
158
|
+
async function sticker(endpoint, url) {
|
|
159
|
+
return fetchApi(`/sticker/${endpoint}`, { url });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Manga wrapper — apocalypse.manga('jagoanmanga', 'search', { q: 'killer' }) */
|
|
163
|
+
async function manga(site, endpoint, params = {}) {
|
|
164
|
+
return fetchApi(`/manga/${site}/${endpoint}`, params);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Game wrapper — apocalypse.game(endpoint, params) */
|
|
168
|
+
async function game(endpoint, params = {}) {
|
|
169
|
+
return fetchApi(`/game/${endpoint}`, params);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
// Core
|
|
174
|
+
get,
|
|
175
|
+
fetch: fetchApi,
|
|
176
|
+
post,
|
|
177
|
+
// Shorthands
|
|
178
|
+
search,
|
|
179
|
+
download,
|
|
180
|
+
ai,
|
|
181
|
+
sticker,
|
|
182
|
+
manga,
|
|
183
|
+
game,
|
|
184
|
+
// Expose base URL
|
|
185
|
+
BASE_URL,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Instance default tanpa API key — siap pakai langsung.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* import { apocalypse } from '@blckrose/baileys';
|
|
194
|
+
* const res = await apocalypse.get('/search/spotify?q=swim');
|
|
195
|
+
*/
|
|
196
|
+
export const apocalypse = createApocalypseApi();
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apocalypse API client declarations.
|
|
3
|
+
* https://api.apocalypse.web.id
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface ApocalypseConfig {
|
|
7
|
+
/** Override base URL (default: https://api.apocalypse.web.id) */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** API key — dikirim sebagai header x-api-key */
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
/** Timeout request dalam ms (default: 30000) */
|
|
12
|
+
timeout?: number;
|
|
13
|
+
/** Header tambahan */
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ApocalypseResponse<T = any> {
|
|
18
|
+
/** Data utama dari API (data.result / data.data / root) */
|
|
19
|
+
readonly result: T;
|
|
20
|
+
/** true jika API mengembalikan status sukses */
|
|
21
|
+
readonly status: boolean;
|
|
22
|
+
/** Pesan dari API */
|
|
23
|
+
readonly message: string;
|
|
24
|
+
/** Full response JSON mentah */
|
|
25
|
+
readonly raw: any;
|
|
26
|
+
/** URL yang dipanggil */
|
|
27
|
+
readonly url: string;
|
|
28
|
+
/** Ambil field tertentu dari result */
|
|
29
|
+
get<K extends keyof T>(key: K): T[K] | undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ApocalypseCategoryClient {
|
|
33
|
+
/**
|
|
34
|
+
* GET ke /{category}/{endpoint}
|
|
35
|
+
* @example
|
|
36
|
+
* const search = apocalypse.category('search');
|
|
37
|
+
* await search.get('spotify', { q: 'swim' });
|
|
38
|
+
*/
|
|
39
|
+
get<T = any>(endpoint: string, params?: Record<string, string | number>): Promise<ApocalypseResponse<T>>;
|
|
40
|
+
/**
|
|
41
|
+
* POST ke /{category}/{endpoint}
|
|
42
|
+
*/
|
|
43
|
+
post<T = any>(endpoint: string, body?: object, params?: Record<string, string | number>): Promise<ApocalypseResponse<T>>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ApocalypseClient {
|
|
47
|
+
/**
|
|
48
|
+
* GET request ke Apocalypse API.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* await apocalypse.get('/search/spotify?q=swim');
|
|
52
|
+
* await apocalypse.get('/search/spotify', { q: 'swim' });
|
|
53
|
+
* await apocalypse.get('/manga/jagoanmanga/search', { q: 'killer+peter' });
|
|
54
|
+
*/
|
|
55
|
+
get<T = any>(path: string, params?: Record<string, string | number>): Promise<ApocalypseResponse<T>>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* POST request ke Apocalypse API.
|
|
59
|
+
*/
|
|
60
|
+
post<T = any>(path: string, body?: object, params?: Record<string, string | number>): Promise<ApocalypseResponse<T>>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Buat caller untuk kategori tertentu.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const search = apocalypse.category('search');
|
|
67
|
+
* await search.get('spotify', { q: 'swim' });
|
|
68
|
+
*
|
|
69
|
+
* const manga = apocalypse.category('manga/jagoanmanga');
|
|
70
|
+
* await manga.get('search', { q: 'naruto' });
|
|
71
|
+
*/
|
|
72
|
+
category(cat: string): ApocalypseCategoryClient;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Set API key untuk global apocalypse instance.
|
|
76
|
+
* Cukup tulis SEKALI di bot.js — berlaku untuk semua request setelahnya.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Di bot.js, setelah require baileys:
|
|
80
|
+
* apocalypse.setKey('API_KEY_KAMU')
|
|
81
|
+
*
|
|
82
|
+
* // Di handler manapun:
|
|
83
|
+
* const res = await apocalypse.get('/premium/endpoint', { q: 'test' })
|
|
84
|
+
*/
|
|
85
|
+
setKey(key: string): void;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Set konfigurasi lengkap untuk global apocalypse instance.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* apocalypse.setConfig({ apiKey: 'xxx', timeout: 15000 })
|
|
92
|
+
*/
|
|
93
|
+
setConfig(config: ApocalypseConfig): void;
|
|
94
|
+
|
|
95
|
+
/** Base URL yang dipakai */
|
|
96
|
+
readonly baseUrl: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Buat instance Apocalypse API client baru.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* const apocalypse = createApocalypse({ apiKey: 'xxx' });
|
|
104
|
+
* const res = await apocalypse.get('/search/spotify', { q: 'swim' });
|
|
105
|
+
* console.log(res.result);
|
|
106
|
+
*/
|
|
107
|
+
export declare function createApocalypse(config?: ApocalypseConfig): ApocalypseClient;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Instance default siap pakai (tanpa konfigurasi).
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* import { apocalypse } from '@blckrose/baileys';
|
|
114
|
+
* const { result } = await apocalypse.get('/search/spotify', { q: 'swim' });
|
|
115
|
+
*/
|
|
116
|
+
export declare const apocalypse: ApocalypseClient;
|