328 lines
11 KiB
JavaScript
328 lines
11 KiB
JavaScript
(function () {
|
|
function initTelegramFab() {
|
|
const root = document.getElementById('telegramFabRoot');
|
|
if (!root || root.dataset.initialized === 'true') {
|
|
return;
|
|
}
|
|
|
|
root.dataset.initialized = 'true';
|
|
|
|
const dataset = root.dataset;
|
|
const offcanvasElement = document.getElementById('telegramPremiumOffcanvas');
|
|
const loadingSection = document.getElementById('telegramFabLoading');
|
|
const connectedSection = document.getElementById('telegramFabConnected');
|
|
const disconnectedSection = document.getElementById('telegramFabDisconnected');
|
|
const alertElement = document.getElementById('telegramFabAlert');
|
|
const retryButton = root.querySelector('.telegram-fab-retry');
|
|
const openButton = root.querySelector('.telegram-fab-open');
|
|
const unlinkButton = root.querySelector('.telegram-fab-unlink');
|
|
const usernameElement = root.querySelector('.telegram-fab-username');
|
|
const widgetPlaceholder = document.getElementById('telegramLoginWidgetPlaceholder');
|
|
const toastContainer = document.getElementById('telegramFabToasts');
|
|
const fabButton = document.getElementById('telegramPremiumFab');
|
|
|
|
if (!offcanvasElement || !loadingSection || !connectedSection || !disconnectedSection) {
|
|
console.warn('[Telegram FAB] Missing required DOM nodes. Aborting initialization.');
|
|
return;
|
|
}
|
|
|
|
const offcanvas = bootstrap.Offcanvas.getOrCreateInstance(offcanvasElement);
|
|
let currentStatus = null;
|
|
let currentDeepLink = null;
|
|
let widgetMounted = false;
|
|
|
|
const messages = {
|
|
loading: dataset.statusLoading || 'Loading...',
|
|
error: dataset.statusError || 'Something went wrong.',
|
|
connectedTemplate: dataset.statusConnected || 'Connected as {0}',
|
|
disconnected: dataset.statusDisconnected || '',
|
|
linkSuccess: dataset.linkSuccess || 'Linked successfully.',
|
|
unlinkSuccess: dataset.unlinkSuccess || 'Unlinked successfully.',
|
|
linkError: dataset.linkError || 'Unable to link. Try again.',
|
|
unlinkError: dataset.unlinkError || 'Unable to unlink. Try again.',
|
|
retry: dataset.retryLabel || 'Try again',
|
|
open: dataset.openLabel || 'Open',
|
|
unlink: dataset.unlinkLabel || 'Unlink'
|
|
};
|
|
|
|
function toggleSections(state) {
|
|
loadingSection.classList.toggle('d-none', state !== 'loading');
|
|
connectedSection.classList.toggle('d-none', state !== 'connected');
|
|
disconnectedSection.classList.toggle('d-none', state !== 'disconnected');
|
|
}
|
|
|
|
function showAlert(message) {
|
|
if (!alertElement) {
|
|
return;
|
|
}
|
|
|
|
alertElement.textContent = message;
|
|
alertElement.classList.remove('d-none');
|
|
}
|
|
|
|
function hideAlert() {
|
|
if (!alertElement) {
|
|
return;
|
|
}
|
|
|
|
alertElement.classList.add('d-none');
|
|
alertElement.textContent = '';
|
|
}
|
|
|
|
function showToast(message, type) {
|
|
if (!toastContainer || !message) {
|
|
return;
|
|
}
|
|
|
|
const palette = {
|
|
success: 'text-bg-success',
|
|
error: 'text-bg-danger',
|
|
info: 'text-bg-info'
|
|
};
|
|
const toast = document.createElement('div');
|
|
toast.className = `toast align-items-center ${palette[type] || palette.info} border-0`;
|
|
toast.role = 'status';
|
|
toast.setAttribute('aria-live', 'polite');
|
|
toast.innerHTML = [
|
|
'<div class="d-flex">',
|
|
`<div class="toast-body">${message}</div>`,
|
|
'<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>',
|
|
'</div>'
|
|
].join('');
|
|
|
|
toastContainer.appendChild(toast);
|
|
|
|
const toastInstance = bootstrap.Toast.getOrCreateInstance(toast, {
|
|
delay: 4000,
|
|
autohide: true
|
|
});
|
|
|
|
toast.addEventListener('hidden.bs.toast', function () {
|
|
toast.remove();
|
|
});
|
|
|
|
toastInstance.show();
|
|
}
|
|
|
|
function updateConnectedView(username, deepLink) {
|
|
toggleSections('connected');
|
|
hideAlert();
|
|
|
|
if (usernameElement) {
|
|
usernameElement.textContent = username || '';
|
|
}
|
|
|
|
currentDeepLink = deepLink || null;
|
|
}
|
|
|
|
function updateDisconnectedView() {
|
|
toggleSections('disconnected');
|
|
hideAlert();
|
|
|
|
if (!widgetMounted) {
|
|
mountLoginWidget();
|
|
}
|
|
}
|
|
|
|
function applyErrorState(message) {
|
|
toggleSections('disconnected');
|
|
showAlert(message || messages.error);
|
|
|
|
if (retryButton) {
|
|
retryButton.classList.remove('d-none');
|
|
}
|
|
}
|
|
|
|
async function fetchStatus() {
|
|
toggleSections('loading');
|
|
hideAlert();
|
|
|
|
try {
|
|
const response = await fetch('/telegram/status', {
|
|
method: 'GET',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
'Accept': 'application/json'
|
|
}
|
|
});
|
|
|
|
if (response.status === 401 || response.status === 403) {
|
|
if (fabButton) {
|
|
fabButton.setAttribute('hidden', 'hidden');
|
|
fabButton.setAttribute('tabindex', '-1');
|
|
}
|
|
root.setAttribute('aria-hidden', 'true');
|
|
root.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
if (!response.ok) {
|
|
throw new Error('status_request_failed');
|
|
}
|
|
|
|
currentStatus = await response.json();
|
|
|
|
if (currentStatus && currentStatus.connected) {
|
|
updateConnectedView(currentStatus.username || '', currentStatus.deepLink || null);
|
|
} else {
|
|
updateDisconnectedView();
|
|
}
|
|
} catch (error) {
|
|
console.warn('[Telegram FAB] Status request failed:', error);
|
|
applyErrorState(messages.error);
|
|
}
|
|
}
|
|
|
|
function mountLoginWidget() {
|
|
const botUsernameRaw = (dataset.botUsername || '').trim();
|
|
|
|
if (!botUsernameRaw) {
|
|
console.warn('[Telegram FAB] Telegram bot username missing. Configure Telegram:LoginWidgetBotUsername.');
|
|
applyErrorState(messages.error);
|
|
return;
|
|
}
|
|
|
|
const botUsername = botUsernameRaw.startsWith('@')
|
|
? botUsernameRaw.slice(1)
|
|
: botUsernameRaw;
|
|
|
|
if (!widgetPlaceholder) {
|
|
return;
|
|
}
|
|
|
|
widgetPlaceholder.innerHTML = '';
|
|
|
|
const widgetScript = document.createElement('script');
|
|
widgetScript.src = 'https://telegram.org/js/telegram-widget.js?22';
|
|
widgetScript.async = true;
|
|
widgetScript.dataset.telegramLogin = botUsername;
|
|
widgetScript.dataset.size = 'large';
|
|
widgetScript.dataset.userpic = 'false';
|
|
widgetScript.dataset.requestAccess = dataset.requestAccess || 'write';
|
|
|
|
const lang = (dataset.telegramLang || 'en').replace('-', '_');
|
|
widgetScript.dataset.lang = lang;
|
|
|
|
widgetScript.dataset.onauth = 'telegramFabOnAuth';
|
|
|
|
widgetPlaceholder.appendChild(widgetScript);
|
|
widgetMounted = true;
|
|
}
|
|
|
|
async function linkTelegram(payload) {
|
|
toggleSections('loading');
|
|
hideAlert();
|
|
|
|
try {
|
|
const response = await fetch('/telegram/link', {
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
},
|
|
body: JSON.stringify(payload)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('link_failed');
|
|
}
|
|
|
|
showToast(messages.linkSuccess, 'success');
|
|
await fetchStatus();
|
|
} catch (error) {
|
|
console.error('[Telegram FAB] Link failed:', error);
|
|
showToast(messages.linkError, 'error');
|
|
applyErrorState(messages.linkError);
|
|
}
|
|
}
|
|
|
|
async function unlinkTelegram() {
|
|
toggleSections('loading');
|
|
hideAlert();
|
|
|
|
try {
|
|
const response = await fetch('/telegram/unlink', {
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
'Accept': 'application/json'
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('unlink_failed');
|
|
}
|
|
|
|
showToast(messages.unlinkSuccess, 'success');
|
|
widgetMounted = false;
|
|
await fetchStatus();
|
|
} catch (error) {
|
|
console.error('[Telegram FAB] Unlink failed:', error);
|
|
showToast(messages.unlinkError, 'error');
|
|
toggleSections('connected');
|
|
showAlert(messages.unlinkError);
|
|
}
|
|
}
|
|
|
|
offcanvasElement.addEventListener('show.bs.offcanvas', function () {
|
|
fetchStatus();
|
|
});
|
|
|
|
if (retryButton) {
|
|
retryButton.addEventListener('click', function () {
|
|
hideAlert();
|
|
fetchStatus();
|
|
});
|
|
}
|
|
|
|
if (openButton) {
|
|
openButton.addEventListener('click', function () {
|
|
if (currentDeepLink) {
|
|
window.open(currentDeepLink, '_blank', 'noopener');
|
|
} else {
|
|
fetchStatus();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (unlinkButton) {
|
|
unlinkButton.addEventListener('click', function () {
|
|
unlinkTelegram();
|
|
});
|
|
}
|
|
|
|
window.telegramFabOnAuth = function (user) {
|
|
if (!user) {
|
|
showToast(messages.linkError, 'error');
|
|
return;
|
|
}
|
|
|
|
const payload = {
|
|
id: user.id,
|
|
hash: user.hash,
|
|
first_name: user.first_name,
|
|
last_name: user.last_name,
|
|
username: user.username,
|
|
photo_url: user.photo_url,
|
|
auth_date: user.auth_date,
|
|
bot_id: dataset.botId || null
|
|
};
|
|
|
|
linkTelegram(payload);
|
|
};
|
|
|
|
if (fabButton) {
|
|
fabButton.addEventListener('keydown', function (event) {
|
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
event.preventDefault();
|
|
offcanvas.show();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', initTelegramFab);
|
|
window.initTelegramFab = initTelegramFab;
|
|
})();
|