chore: simpler charts
This commit is contained in:
parent
e8b8bb24b5
commit
eaa43c41af
7 changed files with 59 additions and 1092 deletions
3
.env
3
.env
|
@ -1,6 +1,3 @@
|
||||||
ACCESS_KEY_WASABI=
|
|
||||||
SECRET_KEY_WASABI=
|
|
||||||
BUCKET_WASABI=
|
|
||||||
API_KEY_PLAUSIBLE=
|
API_KEY_PLAUSIBLE=
|
||||||
API_KEY_TRAKT=
|
API_KEY_TRAKT=
|
||||||
API_KEY_WEBMENTIONS_CORYD_DEV=
|
API_KEY_WEBMENTIONS_CORYD_DEV=
|
||||||
|
|
|
@ -1,915 +0,0 @@
|
||||||
{
|
|
||||||
"Punk": [
|
|
||||||
"+44",
|
|
||||||
"wire",
|
|
||||||
"sex-pistols",
|
|
||||||
"rkl",
|
|
||||||
"refused",
|
|
||||||
"propagandhi",
|
|
||||||
"the-pogues",
|
|
||||||
"nomeansno",
|
|
||||||
"nofx",
|
|
||||||
"misfits",
|
|
||||||
"minutemen",
|
|
||||||
"minor-threat",
|
|
||||||
"joyce-manor",
|
|
||||||
"jello-biafra-with-nomeansno",
|
|
||||||
"j-church",
|
|
||||||
"hüsker-dü",
|
|
||||||
"green-day",
|
|
||||||
"fugazi",
|
|
||||||
"fake-names",
|
|
||||||
"descendents",
|
|
||||||
"deep-turtle",
|
|
||||||
"death-from-above-1979",
|
|
||||||
"dead-kennedys",
|
|
||||||
"cock-sparrer",
|
|
||||||
"coachwhips",
|
|
||||||
"cloud-nothings",
|
|
||||||
"the-clash",
|
|
||||||
"box-car-racer",
|
|
||||||
"blink-182",
|
|
||||||
"black-flag",
|
|
||||||
"bad-religion",
|
|
||||||
"bad-brains",
|
|
||||||
"afi"
|
|
||||||
],
|
|
||||||
"Black Metal": [
|
|
||||||
"zhrine",
|
|
||||||
"yellow-eyes",
|
|
||||||
"wormlust",
|
|
||||||
"woods-of-ypres",
|
|
||||||
"woods-of-desolation",
|
|
||||||
"wolves-in-the-throne-room",
|
|
||||||
"white-ward",
|
|
||||||
"weakling",
|
|
||||||
"vital-spirit",
|
|
||||||
"ved-buens-ende...",
|
|
||||||
"vaura",
|
|
||||||
"unanimated",
|
|
||||||
"ultha",
|
|
||||||
"ultar",
|
|
||||||
"trna",
|
|
||||||
"tómarúm",
|
|
||||||
"tod-huetet-uebel",
|
|
||||||
"thou,-mizmor-&-emma-ruth-rundle",
|
|
||||||
"thantifaxath",
|
|
||||||
"tardigrada",
|
|
||||||
"svartidauði",
|
|
||||||
"sunken",
|
|
||||||
"stormkeep",
|
|
||||||
"skáphe",
|
|
||||||
"sinmara",
|
|
||||||
"the-silver",
|
|
||||||
"show-me-a-dinosaur",
|
|
||||||
"sacramentum",
|
|
||||||
"rebirth-of-nefast",
|
|
||||||
"pillorian",
|
|
||||||
"panopticon",
|
|
||||||
"outre",
|
|
||||||
"ossuaire",
|
|
||||||
"örmagna",
|
|
||||||
"olhava",
|
|
||||||
"odraza",
|
|
||||||
"oathbreaker",
|
|
||||||
"numenorean",
|
|
||||||
"nordicwinter",
|
|
||||||
"noltem",
|
|
||||||
"moonsorrow",
|
|
||||||
"møl",
|
|
||||||
"mizmor-&-thou",
|
|
||||||
"mizmor-&-andrew-black",
|
|
||||||
"mizmor",
|
|
||||||
"misþyrming",
|
|
||||||
"mgła",
|
|
||||||
"mare-cognitum",
|
|
||||||
"mannveira",
|
|
||||||
"lunar-aurora",
|
|
||||||
"lantlôs",
|
|
||||||
"kriegsmaschine",
|
|
||||||
"krallice",
|
|
||||||
"kostnatění",
|
|
||||||
"karg",
|
|
||||||
"hræ",
|
|
||||||
"helfró",
|
|
||||||
"harakiri-for-the-sky",
|
|
||||||
"grey-waters",
|
|
||||||
"gravenchalice",
|
|
||||||
"furia",
|
|
||||||
"fen",
|
|
||||||
"falls-of-rauros",
|
|
||||||
"enslaved",
|
|
||||||
"emperor",
|
|
||||||
"embrace-of-thorns",
|
|
||||||
"drudkh",
|
|
||||||
"drought",
|
|
||||||
"deathspell-omega",
|
|
||||||
"deafheaven",
|
|
||||||
"the-clearing-path",
|
|
||||||
"celeste",
|
|
||||||
"carpe-noctem",
|
|
||||||
"bosse-de-nage",
|
|
||||||
"blut-aus-nord",
|
|
||||||
"behemoth",
|
|
||||||
"an-autumn-for-crippled-children",
|
|
||||||
"au-dessus",
|
|
||||||
"ash-borer",
|
|
||||||
"arcturus",
|
|
||||||
"aosoth",
|
|
||||||
"aoratos",
|
|
||||||
"andavald",
|
|
||||||
"amesoeurs",
|
|
||||||
"altar-of-plagues",
|
|
||||||
"akhlys",
|
|
||||||
"agalloch",
|
|
||||||
"afsky"
|
|
||||||
],
|
|
||||||
"Death Metal": [
|
|
||||||
"zealotry",
|
|
||||||
"xysma",
|
|
||||||
"xoth",
|
|
||||||
"xenomorph",
|
|
||||||
"wretched-fate",
|
|
||||||
"worthless",
|
|
||||||
"worm",
|
|
||||||
"wombbath",
|
|
||||||
"witherscape",
|
|
||||||
"witch-vomit",
|
|
||||||
"weeping-sores",
|
|
||||||
"warp-chamber",
|
|
||||||
"vrenth",
|
|
||||||
"vorum",
|
|
||||||
"voimaton",
|
|
||||||
"voidceremony",
|
|
||||||
"void-terror",
|
|
||||||
"void-rot",
|
|
||||||
"vircolac",
|
|
||||||
"vertebra-atlantis",
|
|
||||||
"venomous-skeleton",
|
|
||||||
"vengeful",
|
|
||||||
"venenum",
|
|
||||||
"vasaeleth",
|
|
||||||
"vader",
|
|
||||||
"vacuous",
|
|
||||||
"vacivus",
|
|
||||||
"unleashed",
|
|
||||||
"universally-estranged",
|
|
||||||
"undersave",
|
|
||||||
"undergang",
|
|
||||||
"under-the-church",
|
|
||||||
"undeath",
|
|
||||||
"unbounded-terror",
|
|
||||||
"unaussprechlichen-kulten",
|
|
||||||
"unanimated",
|
|
||||||
"ulthar",
|
|
||||||
"úlfúð",
|
|
||||||
"ulcerate",
|
|
||||||
"turris-eburnea",
|
|
||||||
"tumba-de-carne",
|
|
||||||
"tribulation",
|
|
||||||
"trenchrot",
|
|
||||||
"transgressor",
|
|
||||||
"toughness",
|
|
||||||
"totten-korps",
|
|
||||||
"torchure",
|
|
||||||
"tomb-mold",
|
|
||||||
"timeghoul",
|
|
||||||
"tiamat",
|
|
||||||
"therion",
|
|
||||||
"thergothon",
|
|
||||||
"thanatos",
|
|
||||||
"temisto",
|
|
||||||
"teleport",
|
|
||||||
"teitanblood",
|
|
||||||
"teeth",
|
|
||||||
"taphos",
|
|
||||||
"sxuperion",
|
|
||||||
"sweven",
|
|
||||||
"swallowed",
|
|
||||||
"suppression",
|
|
||||||
"superstition",
|
|
||||||
"sunless",
|
|
||||||
"sulphurous",
|
|
||||||
"sulphur-aeon",
|
|
||||||
"suffocation",
|
|
||||||
"suffering-hour",
|
|
||||||
"stench",
|
|
||||||
"stargazer",
|
|
||||||
"spectral-voice",
|
|
||||||
"spawn-of-possession",
|
|
||||||
"spasme",
|
|
||||||
"sororicide",
|
|
||||||
"sorcery",
|
|
||||||
"sonne-adam",
|
|
||||||
"solothus",
|
|
||||||
"snorlax",
|
|
||||||
"sněť",
|
|
||||||
"slugathor",
|
|
||||||
"skullcrush",
|
|
||||||
"skeletal-remains",
|
|
||||||
"skeletal",
|
|
||||||
"sinister",
|
|
||||||
"siderean",
|
|
||||||
"shub-niggurath",
|
|
||||||
"shards-of-humanity",
|
|
||||||
"setentia",
|
|
||||||
"sermon-of-flames",
|
|
||||||
"seputus",
|
|
||||||
"sepulcher",
|
|
||||||
"sentient-horror",
|
|
||||||
"sentenced",
|
|
||||||
"sedimentum",
|
|
||||||
"seance",
|
|
||||||
"scythian",
|
|
||||||
"scorched",
|
|
||||||
"sarmat",
|
|
||||||
"runemagick",
|
|
||||||
"rune",
|
|
||||||
"rottrevore",
|
|
||||||
"rotted",
|
|
||||||
"rothadás",
|
|
||||||
"ritual-necromancy",
|
|
||||||
"ripping-corpse",
|
|
||||||
"ripped-to-shreds",
|
|
||||||
"resurgency",
|
|
||||||
"reptilian",
|
|
||||||
"replicant",
|
|
||||||
"reeking-aura",
|
|
||||||
"ravenous-death",
|
|
||||||
"rapture",
|
|
||||||
"question",
|
|
||||||
"qrixkuor",
|
|
||||||
"pyrrhon",
|
|
||||||
"pyrexia",
|
|
||||||
"pyre",
|
|
||||||
"putrescine",
|
|
||||||
"purtenance",
|
|
||||||
"pungent-stench",
|
|
||||||
"psycroptic",
|
|
||||||
"possessed",
|
|
||||||
"portal",
|
|
||||||
"poisonous",
|
|
||||||
"plague-bearer",
|
|
||||||
"phrenelith",
|
|
||||||
"phobophilic",
|
|
||||||
"pestilength",
|
|
||||||
"perilaxe-occlusion",
|
|
||||||
"pan.thy.monium",
|
|
||||||
"outre-tombe",
|
|
||||||
"outer-heaven",
|
|
||||||
"ossuarium",
|
|
||||||
"orthodoxy",
|
|
||||||
"oksennus",
|
|
||||||
"of-feather-and-bone",
|
|
||||||
"obscure-infinity",
|
|
||||||
"obscura",
|
|
||||||
"obscene",
|
|
||||||
"obliveon",
|
|
||||||
"obliteration",
|
|
||||||
"obituary",
|
|
||||||
"nucleus",
|
|
||||||
"nothingness",
|
|
||||||
"noisem",
|
|
||||||
"nocturnus",
|
|
||||||
"nithing",
|
|
||||||
"nihilist",
|
|
||||||
"nex-carnis",
|
|
||||||
"neuraxis",
|
|
||||||
"nekrovault",
|
|
||||||
"nekrofilth",
|
|
||||||
"negativa",
|
|
||||||
"necrovorous",
|
|
||||||
"necrovore",
|
|
||||||
"necrovation",
|
|
||||||
"necrot",
|
|
||||||
"necros-christos",
|
|
||||||
"necrophobic",
|
|
||||||
"necrophiliac",
|
|
||||||
"napalm-death",
|
|
||||||
"moss-upon-the-skull",
|
|
||||||
"mortuous",
|
|
||||||
"mortuary",
|
|
||||||
"mortiferum",
|
|
||||||
"mortem",
|
|
||||||
"mortal-incarnation",
|
|
||||||
"morta-skuld",
|
|
||||||
"morpheus-descends",
|
|
||||||
"morgue",
|
|
||||||
"mordicus",
|
|
||||||
"morbus-chron",
|
|
||||||
"morbid-angel",
|
|
||||||
"monstrosity",
|
|
||||||
"molested",
|
|
||||||
"mitochondrion",
|
|
||||||
"mithridatum",
|
|
||||||
"mithras",
|
|
||||||
"miscreance",
|
|
||||||
"miasma",
|
|
||||||
"merciless",
|
|
||||||
"megaslaughter",
|
|
||||||
"mefitis",
|
|
||||||
"master",
|
|
||||||
"massacre",
|
|
||||||
"martyr",
|
|
||||||
"malignant-altar",
|
|
||||||
"malevolent-creation",
|
|
||||||
"lykathea-aflame",
|
|
||||||
"lurid-panacea",
|
|
||||||
"lunar-chamber",
|
|
||||||
"luciferion",
|
|
||||||
"lost-harvest",
|
|
||||||
"last-sacrament",
|
|
||||||
"lantern",
|
|
||||||
"krypts",
|
|
||||||
"kronos",
|
|
||||||
"kralizec",
|
|
||||||
"krabathor",
|
|
||||||
"killing-addiction",
|
|
||||||
"khthoniik-cerviiks",
|
|
||||||
"kever",
|
|
||||||
"karmacipher",
|
|
||||||
"jumpin'-jesus",
|
|
||||||
"jordablod",
|
|
||||||
"intellect-devourer",
|
|
||||||
"innumerable-forms",
|
|
||||||
"infester",
|
|
||||||
"infernal-coil",
|
|
||||||
"inculter",
|
|
||||||
"incantation",
|
|
||||||
"inanna",
|
|
||||||
"imprecation",
|
|
||||||
"imperial-triumphant",
|
|
||||||
"impaler",
|
|
||||||
"immortalis",
|
|
||||||
"immolation",
|
|
||||||
"ignivomous",
|
|
||||||
"hypocrisy",
|
|
||||||
"hyperdontia",
|
|
||||||
"howls-of-ebb",
|
|
||||||
"howls-of-ebb",
|
|
||||||
"hour-of-penance",
|
|
||||||
"horror-god",
|
|
||||||
"hooded-menace",
|
|
||||||
"hissing",
|
|
||||||
"hideous-divinity",
|
|
||||||
"heaving-earth",
|
|
||||||
"haunter",
|
|
||||||
"hail-of-bullets",
|
|
||||||
"gutvoid",
|
|
||||||
"gutter-instinct",
|
|
||||||
"grenadier",
|
|
||||||
"graveyard",
|
|
||||||
"graveside",
|
|
||||||
"grave-ritual",
|
|
||||||
"grave-miasma",
|
|
||||||
"grave-infestation",
|
|
||||||
"grave",
|
|
||||||
"gosudar",
|
|
||||||
"gorguts",
|
|
||||||
"gorephilia",
|
|
||||||
"gorefest",
|
|
||||||
"golgothan-remains",
|
|
||||||
"gold-spire",
|
|
||||||
"god-macabre",
|
|
||||||
"glacial-tomb",
|
|
||||||
"gigan",
|
|
||||||
"ghoulgotha",
|
|
||||||
"ghastly",
|
|
||||||
"gateway",
|
|
||||||
"garroted",
|
|
||||||
"galvanizer",
|
|
||||||
"funeral-leech",
|
|
||||||
"funebre",
|
|
||||||
"funebrarum",
|
|
||||||
"fuming-mouth",
|
|
||||||
"frozen-soul",
|
|
||||||
"flourishing",
|
|
||||||
"fleshgod-apocalypse",
|
|
||||||
"fleshcrawl",
|
|
||||||
"fetid",
|
|
||||||
"faceless-burial",
|
|
||||||
"exlimitir",
|
|
||||||
"execration",
|
|
||||||
"excruciate",
|
|
||||||
"evilyn",
|
|
||||||
"eucharist",
|
|
||||||
"eternal-dirge",
|
|
||||||
"epitaph",
|
|
||||||
"entombed",
|
|
||||||
"engulfed",
|
|
||||||
"encoffination",
|
|
||||||
"encenathrakh",
|
|
||||||
"emptiness",
|
|
||||||
"electrocution",
|
|
||||||
"egregore",
|
|
||||||
"edge-of-sanity",
|
|
||||||
"dream-unending",
|
|
||||||
"dragged-into-sunlight",
|
|
||||||
"dormant-ordeal",
|
|
||||||
"dominus-xul",
|
|
||||||
"domains",
|
|
||||||
"dismember",
|
|
||||||
"disma",
|
|
||||||
"diskord",
|
|
||||||
"disincarnate",
|
|
||||||
"disharmonic-orchestra",
|
|
||||||
"disembarkation",
|
|
||||||
"disciples-of-mockery",
|
|
||||||
"disastrous-murmur",
|
|
||||||
"dig-that-body-up,-it's-alive!",
|
|
||||||
"devoid-of-thought",
|
|
||||||
"deteriorate",
|
|
||||||
"desultory",
|
|
||||||
"desolation-realm",
|
|
||||||
"desecresy",
|
|
||||||
"depravity",
|
|
||||||
"demilich",
|
|
||||||
"demigod",
|
|
||||||
"demented-ted",
|
|
||||||
"deiquisitor",
|
|
||||||
"deicide",
|
|
||||||
"degial",
|
|
||||||
"defeated-sanity",
|
|
||||||
"defacement",
|
|
||||||
"deceased",
|
|
||||||
"decaying-purity",
|
|
||||||
"death",
|
|
||||||
"dead-congregation",
|
|
||||||
"darkthrone",
|
|
||||||
"cryptworm",
|
|
||||||
"cryptopsy",
|
|
||||||
"cryptic-shift",
|
|
||||||
"cryptborn",
|
|
||||||
"crypt-of-kerberos",
|
|
||||||
"cruciamentum",
|
|
||||||
"cosmovore",
|
|
||||||
"cosmic-putrefaction",
|
|
||||||
"cosmic-atrophy",
|
|
||||||
"coscradh",
|
|
||||||
"corpsessed",
|
|
||||||
"convulsing",
|
|
||||||
"convulse",
|
|
||||||
"contaminated",
|
|
||||||
"concrete-winds",
|
|
||||||
"comecon",
|
|
||||||
"coffincraft",
|
|
||||||
"coffin-texts",
|
|
||||||
"coffin-curse",
|
|
||||||
"cianide",
|
|
||||||
"chthe'ilist",
|
|
||||||
"the-chasm",
|
|
||||||
"chapel-of-disease",
|
|
||||||
"chaotian",
|
|
||||||
"chainsword",
|
|
||||||
"cerebral-rot",
|
|
||||||
"centinex",
|
|
||||||
"cenotaph",
|
|
||||||
"cemetery-filth",
|
|
||||||
"cemetary",
|
|
||||||
"carnal-tomb",
|
|
||||||
"carnage",
|
|
||||||
"carcinoma",
|
|
||||||
"carcass",
|
|
||||||
"carbonized",
|
|
||||||
"cancer",
|
|
||||||
"cambion",
|
|
||||||
"cadaveric-fumes",
|
|
||||||
"cadaver",
|
|
||||||
"burial-invocation",
|
|
||||||
"brutality",
|
|
||||||
"broken-hope",
|
|
||||||
"borgia",
|
|
||||||
"bolt-thrower",
|
|
||||||
"bog-body",
|
|
||||||
"bloodsoaked-necrovoid",
|
|
||||||
"bloodbath",
|
|
||||||
"blood-spore",
|
|
||||||
"blood-incantation",
|
|
||||||
"black-curse",
|
|
||||||
"benediction",
|
|
||||||
"behemoth",
|
|
||||||
"bedsore",
|
|
||||||
"baphomet",
|
|
||||||
"backyard-mortuary",
|
|
||||||
"azath",
|
|
||||||
"autopsy",
|
|
||||||
"autophagy",
|
|
||||||
"authorize",
|
|
||||||
"augury",
|
|
||||||
"atrocity",
|
|
||||||
"atheist",
|
|
||||||
"atemporal",
|
|
||||||
"ataraxy",
|
|
||||||
"astriferous",
|
|
||||||
"asphyx",
|
|
||||||
"appalling-spawn",
|
|
||||||
"anatomia",
|
|
||||||
"amputory",
|
|
||||||
"amorphis",
|
|
||||||
"altered-dead",
|
|
||||||
"altars-ablaze",
|
|
||||||
"altars",
|
|
||||||
"altarage",
|
|
||||||
"agony",
|
|
||||||
"afflicted",
|
|
||||||
"aeviterne",
|
|
||||||
"adversarial",
|
|
||||||
"adramelech",
|
|
||||||
"ad-vitam-infernal",
|
|
||||||
"ad-nauseam",
|
|
||||||
"acrostichon",
|
|
||||||
"acephalix",
|
|
||||||
"accidental-suicide",
|
|
||||||
"abhorrence"
|
|
||||||
],
|
|
||||||
"Classic Rock": [
|
|
||||||
"yes",
|
|
||||||
"traveling-wilburys",
|
|
||||||
"tom-petty-and-the-heartbreakers",
|
|
||||||
"tom-petty",
|
|
||||||
"rush",
|
|
||||||
"pink-floyd",
|
|
||||||
"king-crimson",
|
|
||||||
"grave",
|
|
||||||
"bruce-springsteen"
|
|
||||||
],
|
|
||||||
"Alternative": ["year-of-the-rabbit", "failure", "the-cranberries", "bob-mould"],
|
|
||||||
"Sludge Metal": [
|
|
||||||
"yautja",
|
|
||||||
"yashira",
|
|
||||||
"thou-&-the-body",
|
|
||||||
"thou-&-mizmor",
|
|
||||||
"thou-&-emma-ruth-rundle",
|
|
||||||
"thou",
|
|
||||||
"sumac",
|
|
||||||
"primitive-man",
|
|
||||||
"neurosis",
|
|
||||||
"kowloon-walled-city",
|
|
||||||
"keiji-haino-&-sumac",
|
|
||||||
"inter-arma",
|
|
||||||
"full-of-hell-&-primitive-man",
|
|
||||||
"chat-pile",
|
|
||||||
"acid-bath"
|
|
||||||
],
|
|
||||||
"Indie": [
|
|
||||||
"the-xx",
|
|
||||||
"will-sheff",
|
|
||||||
"sufjan-stevens",
|
|
||||||
"the-stone-roses",
|
|
||||||
"the-postal-service",
|
|
||||||
"p.-wolf-and-avi",
|
|
||||||
"okkervil-river",
|
|
||||||
"neutral-milk-hotel",
|
|
||||||
"the-japanese-house",
|
|
||||||
"iron-&-wine",
|
|
||||||
"the-head-and-the-heart",
|
|
||||||
"golden-shoulders",
|
|
||||||
"frightened-rabbit",
|
|
||||||
"bright-eyes",
|
|
||||||
"bon-iver",
|
|
||||||
"blind-pilot",
|
|
||||||
"big-red-machine",
|
|
||||||
"better-oblivion-community-center",
|
|
||||||
"all-time-quarterback"
|
|
||||||
],
|
|
||||||
"Indie Rock": [
|
|
||||||
"the-wytches",
|
|
||||||
"wavves-&-cloud-nothings",
|
|
||||||
"the-war-on-drugs",
|
|
||||||
"thom-yorke",
|
|
||||||
"teenage-fanclub",
|
|
||||||
"rogue-wave",
|
|
||||||
"the-replacements",
|
|
||||||
"radiohead",
|
|
||||||
"radioactivity",
|
|
||||||
"pixies",
|
|
||||||
"pedro-the-lion",
|
|
||||||
"pedro-the-lion",
|
|
||||||
"pavement",
|
|
||||||
"okkervil-river",
|
|
||||||
"nova-mob",
|
|
||||||
"no",
|
|
||||||
"the-national",
|
|
||||||
"matt-berninger",
|
|
||||||
"marked-men",
|
|
||||||
"the-kills",
|
|
||||||
"jay-farrar-and-benjamin-gibbard",
|
|
||||||
"japandroids",
|
|
||||||
"interpol",
|
|
||||||
"hop-along",
|
|
||||||
"the-halo-benders",
|
|
||||||
"frances-quinlan",
|
|
||||||
"el-vy",
|
|
||||||
"death-cab-for-cutie",
|
|
||||||
"dredg",
|
|
||||||
"doug-martsch",
|
|
||||||
"the-dismemberment-plan",
|
|
||||||
"dinosaur-jr.",
|
|
||||||
"death-from-above-1979",
|
|
||||||
"death-cab-for-cutie",
|
|
||||||
"death-cab-for-cutie",
|
|
||||||
"damien-jurado",
|
|
||||||
"cloud-nothings",
|
|
||||||
"built-to-spill",
|
|
||||||
"built-to-spill",
|
|
||||||
"boygenius",
|
|
||||||
"atoms-for-peace",
|
|
||||||
"arcade-fire"
|
|
||||||
],
|
|
||||||
"Emo": [
|
|
||||||
"worst-party-ever",
|
|
||||||
"the-wonder-years",
|
|
||||||
"turnover",
|
|
||||||
"title-fight",
|
|
||||||
"tigers-jaw",
|
|
||||||
"taking-back-sunday",
|
|
||||||
"state-lines",
|
|
||||||
"spanish-love-songs",
|
|
||||||
"sincere-engineer",
|
|
||||||
"seahaven",
|
|
||||||
"rites-of-spring",
|
|
||||||
"prince-daddy-&-the-hyena",
|
|
||||||
"pity-sex",
|
|
||||||
"pinegrove",
|
|
||||||
"oso-oso",
|
|
||||||
"the-newfound-interest-in-connecticut",
|
|
||||||
"my-chemical-romance",
|
|
||||||
"michael-cera-palin",
|
|
||||||
"macseal",
|
|
||||||
"knuckle-puck",
|
|
||||||
"joyce-manor",
|
|
||||||
"jimmy-eat-world",
|
|
||||||
"jawbreaker",
|
|
||||||
"the-hotelier",
|
|
||||||
"hot-mulligan",
|
|
||||||
"home-is-where",
|
|
||||||
"have-mercy",
|
|
||||||
"the-get-up-kids",
|
|
||||||
"free-throw",
|
|
||||||
"fiddlehead",
|
|
||||||
"fall-out-boy",
|
|
||||||
"drive-like-jehu",
|
|
||||||
"dogleg",
|
|
||||||
"charmer",
|
|
||||||
"can't-swim",
|
|
||||||
"the-brave-little-abacus",
|
|
||||||
"brand-new",
|
|
||||||
"basement",
|
|
||||||
"balance-and-composure",
|
|
||||||
"the-ataris",
|
|
||||||
"anxious",
|
|
||||||
"american-football",
|
|
||||||
"alkaline-trio"
|
|
||||||
],
|
|
||||||
"Grindcore": [
|
|
||||||
"wormrot",
|
|
||||||
"terrorizer",
|
|
||||||
"rotten-sound",
|
|
||||||
"regional-justice-center",
|
|
||||||
"pig-destroyer",
|
|
||||||
"napalm-death",
|
|
||||||
"nails",
|
|
||||||
"knelt-rote",
|
|
||||||
"full-of-hell-&-merzbow",
|
|
||||||
"full-of-hell",
|
|
||||||
"fawn-limbs",
|
|
||||||
"dephosphorus",
|
|
||||||
"dead-in-the-dirt",
|
|
||||||
"cloud-rat",
|
|
||||||
"cianide",
|
|
||||||
"caustic-wound",
|
|
||||||
"carcass",
|
|
||||||
"the-body-&-full-of-hell"
|
|
||||||
],
|
|
||||||
"Shoegaze": [
|
|
||||||
"whirr",
|
|
||||||
"the-verve",
|
|
||||||
"trauma-ray",
|
|
||||||
"teenage-wrist",
|
|
||||||
"swervedriver",
|
|
||||||
"soul-blind",
|
|
||||||
"slowdive",
|
|
||||||
"slow-crush",
|
|
||||||
"ringo-deathstarr",
|
|
||||||
"ride",
|
|
||||||
"pale-saints",
|
|
||||||
"nothing",
|
|
||||||
"narrow-head",
|
|
||||||
"my-bloody-valentine",
|
|
||||||
"m83",
|
|
||||||
"just-mustard",
|
|
||||||
"ison",
|
|
||||||
"hum",
|
|
||||||
"greet-death",
|
|
||||||
"gleemer",
|
|
||||||
"glare",
|
|
||||||
"glare",
|
|
||||||
"drop-nineteens",
|
|
||||||
"deafcult",
|
|
||||||
"corps-fleur",
|
|
||||||
"cloakroom",
|
|
||||||
"chapterhouse",
|
|
||||||
"catherine-wheel",
|
|
||||||
"black-wing",
|
|
||||||
"beach-house",
|
|
||||||
"autolux",
|
|
||||||
"asobi-seksu",
|
|
||||||
"all-under-heaven",
|
|
||||||
"all-natural-lemon-&-lime-flavors",
|
|
||||||
"alcest",
|
|
||||||
"airiel"
|
|
||||||
],
|
|
||||||
"Rock": [
|
|
||||||
"webbed-wing",
|
|
||||||
"violent-femmes",
|
|
||||||
"superheaven",
|
|
||||||
"superbloom",
|
|
||||||
"sonic-youth",
|
|
||||||
"the-smashing-pumpkins",
|
|
||||||
"sebadoh",
|
|
||||||
"oasis",
|
|
||||||
"nirvana",
|
|
||||||
"kim-gordon-&-j-mascis",
|
|
||||||
"katatonia",
|
|
||||||
"jimmy-eat-world",
|
|
||||||
"foo-fighters",
|
|
||||||
"counting-crows",
|
|
||||||
"audioslave"
|
|
||||||
],
|
|
||||||
"Progressive Black Metal": [
|
|
||||||
"waste-of-space-orchestra",
|
|
||||||
"oranssi-pazuzu",
|
|
||||||
"negură-bunget",
|
|
||||||
"ivar-bjørnson-&-einar-selvik",
|
|
||||||
"ihsahn",
|
|
||||||
"enslaved"
|
|
||||||
],
|
|
||||||
"Progressive Metal": [
|
|
||||||
"virus",
|
|
||||||
"unexpect",
|
|
||||||
"ulver",
|
|
||||||
"sunn-o)))-&-ulver",
|
|
||||||
"sculptured",
|
|
||||||
"opeth",
|
|
||||||
"maudlin-of-the-well",
|
|
||||||
"mastodon",
|
|
||||||
"disillusion",
|
|
||||||
"dan-swanö",
|
|
||||||
"cynic",
|
|
||||||
"cult-of-luna",
|
|
||||||
"anathema"
|
|
||||||
],
|
|
||||||
"Progressive Rock": [
|
|
||||||
"unicorn",
|
|
||||||
"steven-wilson",
|
|
||||||
"riverside",
|
|
||||||
"porcupine-tree",
|
|
||||||
"nightingale",
|
|
||||||
"the-mars-volta",
|
|
||||||
"lunatic-soul"
|
|
||||||
],
|
|
||||||
"Post Rock": [
|
|
||||||
"unconditional-arms",
|
|
||||||
"this-will-destroy-you",
|
|
||||||
"sigur-rós",
|
|
||||||
"red-sparowes",
|
|
||||||
"of-the-vine",
|
|
||||||
"mono",
|
|
||||||
"mogwai",
|
|
||||||
"long-distance-calling-&-leech",
|
|
||||||
"long-distance-calling",
|
|
||||||
"if-these-trees-could-talk",
|
|
||||||
"godspeed-you!-black-emperor",
|
|
||||||
"god-is-an-astronaut",
|
|
||||||
"explosions-in-the-sky",
|
|
||||||
"caspian"
|
|
||||||
],
|
|
||||||
"Hip-Hop": [
|
|
||||||
"the-uncluded",
|
|
||||||
"run-the-jewels",
|
|
||||||
"pusha-t",
|
|
||||||
"mckinley-dixon",
|
|
||||||
"malibu-ken",
|
|
||||||
"kendrick-lamar",
|
|
||||||
"injury-reserve",
|
|
||||||
"hail-mary-mallon",
|
|
||||||
"el-p",
|
|
||||||
"death-grips",
|
|
||||||
"chance-the-rapper",
|
|
||||||
"aesop-rock"
|
|
||||||
],
|
|
||||||
"Indie Pop": ["two-door-cinema-club", "the-smiths"],
|
|
||||||
"Soundtrack": ["trent-reznor-&-atticus-ross", "mogwai"],
|
|
||||||
"Country": [
|
|
||||||
"trampled-by-turtles",
|
|
||||||
"trampled-by-turtles",
|
|
||||||
"sunday-valley",
|
|
||||||
"sturgill-simpson",
|
|
||||||
"johnny-cash",
|
|
||||||
"hiss-golden-messenger"
|
|
||||||
],
|
|
||||||
"Post Hardcore": [
|
|
||||||
"touché-amoré",
|
|
||||||
"thrice",
|
|
||||||
"self-defense-family",
|
|
||||||
"seahaven",
|
|
||||||
"rival-schools",
|
|
||||||
"quicksand",
|
|
||||||
"pitchfork",
|
|
||||||
"modern-color",
|
|
||||||
"militarie-gun",
|
|
||||||
"la-dispute",
|
|
||||||
"jawbox",
|
|
||||||
"hot-snakes",
|
|
||||||
"hell-is-for-heroes",
|
|
||||||
"gospel",
|
|
||||||
"fleshwater",
|
|
||||||
"envy",
|
|
||||||
"drug-church",
|
|
||||||
"drive-like-jehu",
|
|
||||||
"birds-in-row",
|
|
||||||
"big-garden",
|
|
||||||
"at-the-drive-in"
|
|
||||||
],
|
|
||||||
"Singer/Songwriter": [
|
|
||||||
"tom-waits",
|
|
||||||
"sun-kil-moon",
|
|
||||||
"soccer-mommy",
|
|
||||||
"sharon-van-etten",
|
|
||||||
"ryan-adams",
|
|
||||||
"phoebe-bridgers",
|
|
||||||
"kermit-obert",
|
|
||||||
"j-mascis",
|
|
||||||
"giles-corey",
|
|
||||||
"elliott-smith",
|
|
||||||
"dan-campbell",
|
|
||||||
"damien-jurado",
|
|
||||||
"city-and-colour",
|
|
||||||
"bob-dylan",
|
|
||||||
"ben-gibbard"
|
|
||||||
],
|
|
||||||
"Grind": ["terrorizer"],
|
|
||||||
"Pop": ["taylor-swift"],
|
|
||||||
"Post Punk": [
|
|
||||||
"talking-heads",
|
|
||||||
"soft-kill",
|
|
||||||
"shiner",
|
|
||||||
"savages",
|
|
||||||
"revenge-sf",
|
|
||||||
"the-psychedelic-furs",
|
|
||||||
"protomartyr",
|
|
||||||
"peter-&-the-test-tube-babies",
|
|
||||||
"new-order",
|
|
||||||
"modern-english",
|
|
||||||
"mission-of-burma",
|
|
||||||
"joy-division",
|
|
||||||
"the-jesus-and-mary-chain",
|
|
||||||
"idles",
|
|
||||||
"have-a-nice-life",
|
|
||||||
"hands-of-anne-boleyn",
|
|
||||||
"echo-&-the-bunnymen",
|
|
||||||
"damaged-bug",
|
|
||||||
"the-cure",
|
|
||||||
"cold-showers",
|
|
||||||
"the-chameleons",
|
|
||||||
"centaur"
|
|
||||||
],
|
|
||||||
"Jazz": ["sword-&-sandals", "miles-davis", "mahavishnu-orchestra", "bohren-&-der-club-of-gore"],
|
|
||||||
"Screamo": ["state-faults", "senza", "ostraca", "loma-prieta", "frail-body"],
|
|
||||||
"Ambient": ["stars-of-the-lid", "eluvium", "the-dead-texan"],
|
|
||||||
"Post Metal": [
|
|
||||||
"spotlights",
|
|
||||||
"russian-circles",
|
|
||||||
"mouth-of-the-architect",
|
|
||||||
"mono",
|
|
||||||
"lantlôs",
|
|
||||||
"jesu",
|
|
||||||
"isis",
|
|
||||||
"holy-fawn",
|
|
||||||
"envy",
|
|
||||||
"cult-of-luna"
|
|
||||||
],
|
|
||||||
"Noise Rock": ["sonic-youth", "a-place-to-bury-strangers", "pink-&-brown", "metz", "the-drums"],
|
|
||||||
"Folk": ["simon-&-garfunkel"],
|
|
||||||
"Thrash Metal": ["sadus", "kreator"],
|
|
||||||
"Hardcore": ["refused"],
|
|
||||||
"Metalcore": [
|
|
||||||
"portrayal-of-guilt",
|
|
||||||
"loathe",
|
|
||||||
"hacksaw-to-the-throat",
|
|
||||||
"glassing",
|
|
||||||
"fuming-mouth",
|
|
||||||
"converge-&-chelsea-wolfe",
|
|
||||||
"converge",
|
|
||||||
"chat-pile",
|
|
||||||
"cave-in"
|
|
||||||
],
|
|
||||||
"Psychedelic Rock": ["osees", "john-dwyer", "bent-arcana"],
|
|
||||||
"Industrial": ["nine-inch-nails"],
|
|
||||||
"Synthpop": ["m83"],
|
|
||||||
"Electronic": ["lcd-soundsystem", "jesu-/-sun-kil-moon", "jamie-xx", "depeche-mode"],
|
|
||||||
"Doom Metal": ["katatonia"],
|
|
||||||
"Industrial Metal": ["godflesh"],
|
|
||||||
"Alternative Metal": ["deftones"],
|
|
||||||
"Melodic Death Metal": ["dark-tranquillity", "carcass", "at-the-gates", "arsis"]
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"i.rXXXdmUa6Nme-1689970612847": {
|
|
||||||
"name": "Sacrificial Blood Oath In The Temple Of K'zadu",
|
|
||||||
"artist": "Gateway",
|
|
||||||
"album": "Galgendood",
|
|
||||||
"art": "https://store-033.blobstore.apple.com/sq-mq-us-033-000002/18/f1/a3/18f1a37a-8c9a-169a-5458-464aea20ce05/image?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20230721T202228Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Credential=MKIAU0HKO2RBEAT0UMZS%2F20230721%2Fstore-033%2Fs3%2Faws4_request&X-Amz-Signature=85790600221880597074559ed3674564f17ca3df6634d6fa15496baf7aca5d56",
|
|
||||||
"url": "https://rateyourmusic.com/search?searchtype=l&searchterm=Galgendood%20Gateway",
|
|
||||||
"id": "i.rXXXdmUa6Nme",
|
|
||||||
"playTime": 1689970612847,
|
|
||||||
"duration": 338808
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,124 +1,8 @@
|
||||||
const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3')
|
const { AssetCache } = require('@11ty/eleventy-fetch')
|
||||||
const _ = require('lodash')
|
const { aliasArtist, sanitizeMedia, sortByPlays } = require('../utils/media')
|
||||||
const artistGenres = require('./json/artist-genres.json')
|
|
||||||
const mockedMusic = require('./json/mocks/music.json')
|
|
||||||
const { getReadableData } = require('../utils/aws')
|
|
||||||
const { getKeyByValue } = require('../utils/arrays')
|
|
||||||
const { aliasArtist, sanitizeMedia } = require('../utils/media')
|
|
||||||
const { titleCase } = require('../utils/grammar')
|
const { titleCase } = require('../utils/grammar')
|
||||||
|
|
||||||
const getTracksOneHour = (tracks) => {
|
|
||||||
const TIMER_CEILING = 3600000 // 1 hour
|
|
||||||
const tracksOneHour = []
|
|
||||||
let trackIndex = 0
|
|
||||||
let trackTimer = 0
|
|
||||||
|
|
||||||
while (trackTimer < TIMER_CEILING) {
|
|
||||||
if (!tracks[trackIndex]) return tracksOneHour
|
|
||||||
trackTimer = trackTimer + parseInt(tracks[trackIndex].duration)
|
|
||||||
tracksOneHour.push(tracks[trackIndex])
|
|
||||||
trackIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracksOneHour
|
|
||||||
}
|
|
||||||
|
|
||||||
const diffTracks = (cache, tracks) => {
|
|
||||||
const trackCompareSet = Object.values(tracks)
|
|
||||||
const cacheCompareSet = _.orderBy(Object.values(cache), ['time'], ['desc'])
|
|
||||||
const diffedTracks = {}
|
|
||||||
const cacheCompareOneHour = getTracksOneHour(cacheCompareSet)
|
|
||||||
const comparedTracks = _.differenceWith(trackCompareSet, cacheCompareOneHour, (a, b) =>
|
|
||||||
_.isEqual(a.id, b.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
for (let i = 0; i < comparedTracks.length; i++)
|
|
||||||
diffedTracks[`${comparedTracks[i]?.id}-${comparedTracks[i].playTime}`] = comparedTracks[i]
|
|
||||||
|
|
||||||
return diffedTracks
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatTracks = (tracks) => {
|
|
||||||
let formattedTracks = {}
|
|
||||||
let time = new Date().getTime()
|
|
||||||
|
|
||||||
Object.values(tracks).forEach((track) => {
|
|
||||||
const artistFormatted = titleCase(aliasArtist(track.attributes['artistName']))
|
|
||||||
const albumFormatted = titleCase(sanitizeMedia(track.attributes['albumName']))
|
|
||||||
const trackFormatted = sanitizeMedia(track.attributes['name'])
|
|
||||||
formattedTracks[`${track.id}-${time}`] = {
|
|
||||||
name: trackFormatted,
|
|
||||||
artist: artistFormatted,
|
|
||||||
album: albumFormatted,
|
|
||||||
art: track.attributes.artwork.url.replace('{w}', '300').replace('{h}', '300'),
|
|
||||||
url:
|
|
||||||
track['relationships'] && track['relationships'].albums.data.length > 0
|
|
||||||
? `https://song.link/${track['relationships'].albums.data.pop().attributes.url}`
|
|
||||||
: `https://rateyourmusic.com/search?searchtype=l&searchterm=${encodeURI(
|
|
||||||
albumFormatted
|
|
||||||
)}%20${encodeURI(artistFormatted)}`,
|
|
||||||
id: track.id,
|
|
||||||
playTime: time - parseInt(track.attributes['durationInMillis']),
|
|
||||||
duration: parseInt(track.attributes['durationInMillis']),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return formattedTracks
|
|
||||||
}
|
|
||||||
|
|
||||||
const deriveCharts = (tracks) => {
|
|
||||||
const charts = {
|
|
||||||
artists: {},
|
|
||||||
albums: {},
|
|
||||||
}
|
|
||||||
const tracksForLastWeek = Object.values(tracks).filter((track) => {
|
|
||||||
const currentDate = new Date()
|
|
||||||
const currentDateTime = new Date().getTime()
|
|
||||||
const lastWeek = new Date(currentDate.setDate(currentDate.getDate() - 7))
|
|
||||||
const lastWeekDateTime = lastWeek.getTime()
|
|
||||||
const trackDateTime = new Date(track.playTime).getTime()
|
|
||||||
return trackDateTime <= currentDateTime && trackDateTime > lastWeekDateTime
|
|
||||||
})
|
|
||||||
|
|
||||||
tracksForLastWeek.forEach((track) => {
|
|
||||||
if (!charts.artists[track.artist]) {
|
|
||||||
charts.artists[track.artist] = {
|
|
||||||
artist: track.artist,
|
|
||||||
genre: getKeyByValue(artistGenres, track.artist.replace(/\s+/g, '-').toLowerCase()),
|
|
||||||
url: `https://rateyourmusic.com/search?searchterm=${encodeURI(track.artist)}`,
|
|
||||||
plays: 1,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
charts.artists[track.artist].plays++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!charts.albums[track.album]) {
|
|
||||||
charts.albums[track.album] = {
|
|
||||||
name: track.album,
|
|
||||||
artist: track.artist,
|
|
||||||
art: track.art,
|
|
||||||
url: track.url,
|
|
||||||
plays: 1,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
charts.albums[track.album].plays++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return charts
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = async function () {
|
module.exports = async function () {
|
||||||
const client = new S3Client({
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: process.env.ACCESS_KEY_WASABI,
|
|
||||||
secretAccessKey: process.env.SECRET_KEY_WASABI,
|
|
||||||
},
|
|
||||||
endpoint: {
|
|
||||||
url: 'https://s3.us-west-1.wasabisys.com',
|
|
||||||
},
|
|
||||||
region: 'us-west-1',
|
|
||||||
})
|
|
||||||
const WASABI_BUCKET = process.env.BUCKET_WASABI
|
|
||||||
const APPLE_BEARER = process.env.API_BEARER_APPLE_MUSIC
|
const APPLE_BEARER = process.env.API_BEARER_APPLE_MUSIC
|
||||||
const APPLE_MUSIC_TOKEN = process.env.API_TOKEN_APPLE_MUSIC
|
const APPLE_MUSIC_TOKEN = process.env.API_TOKEN_APPLE_MUSIC
|
||||||
const APPLE_TOKEN_RESPONSE = await fetch(process.env.APPLE_RENEW_TOKEN_URL, {
|
const APPLE_TOKEN_RESPONSE = await fetch(process.env.APPLE_RENEW_TOKEN_URL, {
|
||||||
|
@ -133,15 +17,21 @@ module.exports = async function () {
|
||||||
.then((data) => data.json())
|
.then((data) => data.json())
|
||||||
.catch()
|
.catch()
|
||||||
const APPLE_TOKEN = APPLE_TOKEN_RESPONSE['music-token']
|
const APPLE_TOKEN = APPLE_TOKEN_RESPONSE['music-token']
|
||||||
|
const asset = new AssetCache('recent_tracks_data')
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
const TIMER_CEILING = 3600000 // 1 hour
|
const PAGES = 10
|
||||||
let charts
|
const charts = {
|
||||||
|
artists: {},
|
||||||
|
albums: {},
|
||||||
|
tracks: {},
|
||||||
|
}
|
||||||
let CURRENT_PAGE = 0
|
let CURRENT_PAGE = 0
|
||||||
let trackTimer = 0
|
|
||||||
let res = []
|
let res = []
|
||||||
let cachedTracks = mockedMusic
|
let hasNextPage = true
|
||||||
|
|
||||||
while (trackTimer < TIMER_CEILING) {
|
if (asset.isCacheValid('1h')) return await asset.getCachedValue()
|
||||||
|
|
||||||
|
while (CURRENT_PAGE < PAGES && hasNextPage) {
|
||||||
const URL = `https://api.music.apple.com/v1/me/recent/played/tracks?limit=${PAGE_SIZE}&offset=${
|
const URL = `https://api.music.apple.com/v1/me/recent/played/tracks?limit=${PAGE_SIZE}&offset=${
|
||||||
PAGE_SIZE * CURRENT_PAGE
|
PAGE_SIZE * CURRENT_PAGE
|
||||||
}&include[songs]=albums&extend=artistUrl`
|
}&include[songs]=albums&extend=artistUrl`
|
||||||
|
@ -154,45 +44,54 @@ module.exports = async function () {
|
||||||
})
|
})
|
||||||
.then((data) => data.json())
|
.then((data) => data.json())
|
||||||
.catch()
|
.catch()
|
||||||
|
if (!tracks.next) hasNextPage = false
|
||||||
tracks.data.forEach((track) => {
|
if (tracks.data.length) res = [...res, ...tracks.data]
|
||||||
trackTimer = trackTimer + parseInt(track.attributes['durationInMillis'])
|
|
||||||
if (trackTimer >= TIMER_CEILING) return
|
|
||||||
res.push(track)
|
|
||||||
})
|
|
||||||
CURRENT_PAGE++
|
CURRENT_PAGE++
|
||||||
}
|
}
|
||||||
|
res.forEach((track) => {
|
||||||
|
const formattedArtist = titleCase(aliasArtist(track.attributes['artistName']))
|
||||||
|
const formattedAlbum = titleCase(sanitizeMedia(track.attributes['albumName']))
|
||||||
|
const formattedTrack = sanitizeMedia(track.attributes['name'])
|
||||||
|
|
||||||
if (process.env.ELEVENTY_PRODUCTION === 'true') {
|
if (!charts.artists[formattedArtist]) {
|
||||||
const cachedTracksOutput = await client.send(
|
charts.artists[formattedArtist] = {
|
||||||
new GetObjectCommand({
|
artist: formattedArtist,
|
||||||
Bucket: WASABI_BUCKET,
|
url: `https://rateyourmusic.com/search?searchterm=${encodeURI(formattedArtist)}`,
|
||||||
Key: 'music.json',
|
plays: 1,
|
||||||
})
|
}
|
||||||
)
|
} else {
|
||||||
const cachedTracksData = getReadableData(cachedTracksOutput.Body)
|
charts.artists[formattedArtist].plays++
|
||||||
cachedTracks = await cachedTracksData.then((tracks) => JSON.parse(tracks)).catch()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const diffedTracks = diffTracks(cachedTracks, formatTracks(res))
|
if (!charts.albums[formattedAlbum]) {
|
||||||
const updatedCache = {
|
charts.albums[formattedAlbum] = {
|
||||||
...cachedTracks,
|
name: formattedAlbum,
|
||||||
...diffedTracks,
|
artist: formattedArtist,
|
||||||
}
|
art: track.attributes.artwork.url.replace('{w}', '300').replace('{h}', '300'),
|
||||||
|
url: track['relationships']
|
||||||
charts = deriveCharts(updatedCache)
|
? `https://song.link/${track['relationships'].albums.data.pop().attributes.url}`
|
||||||
charts.artists = _.orderBy(Object.values(charts.artists), ['plays'], ['desc']).splice(0, 8)
|
: `https://rateyourmusic.com/search?searchtype=l&searchterm=${encodeURI(
|
||||||
charts.albums = _.orderBy(Object.values(charts.albums), ['plays'], ['desc']).splice(0, 8)
|
formattedAlbum
|
||||||
|
)}%20${encodeURI(formattedArtist)}`,
|
||||||
if (!_.isEmpty(diffedTracks) && process.env.ELEVENTY_PRODUCTION === 'true') {
|
plays: 1,
|
||||||
await client.send(
|
}
|
||||||
new PutObjectCommand({
|
} else {
|
||||||
Bucket: WASABI_BUCKET,
|
charts.albums[formattedAlbum].plays++
|
||||||
Key: 'music.json',
|
}
|
||||||
Body: JSON.stringify(updatedCache),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!charts.tracks[formattedTrack]) {
|
||||||
|
charts.tracks[formattedTrack] = {
|
||||||
|
name: formattedTrack,
|
||||||
|
artist: formattedArtist,
|
||||||
|
plays: 1,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
charts.tracks[formattedTrack].plays++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
charts.artists = sortByPlays(charts.artists).splice(0, 8)
|
||||||
|
charts.albums = sortByPlays(charts.albums).splice(0, 8)
|
||||||
|
charts.tracks = sortByPlays(charts.tracks).splice(0, 5)
|
||||||
|
await asset.save(charts, 'json')
|
||||||
return charts
|
return charts
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<div class="absolute left-1 bottom-2 drop-shadow-md">
|
<div class="absolute left-1 bottom-2 drop-shadow-md">
|
||||||
<div class="px-1 text-xs font-bold text-white line-clamp-2">{{ artist.artist }}</div>
|
<div class="px-1 text-xs font-bold text-white line-clamp-2">{{ artist.artist }}</div>
|
||||||
<div class="px-1 text-xs text-white">
|
<div class="px-1 text-xs text-white">
|
||||||
{{ artist.genre }}
|
{{ artist.plays }} plays
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{%- capture artistImg %}{{ artist.artist | artist }}{% endcapture -%}
|
{%- capture artistImg %}{{ artist.artist | artist }}{% endcapture -%}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
getKeyByValue: (object, value) => Object.keys(object).find((key) => object[key].includes(value)),
|
|
||||||
}
|
|
|
@ -29,4 +29,5 @@ module.exports = {
|
||||||
/-\s*(?:single|ep)\s*|(\[|\()(Deluxe Edition|Special Edition|Remastered|Full Dynamic Range Edition|Anniversary Edition)(\]|\))/gi
|
/-\s*(?:single|ep)\s*|(\[|\()(Deluxe Edition|Special Edition|Remastered|Full Dynamic Range Edition|Anniversary Edition)(\]|\))/gi
|
||||||
return media.replace(denyList, '').trim()
|
return media.replace(denyList, '').trim()
|
||||||
},
|
},
|
||||||
|
sortByPlays: (array) => Object.values(array).sort((a, b) => b.plays - a.plays),
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue