~repos /website

#astro#js#html#css

git clone https://pyrossh.dev/repos/website.git

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


309efff7 pyrossh

1 year ago
imporve analytics
Files changed (2) hide show
  1. routes/_middleware.ts +16 -23
  2. 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
- const ipInfoClient = new IPinfoWrapper("3f197e26fa9210");
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") && !isbot(userAgent)
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
- console.log("failed to get ip", err);
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", os],
27
+ ["os", parser.getOS().name],
22
- ["browsers", browser],
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
- arr: AnalyticsDataPoint[],
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;