feat: add url metas

This commit is contained in:
oiov
2024-08-02 17:33:25 +08:00
parent 4e87d5e2a7
commit 52e197ea4c
7 changed files with 79 additions and 20 deletions
@@ -84,7 +84,7 @@ function generateStatsList(
let totalClicks = 0;
records.forEach((record) => {
const dimValue = record[dimension] ?? ("(None)" as any);
const dimValue = record[dimension] || ("(None)" as any);
const click = record.click;
if (!dimensionCounts[dimValue]) {
@@ -101,7 +101,7 @@ function generateStatsList(
for (const [dimValue, clicks] of Object.entries(dimensionCounts)) {
const percentage = (clicks / totalClicks) * 100;
statsList.push({
dimension: dimValue,
dimension: dimValue ?? "(None)",
clicks,
percentage: percentage.toFixed(0) + "%",
});
@@ -229,8 +229,12 @@ export function DailyPVUVChart({ data }: { data: UrlMeta[] }) {
</ChartContainer>
<div className="my-5 grid grid-cols-1 gap-6 sm:grid-cols-2">
<StatsList data={refererStats} title="Referrers" />
<StatsList data={countryStats} title="Regions" />
{refererStats.length > 0 && (
<StatsList data={refererStats} title="Referrers" />
)}
{countryStats.length > 0 && (
<StatsList data={countryStats} title="Regions" />
)}
</div>
<VisSingleContainer data={{ areas: areaData }}>
+19 -11
View File
@@ -2,17 +2,22 @@ import { NextRequest, NextResponse } from "next/server";
import { createUserShortUrlMeta, getUrlBySuffix } from "@/lib/dto/short-urls";
export async function GET(req: NextRequest) {
export async function POST(req: NextRequest) {
try {
const url = new URL(req.url);
const slug = url.searchParams.get("slug");
const referer = url.searchParams.get("referer");
const ip = url.searchParams.get("ip");
const city = url.searchParams.get("city");
const region = url.searchParams.get("region");
const country = url.searchParams.get("country");
const latitude = url.searchParams.get("latitude");
const longitude = url.searchParams.get("longitude");
const {
slug,
referer,
ip,
city,
region,
country,
latitude,
longitude,
lang,
device,
browser,
} = await req.json();
if (!slug || !ip) return Response.json(null);
const res = await getUrlBySuffix(slug);
@@ -26,7 +31,7 @@ export async function GET(req: NextRequest) {
return Response.json(null);
}
// console.log("[api/s]", ip, res.id);
console.log("[api/s]", device, browser);
await createUserShortUrlMeta({
urlId: res.id,
click: 1,
@@ -37,6 +42,9 @@ export async function GET(req: NextRequest) {
latitude,
longitude,
referer,
lang,
device,
browser,
});
return Response.json(res.target);
}
+36 -4
View File
@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { geolocation } from "@vercel/functions";
import { auth } from "auth";
import UAParser from "ua-parser-js";
import { siteConfig } from "./config/site";
@@ -12,13 +13,44 @@ export default auth(async (req) => {
const ip = req.headers.get("X-Forwarded-For");
if (req.url.includes("/s/")) {
const match = req.url.match(/[^/]+$/);
const geo = geolocation(req);
if (match) {
const geo = geolocation(req);
const userLanguage = req.headers.get("accept-language")?.split(",")[0];
const ua = req.headers.get("user-agent");
const parser = new UAParser();
parser.setUA(ua);
const browser = parser.getBrowser();
const device = parser.getDevice();
console.log(device, browser);
const referer = req.headers.get("referer") || "(None)";
const res = await fetch(
`${siteConfig.url}/api/s?slug=${match[0]}&referer=${referer}&ip=${ip}&city=${geo?.city}&region=${geo?.region}&country=${geo?.country}&latitude=${geo?.latitude}&longitude=${geo?.longitude}&flag=${geo?.flag}`,
);
// const res1 = await fetch(
// `${siteConfig.url}/api/s?slug=${match[0]}&referer=${referer}&ip=${ip}&city=${geo?.city}&region=${geo?.region}&country=${geo?.country}&latitude=${geo?.latitude}&longitude=${geo?.longitude}&flag=${geo?.flag}`,
// );
const res = await fetch(`${siteConfig.url}/api/s`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
slug: match[0],
referer,
ip,
city: geo?.city,
region: geo?.region,
country: geo?.country,
latitude: geo?.latitude,
longitude: geo?.longitude,
flag: geo?.flag,
lang: userLanguage,
device: device.model || "Unknown",
browser: browser.name || "Unknown",
}),
});
if (!res.ok) {
return NextResponse.redirect(`${siteConfig.url}/docs/short-urls`);
+1
View File
@@ -93,6 +93,7 @@
"swr": "^2.2.5",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"ua-parser-js": "^1.0.38",
"vaul": "^0.9.1",
"zod": "^3.23.8"
},
+8
View File
@@ -230,6 +230,9 @@ importers:
tailwindcss-animate:
specifier: ^1.0.7
version: 1.0.7(tailwindcss@3.4.6)
ua-parser-js:
specifier: ^1.0.38
version: 1.0.38
vaul:
specifier: ^0.9.1
version: 0.9.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -6234,6 +6237,9 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
ua-parser-js@1.0.38:
resolution: {integrity: sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==}
unbox-primitive@1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
@@ -13665,6 +13671,8 @@ snapshots:
typescript@5.5.3: {}
ua-parser-js@1.0.38: {}
unbox-primitive@1.0.2:
dependencies:
call-bind: 1.0.7
@@ -171,5 +171,8 @@ ALTER TABLE "url_metas" ADD COLUMN "region" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "latitude" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "longitude" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "referer" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "lang" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "device" TEXT;
ALTER TABLE "url_metas" ADD COLUMN "browser" TEXT;
ALTER TABLE "user_url" ADD COLUMN "expiration" TEXT NOT NULL DEFAULT '-1';
ALTER TABLE "user_urls" ADD COLUMN "expiration" TEXT NOT NULL DEFAULT '-1';
+3
View File
@@ -133,6 +133,9 @@ model UrlMeta {
latitude String?
longitude String?
referer String?
lang String?
device String?
browser String?
createdAt DateTime @default(now()) @map(name: "created_at")
updatedAt DateTime @default(now()) @map(name: "updated_at")