Răsfoiți Sursa

Merge remote-tracking branch 'origin/main' into feat/ts_migration

Sv443 2 ani în urmă
părinte
comite
1798c139ef
8 a modificat fișierele cu 97 adăugiri și 39 ștergeri
  1. 10 12
      .vscode/launch.json
  2. 10 0
      .vscode/tasks.json
  3. 36 4
      README.md
  4. 14 1
      package-lock.json
  5. 2 1
      package.json
  6. 14 13
      src/songMeta.ts
  7. 9 8
      src/types.d.ts
  8. 2 0
      tsconfig.json

+ 10 - 12
.vscode/launch.json

@@ -5,24 +5,22 @@
     "version": "0.2.0",
     "configurations": [
         {
-            "type": "pwa-node",
+            "type": "node",
             "request": "launch",
             "name": "Launch",
-            "skipFiles": [
-                "<node_internals>/**"
-            ],
-            "program": "${workspaceFolder}\\src\\index.js",
+            "program": "${workspaceFolder}/src/index.ts",
+            "preLaunchTask": "prelaunch",
+            "outFiles": ["${workspaceFolder}/out/**/*.js"],
             "console": "integratedTerminal"
         },
         {
-            "type": "pwa-node",
+            "type": "node",
             "request": "launch",
-            "name": "test.js",
-            "skipFiles": [
-                "<node_internals>/**"
-            ],
-            "program": "${workspaceFolder}\\test.js",
+            "name": "test.ts",
+            "program": "${workspaceFolder}/src/test.ts",
+            "preLaunchTask": "prelaunch",
+            "outFiles": ["${workspaceFolder}/out/**/*.js"],
             "console": "integratedTerminal"
-        }
+        },
     ]
 }

+ 10 - 0
.vscode/tasks.json

@@ -0,0 +1,10 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "prelaunch",
+            "type": "shell",
+            "command": "tsc"
+        }
+    ]
+}

+ 36 - 4
README.md

@@ -57,13 +57,29 @@ All routes support gzip and deflate compression.
 >     "top": {
 >         "url": "https://genius.com/Artist-1-song-name-lyrics",
 >         "path": "/Artist-1-song-name-lyrics",
+>         "language": "en",
 >         "meta": {
 >             "title": "Song Name",
 >             "fullTitle": "Song Name by Artist 1 (ft. Artist 2)",
 >             "artists": "Artist 1 (ft. Artist 2)",
 >             "primaryArtist": {
 >                 "name": "Artist 1",
->                 "url": "https://genius.com/artists/Artist-1"
+>                 "url": "https://genius.com/artists/Artist-1",
+>                 "headerImage": "https://images.genius.com/...",
+>                 "image": "https://images.genius.com/..."
+>             },
+>             "featuredArtists": [
+>                 {
+>                     "name": "Featured Artist 1",
+>                     "url": "https://genius.com/artists/Featured-Artist-1",
+>                     "headerImage": "https://images.genius.com/...",
+>                     "image": "https://images.genius.com/..."
+>                 }
+>             ],
+>             "releaseDate": {
+>                 "year": 2018,
+>                 "month": 9,
+>                 "day": 12
 >             }
 >         },
 >         "resources": {
@@ -143,18 +159,34 @@ All routes support gzip and deflate compression.
 >     "matches": 1,
 >     "url": "https://genius.com/Artist-1-song-name-lyrics",
 >     "path": "/Artist-1-song-name-lyrics",
+>     "language": "en",
 >     "meta": {
 >         "title": "Song Name",
 >         "fullTitle": "Song Name by Artist 1 (ft. Artist 2)",
 >         "artists": "Artist 1 (ft. Artist 2)",
 >         "primaryArtist": {
 >             "name": "Artist 1",
->             "url": "https://genius.com/artists/Artist-1"
+>             "url": "https://genius.com/artists/Artist-1",
+>             "headerImage": "https://images.genius.com/...",
+>             "image": "https://images.genius.com/..."
+>         },
+>         "featuredArtists": [
+>             {
+>                 "name": "Featured Artist 1",
+>                 "url": "https://genius.com/artists/Featured-Artist-1",
+>                 "headerImage": "https://images.genius.com/...",
+>                 "image": "https://images.genius.com/..."
+>             }
+>         ],
+>         "releaseDate": {
+>             "year": 2018,
+>             "month": 9,
+>             "day": 12
 >         }
 >     },
 >     "resources": {
->         "thumbnail": "https://images.genius.com/123456789abcdef.300x300x1.png",
->         "image": "https://images.genius.com/123456789abcdef.1000x1000x1.png"
+>         "thumbnail": "https://images.genius.com/8485557225af0345d2c550af8bae731b.300x300x1.png",
+>         "image": "https://images.genius.com/13d7b13ef827a9f007a5d24c115b9ebb.1000x1000x1.png"
 >     },
 >     "lyricsState": "complete",
 >     "id": 42069,

+ 14 - 1
package-lock.json

@@ -29,7 +29,8 @@
         "@types/tcp-port-used": "^1.0.1",
         "dotenv": "^16.0.0",
         "eslint": "^8.9.0",
-        "nodemon": "^2.0.20"
+        "nodemon": "^2.0.20",
+        "tslib": "^2.4.0"
       }
     },
     "node_modules/@eslint/eslintrc": {
@@ -2110,6 +2111,12 @@
         "nodetouch": "bin/nodetouch.js"
       }
     },
