donat-widget/internal/model/widget-templates.go
2025-04-28 22:54:27 +05:00

221 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import "fmt"
func GetTemplate1(streamerID int, donatHost, ttsHost string) 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;
width: 100%;
max-width: 1920px;
margin: 20px auto;
gap: 20px;
}
#content img {
width: 100%;
height: auto;
max-height: 90vh;
object-fit: contain;
border-radius: 15px;
}
.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: fadeIn 2s forwards;
}
.donation-text {
margin: 0;
}
.donation-amount {
color: #4CAF50;
font-weight: bold;
padding: 5px 15px;
background: rgba(0,0,0,0.7);
border-radius: 8px;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}`
script := fmt.Sprintf(`
let widgetUrl = 'https://%s/api';
let ttsUrl = 'https://%s/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 playSpeech(text, voiceSettings) {
if (!voiceSettings.voice_enabled) return;
const params = new URLSearchParams({
text: text,
speed: voiceSettings.voice_speed || 'medium',
scenery: voiceSettings.scenery || 'default',
sound_percent: voiceSettings.voice_sound_percent || 100,
min_price: voiceSettings.min_price || 0,
languages: voiceSettings.languages?.join(',') || ''
});
const url = ttsUrl + '/generate?' + params.toString();
fetch(url)
.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, voiceSettings) {
playAudio(audioUrl, () => playSpeech(text, voiceSettings));
}
async function widgetView() {
const streamerID = '%v';
const contentDiv = document.getElementById('content');
const REQUEST_INTERVAL = 5000;
if (!contentDiv) {
console.error('Content container not found!');
return;
}
while (true) {
const iterationStart = Date.now();
try {
const donat = await getDonatInfo(streamerID);
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) {
const textElement = donat.amount
? createTextWithAmount(donat.text, donat.amount)
: createTextElement(donat.text);
contentDiv.appendChild(textElement);
}
// Воспроизведение аудио и TTS
const voiceSettings = {
voice_speed: donat.voice_speed,
scenery: donat.scenery,
voice_sound_percent: donat.voice_sound_percent,
min_price: donat.min_price,
languages: donat.languages,
voice_enabled: donat.voice_enabled
};
if (donat.audio_link) {
playSpeechAfterAudio(donat.audio_link, donat.text, voiceSettings);
} else if (donat.text && donat.voice_enabled) {
playSpeech(donat.text, voiceSettings);
}
// Таймаут на основе duration
await new Promise(r => setTimeout(r, donat.duration * 1000));
// Отправка подтверждения просмотра
if (donat.order_id) {
try {
const response = await fetch(widgetUrl + '/widget/donat/viewed', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({order_id: donat.order_id}),
});
if (!response.ok) console.error('Ошибка подтверждения просмотра');
} catch (error) {
console.error('Ошибка:', error);
}
}
} catch (error) {
console.error('Ошибка в цикле:', error);
} finally {
// Гарантируем задержку между итерациями
const elapsed = Date.now() - iterationStart;
const remaining = REQUEST_INTERVAL - elapsed;
if (remaining > 0) {
await new Promise(r => setTimeout(r, remaining));
}
}
}
}
document.addEventListener('DOMContentLoaded', widgetView);`, donatHost, ttsHost, streamerID)
template := fmt.Sprintf(`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>%s</style>
</head>
<body>
<div id='content'></div>
<script>%s</script>
</body>
</html>`, style, script)
return template
}