mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 09:19:51 +00:00
Complete WhatsApp CRM application built with Next.js 14 (App Router), Supabase (PostgreSQL + Auth + Realtime), and shadcn/ui. Features: - Auth: Login, signup, forgot password with Supabase Auth - Dashboard: Analytics overview with stats, recent activity - Inbox: Real-time WhatsApp conversations with message threading - Contacts: CRUD with tags, custom fields, notes, CSV import - Broadcasts: 4-step wizard with audience selection, template sending - Pipelines: Kanban board with deal management - Settings: WhatsApp API config, templates, tags - WhatsApp API: Webhook (verify + receive), send, broadcast, media proxy - Database: 16 tables with RLS policies, indexes, realtime subscriptions - Dark theme throughout with emerald accents Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import { createClient } from '@/lib/supabase/server'
|
|
import { getMediaUrl, downloadMedia } from '@/lib/whatsapp/meta-api'
|
|
import { decrypt } from '@/lib/whatsapp/encryption'
|
|
|
|
export async function GET(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ mediaId: string }> }
|
|
) {
|
|
try {
|
|
const { mediaId } = await params
|
|
|
|
if (!mediaId) {
|
|
return NextResponse.json(
|
|
{ error: 'Media ID is required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
const supabase = await createClient()
|
|
|
|
const {
|
|
data: { user },
|
|
error: authError,
|
|
} = await supabase.auth.getUser()
|
|
|
|
if (authError || !user) {
|
|
return NextResponse.json(
|
|
{ error: 'Unauthorized' },
|
|
{ status: 401 }
|
|
)
|
|
}
|
|
|
|
// Fetch and decrypt WhatsApp config
|
|
const { data: config, error: configError } = await supabase
|
|
.from('whatsapp_config')
|
|
.select('*')
|
|
.eq('user_id', user.id)
|
|
.single()
|
|
|
|
if (configError || !config) {
|
|
return NextResponse.json(
|
|
{ error: 'WhatsApp not configured' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
const accessToken = decrypt(config.access_token)
|
|
|
|
// Get the download URL from Meta
|
|
const mediaInfo = await getMediaUrl(mediaId, accessToken)
|
|
|
|
// Download the binary data
|
|
const { buffer, contentType } = await downloadMedia(mediaInfo.url, accessToken)
|
|
|
|
return new Response(new Uint8Array(buffer), {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': contentType || mediaInfo.mimeType || 'application/octet-stream',
|
|
'Cache-Control': 'public, max-age=86400',
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('Error in WhatsApp media GET:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to fetch media' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|