mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-10-21 14:51:49 +02:00
feat: proxy change-IP link
This commit is contained in:
1 parent
69d3c90a7c
commit
3f07a41fac
25 files changed
+925
-51
No files matched your search
@@ -30,6 +30,11 @@ export type BackendErrorCode =
|
||||
| "PROFILE_STATUS_COLOR_INVALID"
|
||||
| "PROFILE_STATUS_NAME_TOO_LONG"
|
||||
| "PROFILE_STATUS_LIMIT_REACHED"
|
||||
| "PROXY_ROTATION_URL_INVALID"
|
||||
| "PROXY_ROTATION_URL_MISSING"
|
||||
| "PROXY_ROTATION_TIMEOUT"
|
||||
| "PROXY_ROTATION_UNREACHABLE"
|
||||
| "PROXY_ROTATION_FAILED"
|
||||
| "COOKIE_DB_LOCKED"
|
||||
| "COOKIE_DB_UNAVAILABLE"
|
||||
| "COOKIE_IMPORT_BROWSER_RUNNING"
|
||||
@@ -376,6 +381,18 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.profileStatusNameTooLong");
|
||||
case "PROFILE_STATUS_LIMIT_REACHED":
|
||||
return t("backendErrors.profileStatusLimitReached");
|
||||
case "PROXY_ROTATION_URL_INVALID":
|
||||
return t("backendErrors.proxyRotationUrlInvalid");
|
||||
case "PROXY_ROTATION_URL_MISSING":
|
||||
return t("backendErrors.proxyRotationUrlMissing");
|
||||
case "PROXY_ROTATION_TIMEOUT":
|
||||
return t("backendErrors.proxyRotationTimeout");
|
||||
case "PROXY_ROTATION_UNREACHABLE":
|
||||
return t("backendErrors.proxyRotationUnreachable");
|
||||
case "PROXY_ROTATION_FAILED":
|
||||
return t("backendErrors.proxyRotationFailed", {
|
||||
status: parsed.params?.status ?? "",
|
||||
});
|
||||
case "COOKIE_DB_LOCKED":
|
||||
return t("backendErrors.cookieDbLocked");
|
||||
case "COOKIE_DB_UNAVAILABLE":
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import type { TFunction } from "i18next";
|
||||
import { translateBackendError } from "@/lib/backend-errors";
|
||||
import { showErrorToast, showSuccessToast } from "@/lib/toast-utils";
|
||||
import type { StoredProxy } from "@/types";
|
||||
|
||||
/** `RotationResult` in `src-tauri/src/proxy_rotation.rs`. */
|
||||
interface RotationResult {
|
||||
proxy_id: string;
|
||||
status: number | null;
|
||||
elapsed_ms: number;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
/** A link worth sending to the backend, which checks it again. */
|
||||
export function looksLikeRotationUrl(value: string): boolean {
|
||||
return /^https?:\/\/\S+$/i.test(value.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the providers of these proxies for new IPs and say what happened. Proxies
|
||||
* without a change-IP link are left out.
|
||||
*/
|
||||
export async function rotateProxyIps(
|
||||
proxies: StoredProxy[],
|
||||
t: TFunction,
|
||||
): Promise<void> {
|
||||
const rotatable = proxies.filter((proxy) => proxy.rotation_url);
|
||||
if (rotatable.length === 0) {
|
||||
showErrorToast(t("proxies.rotation.noneSelected"));
|
||||
return;
|
||||
}
|
||||
if (rotatable.length === 1) {
|
||||
const [proxy] = rotatable;
|
||||
try {
|
||||
await invoke<RotationResult>("rotate_proxy_ip", { proxyId: proxy.id });
|
||||
showSuccessToast(t("proxies.rotation.requested", { name: proxy.name }));
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
t("proxies.rotation.failedFor", {
|
||||
name: proxy.name,
|
||||
error: translateBackendError(t, error),
|
||||
}),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const results = await invoke<RotationResult[]>("rotate_proxy_ips", {
|
||||
proxyIds: rotatable.map((proxy) => proxy.id),
|
||||
});
|
||||
const succeeded = results.filter((result) => !result.error).length;
|
||||
if (succeeded > 0) {
|
||||
showSuccessToast(t("proxies.rotation.requestedMany", { count: succeeded }));
|
||||
}
|
||||
for (const result of results) {
|
||||
if (!result.error) continue;
|
||||
const name =
|
||||
rotatable.find((proxy) => proxy.id === result.proxy_id)?.name ??
|
||||
result.proxy_id;
|
||||
showErrorToast(
|
||||
t("proxies.rotation.failedFor", {
|
||||
name,
|
||||
error: translateBackendError(t, result.error),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user