Track targets and assists for Torn faction wars using Direct REST API
当前为
// ==UserScript==
// @name BW WAR Tracker (REST API v2.0)
// @namespace http://tampermonkey.net/
// @version 2.0
// @description Track targets and assists for Torn faction wars using Direct REST API
// @author Tu
// @match https://www.torn.com/*
// @icon https://www.torn.com/favicon.ico
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @connect api.torn.com
// @connect www.tornstats.com
// @connect bw-war-tracker-default-rtdb.europe-west1.firebasedatabase.app
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
let currentUser = null;
let factionMembers = [];
let myTargets = GM_getValue('bw_my_targets', []);
let assists = [];
// Configurare Directă Bază de Date (Fără librării externe)
const DB_URL = "https://bw-war-tracker-default-rtdb.europe-west1.firebasedatabase.app";
function initScript() {
if (document.body) {
setupScript();
} else {
setTimeout(initScript, 100);
}
}
function setupScript() {
GM_addStyle(`
#bw-war-button { position: fixed !important; bottom: 20px !important; left: 20px !important; background-color: #000 !important; color: #fff !important; border: 2px solid #fff !important; padding: 12px 24px !important; font-size: 14px !important; font-weight: bold; cursor: pointer; border-radius: 5px; z-index: 999999 !important; box-shadow: 0 2px 10px rgba(0,0,0,0.3) !important; transition: all 0.3s !important; }
#bw-war-button:hover { background-color: #333 !important; transform: translateY(-2px) !important; }
#bw-war-modal, #bw-settings-modal { display: none !important; position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; width: 85% !important; max-width: 1000px !important; height: 75% !important; background-color: rgba(26, 26, 26, 0.95) !important; border: 2px solid #333 !important; border-radius: 10px !important; z-index: 999999 !important; box-shadow: 0 5px 30px rgba(0,0,0,0.5) !important; }
#bw-war-modal.active, #bw-settings-modal.active { display: flex !important; flex-direction: column !important; overflow: hidden !important; }
#bw-war-overlay { display: none !important; position: fixed !important; top: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; background-color: rgba(0,0,0,0.7) !important; z-index: 999998 !important; }
#bw-war-overlay.active { display: block !important; }
.bw-modal-header { background: linear-gradient(135deg, #000 0%, #1a1a1a 100%) !important; color: #fff !important; padding: 20px !important; border-radius: 8px 8px 0 0 !important; display: flex !important; flex-direction: column !important; align-items: center !important; border-bottom: 3px solid #333 !important; position: relative !important; }
.bw-modal-title { font-size: 24px !important; font-weight: 900 !important; }
.bw-header-buttons { position: absolute !important; top: 20px !important; right: 20px !important; display: flex !important; gap: 10px !important; }
.bw-settings-button, .bw-close-button { background: none !important; border: 2px solid #fff !important; color: #fff !important; font-size: 20px !important; cursor: pointer !important; padding: 8px 12px !important; border-radius: 5px !important; width: 40px !important; height: 40px !important; }
.bw-tabs { display: flex !important; background-color: #2a2a2a !important; border-bottom: 2px solid #333 !important; }
.bw-tab { flex: 1 !important; padding: 15px !important; background-color: #2a2a2a !important; color: #999 !important; border: none !important; cursor: pointer !important; font-weight: bold !important; }
.bw-tab.active { background-color: #000 !important; color: #fff !important; border-bottom: 3px solid #4CAF50 !important; }
.bw-tab-content { display: none !important; padding: 20px !important; overflow-y: auto !important; flex: 1 !important; color: #fff !important; }
.bw-tab-content.active { display: block !important; }
.bw-member-item, .bw-target-item, .bw-assist-item { background-color: #2a2a2a !important; padding: 12px 15px !important; border-radius: 5px !important; margin-bottom: 8px !important; display: flex !important; justify-content: space-between !important; align-items: center !important; }
.bw-member-name, .bw-target-name { color: #fff !important; cursor: pointer !important; font-weight: bold !important; }
.bw-member-name:hover, .bw-target-name:hover { color: #4CAF50 !important; }
.bw-rank-badge { background-color: #4CAF50 !important; color: #000 !important; padding: 3px 10px !important; border-radius: 12px !important; font-size: 11px !important; font-weight: bold !important; }
.bw-input-section { display: flex !important; gap: 10px !important; margin-bottom: 20px !important; }
.bw-input-field { flex: 1 !important; padding: 10px !important; background-color: #2a2a2a !important; border: 1px solid #444 !important; color: #fff !important; border-radius: 5px !important; }
.bw-add-button { background-color: #2196F3 !important; color: #fff !important; border: none !important; padding: 10px 20px !important; border-radius: 5px !important; cursor: pointer !important; font-weight: bold !important; }
.bw-remove-button { background-color: #f44336 !important; color: #fff !important; border: none !important; padding: 5px 12px !important; border-radius: 3px !important; cursor: pointer !important; font-size: 11px !important; }
.bw-slot-selector { display: flex !important; gap: 5px !important; margin: 0 10px !important; }
.bw-slot-btn { background-color: #2a2a2a !important; color: #fff !important; border: 2px solid #444 !important; padding: 5px 10px !important; border-radius: 3px !important; cursor: pointer !important; font-size: 11px !important; }
.bw-slot-btn.active { background-color: #4CAF50 !important; border-color: #4CAF50 !important; }
.bw-im-in-btn { background-color: #FF9800 !important; color: #fff !important; border: none !important; padding: 6px 15px !important; border-radius: 15px !important; cursor: pointer !important; font-size: 12px !important; font-weight: bold !important; }
.bw-participants { display: flex !important; flex-wrap: wrap !important; gap: 8px !important; margin-top: 10px !important; }
.bw-participant-tag { background-color: #1a1a1a !important; color: #4CAF50 !important; padding: 5px 12px !important; border-radius: 15px !important; font-size: 11px !important; border: 1px solid #4CAF50 !important; }
.bw-loading { text-align: center !important; padding: 20px !important; color: #999 !important; }
`);
const button = document.createElement('button');
button.id = 'bw-war-button';
button.textContent = 'BW WAR';
document.body.appendChild(button);
const overlay = document.createElement('div');
overlay.id = 'bw-war-overlay';
document.body.appendChild(overlay);
const modal = document.createElement('div');
modal.id = 'bw-war-modal';
modal.innerHTML = `
<div class="bw-modal-header">
<div class="bw-header-buttons"><button class="bw-settings-button">⚙️</button><button class="bw-close-button">×</button></div>
<img src="https://factionimages.torn.com/08099e78-0a69-4424-8ccd-5219338250ad-40039.png" class="bw-modal-logo" style="max-width: 200px; height: 50px; margin-bottom: 10px;">
<div class="bw-modal-title">Black & White War Manager</div>
</div>
<div class="bw-tabs">
<button class="bw-tab active" data-tab="info">Info</button>
<button class="bw-tab" data-tab="team">Team</button>
<button class="bw-tab" data-tab="targets">My Targets</button>
<button class="bw-tab" data-tab="assists">Assists</button>
</div>
<div class="bw-tab-content active" id="info-content"><div class="bw-loading">Loading your information...</div></div>
<div class="bw-tab-content" id="team-content"><div class="bw-loading">Loading faction members...</div></div>
<div class="bw-tab-content" id="targets-content">
<div class="bw-input-section"><input type="text" id="mytarget-input" class="bw-input-field" placeholder="Enter username or ID"><button id="add-mytarget-btn" class="bw-add-button">Add Target</button></div>
<div id="mytargets-list"></div>
</div>
<div class="bw-tab-content" id="assists-content">
<div class="bw-input-section">
<input type="text" id="assist-input" class="bw-input-field" placeholder="Enter User ID (Recommended) or Name" style="flex: 2;">
<div class="bw-slot-selector">
<button class="bw-slot-btn" data-slots="1">+1</button><button class="bw-slot-btn" data-slots="2">+2</button><button class="bw-slot-btn" data-slots="3">+3</button><button class="bw-slot-btn" data-slots="4">+4</button>
</div>
<button id="add-assist-btn" class="bw-add-button">Add</button>
</div>
<div id="assists-list"></div>
</div>
`;
document.body.appendChild(modal);
const settingsModal = document.createElement('div');
settingsModal.id = 'bw-settings-modal';
settingsModal.innerHTML = `
<div class="bw-modal-header">
<div class="bw-header-buttons"><button class="bw-close-button settings-close">×</button></div>
<img src="https://factionimages.torn.com/08099e78-0a69-4424-8ccd-5219338250ad-40039.png" class="bw-modal-logo" style="max-width: 200px; height: 50px; margin-bottom: 10px;">
<div class="bw-modal-title">Settings</div>
</div>
<div style="padding: 30px;">
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 8px; font-weight: bold; color: #fff;">Torn API Key:</label>
<input type="text" id="api-key-input" class="bw-input-field" placeholder="Enter your API key">
<button id="save-api-key" class="bw-add-button" style="margin-top: 10px;">Save</button>
</div>
<div style="margin-top: 20px; padding: 15px; background-color: #2a2a2a; border-radius: 5px; font-size: 13px; color: #aaa;">
<strong>Note:</strong> You need a Full Access API key. Get it from: <a href="https://www.torn.com/preferences.php#tab=api" target="_blank" style="color: #4CAF50;">Torn Preferences</a>
</div>
</div>
`;
document.body.appendChild(settingsModal);
function getApiKey() { return GM_getValue('torn_api_key', ''); }
function tornApiCall(endpoint, apiKey = null) {
return new Promise((resolve, reject) => {
const key = apiKey || getApiKey();
if (!key) { reject('No API key set'); return; }
GM_xmlhttpRequest({
method: 'GET',
url: `https://api.torn.com/${endpoint}&key=${key}`,
onload: function(response) {
try {
const data = JSON.parse(response.responseText);
if (data.error) { reject(data.error.error); } else { resolve(data); }
} catch (e) { reject('Failed to parse response'); }
},
onerror: function() { reject('Network error - Check connection or VPN'); }
});
});
}
function formatNumber(num) {
if (!num) return '0';
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// --- DIRECT FIREBASE REST API FUNCTIONS (No Libraries needed) ---
function fetchAssistsFromDB() {
GM_xmlhttpRequest({
method: "GET",
url: `${DB_URL}/assists.json`,
onload: function(response) {
try {
if(response.status === 200) {
const data = JSON.parse(response.responseText);
// Convert Object to Array and add the Firebase Key (ID)
assists = data ? Object.keys(data).map(key => ({ ...data[key], firebaseId: key })) : [];
renderAssists();
}
} catch(e) { console.error("Error parsing DB:", e); }
}
});
}
// Polling function (Refresh data every 5 seconds)
function startDBPolling() {
fetchAssistsFromDB();
setInterval(fetchAssistsFromDB, 5000);
}
function addAssistToFirebase(assist) {
return new Promise((resolve, reject) => {
if (!currentUser) { alert("Error: User info not loaded!"); reject("No user"); return; }
assist.initiatedBy = currentUser.name;
assist.initiatedById = currentUser.player_id;
assist.timestamp = Date.now();
GM_xmlhttpRequest({
method: "POST",
url: `${DB_URL}/assists.json`,
data: JSON.stringify(assist),
headers: { "Content-Type": "application/json" },
onload: function(response) {
if(response.status === 200) {
fetchAssistsFromDB(); // Refresh immediately
resolve(true);
} else {
alert("Database Error: " + response.statusText);
reject(response.responseText);
}
},
onerror: function(err) {
alert("Network Error sending to DB");
reject(err);
}
});
});
}
function updateAssistInFirebase(firebaseId, updates) {
GM_xmlhttpRequest({
method: "PATCH",
url: `${DB_URL}/assists/${firebaseId}.json`,
data: JSON.stringify(updates),
headers: { "Content-Type": "application/json" },
onload: function() { fetchAssistsFromDB(); }
});
}
function removeAssistFromFirebase(firebaseId) {
GM_xmlhttpRequest({
method: "DELETE",
url: `${DB_URL}/assists/${firebaseId}.json`,
onload: function() { fetchAssistsFromDB(); }
});
}
// --- END DB FUNCTIONS ---
async function loadUserInfo() {
const container = document.querySelector('#info-content');
try {
const data = await tornApiCall('user/?selections=profile,battlestats,personalstats');
currentUser = data;
const battlestatsTotal = (data.strength || 0) + (data.defense || 0) + (data.speed || 0) + (data.dexterity || 0);
container.innerHTML = `
<div style="max-width: 600px; margin: 0 auto;">
<div style="background-color: #2a2a2a; border-radius: 8px; padding: 20px; margin-bottom: 20px;">
<a href="https://www.torn.com/profiles.php?XID=${data.player_id}" target="_blank" style="color: #4CAF50; font-size: 20px; font-weight: bold; text-decoration: none;">${data.name} [${data.player_id}]</a>
<span style="color: #999; margin-left: 10px;">Level ${data.level}</span>
<div style="margin-top: 15px; padding: 10px; background-color: #1a1a1a; border-radius: 5px;">
<div style="color: #4CAF50; font-weight: bold; margin-bottom: 8px;">Faction Info</div>
<div style="color: #fff; margin-bottom: 5px;"><span style="color: #999;">Faction:</span> ${data.faction?.faction_name || 'N/A'}</div>
<div style="color: #fff; margin-bottom: 5px;"><span style="color: #999;">Position:</span> <span style="background-color: #4CAF50; color: #000; padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: bold; margin-left: 5px;">${data.faction?.position || 'N/A'}</span></div>
<div style="color: #fff;"><span style="color: #999;">Days in Faction:</span> ${data.faction?.days_in_faction || '0'}</div>
</div>
<div style="margin-top: 20px;">
<div style="color: #4CAF50; font-weight: bold; margin-bottom: 10px;">Battle Stats</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div style="background: #1a1a1a; padding: 10px; border-radius: 5px;"><div style="color: #999; font-size: 12px;">Strength</div><div style="color: #fff; font-weight: bold;">${formatNumber(data.strength)}</div></div>
<div style="background: #1a1a1a; padding: 10px; border-radius: 5px;"><div style="color: #999; font-size: 12px;">Defense</div><div style="color: #fff; font-weight: bold;">${formatNumber(data.defense)}</div></div>
<div style="background: #1a1a1a; padding: 10px; border-radius: 5px;"><div style="color: #999; font-size: 12px;">Speed</div><div style="color: #fff; font-weight: bold;">${formatNumber(data.speed)}</div></div>
<div style="background: #1a1a1a; padding: 10px; border-radius: 5px;"><div style="color: #999; font-size: 12px;">Dexterity</div><div style="color: #fff; font-weight: bold;">${formatNumber(data.dexterity)}</div></div>
</div>
<div style="background: #1a1a1a; padding: 10px; border-radius: 5px; margin-top: 10px;"><div style="color: #999; font-size: 12px;">Total</div><div style="color: #fff; font-weight: bold; font-size: 18px;">${formatNumber(battlestatsTotal)}</div></div>
</div>
</div>
</div>`;
} catch (error) {
container.innerHTML = `<div style="text-align: center; padding: 40px; color: #f44336;">Error: ${error}<br><button onclick="document.querySelector('.bw-settings-button').click()" style="background: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-top: 20px;">Open Settings</button></div>`;
}
}
async function loadFactionMembers() {
const container = document.querySelector('#team-content');
try {
const data = await tornApiCall('faction/?selections=basic');
if (!data.members) throw new Error('No members data received');
factionMembers = Object.keys(data.members).map(id => {
const member = data.members[id];
return { id: id, name: member.name, position: member.position };
});
container.innerHTML = `<div style="color: #4CAF50; font-weight: bold; margin-bottom: 15px; font-size: 18px;">Faction Members (${factionMembers.length})</div>
${factionMembers.map(member => `<div class="bw-member-item"><a href="https://www.torn.com/profiles.php?XID=${member.id}" target="_blank" class="bw-member-name">${member.name} [${member.id}]</a><span class="bw-rank-badge">${member.position}</span></div>`).join('')}`;
} catch (error) {
container.innerHTML = `<div style="text-align: center; padding: 40px; color: #f44336;">Error loading faction: ${error}<br><span style="font-size: 14px; color: #999;">Make sure you have a Full Access API key</span></div>`;
}
}
function renderMyTargets() {
const list = document.getElementById('mytargets-list');
if (myTargets.length === 0) { list.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">No targets added yet</div>'; return; }
list.innerHTML = myTargets.map((target, index) => `
<div class="bw-target-item">
<a href="#" class="bw-target-name" data-id="${target.id}">${target.name} [${target.id}]${target.level ? ' - Level ' + target.level : ''}</a>
<div><button class="bw-add-button" data-id="${target.id}" style="margin-right: 5px; font-size: 11px; padding: 5px 10px;">Attack</button><button class="bw-remove-button" data-index="${index}" data-type="mytarget">Remove</button></div>
</div>`).join('');
document.querySelectorAll('#mytargets-list .bw-target-name').forEach(link => link.addEventListener('click', (e) => { e.preventDefault(); window.open(`https://www.tornstats.com/spy.php?id=${e.target.dataset.id}`, '_blank', 'width=1000,height=700'); }));
document.querySelectorAll('#mytargets-list .bw-add-button').forEach(btn => btn.addEventListener('click', (e) => window.open(`https://www.torn.com/loader.php?sid=attack&user2ID=${e.target.dataset.id}`, '_blank')));
document.querySelectorAll('#mytargets-list .bw-remove-button').forEach(btn => btn.addEventListener('click', (e) => { const index = parseInt(e.target.dataset.index); myTargets.splice(index, 1); GM_setValue('bw_my_targets', myTargets); renderMyTargets(); }));
}
document.getElementById('add-mytarget-btn').addEventListener('click', async () => {
const input = document.getElementById('mytarget-input');
const value = input.value.trim();
if (!value) { alert('Please enter a username or ID'); return; }
try {
let data;
if (/^\d+$/.test(value)) { data = await tornApiCall(`user/${value}?selections=profile`); }
else { data = await tornApiCall(`user/${value}?selections=profile`); }
if (!data || !data.player_id) { alert('User not found! Try using their ID (numbers) instead of username.'); return; }
const newTarget = { id: data.player_id, name: data.name, level: data.level };
if (myTargets.find(t => t.id === newTarget.id)) { alert('Target already added!'); return; }
myTargets.push(newTarget);
GM_setValue('bw_my_targets', myTargets);
input.value = '';
renderMyTargets();
alert(`✓ Added: ${newTarget.name} [${newTarget.id}]`);
} catch (error) { console.error('Add target error:', error); alert('Failed to add target. Try using the ID.'); }
});
renderMyTargets();
let selectedSlots = 1;
document.querySelectorAll('.bw-slot-btn').forEach(btn => btn.addEventListener('click', (e) => { document.querySelectorAll('.bw-slot-btn').forEach(b => b.classList.remove('active')); e.target.classList.add('active'); selectedSlots = parseInt(e.target.dataset.slots); }));
document.querySelector('.bw-slot-btn[data-slots="1"]').classList.add('active');
function renderAssists() {
const list = document.getElementById('assists-list');
if (assists.length === 0) { list.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">No group attacks scheduled</div>'; return; }
list.innerHTML = assists.map((assist, index) => `
<div class="bw-assist-item" style="flex-direction: column; align-items: flex-start;">
<div style="width: 100%; display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div><a href="#" class="bw-target-name" data-id="${assist.id}">${assist.name} [${assist.id}]${assist.level ? ' - Level ' + assist.level : ''}</a><span style="color: #999; margin-left: 10px; font-size: 12px;">(${assist.slots} slots)</span></div>
<div><button class="bw-im-in-btn" data-index="${index}">I'm in</button><button class="bw-add-button" data-id="${assist.id}" style="margin: 0 5px; font-size: 11px; padding: 5px 10px;">Attack</button><button class="bw-remove-button" data-index="${index}" data-type="assist">Remove</button></div>
</div>
${assist.participants && assist.participants.length > 0 ? `<div class="bw-participants">${assist.participants.map(p => `<span class="bw-participant-tag">${p}</span>`).join('')}</div>` : '<div style="color: #666; font-size: 12px;">No participants yet</div>'}
</div>`).join('');
document.querySelectorAll('#assists-list .bw-target-name').forEach(link => link.addEventListener('click', (e) => { e.preventDefault(); window.open(`https://www.tornstats.com/spy.php?id=${e.target.dataset.id}`, '_blank', 'width=1000,height=700'); }));
document.querySelectorAll('#assists-list .bw-add-button').forEach(btn => btn.addEventListener('click', (e) => window.open(`https://www.torn.com/loader.php?sid=attack&user2ID=${e.target.dataset.id}`, '_blank')));
document.querySelectorAll('.bw-im-in-btn').forEach(btn => btn.addEventListener('click', (e) => {
const index = parseInt(e.target.dataset.index);
const assist = assists[index];
if (!currentUser || !currentUser.name) { alert('Please load your info first from the Info tab'); return; }
if (!assist.participants) assist.participants = [];
if (assist.participants.includes(currentUser.name)) { alert('You are already in this assist!'); return; }
if (assist.participants.length >= assist.slots) { alert('This assist is full!'); return; }
assist.participants.push(currentUser.name);
updateAssistInFirebase(assist.firebaseId, { participants: assist.participants });
}));
document.querySelectorAll('#assists-list .bw-remove-button').forEach(btn => btn.addEventListener('click', (e) => { const index = parseInt(e.target.dataset.index); const assist = assists[index]; removeAssistFromFirebase(assist.firebaseId); }));
}
document.getElementById('add-assist-btn').addEventListener('click', async () => {
const input = document.getElementById('assist-input');
const value = input.value.trim();
if (!value) { alert('Please enter a username or ID'); return; }
if(!getApiKey()) { alert("Missing API Key! Please go to Settings and add your Torn API Key."); return; }
try {
let data;
if (/^\d+$/.test(value)) { data = await tornApiCall(`user/${value}?selections=profile`); }
else { data = await tornApiCall(`user/${value}?selections=profile`); }
if (!data || !data.player_id) { alert('User not found! Try using their ID (numbers) instead of username.'); return; }
const newAssist = { id: data.player_id, name: data.name, level: data.level, slots: selectedSlots, participants: [] };
if (assists.find(a => a.id === newAssist.id)) { alert('This target already has an assist scheduled!'); return; }
const success = await addAssistToFirebase(newAssist);
if(success) {
input.value = '';
alert(`✓ Added assist for: ${newAssist.name} [${newAssist.id}]`);
}
} catch (error) {
console.error('Add assist error:', error);
alert('Failed to add assist: ' + (error.message || error));
}
});
function openModal() {
modal.classList.add('active'); overlay.classList.add('active'); settingsModal.classList.remove('active');
loadUserInfo(); loadFactionMembers();
startDBPolling(); // Start checking for updates
}
function openSettingsModal() { settingsModal.classList.add('active'); overlay.classList.add('active'); modal.classList.remove('active'); document.getElementById('api-key-input').value = getApiKey(); }
function closeModals() { modal.classList.remove('active'); settingsModal.classList.remove('active'); overlay.classList.remove('active'); }
button.addEventListener('click', openModal);
modal.querySelector('.bw-settings-button').addEventListener('click', openSettingsModal);
overlay.addEventListener('click', closeModals);
modal.querySelector('.bw-close-button').addEventListener('click', closeModals);
settingsModal.querySelector('.settings-close').addEventListener('click', closeModals);
document.getElementById('save-api-key').addEventListener('click', () => {
const apiKey = document.getElementById('api-key-input').value.trim();
if (apiKey) { GM_setValue('torn_api_key', apiKey); alert('API Key saved!'); closeModals(); }
});
const tabs = modal.querySelectorAll('.bw-tab');
const tabContents = modal.querySelectorAll('.bw-tab-content');
tabs.forEach(tab => tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active')); tabContents.forEach(tc => tc.classList.remove('active'));
tab.classList.add('active'); document.getElementById(`${tab.dataset.tab}-content`).classList.add('active');
}));
}
initScript();
})();