package model import "fmt" func GetTemplate1(streamerID int) string { style := `body { margin: 0; padding: 0; height: 100vh; display: flex; justify-content: center; align-items: flex-start; background-color: #000; font-family: Arial, sans-serif; } #content { display: flex; flex-direction: column; align-items: center; margin-top: 100px; gap: 20px; } #content img { width: 50vw; height: 50vh; object-fit: cover; border-radius: 15px; animation: scaleUp 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .text-container { display: flex; align-items: center; gap: 20px; font-size: 40px; color: #fff; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); opacity: 0; animation: textSlideIn 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards; } .donation-text { margin: 0; transform: translateX(-50px); opacity: 0; animation: textFadeIn 0.6s 0.3s ease-out forwards; } .donation-amount { color: #4CAF50; font-weight: bold; padding: 5px 15px; background: rgba(0,0,0,0.7); border-radius: 8px; transform: translateX(50px); opacity: 0; animation: amountFadeIn 0.6s 0.5s ease-out forwards; } @keyframes scaleUp { from { transform: scale(0.8); opacity: 0; } to { transform: scale(1); opacity: 1; } } @keyframes textSlideIn { from { transform: translateY(100px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes textFadeIn { to { transform: translateX(0); opacity: 1; } } @keyframes amountFadeIn { to { transform: translateX(0); opacity: 1; } }` script := fmt.Sprintf(` let widgetUrl = 'http://212.60.21.70:8002/api'; let ttsUrl = 'http://212.60.21.70:8005/api/tts'; function createTextWithAmount(text, amount) { const container = document.createElement('div'); container.className = 'text-container'; const textElem = document.createElement('p'); textElem.className = 'donation-text'; textElem.textContent = text; const amountElem = document.createElement('div'); amountElem.className = 'donation-amount'; amountElem.textContent = '₽' + amount; container.appendChild(textElem); container.appendChild(amountElem); return container; } async function getDonatInfo(streamerID) { try { let response = await fetch(widgetUrl + '/widget/get-donat-for-playing/' + streamerID); return await response.json(); } catch (error) { console.error('Fetch error:', error); return null; } } function addImage(container, imageUrl) { const img = document.createElement('img'); img.src = imageUrl + '?t=' + new Date().getTime(); container.appendChild(img); } function addText(container, text) { const p = document.createElement('p'); p.className = 'donation-text'; p.textContent = text; container.appendChild(p); } function clearContainer(container) { while (container.firstChild) { container.removeChild(container.firstChild); } } function playAudio(audioUrl, callback) { fetch(audioUrl) .then(response => { if (!response.ok) throw new Error('Audio network error'); return response.blob(); }) .then(blob => { const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play().catch(console.error); setTimeout(() => { audio.pause(); URL.revokeObjectURL(url); if (callback) callback(); }, 7000); }) .catch(console.error); } function playSpeech(text) { fetch(ttsUrl + '/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: text }), }) .then(response => { if (!response.ok) throw new Error('TTS error'); return response.blob(); }) .then(blob => { const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play().catch(console.error); audio.addEventListener('ended', () => { URL.revokeObjectURL(url); }); }) .catch(console.error); } function playSpeechAfterAudio(audioUrl, text) { playAudio(audioUrl, () => playSpeech(text)); } async function widgetView() { const streamerID = '%v'; const contentDiv = document.getElementById('content'); if (!contentDiv) { console.error('Content container not found!'); return; } while (true) { try { const donat = await getDonatInfo(streamerID); console.log('Donat received:', donat); if (!donat || Object.keys(donat).length === 0) { await new Promise(r => setTimeout(r, 5000)); continue; } clearContainer(contentDiv); if (donat.image_link) { addImage(contentDiv, donat.image_link); } if (donat.text && donat.amount) { const textWithAmount = createTextWithAmount(donat.text, donat.amount); contentDiv.appendChild(textWithAmount); } else if (donat.text) { addText(contentDiv, donat.text); } if (donat.audio_link) { playSpeechAfterAudio(donat.audio_link, donat.text); } else if (donat.text) { playSpeech(donat.text); } await new Promise(r => setTimeout(r, donat.duration * 1000)); } catch (error) { console.error('Main loop error:', error); await new Promise(r => setTimeout(r, 5000)); } } } document.addEventListener('DOMContentLoaded', widgetView);`, streamerID) template := fmt.Sprintf(`
`, style, script) return template }