everydaycats commited on
Commit
ab53a5e
·
verified ·
1 Parent(s): 6a186ce

Delete apps/trend_cat.js

Browse files
Files changed (1) hide show
  1. apps/trend_cat.js +0 -252
apps/trend_cat.js DELETED
@@ -1,252 +0,0 @@
1
- // apps/viral_cat.js
2
- import express from 'express';
3
- import { generateCompletion } from '../ai_engine.js';
4
- import { supabase } from '../config/supabaseClient.js';
5
- import fetch from 'node-fetch'; // Ensure you have node-fetch or use native fetch if Node 18+
6
-
7
- const router = express.Router();
8
- const FASTAPI_URL = process.env.FASTAPI_SERVER_URL || 'http://localhost:8000';
9
-
10
- // ── ADMIN AUTH MIDDLEWARE ──
11
- const adminAuth = (req, res, next) => {
12
- const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
13
- const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':');
14
- if (login === 'admin' && password === process.env.VIRAL_CAT_ADMIN_PASS) return next();
15
- res.set('WWW-Authenticate', 'Basic realm="Viral Cat Admin"');
16
- res.status(401).send('Auth required.');
17
- };
18
-
19
- // ── 1. GET TRENDING FEED (Public for App) ──
20
- router.get('/trending', async (req, res) => {
21
- try {
22
- const { data, error } = await supabase
23
- .from('viral_cat_trending')
24
- .select('*')
25
- .order('created_at', { ascending: false });
26
-
27
- if (error) throw error;
28
- res.json({ success: true, data });
29
- } catch (err) {
30
- res.status(500).json({ success: false, error: err.message });
31
- }
32
- });
33
-
34
- // ── 2. ADMIN: ADD TEMPLATE (Manual or Crawler) ──
35
- router.post('/admin/template', adminAuth, async (req, res) => {
36
- const { title, video_url, platform, niche, score } = req.body;
37
-
38
- try {
39
- // Step A: Send to FastAPI to download, extract frames, and transcribe
40
- console.log(`[CRAWLER] Sending ${video_url} to FastAPI Worker...`);
41
- const mediaRes = await fetch(`${FASTAPI_URL}/process-video`, {
42
- method: 'POST',
43
- headers: { 'Content-Type': 'application/json' },
44
- body: JSON.stringify({ url: video_url, platform })
45
- });
46
- const mediaData = await mediaRes.json();
47
-
48
- // Expected from FastAPI: { frames: ["base64..."], transcript: "...", thumbnail_url: "..." }
49
- const { frames, transcript, thumbnail_url } = mediaData;
50
-
51
- // Step B: Send frames to Llama 4 to analyze pacing and environment
52
- const aiPrompt = `Analyze these frames from a viral video. Provide exactly two paragraphs:
53
- Environment:[Describe lighting, setting, subjects]
54
- Pacing: [Describe cuts, camera movement, visual hooks]`;
55
-
56
- const aiResult = await generateCompletion({
57
- model: "maverick",
58
- prompt: aiPrompt,
59
- system_prompt: "You are an elite video metadata extractor.",
60
- images: frames
61
- });
62
-
63
- // Step C: Save everything to Supabase
64
- const { data, error } = await supabase.from('viral_cat_trending').insert([{
65
- platform,
66
- video_url,
67
- thumbnail_url: thumbnail_url || "https://placehold.co/400x600/png",
68
- views: Math.floor(Math.random() * 5000000) + 100000, // Mock stats for now
69
- comments: Math.floor(Math.random() * 10000),
70
- shares: Math.floor(Math.random() * 50000),
71
- transcript: transcript || "No transcript available.",
72
- ai_environment_data: aiResult.data,
73
- ai_scene_changes: "Dynamic framing extracted by AI",
74
- }]).select();
75
-
76
- if (error) throw error;
77
- res.json({ success: true, data });
78
-
79
- } catch (err) {
80
- console.error(err);
81
- res.status(500).json({ success: false, error: err.message });
82
- }
83
- });
84
-
85
- // ── 3. ADMIN: DELETE TEMPLATE ──
86
- router.delete('/admin/template/:id', adminAuth, async (req, res) => {
87
- try {
88
- const { error } = await supabase.from('viral_cat_trending').delete().eq('id', req.params.id);
89
- if (error) throw error;
90
- res.json({ success: true, message: "Deleted successfully" });
91
- } catch (err) {
92
- res.status(500).json({ success: false, error: err.message });
93
- }
94
- });
95
-
96
- // ── 4. CUSTOM REMIX (User inputs ANY link -> FastAPI -> Llama 4) ──
97
- router.post('/custom_remix', async (req, res) => {
98
- const { video_url, platform, user_niche, model } = req.body;
99
-
100
- try {
101
- console.log(`[CUSTOM REMIX] Crawling user requested URL: ${video_url}`);
102
-
103
- // 1. Call FastAPI Media Server
104
- const mediaRes = await fetch(`${FASTAPI_URL}/process-video`, {
105
- method: 'POST',
106
- headers: { 'Content-Type': 'application/json' },
107
- body: JSON.stringify({ url: video_url, platform })
108
- });
109
- const { frames, transcript } = await mediaRes.json();
110
-
111
- // 2. Feed to Llama 4 Maverick to write the script
112
- const systemPrompt = `You are Viral Cat 📈🐈. The user wants to remix an external viral video.
113
- ORIGINAL TRANSCRIPT: ${transcript}
114
- USER'S NEW NICHE: "${user_niche}"
115
-
116
- Look at the attached frames to understand the visual pacing.
117
- Write a highly viral, customized shooting script mapped to the user's niche.
118
- Format in Markdown:
119
- ## 🎬 The Hook (0-3s)
120
- ## 📖 The Body
121
- ## 💥 The Call to Action`;
122
-
123
- const result = await generateCompletion({
124
- model: model || "maverick",
125
- prompt: "Write the custom remix script.",
126
- system_prompt: systemPrompt,
127
- images: frames // Pass the dynamic frames straight to the vision model!
128
- });
129
-
130
- res.json(result);
131
- } catch (err) {
132
- res.status(500).json({ success: false, error: err.message });
133
- }
134
- });
135
-
136
- // ── 5. ADMIN DASHBOARD (Fully Functional) ──
137
- router.get('/admin', adminAuth, (req, res) => {
138
- const html = `
139
- <!DOCTYPE html>
140
- <html lang="en">
141
- <head>
142
- <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
143
- <title>Viral Cat | Creator Admin</title>
144
- <script src="https://cdn.tailwindcss.com"></script>
145
- <style>
146
- body { background-color: #090A0F; color: #FFFFFF; font-family: 'Inter', sans-serif; }
147
- .neon-text { color: #12D8C3; text-shadow: 0 0 10px rgba(18, 216, 195, 0.4); }
148
- .glass-card { background: #16181F; border: 1px solid #2D3748; border-radius: 20px; padding: 24px; }
149
- .btn-cyan { background-color: #12D8C3; color: #000; font-weight: bold; border-radius: 10px; padding: 10px; cursor: pointer; }
150
- input, select { background: #090A0F; border: 1px solid #2D3748; color: white; padding: 10px; border-radius: 10px; width: 100%; margin-bottom: 15px; }
151
- </style>
152
- </head>
153
- <body class="p-8 max-w-6xl mx-auto">
154
- <h1 class="text-3xl font-bold mb-8">Viral Cat <span class="neon-text">Admin</span></h1>
155
-
156
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
157
- <!-- UPLOAD FORM -->
158
- <div class="glass-card">
159
- <h2 class="text-2xl font-bold mb-4 border-b border-gray-700 pb-2">Add Viral Template</h2>
160
- <form id="templateForm" onsubmit="addTemplate(event)">
161
- <label>Video Title</label>
162
- <input type="text" id="title" required />
163
-
164
- <label>Video URL (TikTok/IG/YT)</label>
165
- <input type="url" id="video_url" required />
166
-
167
- <label>Platform</label>
168
- <select id="platform">
169
- <option value="tiktok">TikTok</option>
170
- <option value="instagram">Instagram Reels</option>
171
- <option value="youtube">YouTube Shorts</option>
172
- </select>
173
-
174
- <button type="submit" id="submitBtn" class="btn-cyan w-full mt-4">Crawl & Add to Database</button>
175
- </form>
176
- </div>
177
-
178
- <!-- TEMPLATE LIST -->
179
- <div class="glass-card">
180
- <h2 class="text-2xl font-bold mb-4 border-b border-gray-700 pb-2">Active Templates</h2>
181
- <div id="templateList" class="space-y-4 overflow-y-auto h-96">
182
- <p class="text-gray-400">Loading...</p>
183
- </div>
184
- </div>
185
- </div>
186
-
187
- <script>
188
- // Automatically fetch active templates on load
189
- async function loadTemplates() {
190
- const res = await fetch('/viral_cat/trending');
191
- const json = await res.json();
192
- const list = document.getElementById('templateList');
193
- list.innerHTML = '';
194
-
195
- if(json.data.length === 0) list.innerHTML = '<p>No templates found.</p>';
196
-
197
- json.data.forEach(t => {
198
- list.innerHTML += \`
199
- <div class="bg-gray-800 p-4 rounded-xl flex justify-between items-center border border-gray-700">
200
- <div>
201
- <span class="text-xs bg-[#12D8C3] text-black px-2 py-1 rounded font-bold">\${t.platform.toUpperCase()}</span>
202
- <p class="text-sm mt-2 font-bold truncate w-48">\${t.transcript.substring(0, 30)}...</p>
203
- </div>
204
- <button onclick="deleteTemplate('\${t.id}')" class="bg-red-500 hover:bg-red-600 text-white text-xs px-3 py-2 rounded">Delete</button>
205
- </div>\`;
206
- });
207
- }
208
-
209
- async function addTemplate(e) {
210
- e.preventDefault();
211
- const btn = document.getElementById('submitBtn');
212
- btn.innerText = "Crawling & Processing (Takes 10-20s)...";
213
- btn.disabled = true;
214
-
215
- const payload = {
216
- title: document.getElementById('title').value,
217
- video_url: document.getElementById('video_url').value,
218
- platform: document.getElementById('platform').value,
219
- };
220
-
221
- const res = await fetch('/viral_cat/admin/template', {
222
- method: 'POST',
223
- headers: { 'Content-Type': 'application/json' },
224
- body: JSON.stringify(payload)
225
- });
226
-
227
- if(res.ok) {
228
- alert("Success! Video processed by FastAPI, analyzed by Llama, and saved to DB.");
229
- e.target.reset();
230
- loadTemplates();
231
- } else {
232
- alert("Error processing video.");
233
- }
234
- btn.innerText = "Crawl & Add to Database";
235
- btn.disabled = false;
236
- }
237
-
238
- async function deleteTemplate(id) {
239
- if(!confirm("Are you sure?")) return;
240
- await fetch(\`/viral_cat/admin/template/\${id}\`, { method: 'DELETE' });
241
- loadTemplates();
242
- }
243
-
244
- loadTemplates();
245
- </script>
246
- </body>
247
- </html>
248
- `;
249
- res.send(html);
250
- });
251
-
252
- export default router;