168 lines
5 KiB
JavaScript
168 lines
5 KiB
JavaScript
import { config } from "./config.js";
|
|
import { getBase64 } from "./utils.js";
|
|
|
|
async function request(path, options = {}) {
|
|
const url = `${config.wahaUrl}${path}`;
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'accept': '*/*',
|
|
...options.headers
|
|
};
|
|
if (config.apiKey) {
|
|
headers['X-Api-Key'] = config.apiKey;
|
|
}
|
|
|
|
// console.log(`[WAHA] ${options.method || 'GET'} ${url}`, options.body ? JSON.parse(options.body) : '');
|
|
|
|
const response = await fetch(url, { ...options, headers });
|
|
if (!response.ok) {
|
|
let errorDetail = '';
|
|
try {
|
|
const errBody = await response.json();
|
|
errorDetail = JSON.stringify(errBody);
|
|
console.error(`[WAHA] Error response body:`, errBody);
|
|
} catch (_) {
|
|
errorDetail = await response.text().catch(() => '');
|
|
}
|
|
throw new Error(`WAHA API returned ${response.status}: ${response.statusText} — ${errorDetail}`);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
async function downloadFile(path, options = {}) {
|
|
const url = `${config.wahaUrl}${path}`;
|
|
|
|
const headers = {
|
|
'Content-Type': options.headers?.['Content-Type'] ?? 'application/json',
|
|
'accept': '*/*',
|
|
...options.headers
|
|
};
|
|
|
|
if (config.apiKey) headers['X-Api-Key'] = config.apiKey;
|
|
|
|
console.log(`[WAHA] ${options.method || 'GET'} ${url}`);
|
|
|
|
const response = await fetch(url, { ...options, headers });
|
|
|
|
if (!response.ok) {
|
|
let errorDetail = '';
|
|
try {
|
|
errorDetail = JSON.stringify(await response.json());
|
|
} catch (_) {
|
|
errorDetail = await response.text().catch(() => '');
|
|
}
|
|
throw new Error(`WAHA API returned ${response.status}: ${response.statusText} — ${errorDetail}`);
|
|
}
|
|
|
|
const blob = await response.blob();
|
|
|
|
let filename = 'download';
|
|
const cd = response.headers.get('content-disposition');
|
|
if (cd) {
|
|
const m = cd.match(/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i);
|
|
filename = decodeURIComponent(m?.[1] || m?.[2] || filename);
|
|
}
|
|
|
|
return { blob, filename };
|
|
}
|
|
|
|
|
|
export const waha = {
|
|
async getVersion() {
|
|
return request('/api/version');
|
|
},
|
|
|
|
async getChats() {
|
|
const data = await request(`/api/${config.session}/chats?sortBy=conversationTimestamp`);
|
|
return data.map(chat => {
|
|
let chatId = chat.id;
|
|
if (chatId && typeof chatId === "object") {
|
|
chatId = chatId._serialized || chatId.user || JSON.stringify(chatId);
|
|
}
|
|
return {
|
|
id: chatId || chat.chatId || chat.name,
|
|
name: chat.name || "Unknown Contact",
|
|
unreadCount: chat.unreadCount || 0,
|
|
lastMessage: chat.lastMessage?.body || chat.lastMessageText || "Click to open chat",
|
|
timestamp: chat.lastMessage?.timestamp || new Date()
|
|
};
|
|
});
|
|
},
|
|
|
|
async getChatMessages(chatId) {
|
|
return request(`/api/${config.session}/chats/${chatId}/messages?downloadMedia=false&limit=40`);
|
|
},
|
|
|
|
async getSingleChatMessage(chatId, messageId, downladMedia) {
|
|
return request(`/api/${config.session}/chats/${chatId}/messages/${messageId}?downloadMedia=${downladMedia}`);
|
|
},
|
|
|
|
async getChatPicture(chatId) {
|
|
return request(`/api/${config.session}/chats/${chatId}/picture`);
|
|
},
|
|
|
|
async readChat(chatId) {
|
|
return request('/api/sendSeen', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ chatId, session: config.session })
|
|
});
|
|
},
|
|
|
|
async downloadMedia(file) {
|
|
const { blob, filename } = await downloadFile(`/api/files/${config.session}/${file}`);
|
|
return { blob, filename };
|
|
},
|
|
|
|
async getMyInfo() {
|
|
return request(`/api/sessions/${config.session}/me`);
|
|
},
|
|
|
|
async startTyping(chatId) {
|
|
return request('/api/startTyping', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ chatId, session: config.session })
|
|
});
|
|
},
|
|
|
|
async stopTyping(chatId) {
|
|
return request('/api/stopTyping', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ chatId, session: config.session })
|
|
});
|
|
},
|
|
|
|
async sendTextMessage(chatId, text) {
|
|
return request('/api/sendText', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
chatId,
|
|
text,
|
|
session: config.session
|
|
})
|
|
});
|
|
},
|
|
|
|
async sendFileMessage(chatId, file) {
|
|
const fileBase64 = await getBase64(file);
|
|
const body = {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
chatId,
|
|
file: {
|
|
mimetype: file.type,
|
|
filename: file.name,
|
|
data: fileBase64
|
|
},
|
|
session: config.session
|
|
})
|
|
};
|
|
|
|
let endpoint = "/api/sendFile";
|
|
|
|
if (file.type.startsWith('image/')) endpoint = '/api/sendImage';
|
|
if (file.type.startsWith('video/')) endpoint = '/api/sendVideo';
|
|
|
|
const result = await request(endpoint, body);
|
|
return result;
|
|
}
|
|
};
|