+    "node_modules/tslib": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+      "dev": true
+    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -3845,6 +3852,12 @@
         "nopt": "~1.0.10"
       }
     },
+    "tslib": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+      "dev": true
+    },
     "type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

+ 2 - 1
package.json

@@ -48,6 +48,7 @@
     "@types/tcp-port-used": "^1.0.1",
     "dotenv": "^16.0.0",
     "eslint": "^8.9.0",
-    "nodemon": "^2.0.20"
+    "nodemon": "^2.0.20",
+    "tslib": "^2.4.0"
   }
 }

+ 14 - 13
src/songMeta.ts

@@ -4,7 +4,7 @@ import { randomUUID } from "crypto";
 import { JSONCompatible, reserialize } from "svcorelib";
 import { ApiSearchResult, SongMeta } from "./types";
 
-type SearchHit = (SongMeta & { uuid?: string; });
+type MetaSearchHit = SongMeta & { uuid?: string; };
 
 /**
  * Returns meta information about the top results of a search using the genius API
@@ -25,17 +25,18 @@ export async function getMeta({ q, artist, song }: Partial<Record<"q" | "artist"
         if(response.hits.length === 0)
             return null;
 
-        let hits: SearchHit[] = response.hits
+        let hits: MetaSearchHit[] = response.hits
             .filter(h => h.type === "song")
             .map(({ result }) => ({
                 url: result.url,
                 path: result.path,
+                language: result.language ?? null,
                 meta: {
-                    title: normalizeString(result.title) ?? null,
-                    fullTitle: normalizeString(result.full_title) ?? null,
-                    artists: normalizeString(result.artist_names) ?? null,
+                    title: formatStr(result.title),
+                    fullTitle: formatStr(result.full_title),
+                    artists: formatStr(result.artist_names),
                     primaryArtist: {
-                        name: normalizeString(result.primary_artist.name) ?? null,
+                        name: formatStr(result.primary_artist.name) ?? null,
                         url: result.primary_artist.url ?? null,
                         headerImage: result.primary_artist.header_image_url ?? null,
                         image: result.primary_artist.image_url ?? null,
@@ -67,10 +68,10 @@ export async function getMeta({ q, artist, song }: Partial<Record<"q" | "artist"
                 return h;
             }) as (SongMeta & { uuid: string })[];
 
-            const fuseOpts = {
+            const fuseOpts: Fuse.IFuseOptions<MetaSearchHit> = {
                 ignoreLocation: true,
                 includeScore: true,
-                threshold: 0.5,
+                threshold: 0.6,
             };
 
             const titleFuse = new Fuse(hits, { ...fuseOpts, keys: [ "meta.title" ] });
@@ -106,11 +107,11 @@ export async function getMeta({ q, artist, song }: Partial<Record<"q" | "artist"
                         return hit;
                     }
                 })
-                .filter(h => h !== undefined) as SearchHit[];
+                .filter(h => h !== undefined) as MetaSearchHit[];
         }
 
         return {
-            top: hits[0] as SearchHit,
+            top: hits[0] as MetaSearchHit,
             all: hits.slice(0, 10),
         };
     }
@@ -120,12 +121,12 @@ export async function getMeta({ q, artist, song }: Partial<Record<"q" | "artist"
 
 /**
  * Removes invisible characters and control characters from a string  
- * Returns null if the input is not a string
+ * @throws Throws TypeError if the input is not a string
  */
-function normalizeString(str: unknown)
+function formatStr(str: unknown): string
 {
     if(!str || typeof str !== "string")
-        return null;
+        throw new TypeError("formatStr(): input is not a string");
 
     return str.replace(/[\u0000-\u001F\u007F-\u009F\u200B]/g, "").replace(/\u00A0/g, " ");
 }

+ 9 - 8
src/types.d.ts

@@ -9,12 +9,13 @@ interface Artist {
 
 /** geniURL song meta object */
 export interface SongMeta {
-    url: string | null;
-    path: string | null;
+    url: string;
+    path: string;
+    language: string | null;
     meta: {
-        title: string | null;
-        fullTitle: string | null;
-        artists: string | null;
+        title: string;
+        fullTitle: string;
+        artists: string;
         releaseDate: {
             year: number | null;
             month: number | null;
@@ -27,8 +28,8 @@ export interface SongMeta {
         thumbnail: string | null;
         image: string | null;
     };
-    lyricsState: string | null;
-    id: number | null;
+    lyricsState: string;
+    id: number;
 }
 
 //#SECTION server
@@ -46,7 +47,7 @@ export type ApiSearchResult = {
     };
 };
 
-/** One search result returned by the genius API */
+/** One result returned by the genius API search */
 export type SearchHit = {
     type: "song";
     result: {

+ 2 - 0
tsconfig.json

@@ -6,8 +6,10 @@
     "rootDir": ".",
     "outDir": "./out/",
     "moduleResolution": "node",
+    "sourceMap": true,
     "useDefineForClassFields": true,
     "allowJs": false,
+    "importHelpers": true,
     "skipLibCheck": true,
     "esModuleInterop": true,
     "allowSyntheticDefaultImports": true,