test
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"use server";
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { siteConfig } from "@/config/site";
|
||||
import { createUserShortUrlMeta, getUrlBySuffix } from "@/lib/dto/short-urls";
|
||||
import { redirectMap } from "@/app/ss/[slug]/page";
|
||||
|
||||
export async function RedirectsTo(data: any) {
|
||||
const {
|
||||
slug,
|
||||
referer,
|
||||
ip,
|
||||
city,
|
||||
region,
|
||||
country,
|
||||
latitude,
|
||||
longitude,
|
||||
lang,
|
||||
device,
|
||||
browser,
|
||||
password,
|
||||
} = data;
|
||||
|
||||
if (!slug || !ip)
|
||||
return redirect(`${siteConfig.url}${redirectMap["Missing[0000]"]}${slug}`);
|
||||
|
||||
const res = await getUrlBySuffix(slug);
|
||||
|
||||
if (!res)
|
||||
return redirect(`${siteConfig.url}${redirectMap["Disabled[0002]"]}${slug}`);
|
||||
|
||||
if (res.active !== 1)
|
||||
return redirect(`${siteConfig.url}${redirectMap["Disabled[0002]"]}${slug}`);
|
||||
|
||||
if (res.password !== "") {
|
||||
if (!password) {
|
||||
return redirect(
|
||||
`${siteConfig.url}${redirectMap["PasswordRequired[0004]"]}${slug}`,
|
||||
);
|
||||
}
|
||||
if (password !== res.password) {
|
||||
return redirect(
|
||||
`${siteConfig.url}${redirectMap["IncorrectPassword[0005]"]}${slug}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const createdAt = new Date(res.updatedAt).getTime();
|
||||
const expirationMilliseconds = Number(res.expiration) * 1000;
|
||||
const expirationTime = createdAt + expirationMilliseconds;
|
||||
|
||||
if (res.expiration !== "-1" && now > expirationTime) {
|
||||
return redirect(`${siteConfig.url}${redirectMap["Expired[0001]"]}`);
|
||||
}
|
||||
|
||||
await createUserShortUrlMeta({
|
||||
urlId: res.id,
|
||||
click: 1,
|
||||
ip,
|
||||
city,
|
||||
region,
|
||||
country,
|
||||
latitude,
|
||||
longitude,
|
||||
referer,
|
||||
lang,
|
||||
device,
|
||||
browser,
|
||||
});
|
||||
console.log("到这了");
|
||||
|
||||
redirect(res.target);
|
||||
}
|
||||
+59
-56
@@ -1,12 +1,11 @@
|
||||
import { headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import { RedirectsTo } from "@/actions/redirect";
|
||||
import UAParser from "ua-parser-js";
|
||||
|
||||
import { siteConfig } from "@/config/site";
|
||||
import { createUserShortUrlMeta, getUrlBySuffix } from "@/lib/dto/short-urls";
|
||||
import { extractRealIP, getClientGeolocation } from "@/lib/geo";
|
||||
|
||||
const redirectMap = {
|
||||
export const redirectMap = {
|
||||
"Missing[0000]": "/docs/short-urls#missing-links",
|
||||
"Expired[0001]": "/docs/short-urls#expired-links",
|
||||
"Disabled[0002]": "/docs/short-urls#disabled-links",
|
||||
@@ -31,10 +30,7 @@ export default async function ShortUrlPage({
|
||||
const { slug } = params;
|
||||
const { password = "" } = searchParams;
|
||||
|
||||
if (!slug) redirect(redirectMap["Missing[0000]"]);
|
||||
|
||||
try {
|
||||
// 获取请求头信息
|
||||
const headersList = headers();
|
||||
const userAgent = headersList.get("user-agent") || "";
|
||||
const referer = headersList.get("referer") || "(None)";
|
||||
@@ -48,63 +44,70 @@ export default async function ShortUrlPage({
|
||||
|
||||
const geo = await getClientGeolocation();
|
||||
|
||||
// const trackingData = {
|
||||
// slug,
|
||||
// referer,
|
||||
// ip: realIP,
|
||||
// city: geo?.city,
|
||||
// region: geo?.region,
|
||||
// country: geo?.country,
|
||||
// latitude: geo?.latitude,
|
||||
// longitude: geo?.longitude,
|
||||
// // flag: geo?.flag,
|
||||
// lang: acceptLanguage?.split(",")[0],
|
||||
// device: device.model || "Unknown",
|
||||
// browser: browser.name || "Unknown",
|
||||
// password,
|
||||
// };
|
||||
|
||||
const data = await getUrlBySuffix(slug);
|
||||
if (!data || data.active !== 1) redirect(redirectMap["Disabled[0002]"]);
|
||||
|
||||
if (data.password !== "") {
|
||||
if (!password) {
|
||||
redirect(redirectMap["PasswordRequired[0004]"]);
|
||||
}
|
||||
if (password !== data.password) {
|
||||
redirect(redirectMap["IncorrectPassword[0005]"]);
|
||||
}
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const createdAt = new Date(data.updatedAt).getTime();
|
||||
const expirationMilliseconds = Number(data.expiration) * 1000;
|
||||
const expirationTime = createdAt + expirationMilliseconds;
|
||||
|
||||
if (data.expiration !== "-1" && now > expirationTime) {
|
||||
redirect(redirectMap["Expired[0001]"]);
|
||||
}
|
||||
|
||||
await createUserShortUrlMeta({
|
||||
urlId: data.id,
|
||||
click: 1,
|
||||
ip: realIP,
|
||||
city: geo?.city || "",
|
||||
region: geo?.region || "",
|
||||
country: geo?.country || "",
|
||||
latitude: geo?.latitude || "",
|
||||
longitude: geo?.longitude || "",
|
||||
const trackingData = {
|
||||
slug,
|
||||
referer,
|
||||
lang: acceptLanguage?.split(",")[0] || "",
|
||||
ip: realIP,
|
||||
city: geo?.city,
|
||||
region: geo?.region,
|
||||
country: geo?.country,
|
||||
latitude: geo?.latitude,
|
||||
longitude: geo?.longitude,
|
||||
// flag: geo?.flag,
|
||||
lang: acceptLanguage?.split(",")[0],
|
||||
device: device.model || "Unknown",
|
||||
browser: browser.name || "Unknown",
|
||||
});
|
||||
password,
|
||||
};
|
||||
|
||||
// await RedirectsTo(trackingData);
|
||||
|
||||
// await fetch(`${siteConfig.url}/api/s`, {
|
||||
// method: "POST",
|
||||
// // headers: { "Content-Type": "application/json" },
|
||||
// body: JSON.stringify(trackingData),
|
||||
// });
|
||||
|
||||
// const data = await getUrlBySuffix(slug);
|
||||
// if (!data || data.active !== 1) redirect(redirectMap["Disabled[0002]"]);
|
||||
|
||||
// if (data.password !== "") {
|
||||
// if (!password) {
|
||||
// redirect(redirectMap["PasswordRequired[0004]"]);
|
||||
// }
|
||||
// if (password !== data.password) {
|
||||
// redirect(redirectMap["IncorrectPassword[0005]"]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// const now = Date.now();
|
||||
// const createdAt = new Date(data.updatedAt).getTime();
|
||||
// const expirationMilliseconds = Number(data.expiration) * 1000;
|
||||
// const expirationTime = createdAt + expirationMilliseconds;
|
||||
|
||||
// if (data.expiration !== "-1" && now > expirationTime) {
|
||||
// redirect(redirectMap["Expired[0001]"]);
|
||||
// }
|
||||
|
||||
// await createUserShortUrlMeta({
|
||||
// urlId: data.id,
|
||||
// click: 1,
|
||||
// ip: realIP,
|
||||
// city: geo?.city || "",
|
||||
// region: geo?.region || "",
|
||||
// country: geo?.country || "",
|
||||
// latitude: geo?.latitude || "",
|
||||
// longitude: geo?.longitude || "",
|
||||
// referer,
|
||||
// lang: acceptLanguage?.split(",")[0] || "",
|
||||
// device: device.model || "Unknown",
|
||||
// browser: browser.name || "Unknown",
|
||||
// });
|
||||
|
||||
// 重定向到目标URL
|
||||
window.location.href = data.target;
|
||||
// window.location.href = data.target;
|
||||
// redirect(data.target);
|
||||
} catch (error) {
|
||||
console.error("Short URL redirect error:", error);
|
||||
redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ export function extractRealIP(headers: Headers): string {
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return "::1";
|
||||
}
|
||||
|
||||
function isValidIP(ip: string): boolean {
|
||||
|
||||
+10
-16
@@ -1,8 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { NextResponse, userAgent } from "next/server";
|
||||
import { geolocation } from "@vercel/functions";
|
||||
import { auth } from "auth";
|
||||
import { NextAuthRequest } from "next-auth/lib";
|
||||
import UAParser from "ua-parser-js";
|
||||
|
||||
import { siteConfig } from "./config/site";
|
||||
|
||||
@@ -19,7 +18,6 @@ const redirectMap = {
|
||||
"IncorrectPassword[0005]": "/password-prompt?error=1&slug=",
|
||||
};
|
||||
|
||||
// 提取短链接处理逻辑
|
||||
async function handleShortUrl(req: NextAuthRequest) {
|
||||
if (!req.url.includes("/s/")) return NextResponse.next();
|
||||
|
||||
@@ -29,7 +27,7 @@ async function handleShortUrl(req: NextAuthRequest) {
|
||||
|
||||
const geo = geolocation(req);
|
||||
const headers = req.headers;
|
||||
const { browser, device } = parseUserAgent(headers.get("user-agent") || "");
|
||||
const ua = userAgent(req);
|
||||
|
||||
const url = new URL(req.url);
|
||||
const password = url.searchParams.get("password") || "";
|
||||
@@ -45,11 +43,17 @@ async function handleShortUrl(req: NextAuthRequest) {
|
||||
longitude: geo?.longitude,
|
||||
flag: geo?.flag,
|
||||
lang: headers.get("accept-language")?.split(",")[0],
|
||||
device: device.model || "Unknown",
|
||||
browser: browser.name || "Unknown",
|
||||
device: ua.device.model || "Unknown",
|
||||
browser: ua.browser.name || "Unknown",
|
||||
engine: ua.engine.name || "",
|
||||
os: ua.os.name || "",
|
||||
cpu: ua.cpu.architecture || "",
|
||||
isBot: ua.isBot,
|
||||
password,
|
||||
};
|
||||
|
||||
console.log("Tracking data:", trackingData, siteConfig.url);
|
||||
|
||||
const res = await fetch(`${siteConfig.url}/api/s`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -96,16 +100,6 @@ function extractSlug(url: string): string | null {
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
// 解析用户代理
|
||||
const parser = new UAParser();
|
||||
function parseUserAgent(ua: string) {
|
||||
parser.setUA(ua);
|
||||
return {
|
||||
browser: parser.getBrowser(),
|
||||
device: parser.getDevice(),
|
||||
};
|
||||
}
|
||||
|
||||
export default auth(async (req) => {
|
||||
try {
|
||||
return await handleShortUrl(req);
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user