11import type { IRepository } from "./IRepository" ;
2- import { RawModRepoRelease , ModRepositoryName , ModLoader , ModRepoMetadata , MCVersion , ModLoaderUtil } from ".." ;
2+ import { RawModRepoRelease , ModRepositoryName , ModLoader , ModRepoMetadata , MCVersion } from ".." ;
33import { cf_fingerprint } from 'cf-fingerprint' ;
44import { logger } from "../logger" ;
55
6+ // Translation map for Curseforge modloader IDs
7+ // Source: https://docs.curseforge.com/rest-api/#tocS_ModLoaderType
8+ const LOADERS : { [ key : number ] : ModLoader } = {
9+ 1 : ModLoader . FORGE ,
10+ 4 : ModLoader . FABRIC ,
11+ 5 : ModLoader . QUILT ,
12+ 6 : ModLoader . NEOFORGE
13+ }
14+
615/**
716 * Implementation of IRepository for the CurseForge repository.
817 */
@@ -21,37 +30,22 @@ export class CurseForgeRepository implements IRepository {
2130 }
2231
2332 async getModReleases ( modId : string ) : Promise < RawModRepoRelease [ ] > {
24- type Data = {
25- data : {
26- displayName : string ;
27- gameVersions : string [ ] ;
28- downloadUrl : string ;
29- } [ ] ;
30- } ;
33+ const modInfo = await this . fetchModInfo ( Number ( modId ) ) ;
34+ if ( ! modInfo || ! modInfo . latestFilesIndexes ) return [ ] ;
3135
32- const filesResp = await this . fetchClient ( `${ CurseForgeRepository . BASE_URL } /mods/${ modId } /files` ) ;
33- if ( ! filesResp . ok ) throw new Error ( "Could not fetch files from CurseForge" ) ;
34- const jsonResp : Data = await filesResp . json ( ) ;
35-
36- const releases : RawModRepoRelease [ ] = jsonResp . data . map ( file => {
36+ const releases : RawModRepoRelease [ ] = modInfo . latestFilesIndexes . map ( file => {
3737 const mcVersions : Set < MCVersion > = new Set ( ) ;
3838 const loaders : Set < ModLoader > = new Set ( ) ;
39- for ( let gameVersion of file . gameVersions || [ ] ) {
40- gameVersion = gameVersion . toLowerCase ( ) ;
41- if ( / ^ [ a - z ] + $ / . test ( gameVersion ) ) {
42- loaders . add ( ModLoaderUtil . from ( gameVersion ) ) ;
43- } else {
44- mcVersions . add ( gameVersion ) ;
45- }
46- }
47-
48- return ( {
39+ if ( file . gameVersion ) mcVersions . add ( file . gameVersion ) ;
40+ if ( file . modLoader && LOADERS [ file . modLoader ] ) loaders . add ( LOADERS [ file . modLoader ] ) ;
41+
42+ return {
4943 mcVersions : mcVersions ,
50- modVersion : file . displayName ,
44+ modVersion : file . filename ,
5145 repository : ModRepositoryName . CURSEFORGE ,
5246 loaders : loaders ,
53- downloadUrl : file . downloadUrl || '' ,
54- } )
47+ downloadUrl : '' , // No downloadUrl in latestFilesIndexes, could be fetched if needed
48+ } ;
5549 } ) ;
5650
5751 return releases ;
@@ -95,6 +89,12 @@ export class CurseForgeRepository implements IRepository {
9589 } ) ) ;
9690 }
9791
92+ private async fetchModInfo ( modId : number ) : Promise < ModInfoData | null > {
93+ const modResp = await this . fetchClient ( `${ CurseForgeRepository . BASE_URL } /mods/${ modId } ` ) ;
94+ if ( ! modResp . ok ) return null ;
95+ return ( await modResp . json ( ) ) . data as ModInfoData ;
96+ }
97+
9898 async getByDataHash ( modData : Uint8Array ) : Promise < ModRepoMetadata | null > {
9999 // Calculate CurseForge fingerprint
100100 const start = Date . now ( ) ;
@@ -124,9 +124,8 @@ export class CurseForgeRepository implements IRepository {
124124 const modId : number = fileMatch . file . modId ;
125125
126126 // Get mod info using the mod ID
127- const modResp = await this . fetchClient ( `${ CurseForgeRepository . BASE_URL } /mods/${ modId } ` ) ;
128- if ( ! modResp . ok ) return null ;
129- const modInfo = ( await modResp . json ( ) ) . data ;
127+ const modInfo = await this . fetchModInfo ( modId ) ;
128+ if ( ! modInfo ) return null ;
130129
131130 return {
132131 id : modId . toString ( ) ,
@@ -142,3 +141,21 @@ export class CurseForgeRepository implements IRepository {
142141 return ModRepositoryName . CURSEFORGE ;
143142 }
144143}
144+
145+ type ModInfoData = {
146+ id : number ;
147+ name : string ;
148+ links : {
149+ websiteUrl : string ;
150+ } ;
151+ logo ?: {
152+ url ?: string ;
153+ } ;
154+ downloadCount ?: number ;
155+ latestFilesIndexes ?: {
156+ gameVersion : string ;
157+ fileId : number ;
158+ filename : string ;
159+ modLoader ?: number ;
160+ } [ ] ;
161+ } ;
0 commit comments