From 9b433c82611339eb0f175cb953110f5c84943e18 Mon Sep 17 00:00:00 2001
From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com>
Date: Sat, 21 Feb 2026 20:16:51 +0900
Subject: [PATCH 1/2] =?UTF-8?q?=E6=8A=8A=20fetchIconByDomain=20=E6=94=B9?=
=?UTF-8?q?=E6=88=90=20scriptcat.org?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/store/favicons.ts | 67 ++++---------------------------------
1 file changed, 6 insertions(+), 61 deletions(-)
diff --git a/src/pages/store/favicons.ts b/src/pages/store/favicons.ts
index 0ed61ef6f..488acb1aa 100644
--- a/src/pages/store/favicons.ts
+++ b/src/pages/store/favicons.ts
@@ -2,7 +2,6 @@ import { type Script, ScriptDAO } from "@App/app/repo/scripts";
import { FaviconDAO, type FaviconFile, type FaviconRecord } from "@App/app/repo/favicon";
import { v5 as uuidv5 } from "uuid";
import { getFaviconRootFolder } from "@App/app/service/service_worker/utils";
-import { readBlobContent } from "@App/pkg/utils/encoding";
let scriptDAO: ScriptDAO | null = null;
let faviconDAO: FaviconDAO | null = null;
@@ -92,17 +91,6 @@ export const timeoutAbortSignal =
return signal;
};
-/**
- * 解析相对URL为绝对URL
- */
-const resolveUrl = (href: string, base: string): string => {
- try {
- return new URL(href, base).href;
- } catch {
- return href; // 如果解析失败,返回原始href
- }
-};
-
export const parseFaviconsNew = (html: string, callback: (href: string) => void) => {
// Early exit if no link tags
if (!html.toLowerCase().includes(" void)
return;
};
-const getFilename = (url: string) => {
- const i = url.lastIndexOf("/");
- if (i >= 0) return url.substring(i + 1);
- return url;
-};
-
-const checkFileNameEqual = (a: string, b: string) => {
- const name1 = getFilename(a);
- const name2 = getFilename(b);
- return 0 === name1.localeCompare(name2, "en", { sensitivity: "base" });
-};
-
/**
* 从域名获取favicon
*/
-export async function fetchIconByDomain(domain: string): Promise {
+export async function fetchIconByDomain(domain: string): Promise {
const url = `https://${domain}`;
- const icons: string[] = [];
-
- // 设置超时时间(例如 5 秒)
- const timeout = 5000; // 单位:毫秒
-
- // 获取页面HTML
- const response = await fetch(url, { signal: timeoutAbortSignal(timeout) });
- const html = await readBlobContent(response, response.headers.get("content-type"));
- const resolvedPageUrl = response.url;
- const resolvedUrl = new URL(resolvedPageUrl);
- const resolvedOrigin = resolvedUrl.origin;
-
- parseFaviconsNew(html, (href) => icons.push(resolveUrl(href, resolvedPageUrl)));
-
- // 检查默认favicon位置
- if (icons.length === 0) {
- const faviconUrl = `${resolvedOrigin}/favicon.ico`;
- icons.push(faviconUrl);
+ const sDomain = new URL(url).hostname;
+ if (!sDomain || sDomain.length > 253) {
+ throw new Error("invalid domain name");
}
-
- const urls = await Promise.all(
- icons.map((icon) =>
- fetch(icon, { method: "HEAD", signal: timeoutAbortSignal(timeout) })
- .then((res) => {
- if (res.ok && checkFileNameEqual(res.url, icon)) {
- return res.url;
- }
- })
- .catch(() => {
- // 忽略错误
- })
- )
- );
-
- return urls.filter((url) => !!url) as string[];
+ return `https://scriptcat.org/api/v2/open/favicons?domain=${encodeURIComponent(sDomain)}&sz=64`;
}
// 获取脚本的favicon
@@ -199,8 +145,7 @@ export const getScriptFavicon = async (uuid: string): Promise =
domains.map(async (domain) => {
try {
if (domain.domain) {
- const icons = await fetchIconByDomain(domain.domain);
- const icon = icons.length > 0 ? icons[0] : "";
+ const icon = await fetchIconByDomain(domain.domain);
return { match: domain.match, website: "http://" + domain.domain, icon };
}
} catch {
From 4f3b91884d830fd67c509ce071cdecad88b356d5 Mon Sep 17 00:00:00 2001
From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com>
Date: Tue, 24 Feb 2026 10:20:58 +0900
Subject: [PATCH 2/2] scriptcat.org -> ext.scriptcat.org
---
src/pages/store/favicons.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/pages/store/favicons.ts b/src/pages/store/favicons.ts
index 488acb1aa..541eb8fe7 100644
--- a/src/pages/store/favicons.ts
+++ b/src/pages/store/favicons.ts
@@ -7,6 +7,9 @@ let scriptDAO: ScriptDAO | null = null;
let faviconDAO: FaviconDAO | null = null;
const loadFaviconPromises = new Map(); // 关联 iconUrl 和 blobUrl
+const FETCH_SERVICE_URL = "https://ext.scriptcat.org/api/v1/open/favicons";
+const FETCH_ICON_SIZE = 64;
+
/**
* 从URL模式中提取域名
*/
@@ -122,7 +125,7 @@ export async function fetchIconByDomain(domain: string): Promise {
if (!sDomain || sDomain.length > 253) {
throw new Error("invalid domain name");
}
- return `https://scriptcat.org/api/v2/open/favicons?domain=${encodeURIComponent(sDomain)}&sz=64`;
+ return `${FETCH_SERVICE_URL}?domain=${encodeURIComponent(sDomain)}&sz=${FETCH_ICON_SIZE}`;
}
// 获取脚本的favicon