~repos /website

#astro#js#html#css

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

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


7640f703 pyrossh

1 year ago
improve analytics
components/List.tsx CHANGED
@@ -1,8 +1,12 @@
1
1
  import { AnalyticsDataPoint } from "../services/analytics.ts";
2
2
 
3
+ type ListProps = {
4
+ title: string;
3
- type ListProps = { title: string; entries: AnalyticsDataPoint[] };
5
+ entries: AnalyticsDataPoint[];
6
+ flag?: boolean;
7
+ };
4
8
 
5
- export default function List({ title, entries }: ListProps) {
9
+ export default function List({ title, entries, flag }: ListProps) {
6
10
  return (
7
11
  <div class="bg-white p-6 rounded-lg">
8
12
  <div>
@@ -11,11 +15,16 @@ export default function List({ title, entries }: ListProps) {
11
15
  <div class="mt-4 px-3">
12
16
  {entries.map((entry) => (
13
17
  <div class="flex my-2">
18
+ <div class="flex">
19
+ {flag && (
14
- <div>
20
+ <img
21
+ src={`https://cdn.jsdelivr.net/npm/country-flag-emoji-json@2.0.0/dist/images/${entry.name}.svg`}
22
+ width="18"
23
+ />
24
+ )}
15
25
  <span class="text-base font-medium">{entry.name}</span>
16
26
  </div>
17
27
  <div class="flex-1 flex justify-end">
18
- <i class="icon icon-follow clickable"></i>
19
28
  <span class="text-base font-medium">
20
29
  {entry.count.toString()}
21
30
  </span>
routes/_middleware.ts CHANGED
@@ -15,7 +15,6 @@ export async function handler(req: Request, ctx: FreshContext) {
15
15
  .filter((a) => !["/_404", "/_app", "/_middleware.ts"].includes(a));
16
16
  const userAgent = req.headers.get("user-agent") || "";
17
17
  const referer = req.headers.get("referer") || "";
18
- console.log("referer", referer, req.referrer);
19
18
  const pathname = new URL(req.url).pathname;
20
19
  if (
21
20
  registeredRoutes.includes(pathname) &&
routes/stats.tsx CHANGED
@@ -30,7 +30,7 @@ export default function Stats({ data }: PageProps<AnalyticsData>) {
30
30
  </div>
31
31
  <div class="grid grid-cols-2 gap-8">
32
32
  <List title="Pages" entries={data.pages} />
33
- <List title="Countries" entries={data.countries} />
33
+ <List title="Countries" entries={data.countries} flag />
34
34
  </div>
35
35
  <div class="grid grid-cols-2 gap-8 mt-8">
36
36
  <List title="OS" entries={data.os} />
services/analytics.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import UAParser from "ua-parser-js";
2
2
  import IPinfoWrapper from "ipinfo";
3
- import { getCountryData, getEmojiFlag } from "countries-list";
3
+ import { getCountryData } from "countries-list";
4
4
 
5
5
  const ipInfoClient = new IPinfoWrapper("3f197e26fa9210");
6
6
  const kv = await Deno.openKv();
@@ -18,16 +18,17 @@ export const recordVisit = async (
18
18
  "analytics",
19
19
  `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`,
20
20
  ];
21
- console.log(parser.getBrowser());
21
+ const newVisitor = await kv.get(["visitor", hostname]);
22
22
  const keysToIncrement = [
23
+ newVisitor.value ? [] : ["vistor", hostname],
23
- ["visitors"],
24
+ [...prefix, "visitors"],
24
- ["views"],
25
+ [...prefix, "views"],
25
- ["pages", pathname],
26
+ [...prefix, "pages", pathname],
26
- ["referers", referer],
27
+ [...prefix, "referers", referer],
27
- ["countries", ipRes.countryCode],
28
+ [...prefix, "countries", ipRes.countryCode],
28
- ["os", parser.getOS().name],
29
+ [...prefix, "os", parser.getOS().name],
29
- ["browsers", parser.getBrowser().name],
30
+ [...prefix, "browsers", parser.getBrowser().name],
30
- ].filter((arr) => arr[arr.length - 1]);
31
+ ].filter((arr) => arr.length === 0 || arr[arr.length - 1]);
31
32
  await kv
32
33
  .atomic()
33
34
  .mutate(
@@ -98,7 +99,7 @@ export const getAnalyticsData = async () => {
98
99
  }
99
100
  if (entry.key[2] === "countries") {
100
101
  const code = entry.key[3] as string;
101
- const name = getEmojiFlag(code) + getCountryData(code).name;
102
+ const name = getCountryData(code).name;
102
103
  addMetric(data.countries, name, entry.value as number);
103
104
  }
104
105
  }