feat(bestdebrid): add BestDebrid web-login provider

- New BestDebrid web-login option (BrowserWindow + session.fetch)
- Uses bestdebrid.com/api/v1/generateLink with browser session cookies
- Login via BestDebrid website in embedded browser window
- Toggle "BestDebrid per Web-Login statt API-Token verwenden"
- Provider label shows "BestDebrid (Web)" or "BestDebrid (API)"
- Session persistence respects "Token merken" setting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe
2026-03-06 11:26:48 +01:00
co-authored by Claude Opus 4.6
parent 54e502b9af
commit 438a9f209e
12 changed files with 368 additions and 7 deletions
+20 -3
View File
@@ -63,7 +63,7 @@ const emptyStats = (): DownloadStats => ({
const emptySnapshot = (): UiSnapshot => ({
settings: {
token: "", realDebridUseWebLogin: false, megaLogin: "", megaPassword: "", megaDebridPreferApi: true, bestToken: "", allDebridToken: "", allDebridUseWebLogin: false, ddownloadLogin: "", ddownloadPassword: "", oneFichierApiKey: "",
token: "", realDebridUseWebLogin: false, megaLogin: "", megaPassword: "", megaDebridPreferApi: true, bestToken: "", bestDebridUseWebLogin: false, allDebridToken: "", allDebridUseWebLogin: false, ddownloadLogin: "", ddownloadPassword: "", oneFichierApiKey: "",
archivePasswordList: "",
rememberToken: true, providerPrimary: "realdebrid", providerSecondary: "megadebrid",
providerTertiary: "bestdebrid", autoProviderFallback: true, outputDir: "", packageName: "",
@@ -988,14 +988,14 @@ export function App(): ReactElement {
if (settingsDraft.megaLogin.trim() && settingsDraft.megaPassword.trim()) {
list.push("megadebrid");
}
if (settingsDraft.bestToken.trim()) {
if (settingsDraft.bestDebridUseWebLogin || settingsDraft.bestToken.trim()) {
list.push("bestdebrid");
}
if (settingsDraft.allDebridUseWebLogin || settingsDraft.allDebridToken.trim()) {
list.push("alldebrid");
}
return list;
}, [settingsDraft.token, settingsDraft.realDebridUseWebLogin, settingsDraft.megaLogin, settingsDraft.megaPassword, settingsDraft.bestToken, settingsDraft.allDebridToken, settingsDraft.allDebridUseWebLogin]);
}, [settingsDraft.token, settingsDraft.realDebridUseWebLogin, settingsDraft.megaLogin, settingsDraft.megaPassword, settingsDraft.bestToken, settingsDraft.bestDebridUseWebLogin, settingsDraft.allDebridToken, settingsDraft.allDebridUseWebLogin]);
// DDownload is a direct file hoster (not a debrid service) and is used automatically
// for ddownload.com/ddl.to URLs. It counts as a configured account but does not
@@ -1156,6 +1156,16 @@ export function App(): ReactElement {
});
};
const onOpenBestDebridLogin = async (): Promise<void> => {
await performQuickAction(async () => {
await persistDraftSettings();
await window.rd.openBestDebridLogin();
showToast("BestDebrid Login-Fenster geöffnet", 2200);
}, (error) => {
showToast(`BestDebrid Login fehlgeschlagen: ${String(error)}`, 2800);
});
};
const onCheckUpdates = async (): Promise<void> => {
let updateResult: UpdateCheckResult | null = null;
await performQuickAction(async () => {
@@ -2844,6 +2854,13 @@ export function App(): ReactElement {
<label className="toggle-line"><input type="checkbox" checked={settingsDraft.megaDebridPreferApi} onChange={(e) => setBool("megaDebridPreferApi", e.target.checked)} /> Mega-Debrid bevorzugt über API (schneller, Fallback auf Web)</label>
<label>BestDebrid API Token</label>
<input type="password" value={settingsDraft.bestToken} onChange={(e) => setText("bestToken", e.target.value)} />
<label className="toggle-line"><input type="checkbox" checked={settingsDraft.bestDebridUseWebLogin} onChange={(e) => setBool("bestDebridUseWebLogin", e.target.checked)} /> BestDebrid per Web-Login statt API-Token verwenden</label>
{settingsDraft.bestDebridUseWebLogin && (
<>
<div className="hint">Beim ersten Link oder über den Button unten öffnet sich ein BestDebrid-Browserfenster. Der Login läuft dort manuell über die Website.</div>
<button className="btn" disabled={actionBusy} onClick={() => { void onOpenBestDebridLogin(); }}>BestDebrid Web-Login öffnen</button>
</>
)}
<label>AllDebrid API Key</label>
<input type="password" value={settingsDraft.allDebridToken} onChange={(e) => setText("allDebridToken", e.target.value)} />
<label className="toggle-line"><input type="checkbox" checked={settingsDraft.allDebridUseWebLogin} onChange={(e) => setBool("allDebridUseWebLogin", e.target.checked)} /> AllDebrid per Web-Login statt API-Key verwenden</label>