From a04e60f9306919e84898114b052ae9e1a3818e3c Mon Sep 17 00:00:00 2001 From: pengyunfei Date: Fri, 29 Mar 2024 17:55:56 +0800 Subject: [PATCH] Refactor messageListeners and add utils module to simply use api --- src/background/messageListeners/anime.ts | 117 +++++++++-------- src/background/messageListeners/history.ts | 143 ++++++++++----------- src/background/messageListeners/index.ts | 17 ++- src/background/utils.ts | 100 ++++++++++++++ 4 files changed, 244 insertions(+), 133 deletions(-) create mode 100644 src/background/utils.ts diff --git a/src/background/messageListeners/anime.ts b/src/background/messageListeners/anime.ts index 4c38742d..535a9b1b 100644 --- a/src/background/messageListeners/anime.ts +++ b/src/background/messageListeners/anime.ts @@ -1,57 +1,66 @@ -import browser from 'webextension-polyfill' +import type { APIMAP, _FETCH } from '../utils' +import { AHS } from '../utils' + +const API_ANIME: APIMAP = { + getPopularAnimeList: { + url: 'https://api.bilibili.com/pgc/web/rank/list', + _fetch: { + method: 'get', + }, + params: { + season_type: 1, + day: 3, + }, + afterHandle: AHS.J_D, + }, + getAnimeWatchList: { + url: 'https://api.bilibili.com/x/space/bangumi/follow/list', + _fetch: { + method: 'get', + }, + params: { + pn: 1, + ps: 15, + type: 1, + follow_status: 0, + vmid: '', + }, + afterHandle: AHS.J_D, + }, + getRecommendAnimeList: { + url: 'https://api.bilibili.com/pgc/page/web/v3/feed', + _fetch: { + method: 'get', + }, + params: { + coursor: '', + name: 'anime', + }, + afterHandle: AHS.J_D, + }, + getAnimeTimeTable: { + url: 'https://api.bilibili.com/pgc/web/timeline', + _fetch: { + method: 'get', + }, + params: { + types: 1, + before: 6, + after: 6, + }, + afterHandle: AHS.J_D, + }, + getAnimeDetail: { + url: 'https://api.bilibili.com/pgc/view/web/season', + _fetch: { + method: 'get', + }, + params: { + ep_id: '234406', + }, + afterHandle: AHS.J_D, + }, -function handleMessage(message: any) { - // get popular anime list - if (message.contentScriptQuery === 'getPopularAnimeList') { - const url - = 'https://api.bilibili.com/pgc/web/rank/list?season_type=1&day=3' - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/36e250090800793b41b223b55eefdcbb9391b53e/user/space.md#%E6%9F%A5%E8%AF%A2%E7%94%A8%E6%88%B7%E8%BF%BD%E7%95%AA%E8%BF%BD%E5%89%A7%E6%98%8E%E7%BB%86 - else if (message.contentScriptQuery === 'getAnimeWatchList') { - const url = `https://api.bilibili.com/x/space/bangumi/follow/list?type=1&follow_status=0&pn=${message.pn}&ps=${message.ps}&vmid=${message.vmid}` - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - else if (message.contentScriptQuery === 'getRecommendAnimeList') { - const url = `https://api.bilibili.com/pgc/page/web/v3/feed?name=anime&coursor=${ - message.coursor ?? '' - }` - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/bangumi/timeline.md#%E7%95%AA%E5%89%A7%E6%88%96%E5%BD%B1%E8%A7%86%E6%97%B6%E9%97%B4%E7%BA%BF - else if (message.contentScriptQuery === 'getAnimeTimeTable') { - const url - = 'https://api.bilibili.com/pgc/web/timeline?types=1&before=6&after=6' - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - else if (message.contentScriptQuery === 'getAnimeDetail') { - const url = 'https://api.bilibili.com/pgc/view/web/season?ep_id=234406' - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // TODO: https://api.bilibili.com/pgc/season/index/condition?season_type=1&type=1 } -function handleConnect() { - browser.runtime.onMessage.removeListener(handleMessage) - browser.runtime.onMessage.addListener(handleMessage) -} - -export function setupAnimeMsgLstnr() { - browser.runtime.onConnect.removeListener(handleConnect) - browser.runtime.onConnect.addListener(handleConnect) -} +export default API_ANIME diff --git a/src/background/messageListeners/history.ts b/src/background/messageListeners/history.ts index b438ad9d..265dcea7 100644 --- a/src/background/messageListeners/history.ts +++ b/src/background/messageListeners/history.ts @@ -1,81 +1,74 @@ -import browser from 'webextension-polyfill' +import type { APIMAP, _FETCH } from '../utils' +import { AHS } from '../utils' -function handleMessage(message: any) { - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/history.md#%E8%8E%B7%E5%8F%96%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E5%88%97%E8%A1%A8_web%E7%AB%AF - if (message.contentScriptQuery === 'getHistoryList') { - const url = `https://api.bilibili.com/x/web-interface/history/cursor?ps=20&type=${message.type}&view_at=${message.viewAt}` - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - else if (message.contentScriptQuery === 'searchHistoryList') { - const url = `https://api.bilibili.com/x/web-goblin/history/search?pn=${message.pn}&keyword=${message.keyword}&business=all` - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/history.md#%E5%88%A0%E9%99%A4%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95 - else if (message.contentScriptQuery === 'deleteHistoryItem') { - const url = 'https://api.bilibili.com/x/v2/history/delete' - return fetch(url, { - method: 'POST', +const API_HISTORY: APIMAP = { + getHistoryList: { + url: 'https://api.bilibili.com/x/web-interface/history/cursor', + _fetch: { + method: 'get', + }, + params: { + ps: 20, + type: '', + view_at: '', + }, + afterHandle: AHS.J_D, + }, + searchHistoryList: { + url: 'https://api.bilibili.com/x/web-goblin/history/search', + _fetch: { + method: 'get', + }, + params: { + pn: 1, + keyword: '', + business: 'all', + }, + afterHandle: AHS.J_D, + }, + deleteHistoryItem: { + url: 'https://api.bilibili.com/x/v2/history/delete', + _fetch: { + method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', }, - body: new URLSearchParams({ - kid: message.kid, - csrf: message.csrf, - }), - }) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/history.md#%E6%B8%85%E7%A9%BA%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95 - else if (message.contentScriptQuery === 'clearAllHistory') { - const url = 'https://api.bilibili.com/x/v2/history/clear' - return fetch(url, { - method: 'POST', - body: new URLSearchParams({ - csrf: message.csrf, - }), - }) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/history.md#%E6%9F%A5%E8%AF%A2%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E5%81%9C%E7%94%A8%E7%8A%B6%E6%80%81 - else if (message.contentScriptQuery === 'getHistoryPauseStatus') { - const url = 'https://api.bilibili.com/x/v2/history/shadow' - return fetch(url) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/history.md#%E5%81%9C%E7%94%A8%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95 - else if (message.contentScriptQuery === 'setHistoryPauseStatus') { - const url = 'https://api.bilibili.com/x/v2/history/shadow/set' - return fetch(url, { - method: 'POST', - body: new URLSearchParams({ - switch: message.switch, - csrf: message.csrf, - }), - }) - .then(response => response.json()) - .then(data => data) - .catch(error => console.error(error)) - } + }, + params: { + kid: '', + csrf: '', + }, + afterHandle: AHS.J_D, + }, + clearAllHistory: { + url: 'https://api.bilibili.com/x/v2/history/clear', + _fetch: { + method: 'post', + }, + params: { + csrf: '', + }, + afterHandle: AHS.J_D, + }, + getHistoryPauseStatus: { + url: 'https://api.bilibili.com/x/v2/history/shadow', + _fetch: { + method: 'get', + }, + params: {}, + afterHandle: AHS.J_D, + }, + setHistoryPauseStatus: { + url: 'https://api.bilibili.com/x/v2/history/shadow/set', + _fetch: { + method: 'post', + }, + params: { + switch: '', + csrf: '', + }, + afterHandle: AHS.J_D, + }, } -function handleConnect() { - browser.runtime.onMessage.removeListener(handleMessage) - browser.runtime.onMessage.addListener(handleMessage) -} - -export function setupHistoryMsgLstnr() { - browser.runtime.onConnect.removeListener(handleConnect) - browser.runtime.onConnect.addListener(handleConnect) -} +export default API_HISTORY diff --git a/src/background/messageListeners/index.ts b/src/background/messageListeners/index.ts index d2888651..5a709923 100644 --- a/src/background/messageListeners/index.ts +++ b/src/background/messageListeners/index.ts @@ -1,11 +1,13 @@ -import { setupAnimeMsgLstnr } from './anime' +import browser from 'webextension-polyfill' +import { apiListenerFactory } from '../utils' +import API_ANIME from './anime' import { setupAuthMsgLstnr } from './auth' import { setupVideoMsgLstnr } from './video' import { setupUserMsgLstnr } from './user' import { setupSearchMsgLstnr } from './search' import { setupNotificationMsgLstnr } from './notification' import { setupMomentMsgLstnr } from './moment' -import { setupHistoryMsgLstnr } from './history' +import API_HISTORY from './history' import { setupFavoriteMsgLstnr } from './favorite' import { setupWatchLaterMsgLstnr } from './watchLater' import { setupRankingMsgLstnr } from './ranking' @@ -17,9 +19,16 @@ export function setupAllMsgLstnrs() { setupSearchMsgLstnr() setupNotificationMsgLstnr() setupMomentMsgLstnr() - setupHistoryMsgLstnr() setupFavoriteMsgLstnr() - setupAnimeMsgLstnr() setupWatchLaterMsgLstnr() setupRankingMsgLstnr() + + // 上面的会全部删除, 每个文件只保留定义API 的对象, 在这里进行mixin + // 然后整个开始监听 + + const FullAPI = Object.assign({}, API_ANIME, API_HISTORY) + + const handleMessage = apiListenerFactory(FullAPI) + browser.runtime.onMessage.removeListener(handleMessage) + browser.runtime.onMessage.addListener(handleMessage) } diff --git a/src/background/utils.ts b/src/background/utils.ts new file mode 100644 index 00000000..274618e0 --- /dev/null +++ b/src/background/utils.ts @@ -0,0 +1,100 @@ +// 对于fetch的常见后处理 +// 1. 直接返回data +// 2. json化后返回data + +type FetchAfterHandler = ((data: Response) => Promise) | ((data: any) => any) + +function toJsonHandler(data: Response): Promise { + return data.json() +} +function toData(data: Promise): Promise { + return data +} + +// if need sendResponse, use this +function sendResponseHandler(sendResponse: any) { + return (data: any) => sendResponse(data) +} + +// 定义后处理流 +const AHS: { + J_D: FetchAfterHandler[] + J_S: FetchAfterHandler[] +} = { + J_D: [toJsonHandler, toData], + J_S: [toJsonHandler, sendResponseHandler], +} + +interface Message { + contentScriptQuery: string + [key: string]: any +} + +interface _FETCH { + method: string + headers?: { + [key: string]: any + } + body?: any +} + +interface API { + url: string + _fetch: _FETCH + params: { + [key: string]: any + } + afterHandle: ((response: Response) => Response | Promise)[] +} +interface APIMAP { + [key: string]: API +} +// 工厂函数API_LISTENER_FACTORY +function apiListenerFactory(API_MAP: APIMAP) { + return (message: Message) => { + if (API_MAP[message?.contentScriptQuery]) { + try { + let { contentScriptQuery, ...rest } = message + rest = rest || {} + const { _fetch, url, params, afterHandle } = API_MAP[contentScriptQuery] as API + const { method, headers, body } = _fetch as _FETCH + const targetParams = Object.assign({}, params, rest) + let targetUrl = url + let targetBody = Object.assign({}, body) + + if (method === 'get') { + const urlParams = new URLSearchParams() + for (const key in targetParams) + urlParams.append(key, targetParams[key]) + targetUrl += `?${urlParams.toString()}` + } + else { + targetBody = JSON.stringify(targetParams) + } + // get cant take body + const fetchOpt = method === 'get' ? { method, headers } : { method, headers, body: targetBody } + let baseFunc = fetch(targetUrl, fetchOpt) + afterHandle.forEach(func => baseFunc = baseFunc.then(func)) + baseFunc.catch(console.error) + + return baseFunc + } + catch (e) { + console.error(e) + } + } + } +} + +export { + FetchAfterHandler, + toJsonHandler, + toData, + sendResponseHandler, + AHS, + Message, + _FETCH, + API, + APIMAP, + apiListenerFactory, +}