feat: proxy change-IP link

This commit is contained in:
zhom committed 2026-10-12 00:32:08 +04:00
1 parent 69d3c90a7c
commit 3f07a41fac
25 files changed
+925 -51

No files matched your search

+17
View File
@@ -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":
+67
View File
@@ -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),
}),
);
}
}