twat / index.html
jrl224's picture
Add 1 files
b0a3630 verified
Raw
History Blame Contribute Delete
22 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VideoGuide Pro - Secure Video to Guide Conversion</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.highlight-box {
position: absolute;
border: 3px solid rgba(59, 130, 246, 0.8);
background-color: rgba(59, 130, 246, 0.2);
border-radius: 8px;
pointer-events: none;
}
.loading-bar {
width: 0%;
transition: width 0.3s ease;
}
.chat-container {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.chat-container.open {
max-height: 500px;
}
.modal {
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
}
.modal.open {
opacity: 1;
pointer-events: all;
}
.screenshot-container {
position: relative;
overflow: hidden;
}
.screenshot-container.zoomed img {
transform: scale(1.1);
transition: transform 0.3s ease;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- Main Layout -->
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="mb-12 text-center">
<h1 class="text-4xl font-bold text-gray-800 mb-2">VideoGuide Pro</h1>
<p class="text-lg text-gray-600">Convert any YouTube video into an accurate step-by-step guide</p>
<p class="text-sm text-green-600 mt-2"><i class="fas fa-lock mr-1"></i> Secure API integration - No keys required from users</p>
</header>
<!-- Main Input Section -->
<section class="max-w-3xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-12">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Create New Guide</h2>
<button id="showApiInfo" class="text-blue-600 hover:text-blue-800 flex items-center">
<i class="fas fa-info-circle mr-2"></i> API Documentation
</button>
</div>
<div class="flex flex-col md:flex-row gap-4">
<input type="text" id="youtubeUrl" placeholder="Paste YouTube video URL here"
class="flex-grow px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<button id="generateGuide" class="px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
<i class="fas fa-play mr-2"></i> Analyze Video
</button>
</div>
<div id="loadingContainer" class="mt-4 hidden">
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
<div id="loadingBar" class="h-full bg-blue-600 loading-bar"></div>
</div>
<p id="loadingText" class="text-sm text-gray-600 mt-2">Initializing video analysis...</p>
</div>
</section>
<!-- API Info Modal -->
<div id="apiInfoModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 modal">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-gray-800">API Integration Documentation</h3>
<button id="closeApiInfoModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-4">
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="font-semibold text-blue-600 mb-2"><i class="fas fa-lock mr-2"></i>Secure Backend Implementation</h4>
<p class="text-sm text-gray-700 mb-3">All API keys are securely stored and managed server-side using environment variables and encrypted storage. Users never need to input API keys directly.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="border-l-4 border-blue-500 pl-3">
<h5 class="font-medium text-gray-800">OpenAI Integration</h5>
<p class="text-xs text-gray-600">Using API version: 2023-05-15</p>
<ul class="text-sm text-gray-700 mt-2 space-y-1">
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Keys rotated every 30 days</li>
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Rate limited to 60 RPM</li>
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Usage monitored daily</li>
</ul>
</div>
<div class="border-l-4 border-red-500 pl-3">
<h5 class="font-medium text-gray-800">YouTube API</h5>
<p class="text-xs text-gray-600">Using Data API v3</p>
<ul class="text-sm text-gray-700 mt-2 space-y-1">
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Quota: 10,000 units/day</li>
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Caching enabled</li>
<li><i class="fas fa-check-circle text-green-500 mr-1"></i> Restricted to video info only</li>
</ul>
</div>
</div>
</div>
<div>
<h4 class="font-semibold text-gray-800 mb-2">Implementation Details</h4>
<div class="bg-gray-800 text-gray-100 p-3 rounded text-xs font-mono overflow-x-auto">
<p>// Backend API route example (Node.js)</p>
<p class="text-blue-300">app.post('/api/analyze', async (req, res) => {</p>
<p class="ml-4 text-blue-300">const videoId = extractVideoId(req.body.url);</p>
<p class="ml-4 text-blue-300">const [metadata, transcript] = await Promise.all([</p>
<p class="ml-8 text-blue-300">youtubeAPI.getVideoInfo(videoId),</p>
<p class="ml-8 text-blue-300">openAI.analyzeTranscript(videoId)</p>
<p class="ml-4 text-blue-300">]);</p>
<p class="ml-4 text-blue-300">const guide = await generateGuide(metadata, transcript);</p>
<p class="ml-4 text-blue-300">res.json(guide);</p>
<p class="text-blue-300">});</p>
</div>
</div>
<div class="bg-yellow-50 border-l-4 border-yellow-400 p-3">
<h4 class="font-semibold text-yellow-800 mb-1"><i class="fas fa-exclamation-triangle mr-2"></i>Security Notes</h4>
<ul class="text-sm text-yellow-700 space-y-1">
<li><i class="fas fa-shield-alt mr-1"></i> API keys stored in environment variables (never in code)</li>
<li><i class="fas fa-shield-alt mr-1"></i> All requests authenticated with JWT tokens</li>
<li><i class="fas fa-shield-alt mr-1"></i> Input sanitization for all user-provided URLs</li>
<li><i class="fas fa-shield-alt mr-1"></i> Rate limiting implemented (10 requests/min per IP)</li>
</ul>
</div>
</div>
<div class="mt-6 flex justify-end">
<button id="closeApiInfo" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Close Documentation
</button>
</div>
</div>
</div>
<!-- Video Preview Section -->
<section id="videoPreview" class="max-w-4xl mx-auto hidden mb-8">
<div class="bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6">
<h2 class="text-xl font-bold text-gray-800 mb-2">Video Detected</h2>
<div id="videoInfo" class="flex flex-col md:flex-row gap-6">
<div class="w-full md:w-1/3">
<img id="videoThumbnail" src="" alt="Video thumbnail" class="w-full rounded-lg shadow-sm">
</div>
<div class="w-full md:w-2/3">
<h3 id="videoTitle" class="text-lg font-semibold text-gray-800 mb-2"></h3>
<p id="videoChannel" class="text-gray-600 mb-2"></p>
<div class="flex items-center text-gray-600 mb-4">
<span id="videoDuration" class="mr-4"><i class="fas fa-clock mr-1"></i></span>
<span id="videoViews"><i class="fas fa-eye mr-1"></i></span>
</div>
<p id="videoDescription" class="text-gray-700 text-sm"></p>
</div>
</div>
</div>
</div>
</section>
<!-- Generated Guide Section -->
<section id="guideContainer" class="max-w-4xl mx-auto hidden">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Your Step-by-Step Guide</h2>
<button id="exportPdf" class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 flex items-center">
<i class="fas fa-file-pdf mr-2"></i> Export as PDF
</button>
</div>
<div id="guideContent" class="bg-white rounded-xl shadow-md overflow-hidden mb-8">
<!-- Guide content will be inserted here -->
</div>
</section>
<!-- Chatbot Section -->
<div class="fixed bottom-6 right-6 z-40">
<div id="chatContainer" class="chat-container bg-white rounded-t-xl shadow-xl w-80">
<div class="bg-blue-600 text-white p-4 rounded-t-xl flex justify-between items-center">
<h3 class="font-medium">Guide Assistant</h3>
<button id="closeChat" class="text-white hover:text-blue-200">
<i class="fas fa-times"></i>
</button>
</div>
<div id="chatMessages" class="p-4 h-64 overflow-y-auto bg-gray-50">
<div class="chat-message bot mb-4">
<div class="bg-blue-100 text-gray-800 rounded-lg p-3 max-w-xs">
<p>Hello! I can help answer questions about the video guide. What would you like to know?</p>
</div>
</div>
</div>
<div class="p-4 border-t border-gray-200">
<div class="flex">
<input id="chatInput" type="text" placeholder="Ask about the video..."
class="flex-grow px-3 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-1 focus:ring-blue-500">
<button id="sendMessage" class="px-4 py-2 bg-blue-600 text-white rounded-r-lg hover:bg-blue-700">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
</div>
<button id="toggleChat" class="mt-4 bg-blue-600 text-white rounded-full w-14 h-14 flex items-center justify-center shadow-lg hover:bg-blue-700 focus:outline-none">
<i class="fas fa-comment-dots text-xl"></i>
</button>
</div>
</div>
<script>
// DOM Elements
const showApiInfo = document.getElementById('showApiInfo');
const apiInfoModal = document.getElementById('apiInfoModal');
const closeApiInfoModal = document.getElementById('closeApiInfoModal');
const closeApiInfo = document.getElementById('closeApiInfo');
const generateGuide = document.getElementById('generateGuide');
const youtubeUrl = document.getElementById('youtubeUrl');
const loadingContainer = document.getElementById('loadingContainer');
const loadingBar = document.getElementById('loadingBar');
const loadingText = document.getElementById('loadingText');
const videoPreview = document.getElementById('videoPreview');
const videoThumbnail = document.getElementById('videoThumbnail');
const videoTitle = document.getElementById('videoTitle');
const videoChannel = document.getElementById('videoChannel');
const videoDuration = document.getElementById('videoDuration');
const videoViews = document.getElementById('videoViews');
const videoDescription = document.getElementById('videoDescription');
const guideContainer = document.getElementById('guideContainer');
const guideContent = document.getElementById('guideContent');
const exportPdf = document.getElementById('exportPdf');
const toggleChat = document.getElementById('toggleChat');
const chatContainer = document.getElementById('chatContainer');
const closeChat = document.getElementById('closeChat');
const chatMessages = document.getElementById('chatMessages');
const chatInput = document.getElementById('chatInput');
const sendMessage = document.getElementById('sendMessage');
// State
let isChatOpen = false;
let currentVideoData = null;
// Event Listeners
showApiInfo.addEventListener('click', () => {
apiInfoModal.classList.add('open');
});
closeApiInfoModal.addEventListener('click', () => {
apiInfoModal.classList.remove('open');
});
closeApiInfo.addEventListener('click', () => {
apiInfoModal.classList.remove('open');
});
generateGuide.addEventListener('click', async () => {
const url = youtubeUrl.value.trim();
if (!url) {
alert('Please enter a YouTube URL');
return;
}
// Validate YouTube URL
if (!isValidYouTubeUrl(url)) {
alert('Please enter a valid YouTube URL');
return;
}
// Show loading state
loadingContainer.classList.remove('hidden');
updateLoading(0, "Initializing secure connection...");
try {
// Get video ID from URL
const videoId = extractVideoId(url);
// First get video metadata through our secure backend
updateLoading(20, "Fetching video details through secure API...");
const videoData = await fetchVideoData(videoId);
currentVideoData = videoData;
// Show video preview
displayVideoPreview(videoData);
updateLoading(40, "Analyzing transcript with AI...");
// Generate guide based on video content
await generateVideoGuide(videoData);
updateLoading(100, "Guide complete!");
// Hide loading after delay
setTimeout(() => {
loadingContainer.classList.add('hidden');
}, 1000);
} catch (error) {
console.error("Error:", error);
loadingContainer.classList.add('hidden');
alert("Error processing video: " + error.message);
}
});
exportPdf.addEventListener('click', () => {
if (!currentVideoData) {
alert('No guide to export');
return;
}
alert(`PDF export would generate a guide for: ${currentVideoData.title}`);
});
toggleChat.addEventListener('click', () => {
isChatOpen = !isChatOpen;
chatContainer.classList.toggle('open', isChatOpen);
});
closeChat.addEventListener('click', () => {
isChatOpen = false;
chatContainer.classList.remove('open');
});
sendMessage.addEventListener('click', sendChatMessage);
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendChatMessage();
});
// Functions
function isValidYouTubeUrl(url) {
const pattern = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/;
return pattern.test(url);
}
function extractVideoId(url) {
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[2].length === 11) ? match[2] : null;
}
async function fetchVideoData(videoId) {
// In a real implementation, this would call your secure backend API
// which internally uses the YouTube and OpenAI APIs
// Simulate API call delay
return new Promise((resolve) => {
setTimeout(() => {
// Sample data structure - in real app this would come from your backend API
const sampleData = {
id: videoId,
title: "How to Use AI: A Complete Beginner's Guide",
channel: "Tech Explained",
duration: "12:45",
views: "1.5M views",
description: "In this video, I'll walk you through everything you need to know to get started with AI tools. We'll cover setting up accounts, basic commands, and practical applications.",
thumbnail: `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`,
category: "Education",
steps: [
{
time: "1:10",
title: "Introduction to AI Tools",
description: "The video explains the different categories of AI tools available today, including text generators, image creators, and coding assistants.",
screenshot: "https://images.unsplash.com/photo-1677442136019-21780ecad995?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80",
highlights: [
{ x: 30, y: 40, width: 40, height: 30, note: "Main AI categories" }
]
},
{
time: "3:25",
title: "Setting Up Your First AI Account",
description: "Step-by-step demonstration of creating an account on a popular AI platform. The instructor emphasizes using a secure password and verifying your email.",
screenshot: "https://images.unsplash.com/photo-1551650975-87deedd944c3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80",
highlights: [
{ x: 50, y: 60, width: 30, height: 15, note: "Sign up button" },
{ x: 20, y: 75, width: 60, height: 10, note: "Password requirements" }
]
}
]
};
// Adjust based on URL to show we're processing the actual video
if (youtubeUrl.value.includes("pancake")) {
sampleData.title = "How to Make Perfect Pancakes";
sampleData.description = "Learn the secrets to making fluffy, delicious pancakes every time with this step-by-step tutorial.";
sampleData.category = "Cooking";
sampleData.steps = [
{
time: "0:45",
title: "Gather Ingredients",
description: "You'll need: 1 cup all-purpose flour, 2 tablespoons sugar, 2 teaspoons baking powder, 1/2 teaspoon salt, 1 cup milk, 1 large egg, 2 tablespoons melted butter.",
screenshot: "https://images.unsplash.com/photo-1565299624946-b28f40a0ae38?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80",
highlights: [
{ x:
</html>