90 lines
3.9 KiB
TypeScript
90 lines
3.9 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server"
|
|
import { getSessionUser } from "@/lib/auth"
|
|
|
|
const GIPHY_API_KEY = process.env.GIPHY_API_KEY
|
|
const GIPHY_BASE = "https://api.giphy.com/v1/gifs"
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const user = await getSessionUser()
|
|
if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
|
|
|
|
const { searchParams } = new URL(request.url)
|
|
const q = searchParams.get("q") || ""
|
|
const limit = Math.min(parseInt(searchParams.get("limit") || "20", 10), 50)
|
|
const pos = parseInt(searchParams.get("pos") || "0", 10) || 0
|
|
|
|
if (!GIPHY_API_KEY) {
|
|
console.error("Missing GIPHY_API_KEY environment variable")
|
|
return NextResponse.json({ results: [], noKey: true })
|
|
}
|
|
|
|
let data: any
|
|
|
|
if (q) {
|
|
const url = `${GIPHY_BASE}/search?api_key=${GIPHY_API_KEY}&q=${encodeURIComponent(q)}&limit=${limit}&offset=${pos}&rating=g`
|
|
const res = await fetch(url, { signal: AbortSignal.timeout(8000) })
|
|
if (!res.ok) {
|
|
const errBody = await res.text()
|
|
console.error("GIPHY API search error:", res.status, errBody)
|
|
return NextResponse.json({ results: [], error: `GIPHY error: ${errBody}` }, { status: 502 })
|
|
}
|
|
data = await res.json()
|
|
} else {
|
|
const trendingUrl = `${GIPHY_BASE}/trending?api_key=${GIPHY_API_KEY}&limit=${limit}&offset=${pos}&rating=g`
|
|
const trendingRes = await fetch(trendingUrl, { signal: AbortSignal.timeout(8000) })
|
|
|
|
if (trendingRes.ok) {
|
|
data = await trendingRes.json()
|
|
if (!data.data?.length && pos === 0) {
|
|
console.log("Trending returned no results, falling back to default search")
|
|
const fallbackUrl = `${GIPHY_BASE}/search?api_key=${GIPHY_API_KEY}&q=funny&limit=${limit}&offset=${pos}&rating=g`
|
|
const fallbackRes = await fetch(fallbackUrl, { signal: AbortSignal.timeout(8000) })
|
|
if (!fallbackRes.ok) {
|
|
const errBody = await fallbackRes.text()
|
|
console.error("GIPHY fallback search error:", fallbackRes.status, errBody)
|
|
return NextResponse.json({ results: [], error: `GIPHY error: ${errBody}` }, { status: 502 })
|
|
}
|
|
data = await fallbackRes.json()
|
|
}
|
|
} else {
|
|
const errBody = await trendingRes.text()
|
|
console.error("GIPHY trending error:", trendingRes.status, errBody)
|
|
console.log("Trending failed, falling back to default search")
|
|
const fallbackUrl = `${GIPHY_BASE}/search?api_key=${GIPHY_API_KEY}&q=funny&limit=${limit}&offset=${pos}&rating=g`
|
|
const fallbackRes = await fetch(fallbackUrl, { signal: AbortSignal.timeout(8000) })
|
|
if (!fallbackRes.ok) {
|
|
const fallbackErr = await fallbackRes.text()
|
|
console.error("GIPHY fallback search error:", fallbackRes.status, fallbackErr)
|
|
return NextResponse.json({ results: [], error: `GIPHY error: ${fallbackErr}` }, { status: 502 })
|
|
}
|
|
data = await fallbackRes.json()
|
|
}
|
|
}
|
|
const results = (data.data || []).map((item: any) => {
|
|
const dims = item.images?.original
|
|
return {
|
|
id: item.id,
|
|
title: item.title || "",
|
|
url: dims?.url || "",
|
|
previewUrl: item.images?.fixed_width?.url || "",
|
|
width: dims?.width ? parseInt(dims.width, 10) : 200,
|
|
height: dims?.height ? parseInt(dims.height, 10) : 200,
|
|
}
|
|
})
|
|
|
|
const nextOffset = pos + results.length
|
|
const total = data.pagination?.total_count || 0
|
|
const hasMore = total ? nextOffset < total : results.length === limit
|
|
const nextPos = hasMore ? String(nextOffset) : ""
|
|
|
|
return NextResponse.json({ results, next: nextPos })
|
|
} catch (error: any) {
|
|
console.error("GIF proxy error:", error)
|
|
const message = error?.message === "Failed to fetch"
|
|
? "Could not reach the GIF service."
|
|
: "Failed to fetch GIFs."
|
|
return NextResponse.json({ results: [], error: message }, { status: 500 })
|
|
}
|
|
}
|