Upload via GUI (219 Dateien)

This commit is contained in:
2026-11-09 13:01:07 +00:00
parent 2760253b81
commit cd08d72b2c
3 changed files with 26 additions and 16 deletions
+2 -2
View File
@@ -561,7 +561,7 @@
</section>
<section class="settings-card">
<h5>CurseForge</h5>
<small class="hint s-vorab">Nur für CurseForge-Modpacks und -Mods nötig. Modrinth funktioniert immer ohne.</small>
<small class="hint s-vorab">Für CurseForge ist normalerweise nichts nötig: AeroMC nutzt die Weiterleitung unten. Ein eigener Key ist nur für den Fall gedacht, dass du sie nicht nutzen willst. Modrinth funktioniert immer ohne.</small>
<div class="s-zeile s-voll">
<div class="s-text"><b>Eigener API-Key</b><small>Von CurseForge for Studios (Profil → Schlüssel erstellen, beginnt mit cfc_pat_…) oder ein Organisationsschlüssel. Nach dem Eintragen speichern.</small></div>
<div class="path-row">
@@ -1629,7 +1629,7 @@
<div id="import-pane-modpack" class="import-pane hidden">
<p class="import-copy">Modpack aus dem Katalog installieren oder als Datei importieren.</p>
<p class="hint">Katalog-Suche läuft über Modrinth oder CurseForge. Für CurseForge wird ein eigener API-Key in den Netzwerk-Einstellungen gebraucht (die Weiterleitung reicht nur für den Datei-Import). Datei-Import unterstützt zusätzlich CurseForge-ZIP (manifest.json).</p>
<p class="hint">Katalog-Suche läuft über Modrinth oder CurseForge. Datei-Import unterstützt zusätzlich CurseForge-ZIP (manifest.json).</p>
<div class="field-row" style="margin-top:12px;align-items:flex-end">
<label class="field" style="width:150px">
+7
View File
@@ -4214,6 +4214,13 @@ ipcMain.handle('modpack:installFromCurseForge', async (_e, project) => {
const gameVersion = (project && project.gameVersion) || '';
broadcast('launch:progress', { phase: 'modpack', detail: 'Modpack-Version wird ermittelt …' });
const file = await services.curseforgeResolveModpackFile(zugang, modId, gameVersion);
if (file && file.gesperrt) {
return {
ok: false,
message: 'Der Autor erlaubt kein Laden dieses Modpacks über Launcher. Bitte von Hand laden und über „Importieren“ einlesen: '
+ services.cfProjektSeite(modId),
};
}
if (!file || !file.url) {
return {
ok: false,
+17 -14
View File
@@ -586,8 +586,8 @@ function cfLoaderType(loader) {
}
/*
* CurseForge-Katalogsuche. Braucht direkten API-Key (modus === 'direkt').
* Die Weiterleitung deckt absichtlich nur Dateiauflösung und Download ab.
* CurseForge-Katalogsuche – mit eigenem API-Key (modus 'direkt') oder über die
* Weiterleitung (modus 'weiterleitung'); beide haben dieselben Pfade unter zugang.basis.
*/
/*
@@ -653,13 +653,13 @@ async function curseforgeSearch(zugang, {
query = '', gameVersion = '', loader = '', sort = 'popularity',
limit = 30, offset = 0, art = 'mod',
} = {}) {
if (!zugang || zugang.modus !== 'direkt') {
// Direkt (eigener Key) und über die Weiterleitung laufen über dieselben Pfade
if (!zugang) {
return {
total: 0,
hits: [],
needKey: true,
error: 'Für die CurseForge-Suche brauchst du einen eigenen API-Key in den Netzwerk-Einstellungen. '
+ 'Die Weiterleitung reicht für Downloads, nicht für den Katalog.',
error: 'Kein CurseForge-Zugang eingerichtet. Trage unter Optionen → Netzwerk die Adresse der Weiterleitung oder einen eigenen API-Key ein.',
};
}
if (!CF_CLASS[art]) {
@@ -668,7 +668,7 @@ async function curseforgeSearch(zugang, {
return { total: 0, hits: [], error: 'CurseForge unterstützt diese Inhaltsart hier nicht – bitte Modrinth nutzen.' };
}
const classId = CF_CLASS[art];
const url = new URL(CURSEFORGE + '/mods/search');
const url = new URL(zugang.basis + '/mods/search');
url.searchParams.set('gameId', '432');
url.searchParams.set('classId', String(classId));
if (query) url.searchParams.set('searchFilter', query);
@@ -696,13 +696,16 @@ async function curseforgeSearch(zugang, {
return {
total: 0,
hits: [],
needKey: true,
error: 'CurseForge lehnt den API-Key ab (HTTP ' + res.status + '). '
+ 'Bitte unter Optionen → Netzwerk einen gültigen Schlüssel von console.curseforge.com eintragen. '
+ 'Das Proxy-Token ist kein API-Key.'
+ (detail ? ' (' + detail + ')' : ''),
needKey: zugang.modus === 'direkt',
error: zugang.modus === 'direkt'
? 'CurseForge lehnt den API-Key ab (HTTP ' + res.status + '). '
+ 'Bitte unter Optionen → Netzwerk einen gültigen Schlüssel von console.curseforge.com eintragen. '
+ 'Das Proxy-Token ist kein API-Key.'
+ (detail ? ' (' + detail + ')' : '')
: 'Der CurseForge-Server weist die Anfrage zurück (HTTP ' + res.status + ').',
};
}
if (res.status === 429) throw new Error('Zu viele Anfragen – bitte einen Moment warten.');
throw new Error('CurseForge-Suche fehlgeschlagen: HTTP ' + res.status + (detail ? ' – ' + detail : ''));
}
const data = await res.json();
@@ -750,12 +753,12 @@ function cfFileMatches(file, gameVersion, loader, art) {
}
async function curseforgePickFile(zugang, modId, gameVersion, loader, art) {
if (!zugang || zugang.modus !== 'direkt') {
const err = new Error('CurseForge-Dateiauswahl braucht einen eigenen API-Key.');
if (!zugang) {
const err = new Error('Kein CurseForge-Zugang eingerichtet.');
err.code = 'need-key';
throw err;
}
const url = new URL(CURSEFORGE + '/mods/' + modId + '/files');
const url = new URL(zugang.basis + '/mods/' + modId + '/files');
url.searchParams.set('pageSize', '50');
url.searchParams.set('index', '0');
if (gameVersion) url.searchParams.set('gameVersion', gameVersion);