From 2981e87e76d4026a33d2f46929655a74353ad509 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:08:18 +0100 Subject: [PATCH] Simplify Steam plugin to make it more resilient to API changes --- .../gameyfin/plugins/steam/SteamPlugin.kt | 12 +- .../plugins/steam/dto/SteamGameDetails.kt | 147 +++--------------- .../plugins/steam/dto/SteamGameOverview.kt | 16 +- .../plugins/steam/util/SteamDateSerializer.kt | 2 +- plugins/steam/src/main/resources/MANIFEST.MF | 2 +- 5 files changed, 32 insertions(+), 147 deletions(-) diff --git a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/SteamPlugin.kt b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/SteamPlugin.kt index eb926ea..f75d779 100644 --- a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/SteamPlugin.kt +++ b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/SteamPlugin.kt @@ -28,6 +28,14 @@ import java.net.URLEncoder import java.nio.charset.StandardCharsets class SteamPlugin(wrapper: PluginWrapper) : GameyfinPlugin(wrapper) { + + companion object { + val json = Json { + isLenient = true + ignoreUnknownKeys = true + } + } + override val configMetadata: List = emptyList() override fun validateConfig(config: Map): Boolean { @@ -41,7 +49,7 @@ class SteamPlugin(wrapper: PluginWrapper) : GameyfinPlugin(wrapper) { val client = HttpClient(CIO) { install(ContentNegotiation) { - json() + json(json) } } @@ -85,7 +93,7 @@ class SteamPlugin(wrapper: PluginWrapper) : GameyfinPlugin(wrapper) { if (response.status != HttpStatusCode.OK) return null val responseBody: String = response.bodyAsText(Charsets.UTF_8) - val steamDetailsResultWrapper: Map = Json.decodeFromString(responseBody) + val steamDetailsResultWrapper: Map = json.decodeFromString(responseBody) if (!steamDetailsResultWrapper.containsKey(id)) return null if (steamDetailsResultWrapper[id]?.success != true) return null diff --git a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameDetails.kt b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameDetails.kt index ff16c17..75f85e3 100644 --- a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameDetails.kt +++ b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameDetails.kt @@ -13,170 +13,61 @@ data class SteamDetailsResultWrapper( @Serializable data class SteamGameDetails( - val type: String, val name: String, - @SerialName("steam_appid") val steamAppId: Int, - @SerialName("required_age") val requiredAge: Int, - @SerialName("is_free") val isFree: Boolean, - @SerialName("controller_support") val controllerSupport: String?, - val dlc: List?, @SerialName("detailed_description") val detailedDescription: String, - @SerialName("about_the_game") val aboutTheGame: String, - @SerialName("short_description") val shortDescription: String, - @SerialName("supported_languages") val supportedLanguages: String, - val reviews: String, @SerialName("header_image") val headerImage: String, - @SerialName("capsule_image") val capsuleImage: String, - @SerialName("capsule_imagev5") val capsuleImageV5: String, - val website: String?, - @SerialName("pc_requirements") val pcRequirements: SystemRequirements, - @SerialName("mac_requirements") val macRequirements: SystemRequirements, - @SerialName("linux_requirements") val linuxRequirements: SystemRequirements, - @SerialName("legal_notice") val legalNotice: String?, - @SerialName("drm_notice") val drmNotice: String?, - @SerialName("ext_user_account_notice") val extUserAccountNotice: String?, val developers: List, val publishers: List, - @SerialName("price_overview") val priceOverview: PriceOverview?, - val packages: List?, - @SerialName("package_groups") val packageGroups: List, - val platforms: Platforms, val categories: List, val genres: List, val screenshots: List, val movies: List, - val recommendations: Recommendations?, - val achievements: Achievements?, - @SerialName("release_date") val releaseDate: ReleaseDate?, - @SerialName("support_info") val supportInfo: SupportInfo?, - val background: String?, - @SerialName("background_raw") val backgroundRaw: String?, - @SerialName("content_descriptors") val contentDescriptors: ContentDescriptors?, - @SerialName("ratings") val ratings: Map? -) - -@Serializable -data class SystemRequirements( - val minimum: String?, - val recommended: String? -) - -@Serializable -data class PriceOverview( - val currency: String?, - val initial: Int?, - val final: Int?, - @SerialName("discount_percent") val discountPercent: Int?, - @SerialName("initial_formatted") val initialFormatted: String?, - @SerialName("final_formatted") val finalFormatted: String? -) - -@Serializable -data class PackageGroup( - val name: String?, - val title: String?, - val description: String?, - @SerialName("selection_text") val selectionText: String?, - @SerialName("save_text") val saveText: String?, - @SerialName("display_type") val displayType: Int?, - @SerialName("is_recurring_subscription") val isRecurringSubscription: Boolean?, - val subs: List? -) - -@Serializable -data class Sub( - @SerialName("packageid") val packageId: Int, - @SerialName("percent_savings_text") val percentSavingsText: String?, - @SerialName("percent_savings") val percentSavings: Int?, - @SerialName("option_text") val optionText: String?, - @SerialName("option_description") val optionDescription: String?, - @SerialName("can_get_free_license") val canGetFreeLicense: String?, - @SerialName("is_free_license") val isFreeLicense: Boolean, - @SerialName("price_in_cents_with_discount") val priceInCentsWithDiscount: Int? + @SerialName("release_date") val releaseDate: ReleaseDate? = null ) @Serializable data class Category( - val id: Int, - val description: String? + val id: Int? = null, + val description: String? = null ) @Serializable data class SteamGenre( - val id: Int, - val description: String? + val id: Int? = null, + val description: String? = null ) @Serializable data class Screenshot( val id: Int, - @SerialName("path_thumbnail") val pathThumbnail: String?, - @SerialName("path_full") val pathFull: String? + @SerialName("path_thumbnail") val pathThumbnail: String? = null, + @SerialName("path_full") val pathFull: String? = null ) @Serializable data class Movie( - val id: Int, - val name: String?, - val thumbnail: String?, - val webm: Webm?, - val mp4: Mp4?, - val highlight: Boolean + val id: Int? = null, + val name: String? = null, + val thumbnail: String? = null, + val webm: Webm? = null, + val mp4: Mp4? = null, + val highlight: Boolean? = null ) @Serializable data class Webm( - val `480`: String, - val max: String + val `480`: String? = null, + val max: String? = null ) @Serializable data class Mp4( - val `480`: String, - val max: String -) - -@Serializable -data class Recommendations( - val total: Int? -) - -@Serializable -data class Achievements( - val total: Int, - val highlighted: List? -) - -@Serializable -data class Achievement( - val name: String?, - val path: String? + val `480`: String? = null, + val max: String? = null ) @Serializable data class ReleaseDate( - @SerialName("coming_soon") val comingSoon: Boolean, - @Serializable(with = SteamDateSerializer::class) val date: Instant? -) - -@Serializable -data class SupportInfo( - val url: String?, - val email: String? -) - -@Serializable -data class ContentDescriptors( - val ids: List, - val notes: String? -) - -@Serializable -data class Rating( - val rating: String, - val descriptors: String? = null, - @SerialName("display_online_notice") val displayOnlineNotice: Boolean? = null, - @SerialName("use_age_gate") val useAgeGate: Boolean? = null, - @SerialName("required_age") val requiredAge: Int? = null, - @SerialName("interactive_elements") val interactiveElements: String? = null + @SerialName("coming_soon") val comingSoon: Boolean? = null, + @Serializable(with = SteamDateSerializer::class) val date: Instant? = null ) \ No newline at end of file diff --git a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameOverview.kt b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameOverview.kt index 44dfd25..69299fa 100644 --- a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameOverview.kt +++ b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/dto/SteamGameOverview.kt @@ -1,6 +1,5 @@ package de.grimsi.gameyfin.plugins.steam.dto -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable @@ -13,18 +12,5 @@ data class SteamSearchResult( data class SteamGame( val type: String, val name: String, - val id: Int, - val price: Price, - @SerialName("tiny_image") val tinyImage: String, - val metascore: String, - val platforms: Platforms, - @SerialName("streamingvideo") val streamingVideo: Boolean, - @SerialName("controller_support") val controllerSupport: String -) - -@Serializable -data class Price( - val currency: String, - val initial: Int, - val final: Int + val id: Int ) \ No newline at end of file diff --git a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/util/SteamDateSerializer.kt b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/util/SteamDateSerializer.kt index 1e898ac..856b7ab 100644 --- a/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/util/SteamDateSerializer.kt +++ b/plugins/steam/src/main/kotlin/de/grimsi/gameyfin/plugins/steam/util/SteamDateSerializer.kt @@ -16,7 +16,7 @@ import java.util.* class SteamDateSerializer : KSerializer { companion object { - val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM, yyyy", Locale.ENGLISH) + val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("d MMM, yyyy", Locale.ENGLISH) } override fun deserialize(decoder: Decoder): Instant = fromString(decoder.decodeString()) diff --git a/plugins/steam/src/main/resources/MANIFEST.MF b/plugins/steam/src/main/resources/MANIFEST.MF index dd0d496..414fb2d 100644 --- a/plugins/steam/src/main/resources/MANIFEST.MF +++ b/plugins/steam/src/main/resources/MANIFEST.MF @@ -2,5 +2,5 @@ Manifest-Version: 1.0 Plugin-Class: de.grimsi.gameyfin.plugins.steam.SteamPlugin Plugin-Id: steam Plugin-Description: Steam Metadata -Plugin-Version: 1.0.0-alpha1 +Plugin-Version: 1.0.0-alpha2 Plugin-Provider: grimsi