fix(realdebrid): respect dismissed login windows
Remember a user-dismissed browser login per Real-Debrid web account so queued and repeated unrestrict attempts cannot reopen it. Clear the suppression only after explicit login or successful authentication, and close successful login windows without treating them as user cancellations.
This commit is contained in:
@@ -135,6 +135,8 @@ export class RealDebridWebFallback {
|
|||||||
|
|
||||||
private onClosed?: () => void;
|
private onClosed?: () => void;
|
||||||
|
|
||||||
|
private interactiveLoginDismissed = false;
|
||||||
|
|
||||||
private persistentPartition: string;
|
private persistentPartition: string;
|
||||||
|
|
||||||
private transientPartition: string;
|
private transientPartition: string;
|
||||||
@@ -176,6 +178,7 @@ export class RealDebridWebFallback {
|
|||||||
|
|
||||||
public async openLoginWindow(): Promise<void> {
|
public async openLoginWindow(): Promise<void> {
|
||||||
this.throwIfDisposed();
|
this.throwIfDisposed();
|
||||||
|
this.interactiveLoginDismissed = false;
|
||||||
const window = await this.ensureLoginWindow();
|
const window = await this.ensureLoginWindow();
|
||||||
if (window.isMinimized()) {
|
if (window.isMinimized()) {
|
||||||
window.restore();
|
window.restore();
|
||||||
@@ -340,6 +343,7 @@ export class RealDebridWebFallback {
|
|||||||
let closingTokenProbe: Promise<void> = Promise.resolve();
|
let closingTokenProbe: Promise<void> = Promise.resolve();
|
||||||
window.on("close", () => {
|
window.on("close", () => {
|
||||||
if (!this.programmaticClosures.has(window)) {
|
if (!this.programmaticClosures.has(window)) {
|
||||||
|
this.interactiveLoginDismissed = true;
|
||||||
closingTokenProbe = this.primeTokenFromWindow(window, windowGeneration);
|
closingTokenProbe = this.primeTokenFromWindow(window, windowGeneration);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -372,6 +376,7 @@ export class RealDebridWebFallback {
|
|||||||
const changed = token !== this.cachedToken;
|
const changed = token !== this.cachedToken;
|
||||||
this.cachedToken = token;
|
this.cachedToken = token;
|
||||||
this.cachedTokenAt = Date.now();
|
this.cachedTokenAt = Date.now();
|
||||||
|
this.interactiveLoginDismissed = false;
|
||||||
if (changed && this.onAuthenticated) {
|
if (changed && this.onAuthenticated) {
|
||||||
void Promise.resolve().then(() => this.onAuthenticated?.());
|
void Promise.resolve().then(() => this.onAuthenticated?.());
|
||||||
}
|
}
|
||||||
@@ -582,6 +587,9 @@ export class RealDebridWebFallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async waitForLoginAndGenerate(link: string, signal?: AbortSignal): Promise<UnrestrictedLink | null> {
|
private async waitForLoginAndGenerate(link: string, signal?: AbortSignal): Promise<UnrestrictedLink | null> {
|
||||||
|
if (this.interactiveLoginDismissed) {
|
||||||
|
throw new Error("Real-Debrid Web-Login abgebrochen");
|
||||||
|
}
|
||||||
const window = await this.ensureLoginWindow();
|
const window = await this.ensureLoginWindow();
|
||||||
if (window.isMinimized()) {
|
if (window.isMinimized()) {
|
||||||
window.restore();
|
window.restore();
|
||||||
@@ -599,6 +607,7 @@ export class RealDebridWebFallback {
|
|||||||
const outcome = await this.generate(link, signal);
|
const outcome = await this.generate(link, signal);
|
||||||
if (outcome.kind === "success") {
|
if (outcome.kind === "success") {
|
||||||
if (!window.isDestroyed()) {
|
if (!window.isDestroyed()) {
|
||||||
|
this.programmaticClosures.add(window);
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
return outcome.value;
|
return outcome.value;
|
||||||
|
|||||||
@@ -197,6 +197,30 @@ describe("realdebrid-web", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not reopen an automatically required login after the user closed it", async () => {
|
||||||
|
mockExecuteJavaScript.mockResolvedValue("");
|
||||||
|
mockSessionFetch.mockImplementation(async () => new Response("<html>login</html>", { status: 200 }));
|
||||||
|
const fallback = new RealDebridWebFallback("persist:realdebrid-web-rdw_dismissed", () => true);
|
||||||
|
|
||||||
|
await fallback.openLoginWindow();
|
||||||
|
mockBrowserWindow.close();
|
||||||
|
|
||||||
|
await expect(fallback.unrestrict("https://rapidgator.net/file/first")).rejects.toThrow("abgebrochen");
|
||||||
|
await expect(fallback.unrestrict("https://rapidgator.net/file/second")).rejects.toThrow("abgebrochen");
|
||||||
|
expect(mockBrowserWindowCtor).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows an explicitly requested login after the user closed the previous window", async () => {
|
||||||
|
mockExecuteJavaScript.mockResolvedValue("");
|
||||||
|
const fallback = new RealDebridWebFallback("persist:realdebrid-web-rdw_reopen", () => true);
|
||||||
|
|
||||||
|
await fallback.openLoginWindow();
|
||||||
|
mockBrowserWindow.close();
|
||||||
|
await fallback.openLoginWindow();
|
||||||
|
|
||||||
|
expect(mockBrowserWindowCtor).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
|
||||||
it("notifies the controller when a new browser token is detected", async () => {
|
it("notifies the controller when a new browser token is detected", async () => {
|
||||||
mockExecuteJavaScript.mockResolvedValue("new-browser-token");
|
mockExecuteJavaScript.mockResolvedValue("new-browser-token");
|
||||||
const onAuthenticated = vi.fn();
|
const onAuthenticated = vi.fn();
|
||||||
|
|||||||
Reference in New Issue
Block a user