@@ -0,0 +1,57 @@
|
||||
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 })
|
||||
}
|
||||
|
||||
if (!GIPHY_API_KEY) {
|
||||
return NextResponse.json({ error: "GIPHY API key not configured" }, { status: 500 })
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(request.url)
|
||||
const type = searchParams.get("type") || "trending"
|
||||
const query = searchParams.get("q") || ""
|
||||
const offset = parseInt(searchParams.get("offset") || "0", 10)
|
||||
const limit = Math.min(parseInt(searchParams.get("limit") || "20", 10), 50)
|
||||
|
||||
let url: string
|
||||
if (type === "search" && query) {
|
||||
url = `${GIPHY_BASE}/search?api_key=${GIPHY_API_KEY}&q=${encodeURIComponent(query)}&limit=${limit}&offset=${offset}&rating=g`
|
||||
} else {
|
||||
url = `${GIPHY_BASE}/trending?api_key=${GIPHY_API_KEY}&limit=${limit}&offset=${offset}&rating=g`
|
||||
}
|
||||
|
||||
const res = await fetch(url)
|
||||
if (!res.ok) {
|
||||
const errBody = await res.text()
|
||||
console.error("GIPHY API error:", res.status, errBody)
|
||||
return NextResponse.json({ error: `GIPHY API error (${res.status}): ${errBody}` }, { status: res.status })
|
||||
}
|
||||
|
||||
const data = await res.json()
|
||||
const gifs = (data.data || []).map((gif: any) => ({
|
||||
id: gif.id,
|
||||
title: gif.title,
|
||||
url: gif.images?.original?.url || "",
|
||||
previewUrl: gif.images?.fixed_width?.url || "",
|
||||
previewHeight: gif.images?.fixed_width?.height || 150,
|
||||
width: gif.images?.original?.width || 0,
|
||||
height: gif.images?.original?.height || 0,
|
||||
}))
|
||||
|
||||
return NextResponse.json({
|
||||
gifs,
|
||||
pagination: data.pagination || { total_count: 0, count: gifs.length, offset },
|
||||
})
|
||||
} catch (error: any) {
|
||||
console.error("GIPHY proxy error:", error)
|
||||
return NextResponse.json({ error: error.message || "Internal server error" }, { status: 500 })
|
||||
}
|
||||
}
|
||||
+62
-25
@@ -1,8 +1,8 @@
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
import { getSessionUser } from "@/lib/auth"
|
||||
|
||||
const TENOR_API_KEY = process.env.TENOR_API_KEY || ""
|
||||
const TENOR_BASE = "https://tenor.googleapis.com/v2"
|
||||
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 {
|
||||
@@ -12,41 +12,78 @@ export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const q = searchParams.get("q") || ""
|
||||
const limit = Math.min(parseInt(searchParams.get("limit") || "20", 10), 50)
|
||||
const pos = searchParams.get("pos") || ""
|
||||
const pos = parseInt(searchParams.get("pos") || "0", 10) || 0
|
||||
|
||||
if (!TENOR_API_KEY) {
|
||||
if (!GIPHY_API_KEY) {
|
||||
console.error("Missing GIPHY_API_KEY environment variable")
|
||||
return NextResponse.json({ results: [], noKey: true })
|
||||
}
|
||||
|
||||
const endpoint = q
|
||||
? `${TENOR_BASE}/search?q=${encodeURIComponent(q)}&key=${TENOR_API_KEY}&limit=${limit}&media_filter=minimal`
|
||||
: `${TENOR_BASE}/featured?key=${TENOR_API_KEY}&limit=${limit}&media_filter=minimal`
|
||||
let data: any
|
||||
|
||||
const url = pos ? `${endpoint}&pos=${pos}` : endpoint
|
||||
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) })
|
||||
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(8000) })
|
||||
if (!res.ok) {
|
||||
return NextResponse.json({ results: [], error: "Tenor API error" }, { status: 502 })
|
||||
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 data = await res.json()
|
||||
|
||||
const results = (data.results || []).map((item: any) => {
|
||||
const media = item.media_formats?.gif || item.media_formats?.tinygif || {}
|
||||
const preview = item.media_formats?.tinygif || item.media_formats?.gif || {}
|
||||
const results = (data.data || []).map((item: any) => {
|
||||
const dims = item.images?.original
|
||||
return {
|
||||
id: item.id,
|
||||
title: item.title || "",
|
||||
url: media.url || "",
|
||||
previewUrl: preview.url || "",
|
||||
width: media.dims?.[0] || 200,
|
||||
height: media.dims?.[1] || 200,
|
||||
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,
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ results, next: data.next || "" })
|
||||
} catch (error) {
|
||||
console.error("GIF API error:", error)
|
||||
return NextResponse.json({ results: [], error: "Failed to fetch GIFs" }, { status: 500 })
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user