Files
2025-05-26 18:05:23 +08:00

128 lines
3.5 KiB
TypeScript

import cheerio from "cheerio";
import { checkApiKey } from "@/lib/dto/api-key";
import { createScrapeMeta } from "@/lib/dto/scrape";
import { getIpInfo } from "@/lib/geo";
import { isLink, removeUrlSuffix } from "@/lib/utils";
export const revalidate = 600;
export const dynamic = "force-dynamic";
export async function GET(req: Request) {
try {
const url = new URL(req.url);
const link = url.searchParams.get("url");
if (!link || !isLink(link)) {
return Response.json(
{ statusText: "Url is required" },
{
status: 400,
},
);
}
// Get the API key from the request
const custom_apiKey = url.searchParams.get("key");
if (!custom_apiKey) {
return Response.json(
{
statusText:
"API key is required. You can get your API key from Dashboard->Settings.",
},
{ status: 400 },
);
}
// Check if the API key is valid
const user_apiKey = await checkApiKey(custom_apiKey);
if (!user_apiKey?.id) {
return Response.json(
{
statusText:
"Invalid API key. You can get your API key from Dashboard->Settings.",
},
{ status: 401 },
);
}
const res = await fetch(link);
if (!res.ok) {
return Response.json(
{ statusText: `Failed to fetch url. ${res.statusText}` },
{
status: res.status || 405,
},
);
}
const html = await res.text();
// console.log(html);
const $ = cheerio.load(html);
const title =
$("title").text() ||
$("meta[property='og:title']").attr("content") ||
$("meta[name='twitter:title']").attr("content");
const description =
$("meta[name='description']").attr("content") ||
$("meta[property='og:description']").attr("content") ||
$("meta[name='twitter:description']").attr("content");
const image =
$("meta[property='og:image']").attr("content") ||
$("meta[name='og:image']").attr("content") ||
$("meta[property='twitter:image']").attr("content") ||
$("meta[name='twitter:image']").attr("content");
const icon =
$("link[rel='icon']").attr("href") ||
$("link[rel='apple-touch-icon']").attr("href") ||
`https://icon.wr.do/${removeUrlSuffix(link)}.ico`;
const lang =
$("html").attr("lang") ||
$("html").attr("xml:lang") ||
$("body").attr("lang") ||
$("body").attr("xml:lang");
const author =
$("meta[name='author']").attr("content") ||
$("meta[property='author']").attr("content");
const stats = await getIpInfo(req);
await createScrapeMeta({
ip: stats.ip || "::1",
type: "meta-info",
referer: stats.referer,
city: stats.city,
region: stats.region,
country: stats.country,
latitude: stats.latitude,
longitude: stats.longitude,
lang: stats.lang,
device: stats.device,
browser: stats.browser,
click: 1,
userId: user_apiKey.id,
apiKey: custom_apiKey,
link,
});
return Response.json({
title,
description,
image,
icon,
url: link,
lang,
author,
timestamp: Date.now(),
payload: `https://wr.do/api/v1/scraping/meta?url=${link}&key=${custom_apiKey}`,
});
} catch (error) {
console.log(error);
return Response.json(
{ statusText: "Server error" },
{
status: 500,
},
);
}
}