diff --git a/src/publishing/modrinth/modrinth-publisher.ts b/src/publishing/modrinth/modrinth-publisher.ts index b570890..3c00635 100644 --- a/src/publishing/modrinth/modrinth-publisher.ts +++ b/src/publishing/modrinth/modrinth-publisher.ts @@ -22,7 +22,7 @@ export default class ModrinthPublisher extends ModPublisher { const projects = (await Promise.all(dependencies .filter((x, _, self) => (x.kind !== DependencyKind.Suggests && x.kind !== DependencyKind.Includes) || !self.find(y => y.id === x.id && y.kind !== DependencyKind.Suggests && y.kind !== DependencyKind.Includes)) .map(async x => ({ - project_id: (await getProject(x.getProjectSlug(this.target))).id, + project_id: (await getProject(x.getProjectSlug(this.target)))?.id, dependency_type: modrinthDependencyKinds.get(x.kind) })))) .filter(x => x.project_id && x.dependency_type); diff --git a/src/utils/curseforge-utils.ts b/src/utils/curseforge-utils.ts index cfeb1cb..b2c76bb 100644 --- a/src/utils/curseforge-utils.ts +++ b/src/utils/curseforge-utils.ts @@ -33,6 +33,25 @@ class CurseForgeUploadError extends SoftError { } } +async function fetchJsonArray(url: string): Promise { + const response = await fetch(url); + if (!response.ok) { + const isServerError = response.status >= 500; + throw new SoftError(isServerError, `${response.status} (${response.statusText})`); + } + + let array: T[]; + try { + array = await response.json(); + } catch { + array = null; + } + + if (!Array.isArray(array)) { + throw new SoftError(true, "CurseForge sometimes returns Cloudflare's HTML page instead of its API response. Yeah, I know, very cool. Just wait 15-20 minutes, then try re-running this action, and you should be fine."); + } + return array; +} let cachedCurseForgeVersions: CurseForgeVersions = null; async function getCurseForgeVersions(token: string): Promise { @@ -43,12 +62,12 @@ async function getCurseForgeVersions(token: string): Promise } async function loadCurseForgeVersions(token: string): Promise { - const versionTypes = <{ id: number, slug: string }[]>await (await fetch(`${baseUrl}/game/version-types?token=${token}`)).json(); + const versionTypes = await fetchJsonArray<{ id: number, slug: string }>(`${baseUrl}/game/version-types?token=${token}`); const javaVersionTypes = versionTypes.filter(x => x.slug.startsWith("java")).map(x => x.id); const minecraftVersionTypes = versionTypes.filter(x => x.slug.startsWith("minecraft")).map(x => x.id); const loaderVersionTypes = versionTypes.filter(x => x.slug.startsWith("modloader")).map(x => x.id); - const versions = await (await fetch(`${baseUrl}/game/versions?token=${token}`)).json(); + const versions = await fetchJsonArray(`${baseUrl}/game/versions?token=${token}`); return versions.reduce((container, version) => { if (javaVersionTypes.includes(version.gameVersionTypeID)) { container.java.push(version);