everything / apps /viralcat2.js
everydaycats's picture
Rename apps/viralcat.js to apps/viralcat2.js
1e731aa verified
import express from 'express';
import { generateCompletion } from '../ai_engine.js';
import { supabase } from '../config/supabaseClient.js';
import fetch from 'node-fetch';
const router = express.Router();
const FASTAPI_URL = process.env.FASTAPI_SERVER_URL || 'http://localhost:8000';
router.get('/trending', async (req, res) => {
try {
const { data, error } = await supabase.from('viral_cat_trending').select('*').order('created_at', { ascending: false });
if (error) throw error;
res.json({ success: true, data });
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
router.post('/admin/template', async (req, res) => {
try {
const { title, video_url, platform, video_base64 } = req.body;
const mediaRes = await fetch(`${FASTAPI_URL}/process-video`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ video_base64 })
});
const mediaData = await mediaRes.json();
console.log(mediaData);
if (!mediaData.success) throw new Error(mediaData.error);
const aiPrompt = `Analyze this video transcript and these 15 frames.
TRANSCRIPT: "${mediaData.transcript}"
Format: TRANSCRIPT:[text], ENVIRONMENT:[text], PACING:[text]`;
const aiResult = await generateCompletion({
model: "maverick",
prompt: aiPrompt,
images: mediaData.frames
});
console.log(aiResult);
const transcriptMatch = aiResult.data.match(/TRANSCRIPT:\s*(.*?)(?=ENVIRONMENT:)/is);
const envMatch = aiResult.data.match(/ENVIRONMENT:\s*(.*?)(?=PACING:)/is);
const pacingMatch = aiResult.data.match(/PACING:\s*(.*)/is);
const { error } = await supabase.from('viral_cat_trending').insert([{
platform, video_url, title,
thumbnail_url: `data:image/jpeg;base64,${mediaData.thumbnail}`,
transcript: transcriptMatch ? transcriptMatch[1].trim() : mediaData.transcript,
ai_environment_data: envMatch ? envMatch[1].trim() : "N/A",
ai_scene_changes: pacingMatch ? pacingMatch[1].trim() : "N/A",
}]);
if (error) throw error;
res.json({ success: true });
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
router.post('/custom_remix', async (req, res) => {
try {
const { user_niche, video_base64 } = req.body;
const mediaRes = await fetch(`${FASTAPI_URL}/process-video`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ video_base64 })
});
const mediaData = await mediaRes.json();
if (!mediaData.success) throw new Error(mediaData.error);
const result = await generateCompletion({
model: "maverick",
prompt: `Remix for niche: "${user_niche}". Transcript: ${mediaData.transcript}`,
images: mediaData.frames
});
res.json(result);
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
router.delete('/admin/template/:id', async (req, res) => {
await supabase.from('viral_cat_trending').delete().eq('id', req.params.id);
res.json({ success: true });
});
router.get('/admin', (req, res) => {
res.send(`<!DOCTYPE html><html><head><title>Viral Cat Admin</title><script src="https://cdn.tailwindcss.com"></script></head>
<body class="bg-[#090A0F] text-white p-8"><h1 class="text-3xl font-bold text-[#12D8C3] mb-8">Viral Cat Admin</h1>
<div class="grid grid-cols-2 gap-8"><div class="bg-[#16181F] p-6 rounded-2xl">
<form id="f" class="space-y-4"><input id="t" placeholder="Title" class="w-full p-2 bg-black border border-gray-700 rounded"/>
<input id="u" placeholder="Embed URL" class="w-full p-2 bg-black border border-gray-700 rounded"/>
<select id="p" class="w-full p-2 bg-black border border-gray-700 rounded"><option value="tiktok">TikTok</option><option value="instagram">Instagram</option></select>
<input type="file" id="v" accept="video/mp4" class="w-full"/><button type="submit" class="w-full bg-[#12D8C3] text-black p-2 rounded font-bold">Process Video</button></form></div>
<div id="list" class="space-y-2"></div></div>
<script>
const toB64 = f => new Promise((res,rej)=>{const r=new FileReader();r.readAsDataURL(f);r.onload=()=>res(r.result.split(',')[1]);});
async function load(){const r=await fetch('/api/viralcat/trending');const j=await r.json();document.getElementById('list').innerHTML=j.data.map(t=>\`<div class="p-4 bg-gray-900 flex justify-between"><span>\${t.title}</span><button onclick="del('\${t.id}')">Delete</button></div>\`).join('');}
async function del(id){await fetch('/api/viralcat/admin/template/'+id,{method:'DELETE'});load();}
document.getElementById('f').onsubmit=async e=>{e.preventDefault();const b=e.target.querySelector('button');b.innerText="Wait...";
const b64=await toB64(document.getElementById('v').files[0]);
await fetch('/api/viralcat/admin/template',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({title:document.getElementById('t').value,video_url:document.getElementById('u').value,platform:document.getElementById('p').value,video_base64:b64})});
b.innerText="Process Video";load();};load();
</script></body></html>`);
});
export default router;