diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/deno.json b/deno.json index 239114c..46d4b7a 100644 --- a/deno.json +++ b/deno.json @@ -1,9 +1,11 @@ { "tasks": { - "dev": "deno run --allow-read=./ --allow-net main.ts" + "dev": "deno run --allow-read=./ --allow-net --allow-env main.ts" }, "imports": { "@std/assert": "jsr:@std/assert@1", + "@std/dotenv": "jsr:@std/dotenv@^0.225.6", + "@std/fs": "jsr:@std/fs@^1.0.21", "@std/media-types": "jsr:@std/media-types@^1.1.0" } } diff --git a/deno.lock b/deno.lock index 5397edb..47f2e6b 100644 --- a/deno.lock +++ b/deno.lock @@ -2,8 +2,11 @@ "version": "5", "specifiers": { "jsr:@std/assert@1": "1.0.16", + "jsr:@std/dotenv@~0.225.6": "0.225.6", + "jsr:@std/fs@^1.0.21": "1.0.21", "jsr:@std/internal@^1.0.12": "1.0.12", - "jsr:@std/media-types@^1.1.0": "1.1.0" + "jsr:@std/media-types@^1.1.0": "1.1.0", + "jsr:@std/path@^1.1.4": "1.1.4" }, "jsr": { "@std/assert@1.0.16": { @@ -12,16 +15,34 @@ "jsr:@std/internal" ] }, + "@std/dotenv@0.225.6": { + "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" + }, + "@std/fs@1.0.21": { + "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd", + "dependencies": [ + "jsr:@std/internal", + "jsr:@std/path" + ] + }, "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" }, "@std/media-types@1.1.0": { "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] } }, "workspace": { "dependencies": [ "jsr:@std/assert@1", + "jsr:@std/dotenv@~0.225.6", + "jsr:@std/fs@^1.0.21", "jsr:@std/media-types@^1.1.0" ] } diff --git a/main.ts b/main.ts index be1bce3..8368a31 100644 --- a/main.ts +++ b/main.ts @@ -1,27 +1,22 @@ import path from "node:path"; +import { walk } from "@std/fs/walk"; +import "@std/dotenv/load"; +import { contentType } from "@std/media-types"; -const NET_PORT = 4536; -const NET_HOST = '127.0.0.1'; -const WEB_ROOT = './res/'; +const _PORT = Deno.env.get('NET_PORT'); +if (!_PORT || isNaN(parseInt(_PORT))) throw new Error("No NET_PORT specified in env"); +const NET_PORT = parseInt(_PORT); -interface FileMapping { - endpoints: string[], - path: string, - mime: string -} +const NET_HOST = Deno.env.get('NET_HOST'); +if (!NET_HOST) throw new Error("No NET_HOST specified in env"); -const mappings: FileMapping[] = [ - { - endpoints: ['/', '/index.html'], - path: "/index.html", - mime: "text/html" - }, - { - endpoints: ['/style.css'], - path: "/style.css", - mime: "text/css" - } -] as const; +const WEB_ROOT = Deno.env.get('WEB_ROOT'); +if (!WEB_ROOT) throw new Error("No WEB_ROOT specified in env"); + +const DIR_ROOT = path.join(Deno.cwd(), WEB_ROOT); +const FILES = (await Array.fromAsync(walk(DIR_ROOT))).filter(entry => entry.isFile).map(entry => entry.path.replaceAll(Deno.cwd(), '').replaceAll('\\', '/')); + +console.log(FILES) Deno.serve({ hostname: NET_HOST, @@ -34,21 +29,34 @@ Deno.serve({ headers: { "Content-Type": "text/plain" } }); - const url = new URL(req.url); + try { + const url = new URL(req.url); - if (url.pathname == '/') url.pathname = '/index.html'; + if (req.headers.get('user-agent')?.includes("Mobile") && url.pathname == '/') url.pathname = '/mobile.html'; + else if (url.pathname == '/') url.pathname = '/index.html'; - const mapping = mappings.find(val => val.endpoints.some(val => url.pathname === val)); + const match = FILES.find(file => file.replace(WEB_ROOT, '') == url.pathname); - console.log(`${addr.remoteAddr.hostname}:${addr.remoteAddr.port} ${req.method} ${url.pathname} | mapping exists: ${typeof mapping !== 'undefined'}`); - return new Promise(resolve => { - if (mapping) { - Deno.readFile(path.join(WEB_ROOT, mapping.path)).then(data => { - resolve(new Response(data, { headers: { "Content-Type": mapping.mime }})); - }).catch(reason => { - console.error(reason); - resolve(notFound); - }); - } else resolve(notFound); - }); + console.log(`${addr.remoteAddr.hostname}:${addr.remoteAddr.port} ${req.method} ${url.pathname} | mapping exists: ${typeof match !== 'undefined'}`); + return new Promise(resolve => { + if (match) { + Deno.readFile(path.join(Deno.cwd(), match)).then(data => { + const headers = new Headers(); + + const last = match.split('/').at(-1); + if (last) { + const mime = contentType(last.substring(last.indexOf('.'))); + if (mime) headers.set("Content-Type", mime); + } + + resolve(new Response(data, { headers })); + }).catch(reason => { + console.error(reason); + resolve(notFound); + }); + } else resolve(notFound); + }); + } catch { + return notFound; + } }); \ No newline at end of file diff --git a/res/imgs/Hatsune_Discord_Banner_BG_Only_Banner_Ratio_.png b/res/imgs/Hatsune_Discord_Banner_BG_Only_Banner_Ratio_.png new file mode 100644 index 0000000..7ea9859 Binary files /dev/null and b/res/imgs/Hatsune_Discord_Banner_BG_Only_Banner_Ratio_.png differ diff --git a/res/imgs/Miku_With_Tag.png b/res/imgs/Miku_With_Tag.png new file mode 100644 index 0000000..e393cdf Binary files /dev/null and b/res/imgs/Miku_With_Tag.png differ diff --git a/res/imgs/Miku_badge_transparent.png b/res/imgs/Miku_badge_transparent.png new file mode 100644 index 0000000..146ea59 Binary files /dev/null and b/res/imgs/Miku_badge_transparent.png differ diff --git a/res/imgs/New_Drawing1.png b/res/imgs/New_Drawing1.png new file mode 100644 index 0000000..e952979 Binary files /dev/null and b/res/imgs/New_Drawing1.png differ diff --git a/res/imgs/Wing_of_Form.png b/res/imgs/Wing_of_Form.png new file mode 100644 index 0000000..059956a Binary files /dev/null and b/res/imgs/Wing_of_Form.png differ diff --git a/res/imgs/Wing_of_Sound.png b/res/imgs/Wing_of_Sound.png new file mode 100644 index 0000000..9e9d39a Binary files /dev/null and b/res/imgs/Wing_of_Sound.png differ diff --git a/res/imgs/absolute_comfy.png b/res/imgs/absolute_comfy.png new file mode 100644 index 0000000..28b2ac8 Binary files /dev/null and b/res/imgs/absolute_comfy.png differ diff --git a/res/imgs/cmpfpf.png b/res/imgs/cmpfpf.png new file mode 100644 index 0000000..ab0a6e5 Binary files /dev/null and b/res/imgs/cmpfpf.png differ diff --git a/res/imgs/digiral/Affection_-_Miku_and_Heart_Pose.png b/res/imgs/digiral/Affection_-_Miku_and_Heart_Pose.png new file mode 100644 index 0000000..ef00582 Binary files /dev/null and b/res/imgs/digiral/Affection_-_Miku_and_Heart_Pose.png differ diff --git a/res/imgs/digiral/Angry_-_Miku_and_Punch.png b/res/imgs/digiral/Angry_-_Miku_and_Punch.png new file mode 100644 index 0000000..aa193bc Binary files /dev/null and b/res/imgs/digiral/Angry_-_Miku_and_Punch.png differ diff --git a/res/imgs/digiral/Excitement_-_Miku_and_Sparkling_Eyes.png b/res/imgs/digiral/Excitement_-_Miku_and_Sparkling_Eyes.png new file mode 100644 index 0000000..bd302da Binary files /dev/null and b/res/imgs/digiral/Excitement_-_Miku_and_Sparkling_Eyes.png differ diff --git a/res/imgs/digiral/Ideas_-_Miku_and_Ideas.png b/res/imgs/digiral/Ideas_-_Miku_and_Ideas.png new file mode 100644 index 0000000..0cd52a8 Binary files /dev/null and b/res/imgs/digiral/Ideas_-_Miku_and_Ideas.png differ diff --git a/res/imgs/digiral/Joy_-_Miku_and_Air_Guitar.png b/res/imgs/digiral/Joy_-_Miku_and_Air_Guitar.png new file mode 100644 index 0000000..5b9c111 Binary files /dev/null and b/res/imgs/digiral/Joy_-_Miku_and_Air_Guitar.png differ diff --git a/res/imgs/digiral/Relaxed_-_Miku_and_Strawberry_Milk_Tea.png b/res/imgs/digiral/Relaxed_-_Miku_and_Strawberry_Milk_Tea.png new file mode 100644 index 0000000..fbef6db Binary files /dev/null and b/res/imgs/digiral/Relaxed_-_Miku_and_Strawberry_Milk_Tea.png differ diff --git a/res/imgs/digiral/Supportive_-_Miku_and_Ganbatte.png b/res/imgs/digiral/Supportive_-_Miku_and_Ganbatte.png new file mode 100644 index 0000000..d0181fe Binary files /dev/null and b/res/imgs/digiral/Supportive_-_Miku_and_Ganbatte.png differ diff --git a/res/imgs/miku_hammer.png b/res/imgs/miku_hammer.png new file mode 100644 index 0000000..3448734 Binary files /dev/null and b/res/imgs/miku_hammer.png differ diff --git a/res/imgs/miku_loading_please_wait.png b/res/imgs/miku_loading_please_wait.png new file mode 100644 index 0000000..e676b8c Binary files /dev/null and b/res/imgs/miku_loading_please_wait.png differ diff --git a/res/imgs/poco_eevee.png b/res/imgs/poco_eevee.png new file mode 100644 index 0000000..8e03c35 Binary files /dev/null and b/res/imgs/poco_eevee.png differ diff --git a/res/index.html b/res/index.html index f3fe4d3..49cce6e 100644 --- a/res/index.html +++ b/res/index.html @@ -8,7 +8,7 @@ - + @@ -21,20 +21,25 @@

We would like to present the highlights.

- -

See Below

- arrow_downward + +
-
+
-

Is it just me, or is it comfy in here?

-

Here are the top 10 most used reactions:

-
    +
    +

    Is it just me, or is it comfy in here?

    + +
    +
    + +

    Here are the top 10 most used reactions:

    +
    +
    1. x13,594 @@ -75,16 +80,16 @@ x2,460
    2. -
+

-

Add some spice to your message.

-

Here are the top 10 most used emojis:

-
    +

    Add some spice to your message.

    +

    Here are the top 10 most used emojis:

    +
    1. x10,285 @@ -125,16 +130,19 @@ x2,394
    2. -
+

-
-

Stickerbomb!

-

Here are the top 10 most used stickers:

-
    +
    +
    +

    Stickerbomb!

    + +
    +

    Here are the top 10 most used stickers:

    +
    1. x624 @@ -175,27 +183,28 @@ x110
    2. -
+

-
-
-

Let's talk messages.

-

We sent 1,091,742 of them.

-

Jeez.

+
+

Let's talk messages.

+

We sent 1,091,742 of them.

+

We're glad you spent this much time with us.

+
+

-

Some of those messages were pretty popular.

-

Here are each month's most reacted messages:

-
    +

    Some of those messages were pretty popular.

    +

    Here are each month's most reacted messages:

    +
    • January: #general-01 by powerblade3 - 220
    • February: #general-01 by mikuoctoling39 - 119
    • March: #general-01 by miku.hatsune - 99
    • @@ -215,9 +224,9 @@
      -

      We had several keyboard enthusiasts.

      -

      Here are the top 10 users with the most messages:

      -
        +

        We had several keyboard enthusiasts.

        +

        Here are the top 10 users with the most messages:

        +
        1. @miraigummies - 52,746
        2. @koolaidkan - 42,391
        3. @iam_stove - 35,365
        4. @@ -228,16 +237,19 @@
        5. @zunda_nectar - 28,119
        6. @simplename21 - 23,234
        7. @kelcody - 22,782
        8. -
      +

      -

      You were always here with us.

      -

      Here are the top 10 users with the most '39' messages:

      -
        +
        +

        You were always here with us.

        + +
        +

        Here are the top 10 users with the most '39' messages:

        +
        1. @iam_stove - 3,790
        2. @aozora39 - 3,445
        3. @cfm_megurine_luka - 3,325
        4. @@ -247,8 +259,8 @@
        5. @the_apricity_effect - 1,706
        6. @yokoo99 - 1,354
        7. @_1v40_ - 1,294
        8. -
        9. @iam_stove - 1,262
        10. -
      +
    • @39.mik - 1,262
    • +

      @@ -256,6 +268,10 @@

      Thank you all for a great year! We're here to share the next with you.