Refactor/rpc (#700)

* refactor(rpc): improve type, and type safe (#673)

* refactor(rpc): improve type, and type safe

* revert `pnpm-lock.yaml` file

* improve api merge

* fix: type annotation in background/index.ts

* fix: type annotation in background/index.ts

---------

Co-authored-by: star knight <64941905+starknt@users.noreply.github.com>
This commit is contained in:
Hakadao
2024-05-02 02:45:59 +08:00
committed by GitHub
parent 79f11cbb87
commit dd24072f02
20 changed files with 70 additions and 137 deletions

View File

@@ -13,7 +13,7 @@ function isExtensionUri(url: string) {
// eslint-disable-next-line node/prefer-global/process
if (process.env.FIREFOX) {
browser.webRequest.onBeforeSendHeaders.addListener(
(details) => {
(details: any) => {
const requestHeaders: browser.WebRequest.HttpHeaders = []
if (details.documentUrl) {
const url = new URL(details.documentUrl)

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_ANIME: APIMAP = {
const API_ANIME = {
// 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
getPopularAnimeList: {
url: 'https://api.bilibili.com/pgc/web/rank/list',
@@ -35,7 +35,7 @@ const API_ANIME: APIMAP = {
method: 'get',
},
params: {
coursor: '',
coursor: 0,
name: 'anime',
},
afterHandle: AHS.J_D,
@@ -63,6 +63,6 @@ const API_ANIME: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_ANIME

View File

@@ -2,7 +2,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_AUTH: APIMAP = {
const API_AUTH = {
// biliJct 似乎没有使用
logout: {
url: 'https://passport.bilibili.com/login/exit/v2',
@@ -54,6 +54,6 @@ const API_AUTH: APIMAP = {
},
afterHandle: AHS.J_S,
},
}
} satisfies APIMAP
export default API_AUTH

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_FAVORITE: APIMAP = {
const API_FAVORITE = {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/fav/info.md#%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E7%94%A8%E6%88%B7%E5%88%9B%E5%BB%BA%E7%9A%84%E6%89%80%E6%9C%89%E6%94%B6%E8%97%8F%E5%A4%B9%E4%BF%A1%E6%81%AF
getFavoriteCategories: {
url: 'https://api.bilibili.com/x/v3/fav/folder/created/list-all',
@@ -20,7 +20,7 @@ const API_FAVORITE: APIMAP = {
method: 'get',
},
params: {
media_id: '',
media_id: -1,
pn: 1,
ps: 20,
keyword: '',
@@ -39,11 +39,11 @@ const API_FAVORITE: APIMAP = {
},
params: {
resources: '',
media_id: '',
media_id: 0,
csrf: '',
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_FAVORITE

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_HISTORY: APIMAP = {
const API_HISTORY = {
// 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
getHistoryList: {
url: 'https://api.bilibili.com/x/web-interface/history/cursor',
@@ -11,7 +11,7 @@ const API_HISTORY: APIMAP = {
params: {
ps: 20,
type: '',
view_at: '',
view_at: 0,
},
afterHandle: AHS.J_D,
},
@@ -36,7 +36,7 @@ const API_HISTORY: APIMAP = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: {
aid: '',
kid: '',
csrf: '',
},
},
@@ -74,12 +74,12 @@ const API_HISTORY: APIMAP = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: {
switch: '',
switch: false,
csrf: '',
},
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_HISTORY

View File

@@ -13,8 +13,26 @@ import API_USER from './user'
import API_VIDEO from './video'
import API_WATCHLATER from './watchLater'
export const API_COLLECTION = {
AUTH: API_AUTH,
ANIME: API_ANIME,
HISTORY: API_HISTORY,
FAVORITE: API_FAVORITE,
MOMENT: API_MOMENT,
NOTIFICATION: API_NOTIFICATION,
RANKING: API_RANKING,
SEARCH: API_SEARCH,
USER: API_USER,
VIDEO: API_VIDEO,
WATCHLATER: API_WATCHLATER,
[Symbol.iterator]() {
return Object.values(this).values()
},
}
// Merge all API objects into one
const FullAPI = Object.assign({}, API_AUTH, API_ANIME, API_HISTORY, API_FAVORITE, API_MOMENT, API_NOTIFICATION, API_RANKING, API_SEARCH, API_USER, API_VIDEO, API_WATCHLATER)
const FullAPI = Object.assign({}, ...API_COLLECTION)
// Create a message listener for each API
const handleMessage = apiListenerFactory(FullAPI)

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_MOMENT: APIMAP = {
const API_MOMENT = {
getTopBarNewMomentsCount: {
url: 'https://api.bilibili.com/x/web-interface/dynamic/entrance',
_fetch: {
@@ -39,13 +39,12 @@ const API_MOMENT: APIMAP = {
method: 'get',
},
params: {
type: 268435455,
type: 'all',
offset: 0,
update_baseline: 0,
update_baseline: '',
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_MOMENT

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_NOTIFICATION: APIMAP = {
const API_NOTIFICATION = {
getUnreadMsg: {
url: 'https://api.bilibili.com/x/msgfeed/unread',
_fetch: {
@@ -25,6 +25,6 @@ const API_NOTIFICATION: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_NOTIFICATION

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_RANKING: APIMAP = {
const API_RANKING = {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/7873a79022a5606e2391d93b411a05576a0df111/docs/video_ranking/ranking.md#%E8%8E%B7%E5%8F%96%E5%88%86%E5%8C%BA%E8%A7%86%E9%A2%91%E6%8E%92%E8%A1%8C%E6%A6%9C%E5%88%97%E8%A1%A8
getRankingVideos: {
url: 'https://api.bilibili.com/x/web-interface/ranking/v2',
@@ -25,6 +25,6 @@ const API_RANKING: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_RANKING

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_SEARCH: APIMAP = {
const API_SEARCH = {
getSearchSuggestion: {
url: 'https://s.search.bilibili.com/main/suggest',
_fetch: {
@@ -13,6 +13,6 @@ const API_SEARCH: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_SEARCH

View File

@@ -1,8 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
import API from '../msg.define'
const API_USER: APIMAP = {
const API_USER = {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/e379d904c2753fa30e9083f59016f07e89d19467/docs/login/login_info.md#%E5%AF%BC%E8%88%AA%E6%A0%8F%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF
getUserInfo: {
url: 'https://api.bilibili.com/x/web-interface/nav',
@@ -19,7 +18,7 @@ const API_USER: APIMAP = {
afterHandle: AHS.J_D,
},
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/ed9ac01b6769430aa3f12ad02c2ed337a96924eb/docs/user/relation.md#操作用户关系
[API.USER.RELATION_MODIFY]: {
relationModify: {
url: 'https://api.bilibili.com/x/relation/modify',
_fetch: {
method: 'post',
@@ -32,7 +31,6 @@ const API_USER: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_USER

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_VIDEO: APIMAP = {
const API_VIDEO = {
getRecommendVideos: {
url: 'https://api.bilibili.com/x/web-interface/index/top/feed/rcmd',
_fetch: {
@@ -43,7 +43,7 @@ const API_VIDEO: APIMAP = {
access_key: '',
goto: '',
id: 0,
idx: 0,
idx: '',
reason_id: 1,
device: '',
mobi_app: '',
@@ -94,7 +94,7 @@ const API_VIDEO: APIMAP = {
params: {
csrf: '',
type: 1,
oid: '',
oid: 0,
sort: 0,
nohot: 0,
pn: 1,
@@ -125,10 +125,10 @@ const API_VIDEO: APIMAP = {
fnver: 0,
fnval: 1,
bvid: '',
cid: '',
cid: 0,
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_VIDEO

View File

@@ -1,7 +1,7 @@
import type { APIMAP } from '../utils'
import { AHS } from '../utils'
const API_WATCHLATER: APIMAP = {
const API_WATCHLATER = {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/history&toview/toview.md#%E8%A7%86%E9%A2%91%E6%B7%BB%E5%8A%A0%E7%A8%8D%E5%90%8E%E5%86%8D%E7%9C%8B
saveToWatchLater: {
url: 'https://api.bilibili.com/x/v2/history/toview/add',
@@ -11,7 +11,7 @@ const API_WATCHLATER: APIMAP = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: {
aid: '',
aid: 0,
csrf: '',
},
},
@@ -26,12 +26,12 @@ const API_WATCHLATER: APIMAP = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: {
viewed: '',
viewed: false,
csrf: '',
},
},
params: {
aid: '',
aid: 0,
},
afterHandle: AHS.J_D,
},
@@ -57,6 +57,6 @@ const API_WATCHLATER: APIMAP = {
},
afterHandle: AHS.J_D,
},
}
} satisfies APIMAP
export default API_WATCHLATER

View File

@@ -1,83 +0,0 @@
// 这个文件不要引用其他文件,我怕打包时候会把引用的部分也打包成两分
// en: This file should not reference other files, I am afraid that the referenced part will also be packaged into two parts when packaging
enum AUTH {
LOGOUT = 'logout',
GET_LOGIN_QR_CODE = 'getLoginQRCode',
QR_CODE_LOGIN = 'qrCodeLogin',
}
enum ANIME {
GET_ANIME = 'getAnime',
GET_ANIME_WATCH_LIST = 'getAnimeWatchList',
GET_RECOMMEND_ANIME_LIST = 'getRecommendAnimeList',
GET_ANIME_TIME_TABLE = 'getAnimeTimeTable',
GET_ANIME_DETAIL = 'getAnimeDetail',
GET_POPULAR_ANIME_LIST = 'getPopularAnimeList',
}
enum FAVORITE {
GET_FAVORITE_CATEGORIES = 'getFavoriteCategories',
GET_FAVORITE_RESOURCES = 'getFavoriteResources',
PATCH_DEL_FAVORITE_RESOURCES = 'patchDelFavoriteResources',
}
enum HISTORY {
GET_HISTORY_LIST = 'getHistoryList',
SEARCH_HISTORY_LIST = 'searchHistoryList',
DELETE_HISTORY_ITEM = 'deleteHistoryItem',
CLEAR_ALL_HISTORY = 'clearAllHistory',
GET_HISTORY_PAUSE_STATUS = 'getHistoryPauseStatus',
SET_HISTORY_PAUSE_STATUS = 'setHistoryPauseStatus',
}
enum MOMENT {
GET_TOP_BAR_NEW_MOMENTS_COUNT = 'getTopBarNewMomentsCount',
GET_TOP_BAR_MOMENTS = 'getTopBarMoments',
GET_TOP_BAR_LIVE_MOMENTS = 'getTopBarLiveMoments',
GET_MOMENTS = 'getMoments',
}
enum NOTIFICATION {
GET_UNREAD_MSG = 'getUnreadMsg',
GET_UNREAD_DM = 'getUnreadDm',
}
enum RANKING {
GET_RANKING_VIDEOS = 'getRankingVideos',
GET_RANKING_PGC = 'getRankingPgc',
}
enum SEARCH {
GET_SEARCH_SUGGESTION = 'getSearchSuggestion',
}
enum USER {
GET_USER_INFO = 'getUserInfo',
GET_USER_STAT = 'getUserStat',
RELATION_MODIFY = 'relationModify',
}
enum VIDEO {
GET_RECOMMEND_VIDEOS = 'getRecommendVideos',
GET_APP_RECOMMEND_VIDEOS = 'getAppRecommendVideos',
DISLIKE_VIDEO = 'dislikeVideo',
UNDO_DISLIKE_VIDEO = 'undoDislikeVideo',
GET_VIDEO_INFO = 'getVideoInfo',
GET_VIDEO_COMMENTS = 'getVideoComments',
GET_POPULAR_VIDEOS = 'getPopularVideos',
GET_VIDEO_PREVIEW = 'getVideoPreview',
}
enum WATCHLATER {
SAVE_TO_WATCH_LATER = 'saveToWatchLater',
REMOVE_FROM_WATCH_LATER = 'removeFromWatchLater',
GET_ALL_WATCH_LATER_LIST = 'getAllWatchLaterList',
CLEAR_ALL_WATCH_LATER = 'clearAllWatchLater',
}
const API = {
AUTH,
ANIME,
FAVORITE,
HISTORY,
MOMENT,
NOTIFICATION,
RANKING,
SEARCH,
USER,
VIDEO,
WATCHLATER,
}
export default API

View File

@@ -51,7 +51,7 @@ interface API {
}
// 重载API 可以为函数
type APIFunction = (message: Message, sender?: any, sendResponse?: Function) => any
type APIType = API | APIFunction
export type APIType = API | APIFunction
interface APIMAP {
[key: string]: APIType
}

View File

@@ -1,17 +1,18 @@
import type API from '~/background/msg.define'
import type { API_COLLECTION } from '~/background/messageListeners'
type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>
type APIFunction<T = typeof API> = {
type APIFunction<T = typeof API_COLLECTION> = {
[K in keyof T as CamelCase<string & K>]: {
[P in keyof T[K] as CamelCase<string & P>]: (options?: object) => Promise<any>
// @ts-expect-error allow params
[P in keyof T[K]]: T[K][P] extends Function ? T[K][P] : Lowercase<T[K][P]['_fetch']['method']> extends 'get' ? (options?: Partial<T[K][P]['params']>) => Promise<any> : (options?: Partial<T[K][P]['params'] & T[K][P]['_fetch']['body']>) => Promise<any>
}
}
// eslint-disable-next-line ts/no-unsafe-declaration-merging
export interface APIClient extends APIFunction {
export interface APIClient extends APIFunction<typeof API_COLLECTION> {
}

View File

@@ -85,7 +85,7 @@ async function getFollowedUsersVideos() {
try {
const response: MomentResult = await api.moment.getMoments({
type: 'video',
offset: offset.value,
offset: Number(offset.value),
update_baseline: updateBaseline.value,
})

View File

@@ -181,7 +181,7 @@ async function getAppRecommendVideos() {
const response: AppForYouResult = await api.video.getAppRecommendVideos({
access_key: accessKey.value,
s_locale: settings.value.language === LanguageType.Mandarin_TW || settings.value.language === LanguageType.Cantonese ? 'zh-Hant_TW' : 'zh-Hans_CN',
c_locale: settings.value.language === LanguageType.Mandarin_TW || settings.value.language === LanguageType.Cantonese ? 'zh-Hant_TW' : 'zh-Hans_CN',
c_locate: settings.value.language === LanguageType.Mandarin_TW || settings.value.language === LanguageType.Cantonese ? 'zh-Hant_TW' : 'zh-Hans_CN',
appkey: TVAppKey.appkey,
idx: appVideoList.length > 0 ? appVideoList[appVideoList.length - 1].idx : 1,
})
@@ -287,7 +287,7 @@ function handleAppDislike() {
const params = {
access_key: accessKey.value,
goto: activatedAppVideo.value?.goto,
id: activatedAppVideo.value?.param,
id: Number(activatedAppVideo.value?.param),
// https://github.com/magicdawn/bilibili-app-recommend/blob/cb51f75f415f48235ce048537f2013122c16b56b/src/components/VideoCard/card.service.ts#L115
idx: (Date.now() / 1000).toFixed(0),
reason_id: selectedDislikeReason.value,
@@ -322,9 +322,9 @@ function handleAppUndoDislike(video: AppVideoItem) {
const params = {
access_key: accessKey.value,
goto: video.goto,
id: video.param,
id: Number(video.param),
// https://github.com/magicdawn/bilibili-app-recommend/blob/cb51f75f415f48235ce048537f2013122c16b56b/src/components/VideoCard/card.service.ts#L115
idx: (Date.now() / 1000).toFixed(0),
idx: Number((Date.now() / 1000).toFixed(0)),
reason_id: selectedDislikeReason.value, // 1 means dislike, e.g. {"id": 1, "name": "不感兴趣","toast": "将减少相似内容推荐"}
build: 74800100,
device: 'pad',

View File

@@ -87,7 +87,7 @@ async function getFollowedUsersVideos() {
try {
const response: MomentResult = await api.moment.getMoments({
type: 'pgc',
offset: offset.value,
offset: Number(offset.value),
update_baseline: updateBaseline.value,
})

View File

@@ -72,7 +72,7 @@ async function getVideoInfo() {
let res
if (isBV)
res = await api.video.getVideoInfo({ videoId })
res = await api.video.getVideoInfo({ bvid: videoId })
else
res = await api.video.getVideoInfo({ aid: videoId.replace('av', '') })
if (res.code === 0) {