11package org.hyacinthbots.allium.extensions
22
3+ import dev.kord.common.entity.MessageFlag
4+ import dev.kord.common.entity.SeparatorSpacingSize
5+ import dev.kord.core.event.message.MessageCreateEvent
6+ import dev.kord.rest.builder.component.actionRow
7+ import dev.kord.rest.builder.component.section
8+ import dev.kord.rest.builder.component.textDisplay
39import dev.kord.rest.builder.message.EmbedBuilder
10+ import dev.kord.rest.builder.message.container
411import dev.kord.rest.builder.message.embed
12+ import dev.kord.rest.builder.message.messageFlags
513import dev.kordex.core.commands.Arguments
614import dev.kordex.core.commands.application.slash.publicSubCommand
715import dev.kordex.core.commands.converters.impl.defaultingInt
816import dev.kordex.core.commands.converters.impl.string
917import dev.kordex.core.extensions.Extension
18+ import dev.kordex.core.extensions.event
1019import dev.kordex.core.extensions.publicSlashCommand
20+ import dev.kordex.core.utils.respond
21+ import io.github.oshai.kotlinlogging.KotlinLogging
1122import io.ktor.client.*
1223import io.ktor.client.call.*
1324import io.ktor.client.plugins.*
1425import io.ktor.client.plugins.contentnegotiation.*
1526import io.ktor.client.request.*
27+ import io.ktor.client.statement.request
1628import io.ktor.http.*
1729import io.ktor.serialization.kotlinx.json.*
1830import kotlin.time.Instant
@@ -69,10 +81,66 @@ class CurseForge : Extension() {
6981 }
7082 }
7183 }
84+
85+ event<MessageCreateEvent > {
86+ action {
87+ val message = event.message.content
88+ val regex = Regex (" https?://(?:www\\ .)?curseforge\\ .com/minecraft/(?:mc-mods|modpacks|shaders|bukkit-plugins|mc-addons|worlds|texture-packs|customization|data-packs)/([^/\\ s]+)" )
89+ val match = regex.find(message)
90+ if (match != null ) {
91+ val slug = match.groupValues[1 ]
92+ val response = searchCurseForge(slug, 1 )
93+ val project = response.data.firstOrNull { it.slug == slug } ? : return @action
94+
95+ event.message.respond {
96+ messageFlags {
97+ + MessageFlag .IsComponentsV2
98+ }
99+ container {
100+ section {
101+ textDisplay(" # ${project.name} " )
102+ thumbnailAccessory {
103+ url = project.logo.url
104+ description = " ${project.name} logo"
105+ }
106+ textDisplay(project.summary)
107+ }
108+ separator(SeparatorSpacingSize .Large )
109+ textDisplay(""" Downloads: ${project.downloadCount}
110+ |Latest supported Minecraft version: N/A due to bad sorting on Curseforge's End
111+ |Authors: ${project.authors.joinToString(" , " ) { it.name }}
112+ |Last Update: <t:${Instant .parse(project.dateModified).epochSeconds} >
113+ """ .trimMargin())
114+ separator(SeparatorSpacingSize .Large )
115+ actionRow {
116+ if (! project.links.sourceUrl.isNullOrBlank()) {
117+ linkButton(project.links.sourceUrl) {
118+ label = " Project Source Code"
119+ }
120+ }
121+ if (! project.links.wikiUrl.isNullOrBlank()) {
122+ linkButton(project.links.wikiUrl) {
123+ label = " Project Wiki"
124+ }
125+ }
126+ if (! project.links.issuesUrl.isNullOrBlank()) {
127+ linkButton(project.links.issuesUrl) {
128+ label = " Project Issues"
129+ }
130+ }
131+ linkButton(project.links.websiteUrl) {
132+ label = " CurseForge Page"
133+ }
134+ }
135+ }
136+ }
137+ }
138+ }
139+ }
72140 }
73141
74142 private suspend fun searchCurseForge (query : String , limit : Int ): SearchResponse {
75- return client.get(CURSEFORGE_ENDPOINT ) {
143+ val a = client.get(CURSEFORGE_ENDPOINT ) {
76144 url {
77145 path(" v1/mods/search" )
78146 parameter(" gameId" , 432 )
@@ -86,7 +154,9 @@ class CurseForge : Extension() {
86154 append(" x-api-key" , CURSEFORGE_API_KEY )
87155 append(" Accept" , " application/json" )
88156 }
89- }.body()
157+ }
158+ KotlinLogging .logger(" DEBUG" ).info { a.request.url.toString() }
159+ return a.body()
90160 }
91161
92162 @OptIn(ExperimentalTime ::class )
@@ -130,7 +200,7 @@ class CurseForge : Extension() {
130200
131201 @Serializable
132202 data class SearchResponse (
133- val data : MutableList <Mod >,
203+ val data : List <Mod >,
134204 val pagination : Pagination
135205 )
136206
@@ -139,12 +209,21 @@ class CurseForge : Extension() {
139209 val id : Int ,
140210 val name : String ,
141211 val slug : String ,
212+ val links : ModLinks ,
142213 val summary : String ,
143214 val downloadCount : Long ,
144- val authors : MutableList <ModAuthor >,
215+ val authors : List <ModAuthor >,
145216 val logo : ModAsset ,
146217 val dateModified : String ,
147- val allowModDistribution : Boolean?
218+ val latestFiles : List <ModFile > = emptyList()
219+ )
220+
221+ @Serializable
222+ data class ModLinks (
223+ val websiteUrl : String ,
224+ val wikiUrl : String? = null ,
225+ val issuesUrl : String? = null ,
226+ val sourceUrl : String? = null
148227 )
149228
150229 @Serializable
@@ -164,6 +243,15 @@ class CurseForge : Extension() {
164243 val url : String
165244 )
166245
246+ @Serializable
247+ data class ModFile (
248+ val id : Int ,
249+ val displayName : String ,
250+ val fileName : String ,
251+ val fileDate : String ,
252+ val gameVersions : List <String >
253+ )
254+
167255 @Serializable
168256 data class Pagination (
169257 val index : Int ,
0 commit comments