253 lines
8.4 KiB
JavaScript
253 lines
8.4 KiB
JavaScript
const socket = io({ path: '/proxy/whatsapp/socket.io' });
|
|
|
|
// UI Elements
|
|
const statusBadge = document.getElementById('status-badge');
|
|
const qrContainer = document.getElementById('qr-container');
|
|
const activityLog = document.getElementById('activity-log');
|
|
const groupsTableBody = document.getElementById('groups-table-body');
|
|
const appsTableBody = document.getElementById('apps-table-body');
|
|
const inviteModal = document.getElementById('invite-modal');
|
|
const inviteLinkInput = document.getElementById('invite-link-input');
|
|
|
|
// Tab Switching
|
|
document.querySelectorAll('.nav-btn').forEach(btn => {
|
|
btn.addEventListener('click', (e) => {
|
|
document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active'));
|
|
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
|
|
|
|
e.target.classList.add('active');
|
|
document.getElementById(e.target.dataset.tab).classList.add('active');
|
|
|
|
if (e.target.dataset.tab === 'groups') {
|
|
fetchGroups();
|
|
}
|
|
if (e.target.dataset.tab === 'apps') {
|
|
fetchApps();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Logging
|
|
function logActivity(msg, type = 'info') {
|
|
const entry = document.createElement('p');
|
|
entry.className = `log-entry ${type}`;
|
|
const time = new Date().toLocaleTimeString();
|
|
entry.textContent = `[${time}] ${msg}`;
|
|
activityLog.prepend(entry);
|
|
}
|
|
|
|
// Socket Events
|
|
socket.on('status', (data) => {
|
|
updateStatus(data.ready);
|
|
if (data.qr && !data.ready) renderQR(data.qr);
|
|
});
|
|
|
|
socket.on('qr', (qr) => {
|
|
renderQR(qr);
|
|
logActivity('New QR code generated', 'system');
|
|
});
|
|
|
|
socket.on('ready', () => {
|
|
updateStatus(true);
|
|
qrContainer.innerHTML = '<h3>✅ Connected</h3><p>Session is active and authenticated.</p>';
|
|
logActivity('Client successfully authenticated and ready', 'success');
|
|
});
|
|
|
|
socket.on('disconnected', (reason) => {
|
|
updateStatus(false);
|
|
logActivity(`Disconnected: ${reason}`, 'error');
|
|
});
|
|
|
|
socket.on('incoming_message', (msg) => {
|
|
logActivity(`Msg from ${msg.from}: ${msg.body.substring(0, 50)}...`, 'info');
|
|
});
|
|
|
|
function updateStatus(isReady) {
|
|
if (isReady) {
|
|
statusBadge.textContent = 'Connected';
|
|
statusBadge.className = 'badge success';
|
|
} else {
|
|
statusBadge.textContent = 'Disconnected';
|
|
statusBadge.className = 'badge error';
|
|
}
|
|
}
|
|
|
|
function renderQR(qrText) {
|
|
qrContainer.innerHTML = '';
|
|
const qr = qrcode(0, 'L');
|
|
qr.addData(qrText);
|
|
qr.make();
|
|
qrContainer.innerHTML = qr.createImgTag(5);
|
|
}
|
|
|
|
// Groups Tab functionality
|
|
async function fetchGroups() {
|
|
groupsTableBody.innerHTML = '<tr><td colspan="3" class="text-center">Loading...</td></tr>';
|
|
try {
|
|
const res = await fetch('api/groups');
|
|
const data = await res.json();
|
|
|
|
if (!data.success) {
|
|
groupsTableBody.innerHTML = `<tr><td colspan="3" class="text-center">Error: ${data.error || 'Not connected'}</td></tr>`;
|
|
return;
|
|
}
|
|
|
|
if (data.groups.length === 0) {
|
|
groupsTableBody.innerHTML = '<tr><td colspan="3" class="text-center">No groups found.</td></tr>';
|
|
return;
|
|
}
|
|
|
|
groupsTableBody.innerHTML = '';
|
|
data.groups.forEach(g => {
|
|
const tr = document.createElement('tr');
|
|
tr.innerHTML = `
|
|
<td><strong>${g.name}</strong><br><small style="color:var(--text-muted)">${g.id}</small></td>
|
|
<td>${g.participants}</td>
|
|
<td>
|
|
<button class="secondary-btn" onclick="getInviteLink('${g.id}')">Get Invite Link</button>
|
|
</td>
|
|
`;
|
|
groupsTableBody.appendChild(tr);
|
|
});
|
|
|
|
} catch (e) {
|
|
groupsTableBody.innerHTML = `<tr><td colspan="3" class="text-center">Fetch failed.</td></tr>`;
|
|
}
|
|
}
|
|
|
|
document.getElementById('btn-refresh-groups').addEventListener('click', fetchGroups);
|
|
|
|
// Connected Apps functionality
|
|
async function fetchApps() {
|
|
appsTableBody.innerHTML = '<tr><td colspan="4" class="text-center">Loading...</td></tr>';
|
|
try {
|
|
const res = await fetch('api/apps');
|
|
const data = await res.json();
|
|
|
|
if (!data.success) {
|
|
appsTableBody.innerHTML = `<tr><td colspan="4" class="text-center">Error fetching apps</td></tr>`;
|
|
return;
|
|
}
|
|
|
|
if (data.apps.length === 0) {
|
|
appsTableBody.innerHTML = '<tr><td colspan="4" class="text-center">No apps connected yet. Send a message to see an app appear here!</td></tr>';
|
|
return;
|
|
}
|
|
|
|
appsTableBody.innerHTML = '';
|
|
data.apps.sort((a, b) => new Date(b.lastSeen) - new Date(a.lastSeen)).forEach(app => {
|
|
const tr = document.createElement('tr');
|
|
tr.innerHTML = `
|
|
<td><strong>${app.name}</strong></td>
|
|
<td>${app.messageCount}</td>
|
|
<td>${new Date(app.lastSeen).toLocaleString()}</td>
|
|
<td><small style="color:var(--text-muted)">${app.lastIp}</small></td>
|
|
`;
|
|
appsTableBody.appendChild(tr);
|
|
});
|
|
|
|
} catch (e) {
|
|
appsTableBody.innerHTML = `<tr><td colspan="4" class="text-center">Fetch failed.</td></tr>`;
|
|
}
|
|
}
|
|
|
|
document.getElementById('btn-refresh-apps').addEventListener('click', fetchApps);
|
|
|
|
// Create Group
|
|
document.getElementById('create-group-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const btn = e.target.querySelector('button');
|
|
btn.textContent = 'Creating...';
|
|
btn.disabled = true;
|
|
|
|
const title = document.getElementById('new-group-name').value;
|
|
const participant = document.getElementById('new-group-participant').value;
|
|
|
|
try {
|
|
const res = await fetch('api/groups/create', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ title, initialParticipants: [participant] })
|
|
});
|
|
const data = await res.json();
|
|
|
|
if (data.success) {
|
|
alert('Group created successfully! ID: ' + data.groupId);
|
|
fetchGroups();
|
|
e.target.reset();
|
|
} else {
|
|
alert('Error: ' + data.error);
|
|
}
|
|
} catch (err) {
|
|
alert('Failed to create group.');
|
|
} finally {
|
|
btn.textContent = 'Create Group';
|
|
btn.disabled = false;
|
|
}
|
|
});
|
|
|
|
// Invite Link Modal
|
|
window.getInviteLink = async (groupId) => {
|
|
try {
|
|
const res = await fetch('api/groups/invite', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ groupId })
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) {
|
|
inviteLinkInput.value = data.inviteLink;
|
|
inviteModal.classList.add('active');
|
|
} else {
|
|
alert('Failed to get invite link: ' + data.error);
|
|
}
|
|
} catch (err) {
|
|
alert('Request failed.');
|
|
}
|
|
};
|
|
|
|
document.querySelector('.close-modal').addEventListener('click', () => {
|
|
inviteModal.classList.remove('active');
|
|
});
|
|
|
|
document.getElementById('btn-copy-link').addEventListener('click', () => {
|
|
inviteLinkInput.select();
|
|
document.execCommand('copy');
|
|
alert('Copied to clipboard!');
|
|
});
|
|
|
|
// Test Message
|
|
document.getElementById('test-msg-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const btn = e.target.querySelector('button');
|
|
const resultDiv = document.getElementById('test-result');
|
|
|
|
btn.textContent = 'Sending...';
|
|
btn.disabled = true;
|
|
resultDiv.textContent = '';
|
|
|
|
const to = document.getElementById('test-to').value;
|
|
const message = document.getElementById('test-body').value;
|
|
|
|
try {
|
|
const res = await fetch('api/send-message', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ to, message })
|
|
});
|
|
const data = await res.json();
|
|
|
|
if (data.success) {
|
|
resultDiv.innerHTML = `<span style="color:var(--success)">✅ Sent successfully (ID: ${data.messageId})</span>`;
|
|
document.getElementById('test-body').value = '';
|
|
} else {
|
|
resultDiv.innerHTML = `<span style="color:var(--error)">❌ ${data.error}</span>`;
|
|
}
|
|
} catch (err) {
|
|
resultDiv.innerHTML = `<span style="color:var(--error)">❌ Request failed.</span>`;
|
|
} finally {
|
|
btn.textContent = 'Send Message';
|
|
btn.disabled = false;
|
|
}
|
|
});
|