feat: mapped CF categories and added loader field to search results

This commit is contained in:
LynithDev 2025-08-10 17:03:55 +02:00
parent 4fda6e44b2
commit f397ed40bd
6 changed files with 162 additions and 89 deletions

View file

@ -64,6 +64,7 @@ pub struct SearchResult {
pub title: String,
pub description: String,
pub categories: PackageCategories,
pub loaders: Vec<GameLoader>,
pub mc_versions: Vec<String>,
pub downloads: usize,
pub icon_url: String,

View file

@ -7,97 +7,124 @@ use crate::api::packages::provider::CurseForgeProviderImpl;
pub struct CurseForgeCategories;
define_category_mapping! {
impl ToProviderCategory<u32, CurseForgeProviderImpl> for CurseForgeCategories {
impl ToProviderCategory<i32, CurseForgeProviderImpl> for CurseForgeCategories {
PackageModCategory as as_mod_out => to_mod {
Adventure => 0,
Library => 0,
Equipment => 0,
Patches => 0,
Cosmetic => 0,
Food => 0,
Magic => 0,
Information => 0,
Misc => 0,
Performance => 0,
Redstone => 0,
ServerUtil => 0,
Storage => 0,
Technology => 0,
Farming => 0,
Automation => 0,
Transport => 0,
Utility => 0,
QoL => 0,
WorldGen => 0,
Mobs => 0,
Economy => 0,
Social => 0,
Adventure => 422,
Library => 421,
Equipment => 434,
Patches => 6821,
Cosmetic => 424,
Food => 436,
Magic => 419,
Information => 423,
Misc => 425,
Performance => 6814,
Redstone => 4558,
ServerUtil => 435,
Storage => 420,
Technology => 412,
Farming => 416,
Automation => 4843,
Transport => 414,
Utility => 5191,
QoL => 5191,
WorldGen => 406,
Mobs => 411,
Economy => -1,
Social => -1,
}
PackageModCategory as as_data_pack_out => to_data_pack {
Adventure => 6948,
Library => 6950,
Equipment => -1,
Patches => 6946,
Cosmetic => -1,
Food => -1,
Magic => 6952,
Information => -1,
Misc => 6947,
Performance => -1,
Redstone => -1,
ServerUtil => -1,
Storage => -1,
Technology => 6951,
Farming => -1,
Automation => -1,
Transport => -1,
Utility => 6953,
QoL => -1,
WorldGen => -1,
Mobs => -1,
Economy => -1,
Social => -1,
}
PackageResourcePackCategory as as_resource_pack_out => to_resource_pack {
X8 => 0,
X16 => 0,
X32 => 0,
X48 => 0,
X64 => 0,
X128 => 0,
X256 => 0,
X512 => 0,
VanillaLike => 0,
Utility => 0,
Tweaks => 0,
Themed => 0,
Simplistic => 0,
Realistic => 0,
Modded => 0,
Decoration => 0,
Cursed => 0,
Combat => 0,
Audio => 0,
Blocks => 0,
CoreShaders => 0,
Gui => 0,
Fonts => 0,
Equipment => 0,
Environment => 0,
Entities => 0,
Items => 0,
Locale => 0,
Models => 0,
X8 => -1,
X16 => 393,
X32 => 394,
X48 => -1,
X64 => 395,
X128 => 396,
X256 => 397,
X512 => 398,
VanillaLike => 403,
Utility => 405,
Tweaks => 405,
Themed => 399,
Simplistic => 401,
Realistic => 400,
Modded => 4465,
Decoration => 405,
Cursed => 405,
Combat => 405,
Audio => 405,
Blocks => 405,
CoreShaders => 405,
Gui => 403,
Fonts => 5244,
Equipment => 405,
Environment => 405,
Entities => 405,
Items => 405,
Locale => 405,
Models => 405,
}
// Curseforge is very bad with shader categories
PackageShaderCategory as as_shader_out => to_shader {
VanillaLike => 0,
SemiRealistic => 0,
Realistic => 0,
Fantasy => 0,
Cursed => 0,
Cartoon => 0,
Bloom => 0,
Atmosphere => 0,
Reflections => 0,
Shadows => 0,
PBR => 0,
PathTracing => 0,
Foliage => 0,
ColoredLightning => 0,
Potato => 0,
Low => 0,
Medium => 0,
High => 0,
Ultra => 0,
VanillaLike => 6555,
SemiRealistic => -1,
Realistic => 6553,
Fantasy => 6554,
Cursed => -1,
Cartoon => -1,
Bloom => -1,
Atmosphere => -1,
Reflections => -1,
Shadows => -1,
PBR => -1,
PathTracing => -1,
Foliage => -1,
ColoredLightning => -1,
Potato => -1,
Low => -1,
Medium => -1,
High => -1,
Ultra => -1,
}
PackageModPackCategory as as_mod_pack_out => to_mod_pack {
Adventure => 0,
Technology => 0,
Quests => 0,
Optimization => 0,
Multiplayer => 0,
Magic => 0,
LightWeight => 0,
Combat => 0,
Challenging => 0,
Adventure => 4475,
Technology => 4472,
Quests => 4478,
Optimization => 4481,
Multiplayer => 4484,
Magic => 4473,
LightWeight => 4481,
Combat => 4483,
Challenging => 4479,
}
}
}

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use chrono::{DateTime, Utc};
use onelauncher_entity::loader::GameLoader;
@ -96,7 +96,7 @@ impl ProviderExt for CurseForgeProviderImpl {
"[{}]",
categories
.iter()
.map(u32::to_string)
.map(i32::to_string)
.collect::<Vec<String>>()
.join(",")
);
@ -354,7 +354,7 @@ impl From<PackageType> for CFPackageType {
}
/// Mapping of Curseforge supported loaders to their respective id
#[derive(Debug, Default, Serialize_repr, Deserialize_repr)]
#[derive(Debug, Default, Clone, Copy, Serialize_repr, Deserialize_repr, Hash, PartialEq)]
#[repr(u8)]
pub enum CFLoader {
#[default]
@ -522,12 +522,24 @@ impl From<CFPackage> for SearchResult {
fn from(value: CFPackage) -> Self {
let mc_versions: Vec<String> = value
.latest_files_indexes
.into_iter()
.map(|index| index.game_version)
.iter()
.map(|index| index.game_version.clone())
.collect();
let package_type: PackageType = value.package_type.into();
let loaders: Vec<GameLoader> = value
.latest_files_indexes
.iter()
.filter_map(|index| {
index
.mod_loader
.and_then(|loader| GameLoader::try_from(loader).ok())
})
.collect::<HashSet<_>>()
.into_iter()
.collect();
Self {
title: value.name,
slug: value.slug,
@ -546,6 +558,7 @@ impl From<CFPackage> for SearchResult {
&package_type,
&value.categories.into_iter().map(|c| c.id).collect(),
),
loaders,
package_type,
mc_versions,
date_created: value.date_created,
@ -555,7 +568,10 @@ impl From<CFPackage> for SearchResult {
.into_iter()
.map(|asset| asset.url)
.collect(),
latest_version: "".to_string(), // TODO: figure out how to get this
latest_version: value
.latest_files_indexes
.first()
.map_or(String::new(), |index| index.file_id.to_string()),
license: None,
}
}
@ -640,7 +656,7 @@ pub struct CFSocialLink {
#[derive(Default, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Category {
pub id: u32,
pub id: i32,
// pub game_id: u32,
// pub name: String,
pub slug: String,

View file

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::str::FromStr;
use super::ProviderExt;
use crate::api::packages::categories::ToProviderCategory;
@ -358,8 +359,15 @@ struct ModrinthSearchResult {
impl From<ModrinthSearchResult> for SearchResult {
fn from(value: ModrinthSearchResult) -> Self {
let loaders: Vec<GameLoader> = value
.categories
.iter()
.filter_map(|category| GameLoader::from_str(category).ok())
.collect();
Self {
categories: ModrinthCategories::to_list(&value.project_type, &value.categories),
loaders,
package_type: value.project_type,
project_id: value.project_id,
slug: value.slug,

View file

@ -3,6 +3,7 @@ use std::sync::LazyLock;
use onelauncher_entity::package::{PackageType, Provider};
use crate::api::packages;
use crate::api::packages::data::SearchQuery;
use crate::api::packages::provider::ProviderExt;
use crate::error::LauncherResult;
use crate::utils::DatabaseModelExt;
@ -200,4 +201,24 @@ pub async fn test_download_packages() -> LauncherResult<()> {
Ok(())
}
#[tokio::test]
pub async fn test_search_packages() -> LauncherResult<()> {
let cf = init!();
for provider in Provider::get_providers().iter() {
if provider == &Provider::CurseForge && !cf {
continue;
}
let query = SearchQuery::default();
let res = provider.search(&query).await?;
dbg!(&res.items);
assert!(!res.items.is_empty());
}
Ok(())
}
// TODO: Add more tests

View file

@ -101,6 +101,6 @@ impl Provider {
#[must_use]
pub const fn get_providers() -> &'static [Self] {
&[Self::Modrinth, Self::CurseForge, Self::SkyClient]
&[Self::Modrinth, Self::CurseForge]
}
}