~repos /website

#astro#js#html#css

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

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


80ae0539 pyrossh

1 year ago
Fix browsers, countries
Files changed (3) hide show
  1. deno.json +2 -1
  2. routes/stats.tsx +22 -16
  3. services/analytics.ts +7 -4
deno.json CHANGED
@@ -25,7 +25,8 @@
25
25
  "$std/": "https://deno.land/std@0.193.0/",
26
26
  "ua-parser-js": "https://esm.sh/ua-parser-js@1.0.37",
27
27
  "isbot": "https://esm.sh/isbot@3.7.1",
28
- "ipinfo": "https://esm.sh/node-ipinfo@3.5.1"
28
+ "ipinfo": "https://esm.sh/node-ipinfo@3.5.1",
29
+ "countries-list": "https://esm.sh/countries-list@3.0.6"
29
30
  },
30
31
  "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" }
31
32
  }
routes/stats.tsx CHANGED
@@ -13,24 +13,30 @@ export const handler: Handlers<AnalyticsData> = {
13
13
 
14
14
  export default function Stats({ data }: PageProps<AnalyticsData>) {
15
15
  return (
16
+ <>
17
+ <Head>
18
+ <title>pyros.sh | Stats</title>
19
+ <meta name="description" content="Analytics of the pyros.sh website" />
20
+ </Head>
16
- <div class="flex flex-1 flex-col theme-light">
21
+ <div class="flex flex-1 flex-col theme-light">
17
- <div class="py-4 text-lg font-medium text-gray-800">Dashboard</div>
22
+ <div class="py-4 text-lg font-medium text-gray-800">Dashboard</div>
18
- <div class="charts no-select hidden">
23
+ <div class="charts no-select hidden">
19
- <div class="headline">
24
+ <div class="headline">
20
- <div class="metrics">
25
+ <div class="metrics">
21
- <Tile title="Page Visitors" value={data.vistors.toString()} />
26
+ <Tile title="Visitors" value={data.vistors.toString()} />
22
- <Tile title="Page Views" value={data.views.toString()} />
27
+ <Tile title="Views" value={data.views.toString()} />
28
+ </div>
23
29
  </div>
24
30
  </div>
31
+ <div class="grid grid-cols-2 gap-8">
32
+ <List title="Pages" entries={data.pages} />
33
+ <List title="Countries" entries={data.countries} />
34
+ </div>
35
+ <div class="grid grid-cols-2 gap-8 mt-8">
36
+ <List title="OS" entries={data.os} />
37
+ <List title="Browsers" entries={data.browsers} />
38
+ </div>
25
39
  </div>
26
- <div class="grid grid-cols-2 gap-8">
27
- <List title="Pages" entries={data.pages} />
28
- <List title="Countries" entries={data.countries} />
29
- </div>
40
+ </>
30
- <div class="grid grid-cols-2 gap-8 mt-8">
31
- <List title="OS" entries={data.os} />
32
- <List title="Browsers" entries={data.browsers} />
33
- </div>
34
- </div>
35
41
  );
36
42
  }
services/analytics.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import UAParser from "ua-parser-js";
2
2
  import IPinfoWrapper from "ipinfo";
3
+ import { getCountryData, getEmojiFlag } from "countries-list";
3
4
 
4
5
  const ipInfoClient = new IPinfoWrapper("3f197e26fa9210");
5
6
  const kv = await Deno.openKv();
@@ -10,7 +11,7 @@ export const recordVisit = async (
10
11
  pathname: string,
11
12
  referer: string,
12
13
  ) => {
13
- const ipRes: { country: string } = await ipInfoClient.lookupIp(hostname);
14
+ const ipRes: { countryCode: string } = await ipInfoClient.lookupIp(hostname);
14
15
  const parser = new UAParser(userAgent);
15
16
  const now = new Date();
16
17
  const prefix = [
@@ -23,7 +24,7 @@ export const recordVisit = async (
23
24
  ["views"],
24
25
  ["pages", pathname],
25
26
  ["referers", referer],
26
- ["countries", ipRes.country],
27
+ ["countries", ipRes.countryCode],
27
28
  ["os", parser.getOS().name],
28
29
  ["browsers", parser.getBrowser().name],
29
30
  ].filter((arr) => arr[arr.length - 1]);
@@ -83,7 +84,7 @@ export const getAnalyticsData = async () => {
83
84
  if (entry.key[2] === "visitors") {
84
85
  data.vistors = entry.value as number;
85
86
  }
86
- if (entry.key[2] === "browser") {
87
+ if (entry.key[2] === "browsers") {
87
88
  addMetric(data.browsers, entry.key[3] as string, entry.value as number);
88
89
  }
89
90
  if (entry.key[2] === "os") {
@@ -96,7 +97,9 @@ export const getAnalyticsData = async () => {
96
97
  addMetric(data.referrers, entry.key[3] as string, entry.value as number);
97
98
  }
98
99
  if (entry.key[2] === "countries") {
100
+ const code = entry.key[3] as string;
101
+ const name = getEmojiFlag(code) + getCountryData(code).name;
99
- addMetric(data.countries, entry.key[3] as string, entry.value as number);
102
+ addMetric(data.countries, name, entry.value as number);
100
103
  }
101
104
  }
102
105
  return data;