(function() { const userId = document.currentScript.getAttribute('data-user-id'); const baseUrl = 'https://app.layeredy.com'; let loadedAnnouncements = { top: false, bottom: false }; const createStyles = () => { const style = document.createElement('style'); style.textContent = ` .announce-bar { padding: 0.75rem 1rem; text-align: center; display: flex; justify-content: center; align-items: center; z-index: 1000; width: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; font-size: 14px; box-sizing: border-box; } .announce-bar.top { position: fixed; top: 0; left: 0; } .announce-bar.bottom { position: fixed; bottom: 0; left: 0; } .announce-bar .content { margin-right: 0.5rem; } .announce-bar .link a { font-weight: 500; text-decoration: underline; } .announce-bar .close { margin-left: 1rem; cursor: pointer; font-weight: bold; font-size: 1.5rem; line-height: 1; } .announce-bar.default { background-color: #3b82f6; color: white; } .announce-bar.default .link a { color: white; } .announce-bar.dark { background-color: #1a202c; color: white; } .announce-bar.dark .link a { color: white; } .announce-bar.light { background-color: #f8fafc; color: #1e293b; } .announce-bar.light .link a { color: #1e293b; font-weight: 600; } .announce-bar.success { background-color: #10b981; color: white; } .announce-bar.success .link a { color: white; } .announce-bar.warning { background-color: #f59e0b; color: white; } .announce-bar.warning .link a { color: white; } .announce-bar.danger { background-color: #ef4444; color: white; } .announce-bar.danger .link a { color: white; } .announce-bar.info { background-color: #06b6d4; color: white; } .announce-bar.info .link a { color: white; } .announce-bar.primary { background-color: #3b82f6; color: white; } .announce-bar.primary .link a { color: white; } .announce-bar.purple { background-color: #8b5cf6; color: white; } .announce-bar.purple .link a { color: white; } .announce-bar.teal { background-color: #14b8a6; color: white; } .announce-bar.teal .link a { color: white; } .announce-bar.pink { background-color: #ec4899; color: white; } .announce-bar.pink .link a { color: white; } .announce-bar.orange { background-color: #f97316; color: white; } .announce-bar.orange .link a { color: white; } `; document.head.appendChild(style); }; const sanitizeContent = (content) => { if (!content) return ''; try { const div = document.createElement('div'); div.textContent = content; return div.innerHTML; } catch (e) { return ''; } }; const fetchAnnouncement = async () => { try { const response = await fetch(`${baseUrl}/api/announcement/${userId}`); if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') || 60; return new Promise(resolve => { setTimeout(() => { resolve(fetchAnnouncement()); }, retryAfter * 1000); }); } let data; try { data = await response.json(); } catch (parseError) { throw new Error(`HTTP error: ${response.status}`); } if (data.error === 'userBanned') { console.error('lyrdy.co/announce (CRITICAL): Your website or IP has been banned from the Announce platform. If you are the site administrator and seeing this error: please uninstall Announce immediately. Announcement bars will not be displayed.'); return []; } if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } if (data.hasAnnouncement) { return [data]; } return []; } catch (error) { console.error('Error fetching announcement:', error); return []; } }; const createAnnouncementBar = (announcement) => { if (announcement.showOnce && announcement.allowDismissal) { const dismissed = localStorage.getItem(`announce_dismissed_${announcement.id}`); if (dismissed) return; } if (loadedAnnouncements[announcement.position]) return; const announceBar = document.createElement('div'); if (announcement.theme === 'custom') { announceBar.className = `announce-bar custom ${announcement.position}`; const bgColor = announcement.customColor || '#3b82f6'; announceBar.style.backgroundColor = bgColor; if (announcement.customTextColor) { announceBar.style.color = announcement.customTextColor; } else { const hex = bgColor.replace('#', ''); const r = parseInt(hex.substr(0, 2), 16); const g = parseInt(hex.substr(2, 2), 16); const b = parseInt(hex.substr(4, 2), 16); const brightness = (r * 299 + g * 587 + b * 114) / 1000; announceBar.style.color = brightness > 155 ? '#1e293b' : '#ffffff'; } announceBar.style.opacity = announcement.opacity || 1.0; } else { announceBar.className = `announce-bar ${announcement.theme} ${announcement.position}`; } const content = document.createElement('span'); content.className = 'content'; content.innerHTML = sanitizeContent(announcement.content); announceBar.appendChild(content); if (announcement.linkUrl && announcement.linkText) { const linkSpan = document.createElement('span'); linkSpan.className = 'link'; const link = document.createElement('a'); if (/^(https?:\/\/|\/\/)/i.test(announcement.linkUrl)) { link.href = announcement.linkUrl; link.textContent = sanitizeContent(announcement.linkText); link.target = '_blank'; link.rel = 'noopener noreferrer'; if (announcement.theme === 'custom') { link.style.color = 'inherit'; link.style.fontWeight = '600'; } linkSpan.appendChild(link); announceBar.appendChild(linkSpan); } } if (announcement.allowDismissal) { const closeBtn = document.createElement('span'); closeBtn.className = 'close'; closeBtn.textContent = '×'; closeBtn.addEventListener('click', () => { announceBar.remove(); if (announcement.showOnce) { localStorage.setItem(`announce_dismissed_${announcement.id}`, 'true'); } if (announcement.position === 'top') { document.body.style.paddingTop = ''; loadedAnnouncements.top = false; } else if (announcement.position === 'bottom') { document.body.style.paddingBottom = ''; loadedAnnouncements.bottom = false; } }); announceBar.appendChild(closeBtn); } loadedAnnouncements[announcement.position] = true; document.body.appendChild(announceBar); if (announcement.position === 'top') { setTimeout(() => { document.body.style.paddingTop = `${announceBar.offsetHeight}px`; }, 50); } else if (announcement.position === 'bottom') { setTimeout(() => { document.body.style.paddingBottom = `${announceBar.offsetHeight}px`; }, 50); } }; const init = async () => { if (!userId || !/^(usr_|team_)[a-zA-Z0-9]+$/.test(userId)) { console.error('Announce: Invalid user ID format'); return; } createStyles(); const announcements = await fetchAnnouncement(); if (announcements.length > 0) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { announcements.forEach(announcement => createAnnouncementBar(announcement)); }); } else { announcements.forEach(announcement => createAnnouncementBar(announcement)); } } }; setTimeout(init, 10); })();