diff --git a/src/apis/index.js b/src/apis/index.js index be8e2e4..86165c5 100644 --- a/src/apis/index.js +++ b/src/apis/index.js @@ -59,7 +59,7 @@ const apiGoogleTranslate = async (translator, text, to, from) => { "Content-type": "application/json", }, }, - { useCache: true, translator } + { useCache: true, usePool: true, translator } ); }; @@ -70,7 +70,7 @@ const apiGoogleTranslate = async (translator, text, to, from) => { * @param {*} from * @returns */ -const apiMicrosoftTranslate = (translator, text, to, from, token) => { +const apiMicrosoftTranslate = (translator, text, to, from) => { const params = { from, to, @@ -82,12 +82,11 @@ const apiMicrosoftTranslate = (translator, text, to, from, token) => { { headers: { "Content-type": "application/json", - Authorization: `Bearer ${token}`, }, method: "POST", body: JSON.stringify([{ Text: text }]), }, - { useCache: true, translator } + { useCache: true, usePool: true, translator } ); }; @@ -109,8 +108,6 @@ const apiOpenaiTranslate = async (translator, text, to, from) => { { headers: { "Content-type": "application/json", - Authorization: `Bearer ${openaiKey}`, // OpenAI - "api-key": openaiKey, // Azure OpenAI }, method: "POST", body: JSON.stringify({ @@ -129,7 +126,7 @@ const apiOpenaiTranslate = async (translator, text, to, from) => { max_tokens: 256, }), }, - { useCache: true, translator } + { useCache: true, usePool: true, translator, token: openaiKey } ); }; @@ -138,10 +135,7 @@ const apiOpenaiTranslate = async (translator, text, to, from) => { * @param {*} param0 * @returns */ -export const apiTranslate = async ( - { translator, q, fromLang, toLang }, - { token } -) => { +export const apiTranslate = async ({ translator, q, fromLang, toLang }) => { let trText = ""; let isSame = false; @@ -153,7 +147,7 @@ export const apiTranslate = async ( trText = res.sentences.map((item) => item.trans).join(" "); isSame = to === res.src; } else if (translator === OPT_TRANS_MICROSOFT) { - const res = await apiMicrosoftTranslate(translator, q, to, from, token); + const res = await apiMicrosoftTranslate(translator, q, to, from); trText = res[0].translations[0].text; isSame = to === res[0].detectedLanguage.language; } else if (translator === OPT_TRANS_OPENAI) { diff --git a/src/background.js b/src/background.js index f0e5912..3fcefc7 100644 --- a/src/background.js +++ b/src/background.js @@ -1,6 +1,7 @@ import browser from "webextension-polyfill"; import { MSG_FETCH, + MSG_FETCH_LIMIT, DEFAULT_SETTING, DEFAULT_RULES, DEFAULT_SYNC, @@ -12,7 +13,7 @@ import { import storage from "./libs/storage"; import { getSetting } from "./libs"; import { syncAll } from "./libs/sync"; -import { fetchData } from "./libs/fetch"; +import { fetchData, fetchPool } from "./libs/fetch"; /** * 插件安装 @@ -47,7 +48,8 @@ browser.runtime.onMessage.addListener( ({ action, args }, sender, sendResponse) => { switch (action) { case MSG_FETCH: - fetchData(args.input, args.init, args.opts) + const { input, init, opts } = args; + fetchData(input, init, opts) .then((data) => { sendResponse({ data }); }) @@ -55,6 +57,11 @@ browser.runtime.onMessage.addListener( sendResponse({ error: error.message }); }); break; + case MSG_FETCH_LIMIT: + const { interval, limit } = args; + fetchPool.update(interval, limit); + sendResponse({ data: "ok" }); + break; default: sendResponse({ error: `message action is unavailable: ${action}` }); } diff --git a/src/content.js b/src/content.js index 444b217..b2cab77 100644 --- a/src/content.js +++ b/src/content.js @@ -6,7 +6,7 @@ import { } from "./config"; import { getRules, matchRule } from "./libs"; import { getSetting } from "./libs"; -import { transPool } from "./libs/pool"; +import { fetchUpdate } from "./libs/fetch"; import { Translator } from "./libs/translator"; /** @@ -14,7 +14,7 @@ import { Translator } from "./libs/translator"; */ (async () => { const { fetchInterval, fetchLimit } = await getSetting(); - transPool.update(fetchInterval, fetchLimit); + fetchUpdate(fetchInterval, fetchLimit); const rules = await getRules(); const rule = matchRule(rules, document.location.href); diff --git a/src/hooks/Translate.js b/src/hooks/Translate.js index 40415f1..e175019 100644 --- a/src/hooks/Translate.js +++ b/src/hooks/Translate.js @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { useState } from "react"; -import { transPool } from "../libs/pool"; import { detectLang } from "../libs"; +import { apiTranslate } from "../apis"; /** * 翻译hook @@ -25,7 +25,7 @@ export function useTranslate(q, rule) { if (toLang.includes(deLang)) { setSamelang(true); } else { - const [trText, isSame] = await transPool.push({ + const [trText, isSame] = await apiTranslate({ translator, q, fromLang, diff --git a/src/libs/auth.js b/src/libs/auth.js index 303590c..8661076 100644 --- a/src/libs/auth.js +++ b/src/libs/auth.js @@ -1,6 +1,6 @@ import storage from "./storage"; import { STOKEY_MSAUTH, URL_MICROSOFT_AUTH } from "../config"; -import { fetchPolyfill } from "./fetch"; +import { fetchData } from "./fetch"; const parseMSToken = (token) => { try { @@ -34,7 +34,7 @@ const _msAuth = () => { } // 缓存没有或失效,查询接口 - token = await fetchPolyfill(URL_MICROSOFT_AUTH); + token = await fetchData(URL_MICROSOFT_AUTH); exp = parseMSToken(token); await storage.setObj(STOKEY_MSAUTH, { token, exp }); return [token, exp]; diff --git a/src/libs/fetch.js b/src/libs/fetch.js index bacb7b4..acfb25b 100644 --- a/src/libs/fetch.js +++ b/src/libs/fetch.js @@ -1,11 +1,16 @@ import { isExt, isGm } from "./browser"; import { sendMsg } from "./msg"; +import { taskPool } from "./pool"; import { MSG_FETCH, + MSG_FETCH_LIMIT, CACHE_NAME, OPT_TRANS_MICROSOFT, OPT_TRANS_OPENAI, + DEFAULT_FETCH_INTERVAL, + DEFAULT_FETCH_LIMIT, } from "../config"; +import { msAuth } from "./auth"; /** * 油猴脚本的请求封装 @@ -47,14 +52,7 @@ const fetchGM = async (input, { method = "GET", headers, body } = {}) => * @param {*} request * @returns */ -const newCacheReq = async (request, translator) => { - if (translator === OPT_TRANS_MICROSOFT) { - request.headers.delete("Authorization"); - } else if (translator === OPT_TRANS_OPENAI) { - request.headers.delete("Authorization"); - request.headers.delete("api-key"); - } - +const newCacheReq = async (request) => { if (request.method !== "GET") { const body = await request.text(); const cacheUrl = new URL(request.url); @@ -66,7 +64,42 @@ const newCacheReq = async (request, translator) => { }; /** - * 请求数据 + * 发起请求 + * @param {*} param0 + * @returns + */ +const fetchApi = async ({ input, init, useUnsafe, translator, token }) => { + if (translator === OPT_TRANS_MICROSOFT) { + init.headers["Authorization"] = `Bearer ${token}`; + } else if (translator === OPT_TRANS_OPENAI) { + init.headers["Authorization"] = `Bearer ${token}`; // // OpenAI + init.headers["api-key"] = token; // Azure OpenAI + } + + if (isGm && !useUnsafe) { + return fetchGM(input, init); + } + return fetch(input, init); +}; + +/** + * 请求池实例 + */ +export const fetchPool = taskPool( + fetchApi, + async ({ translator }) => { + if (translator === OPT_TRANS_MICROSOFT) { + const [token] = await msAuth(); + return { token }; + } + return {}; + }, + DEFAULT_FETCH_INTERVAL, + DEFAULT_FETCH_LIMIT +); + +/** + * 请求数据统一接口 * @param {*} input * @param {*} init * @param {*} opts @@ -75,9 +108,9 @@ const newCacheReq = async (request, translator) => { export const fetchData = async ( input, init, - { useCache, translator, useUnsafe } = {} + { useCache, usePool, translator, useUnsafe, token } = {} ) => { - const cacheReq = await newCacheReq(new Request(input, init), translator); + const cacheReq = await newCacheReq(new Request(input, init)); const cache = await caches.open(CACHE_NAME); let res; @@ -90,25 +123,25 @@ export const fetchData = async ( } } - // 发送请求 if (!res) { - if (isGm && !useUnsafe) { - res = await fetchGM(input, init); + // 发送请求 + if (usePool) { + res = await fetchPool.push({ input, init, useUnsafe, translator, token }); } else { - res = await fetch(input, init); + res = await fetchApi({ input, init, useUnsafe, translator, token }); } - } - if (!res?.ok) { - throw new Error(`response: ${res.statusText}`); - } + if (!res?.ok) { + throw new Error(`response: ${res.statusText}`); + } - // 插入缓存 - if (useCache) { - try { - await cache.put(cacheReq, res.clone()); - } catch (err) { - console.log("[cache put]", err); + // 插入缓存 + if (useCache) { + try { + await cache.put(cacheReq, res.clone()); + } catch (err) { + console.log("[cache put]", err); + } } } @@ -139,3 +172,19 @@ export const fetchPolyfill = async (input, init, opts) => { // 油猴/网页 return await fetchData(input, init, opts); }; + +/** + * 更新 fetch pool 参数 + * @param {*} interval + * @param {*} limit + */ +export const fetchUpdate = async (interval, limit) => { + if (isExt) { + const res = await sendMsg(MSG_FETCH_LIMIT, { interval, limit }); + if (res.error) { + throw new Error(res.error); + } + } else { + fetchPool.update(interval, limit); + } +}; diff --git a/src/libs/pool.js b/src/libs/pool.js index a3c1a74..ecc3336 100644 --- a/src/libs/pool.js +++ b/src/libs/pool.js @@ -1,12 +1,4 @@ -import { - DEFAULT_FETCH_INTERVAL, - DEFAULT_FETCH_LIMIT, - OPT_TRANS_MICROSOFT, -} from "../config"; -import { apiTranslate } from "../apis"; -import { msAuth } from "./auth"; - -const _taskPool = (fn, preFn, _interval = 100, _limit = 100) => { +export const taskPool = (fn, preFn, _interval = 100, _limit = 100) => { const pool = []; const maxRetry = 2; // 最大重试次数 let maxCount = _limit; // 最大数量 @@ -14,11 +6,16 @@ const _taskPool = (fn, preFn, _interval = 100, _limit = 100) => { let interval = _interval; // 间隔时间 let timer; + /** + * 任务池 + * @param {*} item + * @param {*} preArgs + */ const handleTask = async (item, preArgs) => { curCount++; const { args, resolve, reject, retry } = item; try { - const res = await fn(args, preArgs); + const res = await fn({ ...args, ...preArgs }); resolve(res); } catch (err) { if (retry < maxRetry) { @@ -71,16 +68,3 @@ const _taskPool = (fn, preFn, _interval = 100, _limit = 100) => { }, }; }; - -export const transPool = _taskPool( - apiTranslate, - async ({ translator }) => { - if (translator === OPT_TRANS_MICROSOFT) { - const [token] = await msAuth(); - return { token }; - } - return {}; - }, - DEFAULT_FETCH_INTERVAL, - DEFAULT_FETCH_LIMIT -); diff --git a/src/userscript.js b/src/userscript.js index fd6e545..cf6de63 100644 --- a/src/userscript.js +++ b/src/userscript.js @@ -3,10 +3,9 @@ import ReactDOM from "react-dom/client"; import Action from "./views/Action"; import createCache from "@emotion/cache"; import { CacheProvider } from "@emotion/react"; - +import { fetchUpdate } from "./libs/fetch"; import { getRules, matchRule } from "./libs"; import { getSetting } from "./libs"; -import { transPool } from "./libs/pool"; import { Translator } from "./libs/translator"; /** @@ -35,7 +34,7 @@ import { Translator } from "./libs/translator"; // 翻译页面 const { fetchInterval, fetchLimit } = await getSetting(); - transPool.update(fetchInterval, fetchLimit); + fetchUpdate(fetchInterval, fetchLimit); const rules = await getRules(); const rule = matchRule(rules, document.location.href); const translator = new Translator(rule);