A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at 2b044aaed2c433aca9688cbd767408dc80f1fc4f 58 lines 1.5 kB view raw
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};