forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1import _ from "lodash";
2import * as R from "ramda";
3
4export const dedupeTracksKeepLyrics = (tracks) => {
5 const trackMap = new Map();
6
7 for (const track of tracks) {
8 const key = `${track.discNumber} - ${track.trackNumber}`;
9
10 if (!key) continue;
11
12 const existing = trackMap.get(key);
13
14 // If current has lyrics and either no existing or existing has no lyrics, replace it
15 if (!existing || (!existing.lyrics && track.lyrics)) {
16 trackMap.set(key, track);
17 }
18 }
19
20 return Array.from(trackMap.values());
21};
22
23type AnyObject = Record<string, any>;
24
25const isObject = (val: unknown): val is AnyObject =>
26 typeof val === "object" && val !== null && !Array.isArray(val);
27
28export const deepCamelCaseKeys = <T>(obj: T): any => {
29 if (Array.isArray(obj)) {
30 return obj.map(deepCamelCaseKeys);
31 } else if (isObject(obj)) {
32 return R.pipe(
33 R.toPairs,
34 R.map(
35 ([key, value]) =>
36 [_.camelCase(String(key)), deepCamelCaseKeys(value)] as [string, any],
37 ),
38 R.fromPairs,
39 )(obj as object);
40 }
41 return obj;
42};
43
44export const deepSnakeCaseKeys = <T>(obj: T): any => {
45 if (Array.isArray(obj)) {
46 return obj.map(deepSnakeCaseKeys);
47 } else if (isObject(obj)) {
48 return R.pipe(
49 R.toPairs,
50 R.map(
51 ([key, value]) =>
52 [_.snakeCase(String(key)), deepSnakeCaseKeys(value)] as [string, any],
53 ),
54 R.fromPairs,
55 )(obj as object);
56 }
57 return obj;
58};