Files
2026-04-15 08:00:15 +03:00

176 lines
7.5 KiB
HTML

{{define "content"}}
<div class="card">
<h3>Twitch</h3>
<div>
<p>Статус бота: <span id="twitch-status" class="status">Загрузка...</span></p>
<p>Имя канала: <span id="twitch-channel"></span></p>
</div>
<div style="margin: 10px 0;">
<button id="auth-user-btn">🔐 Авторизовать стримера</button>
<button id="auth-bot-btn">🤖 Авторизовать бота</button>
</div>
<div id="twitch-tokens-info"></div>
<div id="token-expiry-info" style="margin-top: 10px; font-size: 0.9em;">
<p>🕒 Срок действия токенов:</p>
<p>👤 Стример: <span id="user-expiry"></span></p>
<p>🤖 Бот: <span id="bot-expiry"></span></p>
</div>
<!-- Блок для отображения ссылки авторизации БОТА -->
<div id="auth-link-container" style="margin-top: 15px; display: none;">
<label>Скопируйте ссылку и откройте её в браузере, где залогинен аккаунт БОТА:</label>
<div style="display: flex; gap: 10px; margin-top: 5px;">
<input type="text" id="auth-link" readonly style="flex: 1; padding: 8px; font-family: monospace;">
<button id="copy-link-btn">📋 Копировать</button>
</div>
<p id="auth-wait-message" style="color: #666; margin-top: 10px;">Ожидание подтверждения авторизации...</p>
</div>
<div id="notification" style="position: fixed; top: 20px; right: 20px; z-index: 1000; background: #333; color: white; padding: 10px 20px; border-radius: 5px; display: none;"></div>
</div>
<script>
let pollInterval = null;
async function loadSettings() {
try {
const statusRes = await fetch('/api/platforms/twitch/status');
const statusData = await statusRes.json();
const statusSpan = document.getElementById('twitch-status');
if (statusData.connected) {
statusSpan.textContent = 'Подключен';
statusSpan.className = 'status online';
} else {
statusSpan.textContent = 'Отключен';
statusSpan.className = 'status offline';
}
const authRes = await fetch('/api/platforms/twitch/auth');
const authData = await authRes.json();
document.getElementById('twitch-channel').textContent = authData.username || 'не указан';
const tokensDiv = document.getElementById('twitch-tokens-info');
if (authData.hasToken) {
tokensDiv.innerHTML = `<p>🔑 Токен бота: ${authData.maskedToken}</p>`;
loadTokenExpiry();
} else {
tokensDiv.innerHTML = '<p style="color: orange;">⚠️ Токен бота не настроен. Авторизуйте бота.</p>';
}
} catch (err) {
console.error('Ошибка загрузки настроек:', err);
document.getElementById('twitch-status').textContent = 'Ошибка';
}
}
async function updateStatus() {
try {
const res = await fetch('/api/platforms/twitch/status');
const data = await res.json();
const statusSpan = document.getElementById('twitch-status');
if (data.connected) {
statusSpan.textContent = 'Подключен';
statusSpan.className = 'status online';
} else {
statusSpan.textContent = 'Отключен';
statusSpan.className = 'status offline';
}
} catch (err) {}
}
async function authStreamer() {
try {
const res = await fetch('/api/platforms/twitch/auth/user');
const data = await res.json();
if (data.url) {
window.open(data.url, '_blank', 'width=600,height=700');
if (pollInterval) clearInterval(pollInterval);
pollInterval = setInterval(() => checkTokenUpdated('user'), 2000);
} else {
alert('Не удалось получить ссылку для авторизации');
}
} catch (err) {
alert('Ошибка: ' + err.message);
}
}
async function authBot() {
try {
const res = await fetch('/api/platforms/twitch/auth/bot');
const data = await res.json();
if (data.url) {
document.getElementById('auth-link').value = data.url;
document.getElementById('auth-link-container').style.display = 'block';
if (pollInterval) clearInterval(pollInterval);
pollInterval = setInterval(() => checkTokenUpdated('bot'), 2000);
} else {
alert('Не удалось получить ссылку для авторизации');
}
} catch (err) {
alert('Ошибка: ' + err.message);
}
}
async function loadTokenExpiry() {
try {
const res = await fetch('/api/platforms/twitch/token_expiry');
const data = await res.json();
const userSpan = document.getElementById('user-expiry');
const botSpan = document.getElementById('bot-expiry');
if (data.user_expiry_days !== null && data.user_expiry_days !== undefined) {
userSpan.textContent = data.user_expiry_days + ' дн.';
if (data.user_expiry_days < 1) userSpan.style.color = 'red';
else if (data.user_expiry_days < 3) userSpan.style.color = 'orange';
else userSpan.style.color = 'green';
} else {
userSpan.textContent = 'не авторизован';
}
if (data.bot_expiry_days !== null && data.bot_expiry_days !== undefined) {
botSpan.textContent = data.bot_expiry_days + ' дн.';
if (data.bot_expiry_days < 1) botSpan.style.color = 'red';
else if (data.bot_expiry_days < 3) botSpan.style.color = 'orange';
else botSpan.style.color = 'green';
} else {
botSpan.textContent = 'не авторизован';
}
} catch (err) {
console.error('Ошибка загрузки срока токенов:', err);
}
}
function showMessage(text, isError = false) {
const notif = document.getElementById('notification');
notif.textContent = text;
notif.style.backgroundColor = isError ? '#d9534f' : '#5cb85c';
notif.style.display = 'block';
setTimeout(() => { notif.style.display = 'none'; }, 3000);
}
async function checkTokenUpdated(type) {
try {
const res = await fetch(`/api/platforms/twitch/token_check?type=${type}`);
const data = await res.json();
if (data.updated) {
clearInterval(pollInterval);
pollInterval = null;
if (type === 'bot') {
document.getElementById('auth-link-container').style.display = 'none';
}
showMessage(`✅ Токен ${type === 'user' ? 'стримера' : 'бота'} сохранён!`, false);
loadSettings();
}
} catch (err) {
console.error('Ошибка проверки токена:', err);
}
}
document.getElementById('copy-link-btn').addEventListener('click', () => {
const linkInput = document.getElementById('auth-link');
linkInput.select();
document.execCommand('copy');
alert('Ссылка скопирована! Откройте её в другом браузере.');
});
document.getElementById('auth-user-btn').onclick = authStreamer;
document.getElementById('auth-bot-btn').onclick = authBot;
loadSettings();
setInterval(updateStatus, 10000);
</script>
{{end}}