1- using Discord ;
1+ using CurseForge . APIClient . Models . Mods ;
2+ using Discord ;
23using Discord . Interactions ;
34using System . Text ;
5+ using System . Text . Json ;
46
57namespace CFDiscordBot . Commands
68{
@@ -9,7 +11,11 @@ public partial class Lookup
911 [ SlashCommand ( "projectid" , "Looks up a project by its ID" ) ]
1012 public async Task ProjectIdAsync (
1113 [ Summary ( "id" , "The ID of the project to look up" ) ]
12- int projectId
14+ int projectId ,
15+ [ Summary ( "GameVersion" , "The version of the game you want to find info about for this project" ) ]
16+ string ? gameVersion = null ,
17+ [ Summary ( "Modloader" , "The modloader you want to find info about for this project" ) ]
18+ ModLoaderType ? modLoader = null
1319 )
1420 {
1521 CurseForge . APIClient . Models . Mods . Mod ? mod = null ;
@@ -32,6 +38,20 @@ int projectId
3238 return ;
3339 }
3440
41+ List < CurseForge . APIClient . Models . Files . File > matchingFiles = new ( ) ;
42+
43+ bool isFileSearch = false ;
44+
45+ if ( gameVersion is not null || modLoader is not null )
46+ {
47+ isFileSearch = true ;
48+ var fileReq = await apiClient . GetModFilesAsync ( projectId , gameVersion , modLoader ) ;
49+ if ( fileReq ? . Data . Count > 0 )
50+ {
51+ matchingFiles . AddRange ( fileReq . Data ) ;
52+ }
53+ }
54+
3555 var summaryText = new StringBuilder ( ) ;
3656
3757 summaryText . AppendLine ( mod . Summary ) ;
@@ -43,14 +63,10 @@ int projectId
4363 Fields = [ ]
4464 } ;
4565
46- if ( Uri . TryCreate ( mod . Logo ? . ThumbnailUrl , UriKind . Absolute , out var logoUri ) )
47- {
48- projectEmbed . ThumbnailUrl = logoUri . AbsoluteUri ;
49- }
50- else
51- {
52- projectEmbed . ThumbnailUrl = "https://www.curseforge.com/images/flame.svg" ;
53- }
66+ projectEmbed . ThumbnailUrl =
67+ Uri . TryCreate ( mod . Logo ? . ThumbnailUrl , UriKind . Absolute , out var logoUri ) ?
68+ logoUri . AbsoluteUri :
69+ "https://www.curseforge.com/images/flame.svg" ;
5470
5571 var categories = string . Join ( ", " , mod . Categories . Select ( c => $ "[{ c . Name } ]({ c . Url } )") ) ;
5672
@@ -64,12 +80,79 @@ int projectId
6480 new ( ) { Name = "Mod Distribution" , Value = mod . AllowModDistribution ?? true ? "Allowed" : "Not allowed" , IsInline = true } ,
6581 new ( ) { Name = "Is available" , Value = mod . IsAvailable ? "Yes" : "No" , IsInline = true }
6682 } ;
83+
84+ if ( matchingFiles . Count > 0 )
85+ {
86+ List < string > fieldsToRemove = [ "Created" , "Modified" , "Released" , "Downloads" , "Is available" , "Status" , "Mod Distribution" ] ;
87+ fields . RemoveAll ( m => fieldsToRemove . Any ( i => i == m . Name ) ) ;
88+
89+ var latestFile = matchingFiles . OrderByDescending ( f => f . FileDate ) . First ( ) ;
90+
91+ fields . AddRange ( [
92+ new EmbedFieldBuilder { Name = "File Status" , Value = latestFile . FileStatus . ToString ( ) , IsInline = true } ,
93+ new EmbedFieldBuilder { Name = "File Uploaded" , Value = $ "<t:{ latestFile . FileDate . ToUnixTimeSeconds ( ) } :F>", IsInline = true } ,
94+ new EmbedFieldBuilder { Name = "File Downloads" , Value = latestFile . DownloadCount . ToString ( "n0" ) , IsInline = true } ,
95+ new EmbedFieldBuilder { Name = "Mod Distribution" , Value = mod . AllowModDistribution ?? true ? "Allowed" : "Not allowed" , IsInline = true } ,
96+ new EmbedFieldBuilder { Name = "File is available" , Value = latestFile . IsAvailable ? "Yes" : "No" , IsInline = true }
97+ ] ) ;
98+
99+ if ( mod . GameId == 432 )
100+ {
101+ var sides = latestFile . SortableGameVersions
102+ . Where ( i => i . GameVersionTypeId is 75208 )
103+ . Select ( i => i . GameVersionName )
104+ . ToList ( ) ;
105+
106+ if ( sides . Count > 0 )
107+ {
108+ fields . Add ( new EmbedFieldBuilder { Name = "Environments" , Value = string . Join ( ", " , sides ) , IsInline = false } ) ;
109+ }
110+
111+ var modLoaders = latestFile . SortableGameVersions
112+ . Where ( i => i . GameVersionTypeId is 68441 )
113+ . Select ( i => i . GameVersionName )
114+ . ToList ( ) ;
115+
116+ if ( modLoaders . Count > 0 )
117+ {
118+ fields . Add ( new EmbedFieldBuilder { Name = "Modloaders" , Value = string . Join ( ", " , modLoaders ) , IsInline = false } ) ;
119+ }
120+ }
121+
122+ var gameVersions = latestFile . SortableGameVersions
123+ . Where ( v => ! string . IsNullOrWhiteSpace ( v . GameVersion ) )
124+ . OrderByDescending ( v => v . GameVersionPadded )
125+ . Select ( i => i . GameVersionName )
126+ . ToList ( ) ;
127+ if ( gameVersions . Count > 0 )
128+ {
129+ fields . Add ( new EmbedFieldBuilder { Name = "Game versions" , Value = string . Join ( ", " , gameVersions ) , IsInline = false } ) ;
130+ }
131+ }
67132
68133 if ( ! string . IsNullOrWhiteSpace ( categories ) )
69134 {
70135 fields . Add ( new EmbedFieldBuilder { Name = "Categories" , Value = categories , IsInline = false } ) ;
71136 }
72137
138+
139+
140+ if ( isFileSearch && matchingFiles . Count == 0 )
141+ {
142+ var sb = new StringBuilder ( ) ;
143+ if ( gameVersion is not null )
144+ {
145+ sb . AppendLine ( $ "**Game version** - { gameVersion } ") ;
146+ }
147+
148+ if ( modLoader is not null )
149+ {
150+ sb . AppendLine ( $ "**Modloader** - { modLoader } ") ;
151+ }
152+
153+ fields . Add ( new EmbedFieldBuilder { Name = "File matching search criteria not found" , Value = sb . ToString ( ) , IsInline = false } ) ;
154+ }
155+
73156 projectEmbed . Fields . AddRange ( fields ) ;
74157
75158 projectEmbed . Footer = new EmbedFooterBuilder
@@ -131,7 +214,7 @@ int projectId
131214 }
132215
133216 // If the game is Minecraft Bedrock, we do an additional check if MCPEDL has the mod available through a slug lookup.
134- if ( mod . GameId == 78022 && mod . AllowModDistribution . HasValue && mod . AllowModDistribution . Value )
217+ if ( mod is { GameId : 78022 , AllowModDistribution : not null } && mod . AllowModDistribution . Value )
135218 {
136219 var client = httpClientFactory . CreateClient ( ) ;
137220 client . DefaultRequestHeaders . TryAddWithoutValidation ( "User-Agent" , "CFLookup Discord Bot/1.0; (+cflookup@itssimple.se)" ) ;
@@ -155,7 +238,7 @@ await RespondAsync($"Project `{projectId}` is: **[{mod.Name}](https://cflookup.c
155238 components : buttons . Build ( )
156239 ) ;
157240 }
158-
241+
159242 [ SlashCommand ( "cflookup" , "Looks up a project by its ID" , ignoreGroupNames : true ) ]
160243 public async Task CFLookup ( [ Summary ( "id" , "The ID" ) ] int projectId ) => await ProjectIdAsync ( projectId ) ;
161244 }
0 commit comments