public
This commit is contained in:
161
public/script.js
Normal file
161
public/script.js
Normal file
@@ -0,0 +1,161 @@
|
||||
class QuixoticApp {
|
||||
constructor() {
|
||||
this.tg = window.Telegram?.WebApp;
|
||||
this.init();
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
init() {
|
||||
if (this.tg) {
|
||||
this.tg.ready();
|
||||
this.tg.expand();
|
||||
this.tg.MainButton.hide();
|
||||
}
|
||||
|
||||
this.searchInput = document.getElementById('searchInput');
|
||||
this.searchBtn = document.getElementById('searchBtn');
|
||||
this.loading = document.getElementById('loading');
|
||||
this.results = document.getElementById('results');
|
||||
this.noResults = document.getElementById('noResults');
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.searchBtn.addEventListener('click', () => this.search());
|
||||
this.searchInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.search();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async search() {
|
||||
const query = this.searchInput.value.trim();
|
||||
if (!query) return;
|
||||
|
||||
this.showLoading();
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/search', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
userId: this.tg?.initDataUnsafe?.user?.id || 'demo'
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Search failed');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
this.displayResults(data.videos);
|
||||
} catch (error) {
|
||||
console.error('Search error:', error);
|
||||
this.showNoResults();
|
||||
}
|
||||
}
|
||||
|
||||
showLoading() {
|
||||
this.loading.classList.remove('hidden');
|
||||
this.results.classList.add('hidden');
|
||||
this.noResults.classList.add('hidden');
|
||||
this.searchBtn.disabled = true;
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
this.loading.classList.add('hidden');
|
||||
this.searchBtn.disabled = false;
|
||||
}
|
||||
|
||||
displayResults(videos) {
|
||||
this.hideLoading();
|
||||
|
||||
if (!videos || videos.length === 0) {
|
||||
this.showNoResults();
|
||||
return;
|
||||
}
|
||||
|
||||
this.results.innerHTML = videos.map(video => `
|
||||
<div class="video-item" onclick="app.convertVideo('${video.id}', '${this.escapeHtml(video.title)}')">
|
||||
<img class="video-thumbnail" src="${video.thumbnail}" alt="${this.escapeHtml(video.title)}" loading="lazy">
|
||||
<div class="video-info">
|
||||
<div class="video-title">${this.escapeHtml(video.title)}</div>
|
||||
<div class="video-channel">${this.escapeHtml(video.channel)}</div>
|
||||
<div class="video-duration">${this.formatDuration(video.duration)}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
this.results.classList.remove('hidden');
|
||||
this.noResults.classList.add('hidden');
|
||||
}
|
||||
|
||||
showNoResults() {
|
||||
this.hideLoading();
|
||||
this.results.classList.add('hidden');
|
||||
this.noResults.classList.remove('hidden');
|
||||
}
|
||||
|
||||
async convertVideo(videoId, title) {
|
||||
const videoElement = event.currentTarget;
|
||||
videoElement.classList.add('converting');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/convert', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
videoId,
|
||||
title,
|
||||
userId: this.tg?.initDataUnsafe?.user?.id || 'demo'
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Conversion failed');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (this.tg) {
|
||||
this.tg.sendData(JSON.stringify({
|
||||
action: 'send_audio',
|
||||
audioUrl: data.audioUrl,
|
||||
title: title
|
||||
}));
|
||||
} else {
|
||||
// Fallback for testing without Telegram
|
||||
window.open(data.audioUrl, '_blank');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Conversion error:', error);
|
||||
if (this.tg) {
|
||||
this.tg.showAlert('H81:0 ?@8 :>=25@B0F88. >?@>1C9B5 5I5 @07.');
|
||||
} else {
|
||||
alert('H81:0 ?@8 :>=25@B0F88. >?@>1C9B5 5I5 @07.');
|
||||
}
|
||||
} finally {
|
||||
videoElement.classList.remove('converting');
|
||||
}
|
||||
}
|
||||
|
||||
formatDuration(seconds) {
|
||||
if (!seconds) return '';
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = seconds % 60;
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
const app = new QuixoticApp();
|
||||
Reference in New Issue
Block a user