This repository has been archived on 2025-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
coryd.dev-astro/workers/artist-import/index.js

184 lines
6 KiB
JavaScript

import slugify from "slugify";
import countries from "i18n-iso-countries";
countries.registerLocale(require("i18n-iso-countries/langs/en.json"));
function sanitizeMediaString(str) {
const sanitizedString = str
.normalize("NFD")
.replace(/[\u0300-\u036f\u2010\-\.\?\(\)\[\]\{\}]/g, "")
.replace(/\.{3}/g, "");
return slugify(sanitizedString, {
replacement: "-",
remove: /[#,&,+()$~%.'\":*?<>{}]/g,
lower: true,
});
}
export default {
async fetch(request, env) {
const directusUrl = env.DIRECTUS_URL;
const directusToken = env.DIRECTUS_API_TOKEN;
const artistImportToken = env.ARTIST_IMPORT_TOKEN;
const artistFlowID = env.ARTIST_FLOW_ID;
const albumFlowID = env.ALBUM_FLOW_ID;
const placeholderImageId = "4cef75db-831f-4f5d-9333-79eaa5bb55ee";
const requestUrl = new URL(request["url"]);
const providedToken = requestUrl.searchParams.get("token");
if (!providedToken || providedToken !== artistImportToken) return new Response("Unauthorized", { status: 401 });
async function saveToDirectus(endpoint, payload) {
const response = await fetch(`${directusUrl}/items/${endpoint}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${directusToken}`,
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!response.ok) {
throw new Error(
data["errors"]
? data["errors"][0]["message"]
: "Failed to save to Directus"
);
}
return data["data"];
}
async function findGenreIdByName(genreName) {
try {
const response = await fetch(
`${directusUrl}/items/genres?filter[name][_eq]=${encodeURIComponent(
genreName.toLowerCase()
)}`,
{ headers: { Authorization: `Bearer ${directusToken}` } }
);
const data = await response.json();
return data["data"].length > 0 ? data["data"][0]["id"] : null;
} catch (error) {
console.error("Error fetching genre ID:", error["message"]);
return null;
}
}
const artistId = requestUrl.searchParams.get("artist_id");
if (!artistId)
return new Response("artist_id parameter is required", { status: 400 });
let artistData;
try {
const artistResponse = await fetch(
`${directusUrl}/flows/trigger/${artistFlowID}?artist_id=${artistId}&import_token=${artistImportToken}`,
{ headers: { Authorization: `Bearer ${directusToken}` } }
);
artistData = await artistResponse.json();
artistData =
artistData["get_artist_data"]["data"]["MediaContainer"]["Metadata"][0];
} catch (error) {
console.error(
"Error fetching artist data from Directus flow:",
error["message"]
);
return new Response("Error fetching artist data", { status: 500 });
}
const artistName = artistData["title"] || "";
const artistKey = sanitizeMediaString(artistName);
const countryName = artistData["Country"]
? artistData["Country"][0]?.["tag"]
: "";
const countryIsoCode = countries.getAlpha2Code(countryName, "en") || "";
const slug = `/music/artists/${artistKey}-${countryName.toLowerCase()}`;
const description = artistData["summary"] || "";
const mbid = artistData["Guid"]?.[0]?.["id"]?.replace("mbid://", "") || "";
const genreNames = artistData["Genre"]
? artistData["Genre"].map((g) => g["tag"].toLowerCase())
: [];
let genreId = null;
for (const genreName of genreNames) {
genreId = await findGenreIdByName(genreName);
if (genreId) break;
}
const artistPayload = {
name: artistName,
name_string: artistName,
slug: slug,
description: description,
mbid: mbid,
tentative: true,
genres: genreId,
country: countryIsoCode,
art: placeholderImageId,
};
let insertedArtist;
try {
insertedArtist = await saveToDirectus("artists", artistPayload);
} catch (error) {
console.error("Error saving artist:", error["message"]);
return new Response("Error saving artist", { status: 500 });
}
let albumData;
try {
const albumResponse = await fetch(
`${directusUrl}/flows/trigger/${albumFlowID}?artist_id=${artistId}&import_token=${artistImportToken}`,
{ headers: { Authorization: `Bearer ${directusToken}` } }
);
albumData = await albumResponse.json();
albumData =
albumData["get_album_data"]["data"]["MediaContainer"]["Metadata"];
} catch (error) {
console.error(
"Error fetching album data from Directus flow:",
error["message"]
);
return new Response("Error fetching album data", { status: 500 });
}
for (const album of albumData) {
const albumName = album["title"] || "";
const albumKey = `${artistKey}-${sanitizeMediaString(albumName)}`;
const albumSlug = `/music/albums/${albumKey}`;
const albumDescription = album["summary"] || "";
const albumReleaseDate = album["originallyAvailableAt"] || "";
const albumReleaseYear = albumReleaseDate
? new Date(albumReleaseDate).getFullYear()
: null;
const albumGenres = album["Genre"]
? album["Genre"].map((g) => g["tag"])
: [];
const albumMbid =
album["Guid"]?.[0]?.["id"]?.replace("mbid://", "") || null;
const albumPayload = {
name: albumName,
key: albumKey,
slug: albumSlug,
mbid: albumMbid,
description: albumDescription,
release_year: albumReleaseYear,
artist: insertedArtist["id"],
artist_name: artistName,
genres: albumGenres,
art: placeholderImageId,
tentative: true,
};
try {
await saveToDirectus("albums", albumPayload);
} catch (error) {
console.error("Error saving album:", error["message"]);
}
}
return new Response("Artist and albums synced successfully", {
status: 200,
});
},
};