Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mclib/src/query/IModQueryService.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { MCVersion, ModMetadata, ModReleases, ModRepoMetadata, ModRepositoryName } from "../types";
import { MCVersion, ModMetadata, ModReleases, ModRepositoryName } from "../types";

export interface IModQueryService {
getMinecraftVersions(): Promise<MCVersion[]>;
searchMods(
query: string,
specifiedRepos: ModRepositoryName[],
maxResults: number,
): Promise<Array<[ModRepositoryName, ModRepoMetadata]>>;
): Promise<ModMetadata[]>;
getModReleasesFromMetadata(modMeta: ModMetadata): Promise<ModReleases>;
getModByDataHash(modData: Uint8Array): Promise<ModMetadata>;
}
30 changes: 22 additions & 8 deletions mclib/src/query/LocalModQueryService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type MCVersion, type ModRepositoryName, type ModRepoMetadata, type IRepository, type ModMetadata, type ModReleases, ModMetadataUtil, IModQueryService } from "..";
import { type MCVersion, type ModRepositoryName, type IRepository, type ModMetadata, type ModReleases, ModMetadataUtil, IModQueryService } from "..";
import { logger } from "../logger";
import { isSameModAndRepo } from "../utils";

export class LocalModQueryService implements IModQueryService {

Expand All @@ -21,9 +22,9 @@ export class LocalModQueryService implements IModQueryService {
async searchMods(
query: string,
specifiedRepos: ModRepositoryName[],
maxResults: number = 10,
): Promise<Array<[ModRepositoryName, ModRepoMetadata]>> {
const allResults: Array<[ModRepositoryName, ModRepoMetadata]> = [];
maxResults: number,
): Promise<ModMetadata[]> {
const allResults: Array<ModMetadata> = [];

for (const repo of this.repositories) {
try {
Expand All @@ -32,21 +33,34 @@ export class LocalModQueryService implements IModQueryService {
continue; // Skip repositories not in the specified list
}

const results = await repo.searchMods(query, maxResults);
for (const mod of results) {
allResults.push([repoName, mod]);
// Loop over search results of this repository
for (const newModRepo of await repo.searchMods(query, maxResults)) {

// Check if this mod already exists in the aggregated results
let wasMerged = false;
for (const existingMod of allResults) {
if (isSameModAndRepo(existingMod, newModRepo)) {
// Update existing mod entry with additional repository metadata
existingMod.push(newModRepo);
wasMerged = true;
break;
}
}
if (!wasMerged) allResults.push([newModRepo]); // Add as new entry
}
} catch (_) {
// Ignore errors for individual repositories
}
}

// Sort by download count descending
allResults.sort((a, b) => b[1].downloadCount - a[1].downloadCount);
allResults.sort((a, b) => b[0].downloadCount - a[0].downloadCount);

// Limit results if maxResults is specified
if (maxResults !== undefined) {
return allResults.slice(0, maxResults);
}

return allResults;
}

Expand Down
2 changes: 1 addition & 1 deletion mclib/src/query/RemoteModQueryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class RemoteModQueryService implements IModQueryService {
query: string,
specifiedRepos: ModRepositoryName[],
maxResults: number
): Promise<Array<[ModRepositoryName, ModRepoMetadata]>> {
): Promise<ModMetadata[]> {
return this.callEndpoint("searchMods", { query, specifiedRepos, maxResults });
}

Expand Down
14 changes: 14 additions & 0 deletions mclib/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { ModMetadata, ModRepoMetadata } from "./types";

export function validateParam(s: string) {
if (!/^[a-zA-Z0-9]{0,64}$/.test(s)) {
throw new Error('Invalid parameter: must be 0-64 alphanumeric characters');
}
}

export function isSameModAndRepo(modA: ModMetadata, modB: ModRepoMetadata): boolean {
for (const v of modA) {
if (isSameModRepo(v, modB)) return true;
}
return false;
}

// Returns true if id OR slug matches id OR slug of the other mod
export function isSameModRepo(modA: ModRepoMetadata, modB: ModRepoMetadata): boolean {
return [modA.id, modA.slug].some(idA => [modB.id, modB.slug].includes(idA));
}
4 changes: 1 addition & 3 deletions web/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
"search_mod_by_name": "Search for a mod by its name",
"search_mods_button": "Search",
"search_results": {
"loading_mod_search": "Please wait, we're searching your mod",
"downloads_count": "downloads",
"open_mod_repo_link": "See on {repo_name}",
"add_mod": "Add",
"repo_from": "From",
"remove_mod": "Remove"
},
"drag_and_drop": {
Expand Down
4 changes: 1 addition & 3 deletions web/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
"search_mod_by_name": "Recherchez un mod par son nom",
"search_mods_button": "Rechercher",
"search_results": {
"loading_mod_search": "Veuillez patienter, nous recherchons votre mod",
"downloads_count": "téléchargements",
"open_mod_repo_link": "Voir sur {repo_name}",
"add_mod": "Ajouter",
"repo_from": "Depuis",
"remove_mod": "Enlever"
},
"drag_and_drop": {
Expand Down
10 changes: 7 additions & 3 deletions web/src/components/ModSearch.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import * as m from '$msg';
import { ModRepositoryName } from 'mclib';
import type { ModRepoMetadata } from 'mclib';
import type { ModMetadata, ModRepoMetadata } from 'mclib';
import { ModSearchList, ToggleButtons } from '$cmpts';
import { slide } from 'svelte/transition';
import { modQueryService, repositories } from '../config';
Expand All @@ -13,7 +13,7 @@
add_mod_to_list
}: {
search_name_input: string;
search_results: [ModRepositoryName, ModRepoMetadata][];
search_results: ModMetadata[];
is_loading_search: boolean;
add_mod_to_list: (mod: ModRepoMetadata) => void;
} = $props();
Expand All @@ -35,7 +35,11 @@
try {
// set loading mode
is_loading_search = true;
const results = await modQueryService.searchMods(search_name_input, selected_mod_repo_names);
const results = await modQueryService.searchMods(
search_name_input,
selected_mod_repo_names,
20 // bigger number = more chance of having aggregated results between repositories (e.g. "jei" will not match JEI on modrinth for maxResults=10)
);
search_results = results;
} catch (err) {
console.log(err);
Expand Down
Loading