package model import "fmt" func GetTemplate1( streamerID StreamerID, backgroundUrl MediaUrl, ) WidgetHTML { style := fmt.Sprintf(`body { margin: 0; padding: 0; height: 100vh; display: flex; justify-content: center; align-items: flex-start; background-image: url('%s'); background-repeat: no-repeat; background-size: cover; } #content { display: flex; flex-direction: column; align-items: center; margin-top: 100px } #content img { width: 50vw; height: 50vh; object-fit: cover; } #content audio { display: none; } #content p { font-size: 60px; } `, backgroundUrl) script := fmt.Sprintf(` let widgetUrl = 'http://localhost/api' let ttsUrl = 'http://147.45.237.174/api/tts' async function getDonatInfo(streamerID) { let response = await fetch(widgetUrl + '/widget/get-donat-for-playing/' + streamerID); return await response.json(); } function addImage(imageUrl) { const img = document.createElement('img'); img.src = imageUrl + '?t=' + new Date().getTime(); contentDiv.appendChild(img); } function addText(text) { const p = document.createElement('p'); p.textContent = text; contentDiv.appendChild(p); } function playAudio(audioUrl, callback) { fetch(audioUrl) .then(response => { if (!response.ok) throw new Error('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(); audio.remove(); if (callback) callback(); }, 7000); }); } 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); audio.remove(); }); }); } function playSpeechAfterAudio(audioUrl, text) { playAudio(audioUrl, () => playSpeech(text)); } async function endDonat() { while (contentDiv.firstChild) { contentDiv.removeChild(contentDiv.firstChild); } } async function widgetView() { const streamerID = '%v'; const contentDiv = document.getElementById('content'); while (true) { try { const donat = await getDonatInfo(streamerID); if (!donat) { await new Promise(r => setTimeout(r, 5000)); continue; } // Очищаем предыдущий контент endDonat(); // Добавляем изображение если есть if (donat.image_link) { addImage(donat.image_link); } // Добавляем текст if (donat.text) { addText(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('Error:', error); await new Promise(r => setTimeout(r, 5000)); } } } widgetView();`, streamerID) template := fmt.Sprintf(`
`, style, script) return WidgetHTML(template) }