~repos /website
git clone https://pyrossh.dev/repos/website.git
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
309efff7
—
pyrossh 1 year ago
imporve analytics
- routes/_middleware.ts +16 -23
- services/analytics.ts +14 -12
routes/_middleware.ts
CHANGED
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
import { FreshContext } from "$fresh/server.ts";
|
|
2
|
-
import UAParser from "ua-parser-js";
|
|
3
2
|
import isbot from "isbot";
|
|
4
|
-
import IPinfoWrapper from "ipinfo";
|
|
5
3
|
import { recordVisit } from "../services/analytics.ts";
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import manifest from "../fresh.gen.ts";
|
|
8
5
|
|
|
9
6
|
export async function handler(req: Request, ctx: FreshContext) {
|
|
10
7
|
const resp = await ctx.next();
|
|
8
|
+
const registeredRoutes = Object.keys(manifest.routes)
|
|
9
|
+
.map((r) =>
|
|
10
|
+
r
|
|
11
|
+
.replaceAll("./routes", "")
|
|
12
|
+
.replaceAll(".tsx", "")
|
|
13
|
+
.replaceAll("index", "")
|
|
14
|
+
)
|
|
15
|
+
.filter((a) => !["/_404", "/_app", "/_middleware.ts"].includes(a));
|
|
11
16
|
const userAgent = req.headers.get("user-agent") || "";
|
|
17
|
+
const referer = req.headers.get("referer") || "";
|
|
18
|
+
console.log("referer", referer, req.referrer);
|
|
19
|
+
const pathname = new URL(req.url).pathname;
|
|
12
20
|
if (
|
|
21
|
+
registeredRoutes.includes(pathname) &&
|
|
13
|
-
req.headers.get("accept")?.includes("text/html") &&
|
|
22
|
+
req.headers.get("accept")?.includes("text/html") &&
|
|
23
|
+
!isbot(userAgent)
|
|
14
24
|
) {
|
|
15
|
-
ipInfoClient.lookupIp(ctx.remoteAddr.hostname)
|
|
16
|
-
.then((ipRes: { bogon: boolean; country: string }) => {
|
|
17
|
-
if (!ipRes.bogon) {
|
|
18
|
-
const pathname = new URL(req.url).pathname;
|
|
19
|
-
const referer = req.headers.get("referer") || "";
|
|
20
|
-
const parser = new UAParser(userAgent);
|
|
21
|
-
recordVisit(
|
|
22
|
-
pathname,
|
|
23
|
-
referer,
|
|
24
|
-
ipRes.country,
|
|
25
|
-
parser.getOS().name,
|
|
26
|
-
parser.getBrowser().name,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
.catch((err: Error) => {
|
|
31
|
-
|
|
25
|
+
recordVisit(ctx.remoteAddr.hostname, userAgent, pathname, referer);
|
|
32
|
-
});
|
|
33
26
|
}
|
|
34
27
|
return resp;
|
|
35
28
|
}
|
services/analytics.ts
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
+
import UAParser from "ua-parser-js";
|
|
2
|
+
import IPinfoWrapper from "ipinfo";
|
|
3
|
+
|
|
4
|
+
const ipInfoClient = new IPinfoWrapper("3f197e26fa9210");
|
|
1
5
|
const kv = await Deno.openKv();
|
|
2
6
|
|
|
3
7
|
export const recordVisit = async (
|
|
8
|
+
hostname: string,
|
|
9
|
+
userAgent: string,
|
|
4
10
|
pathname: string,
|
|
5
11
|
referer: string,
|
|
6
|
-
country: string,
|
|
7
|
-
os: string,
|
|
8
|
-
browser: string,
|
|
9
12
|
) => {
|
|
13
|
+
const ipRes: { country: string } = await ipInfoClient.lookupIp(hostname);
|
|
14
|
+
const parser = new UAParser(userAgent);
|
|
10
15
|
const now = new Date();
|
|
11
16
|
const prefix = [
|
|
12
17
|
"analytics",
|
|
13
18
|
`${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`,
|
|
14
19
|
];
|
|
20
|
+
console.log(parser.getBrowser());
|
|
15
21
|
const keysToIncrement = [
|
|
16
22
|
["visitors"],
|
|
17
23
|
["views"],
|
|
18
24
|
["pages", pathname],
|
|
19
25
|
["referers", referer],
|
|
20
|
-
["countries", country],
|
|
26
|
+
["countries", ipRes.country],
|
|
21
|
-
["os",
|
|
27
|
+
["os", parser.getOS().name],
|
|
22
|
-
["browsers",
|
|
28
|
+
["browsers", parser.getBrowser().name],
|
|
23
|
-
];
|
|
29
|
+
].filter((arr) => arr[arr.length - 1]);
|
|
24
30
|
await kv
|
|
25
31
|
.atomic()
|
|
26
32
|
.mutate(
|
|
@@ -50,11 +56,7 @@ export interface AnalyticsData {
|
|
|
50
56
|
browsers: AnalyticsDataPoint[];
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
const addMetric = (
|
|
54
|
-
|
|
59
|
+
const addMetric = (arr: AnalyticsDataPoint[], name: string, count: number) => {
|
|
55
|
-
name: string,
|
|
56
|
-
count: number,
|
|
57
|
-
) => {
|
|
58
60
|
const index = arr.findIndex((it) => it.name === name);
|
|
59
61
|
if (index > -1) {
|
|
60
62
|
arr[index].count += count;
|