99import java .net .URI ;
1010import java .nio .file .Files ;
1111import java .nio .file .Path ;
12+ import java .nio .file .Paths ;
1213import java .util .ArrayList ;
1314import java .util .Collections ;
1415import java .util .HashSet ;
@@ -46,10 +47,17 @@ public class ModrinthCommand implements Callable<Integer> {
4647
4748 @ Option (
4849 names = "--projects" ,
49- description = "Project ID or Slug. Prefix with loader: e.g. fabric:project-id" ,
50+ description = "Project ID or Slug. Can be <project ID>|<slug>,"
51+ + " <loader>:<project ID>|<slug>,"
52+ + " <loader>:<project ID>|<slug>:<version ID|version number|release type>,"
53+ + " '@'<filename with ref per line (supports # comments)>"
54+ + "%nExamples: fabric-api, fabric:fabric-api, fabric:fabric-api:0.76.1+1.19.2,"
55+ + " datapack:terralith, @/path/to/modrinth-mods.txt"
56+ + "%nValid release types: release, beta, alpha"
57+ + "%nValid loaders: fabric, forge, paper, datapack, etc." ,
5058 split = SPLIT_COMMA_NL ,
5159 splitSynopsisLabel = SPLIT_SYNOPSIS_COMMA_NL ,
52- paramLabel = "[loader:]id|slug"
60+ paramLabel = "[loader:]id|slug[:version] "
5361 )
5462 List <String > projects ;
5563
@@ -124,7 +132,7 @@ private List<Path> processProjects(List<String> projects) {
124132 //noinspection DataFlowIssue since it thinks block() may return null
125133 return
126134 modrinthApiClient .bulkGetProjects (
127- projects .stream ()
135+ expandProjectListings ( projects ) .stream ()
128136 .filter (s -> !s .trim ().isEmpty ())
129137 .map (ProjectRef ::parse )
130138 )
@@ -142,6 +150,30 @@ private List<Path> processProjects(List<String> projects) {
142150 }
143151 }
144152
153+ private List <String > expandProjectListings (List <String > projects ) {
154+ return projects .stream ()
155+ .distinct ()
156+ // handle @-file containing refs
157+ .flatMap (ref -> {
158+ if (ref .startsWith ("@" )) {
159+ try {
160+ return Files .readAllLines (Paths .get (ref .substring (1 ))).stream ()
161+ .map (s -> s
162+ .replaceFirst ("#.*" , "" )
163+ .trim ()
164+ )
165+ .filter (s -> !s .isEmpty ());
166+ } catch (IOException e ) {
167+ throw new GenericException ("Reading project refs from file: " + ref .substring (1 ), e );
168+ }
169+ }
170+ else {
171+ return Stream .of (ref );
172+ }
173+ })
174+ .collect (Collectors .toList ());
175+ }
176+
145177 private ModrinthManifest loadManifest () throws IOException {
146178 final Path legacyManifestPath = outputDirectory .resolve (LegacyModrinthManifest .FILENAME );
147179
0 commit comments