diff --git a/src/io/com/bilibili/account/api/member/getCardByMid.ts b/src/io/com/bilibili/account/api/member/getCardByMid.ts index 50208f4..a1588e6 100644 --- a/src/io/com/bilibili/account/api/member/getCardByMid.ts +++ b/src/io/com/bilibili/account/api/member/getCardByMid.ts @@ -3,15 +3,14 @@ import { Account } from "../../idenx"; export async function getCardByMid( mid: string | number, ) { - if (CATCH[mid]) return CATCH[mid]; const url = new URL(Account + '/api/member/getCardByMid'); url.searchParams.set('mid', mid); - const response = await fetch(url); - const json = await response.json(); - return (CATCH[mid] = json.card); + CATCH[mid] || (CATCH[mid] = fetch(url)); + const json = await (await CATCH[mid]).clone().json(); + return json.card; } -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IGetCardByMid { DisplayRank: string; diff --git a/src/io/com/bilibili/api/pgc/season/web/related/recommend.ts b/src/io/com/bilibili/api/pgc/season/web/related/recommend.ts index 25b3c45..c2196a4 100644 --- a/src/io/com/bilibili/api/pgc/season/web/related/recommend.ts +++ b/src/io/com/bilibili/api/pgc/season/web/related/recommend.ts @@ -2,15 +2,14 @@ import { Api } from "../../../.."; /** 获取番剧推荐 */ export async function recommend(season_id: number) { - if (CATCH[season_id]) return CATCH[season_id]; const url = new URL(Api + '/pgc/season/web/related/recommend'); url.searchParams.set('season_id', season_id); - const response = await fetch(url, { credentials: 'include' }); - return CATCH[season_id] = (await response.json()).data.season; + CATCH[season_id] || (CATCH[season_id] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[season_id]).clone().json()).data.season; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IRecommend { actor: string; diff --git a/src/io/com/bilibili/api/pgc/view/v2/app/season.ts b/src/io/com/bilibili/api/pgc/view/v2/app/season.ts index 0d03b1a..df36e6f 100644 --- a/src/io/com/bilibili/api/pgc/view/v2/app/season.ts +++ b/src/io/com/bilibili/api/pgc/view/v2/app/season.ts @@ -5,16 +5,15 @@ import { EP_STATUS } from "../../../../../../../stat"; /** APP端pgc信息,或可用于查询区域限制番剧 */ export async function pgcAppSeason({ season_id, ep_id, access_key }: IPgcAppSeasonIn) { const key = ep_id ? `ep_id=${ep_id}` : `season_id=${season_id}`; - if (CATCH[key]) return CATCH[key]; const url = new URL(Api + '/pgc/view/v2/app/season'); ep_id ? url.searchParams.set('ep_id', ep_id) : (season_id && url.searchParams.set('season_id', season_id)); access_key && url.searchParams.set('access_key', access_key); - const response = await fetch(sign(url, '1d8b6e7d45233436'), access_key ? undefined : { credentials: 'include' }); - return (CATCH[key] = (await response.json()).data); + CATCH[key] || (CATCH[key] = fetch(sign(url, '1d8b6e7d45233436'), access_key ? undefined : { credentials: 'include' })); + return (await ((await CATCH[key]).clone()).json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IPgcAppSeasonIn { /** 必须二选一 */ diff --git a/src/io/com/bilibili/api/pgc/view/web/season.ts b/src/io/com/bilibili/api/pgc/view/web/season.ts index 919cb3a..1b627cb 100644 --- a/src/io/com/bilibili/api/pgc/view/web/season.ts +++ b/src/io/com/bilibili/api/pgc/view/web/season.ts @@ -3,13 +3,12 @@ import { EP_STATUS } from "../../../../../../stat"; export async function season(params: ISeasonIn) { const param = params.ep_id ? `ep_id=${params.ep_id}` : `season_id=${params.season_id}`; - if (CATCH[param]) return CATCH[param]; - const response = await fetch(Api + `/pgc/view/web/season?${param}`, { credentials: 'include' }); - return CATCH[param] = (await response.json()).result; + CATCH[param] || (CATCH[param] = fetch(Api + `/pgc/view/web/season?${param}`, { credentials: 'include' })); + return (await (await CATCH[param]).clone().json()).result; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface ISeasonIn { ep_id?: number; diff --git a/src/io/com/bilibili/api/pgc/view/web/season/user/section.ts b/src/io/com/bilibili/api/pgc/view/web/season/user/section.ts index f49f1c5..96b82e5 100644 --- a/src/io/com/bilibili/api/pgc/view/web/season/user/section.ts +++ b/src/io/com/bilibili/api/pgc/view/web/season/user/section.ts @@ -1,14 +1,13 @@ import { Api } from "../../../../.."; export async function pgcSection(season_id: number) { - if (CATCH[season_id]) return CATCH[season_id]; const url = new URL(Api + '/pgc/web/season/section'); url.searchParams.set('season_id', season_id); - const response = await fetch(url, { credentials: 'include' }); - return (CATCH[season_id] = (await response.json()).result); + CATCH[season_id] || (CATCH[season_id] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[season_id]).clone().json()).result; } -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IPgcSection { main_section: { diff --git a/src/io/com/bilibili/api/pugv/view/web/season.ts b/src/io/com/bilibili/api/pugv/view/web/season.ts index fe36f17..9460524 100644 --- a/src/io/com/bilibili/api/pugv/view/web/season.ts +++ b/src/io/com/bilibili/api/pugv/view/web/season.ts @@ -3,13 +3,12 @@ import { Api } from "../../.."; /** 课程基本信息 */ export async function pugvSeason(params: ISeasonIn) { const param = params.season_id ? `season_id=${params.season_id}` : `ep_id=${params.ep_id}`; - if (CATCH[param]) return CATCH[param]; - const response = await fetch(Api + `/pugv/view/web/season?${param}`, { credentials: 'include' }); - return CATCH[param] = (await response.json()).data; + CATCH[param] || (CATCH[param] = fetch(Api + `/pugv/view/web/season?${param}`, { credentials: 'include' })); + return (await (await CATCH[param]).clone().json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface ISeasonIn { ep_id?: number; diff --git a/src/io/com/bilibili/api/x/article/cards.ts b/src/io/com/bilibili/api/x/article/cards.ts index 930fd12..cad8018 100644 --- a/src/io/com/bilibili/api/x/article/cards.ts +++ b/src/io/com/bilibili/api/x/article/cards.ts @@ -13,16 +13,15 @@ export async function cards(param: ICardsIn | string[]) { } if (!arr.length) throw new Error('输入参数不能为空!'); const ids = arr.join(','); - if (CATCH[ids]) return CATCH[ids]; const url = new URL(Api + '/x/article/cards'); url.searchParams.set('ids', ids); - const response = await fetch(url); - const json = await response.json(); - return CATCH[ids] = >json.data; + CATCH[ids] || (CATCH[ids] = fetch(url)); + const json = await (await CATCH[ids]).clone().json(); + return >json.data; } /** 同一请求缓存 */ -const CATCH: Record> = {}; +const CATCH: Record> = {}; interface ICardsIn { av?: number | number[], diff --git a/src/io/com/bilibili/api/x/player/pagelist.ts b/src/io/com/bilibili/api/x/player/pagelist.ts index 8c59c86..05ad2e9 100644 --- a/src/io/com/bilibili/api/x/player/pagelist.ts +++ b/src/io/com/bilibili/api/x/player/pagelist.ts @@ -7,15 +7,14 @@ import { Api } from "../.."; * @param aid */ export async function pagelist(aid: number) { - if (CATCH[aid]) return CATCH[aid]; const url = new URL(Api + '/x/player/pagelist'); url.searchParams.set('aid', aid); - const response = await fetch(url, { credentials: 'include' }); - return CATCH[aid] = (await response.json()).data; + CATCH[aid] || (CATCH[aid] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[aid]).clone().json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IPagelist { cid: number; diff --git a/src/io/com/bilibili/api/x/space/acc/info.ts b/src/io/com/bilibili/api/x/space/acc/info.ts index fe12bf9..76ffcb7 100644 --- a/src/io/com/bilibili/api/x/space/acc/info.ts +++ b/src/io/com/bilibili/api/x/space/acc/info.ts @@ -2,15 +2,14 @@ import { Api } from "../../.."; export async function accInfo(mid: string | number, ) { - if (CATCH[mid]) return CATCH[mid]; const url = new URL(Api + '/x/space/acc/info'); url.searchParams.set('mid', mid); - const response = await fetch(url, { credentials: 'include' }); - const json = await response.json(); - return (CATCH[mid] = json.data); + CATCH[mid] || (CATCH[mid] = fetch(url, { credentials: 'include' })); + const json = await (await CATCH[mid]).clone().json(); + return json.data; } -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IAccInfo { birthday: string; diff --git a/src/io/com/bilibili/api/x/v2/history/toview/web.ts b/src/io/com/bilibili/api/x/v2/history/toview/web.ts index e59d915..54ebfc7 100644 --- a/src/io/com/bilibili/api/x/v2/history/toview/web.ts +++ b/src/io/com/bilibili/api/x/v2/history/toview/web.ts @@ -3,10 +3,13 @@ import { Api } from "../../../.."; export async function toviewWeb(ps?: number) { const url = new URL(Api + '/x/v2/history/toview/web'); ps && url.searchParams.set('ps', ps); - const response = await fetch(url, { credentials: 'include' }); - return (await response.json()).data.list; + CATCH[ps || -1] || (CATCH[ps || -1] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[ps || -1]).clone().json()).data.list; } +/** 同一请求缓存 */ +const CATCH: Record> = {}; + export interface IToviewWeb { add_at: number; aid: number; diff --git a/src/io/com/bilibili/api/x/v3/fav/resource/list.ts b/src/io/com/bilibili/api/x/v3/fav/resource/list.ts index 5868ec0..4400818 100644 --- a/src/io/com/bilibili/api/x/v3/fav/resource/list.ts +++ b/src/io/com/bilibili/api/x/v3/fav/resource/list.ts @@ -11,7 +11,6 @@ export async function favResourceList( pn = 1, ) { const key = `${media_id},${pn}`; - if (CATCH[key]) return CATCH[key]; const url = new URL(Api + '/x/v3/fav/resource/list'); url.searchParams.set('media_id', media_id); url.searchParams.set('pn', pn); @@ -21,11 +20,11 @@ export async function favResourceList( url.searchParams.set('type', '0'); url.searchParams.set('tid', '0'); url.searchParams.set('platform', 'web'); - const response = await fetch(url, { credentials: 'include' }); - return (CATCH[key] = (await response.json()).data); + CATCH[key] || (CATCH[key] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[key]).clone().json()).data; } -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IFavResourceList { has_more: boolean; diff --git a/src/io/com/bilibili/api/x/web-interface/archive/related.ts b/src/io/com/bilibili/api/x/web-interface/archive/related.ts index f6d911b..cd68496 100644 --- a/src/io/com/bilibili/api/x/web-interface/archive/related.ts +++ b/src/io/com/bilibili/api/x/web-interface/archive/related.ts @@ -6,15 +6,14 @@ import { Api } from "../../.."; * @param aid 本视频aid */ export async function related(aid: number) { - if (CATCH[aid]) return CATCH[aid]; const url = new URL(Api + '/x/web-interface/archive/related'); url.searchParams.set('aid', aid); - const response = await fetch(url, { credentials: 'include' }); - return CATCH[aid] = (await response.json()).data; + CATCH[aid] || (CATCH[aid] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[aid]).clone().json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; export interface IRelated { aid: number; diff --git a/src/io/com/bilibili/api/x/web-interface/card.ts b/src/io/com/bilibili/api/x/web-interface/card.ts index 9b40286..9fb9d79 100644 --- a/src/io/com/bilibili/api/x/web-interface/card.ts +++ b/src/io/com/bilibili/api/x/web-interface/card.ts @@ -3,20 +3,19 @@ import { Api } from "../.."; export async function card( mid: string | number, ) { - if (CATCH[mid]) return CATCH[mid]; const url = new URL(Api + '/x/web-interface/card'); url.searchParams.set('mid', mid); url.searchParams.set('photo', '1'); - const response = await fetch(url, { credentials: 'include' }); - const json = await response.json(); - return (CATCH[mid] = json.data); + CATCH[mid] || (CATCH[mid] = fetch(url, { credentials: 'include' })); + const json = await (await CATCH[mid]).clone().json(); + return json.data; } card.noCatch = function (mid: string | number,) { delete CATCH[mid]; } -const CATCH: Record = {}; +const CATCH: Record> = {}; interface ICard { archive_count: number; diff --git a/src/io/com/bilibili/api/x/web-interface/view/detail.ts b/src/io/com/bilibili/api/x/web-interface/view/detail.ts index 854456c..2c00c62 100644 --- a/src/io/com/bilibili/api/x/web-interface/view/detail.ts +++ b/src/io/com/bilibili/api/x/web-interface/view/detail.ts @@ -2,15 +2,14 @@ import { Api } from "../../.."; import { IRelated } from "../archive/related"; export async function detail(aid: number) { - if (CATCH[aid]) return CATCH[aid]; const url = new URL(Api + '/x/web-interface/view/detail'); url.searchParams.set('aid', aid); - const response = await fetch(url, { credentials: 'include' }); - return CATCH[aid] = (await response.json()).data; + CATCH[aid] || (CATCH[aid] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[aid]).clone().json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IDetail { Card: ICard; diff --git a/src/io/com/bilibili/api/x/web-show/page/header.ts b/src/io/com/bilibili/api/x/web-show/page/header.ts index 83f66d1..85b1ba9 100644 --- a/src/io/com/bilibili/api/x/web-show/page/header.ts +++ b/src/io/com/bilibili/api/x/web-show/page/header.ts @@ -6,15 +6,14 @@ import { Api } from "../../.."; * @param resource_id 资源id */ export async function header(resource_id = 142) { - if (CATCH[resource_id]) return CATCH[resource_id]; const url = new URL(Api + '/x/web-show/page/header'); url.searchParams.set('resource_id', resource_id); - const response = await fetch(url, { credentials: 'include' }); - return CATCH[resource_id] = (await response.json()).data; + CATCH[resource_id] || (CATCH[resource_id] = fetch(url, { credentials: 'include' })); + return (await (await CATCH[resource_id]).clone().json()).data; } /** 同一请求缓存 */ -const CATCH: Record = {}; +const CATCH: Record> = {}; interface IHeader { is_split_layer: number; diff --git a/src/main/bilibili/comment/index.ts b/src/main/bilibili/comment/index.ts index feedede..d5f1022 100644 --- a/src/main/bilibili/comment/index.ts +++ b/src/main/bilibili/comment/index.ts @@ -1,11 +1,16 @@ +import { ROUTER } from ".."; +import { pgcAppSeason } from "../../../io/com/bilibili/api/pgc/view/v2/app/season"; +import { pgcSection } from "../../../io/com/bilibili/api/pgc/view/web/season/user/section"; import { emoteWeb } from "../../../io/com/bilibili/api/x/emote/user/panel/web"; +import { toviewWeb } from "../../../io/com/bilibili/api/x/v2/history/toview/web"; import { reply } from "../../../io/com/bilibili/api/x/v2/reply"; import { action } from "../../../io/com/bilibili/api/x/v2/reply/action"; import { replyAdd } from "../../../io/com/bilibili/api/x/v2/reply/add"; -import { hate } from "../../../io/com/bilibili/api/x/v2/reply/hate"; import { replyMain } from "../../../io/com/bilibili/api/x/v2/reply/main"; +import { favResourceList } from "../../../io/com/bilibili/api/x/v3/fav/resource/list"; import { nav } from "../../../io/com/bilibili/api/x/web-interface/nav"; import svg_emoji from "../../../player/assets/svg/emoji.svg"; +import { AV } from "../../../utils/av"; import { cookie } from "../../../utils/cookie"; import { customElement } from "../../../utils/Decorator/customElement"; import { Element } from "../../../utils/element"; @@ -133,6 +138,12 @@ export class Comment extends HTMLDivElement { #emote?: Awaited>; + #aid = 0; + + #ssid = 0; + + #epid = 0; + constructor() { super(); this.insertAdjacentHTML('beforeend', ``); @@ -263,6 +274,116 @@ export class Comment extends HTMLDivElement { }) } + async navigate(router: ROUTER, url: URL | Location) { + url instanceof Location && (url = new URL(url.href)); + switch (router) { + case ROUTER.AV: { + const path = url.pathname.split('/'); + switch (true) { + case /^av\d+$/i.test(path[2]): { + this.#aid = +path[2].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[2]): { + this.#aid = +AV.fromBV(path[2]); + break; + } + } + if (this.#aid) { + this.oid = this.#aid; + } else { + console.error('解析av号出错~'); + } + break; + } + case ROUTER.BANGUMI: { + const path = url.pathname.split('/'); + switch (true) { + case /^ss\d+$/i.test(path[3]): { + this.#ssid = +path[3].slice(2); + break; + } + case /^ep\d+$/i.test(path[3]): { + this.#epid = +path[3].slice(2); + break; + } + } + if (this.#ssid || this.#epid) { + pgcAppSeason(this.#ssid ? { season_id: this.#ssid } : { ep_id: this.#epid }) + .then(async season => { + this.#ssid || (this.#ssid = season.season_id); + season.modules.forEach(d => { + switch (d.style) { + case "positive": + case "section": { + this.#epid || (this.#epid = d.data.episodes[0]?.ep_id); + if (this.#epid) { + const ep = d.data.episodes.find(d => d.ep_id === this.#epid); + if (ep) { + this.#aid = ep.aid; + } + } + break; + } + } + }); + if (!this.#aid && this.#ssid) { + const d = await pgcSection(this.#ssid); + const eps = d.main_section.episodes.concat(...d.section.map(d => d.episodes)); + const ep = this.#epid ? eps.find(d => d.id === this.#epid) : eps[0]; + if (ep) { + this.#aid = ep.aid; + } + } + this.#aid && (this.oid = this.#aid); + }); + } else { + console.error('解析Bangumi出错~'); + } + break; + } + case ROUTER.TOVIEW: { + const path = url.hash.split('/'); + switch (true) { + case /^av\d+$/i.test(path[1]): { + this.#aid = +path[1].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[1]): { + this.#aid = +AV.fromBV(path[1]); + break; + } + } + toviewWeb().then(toview => { + this.#aid || (toview.length && (this.#aid = toview[0].aid)); + if (this.#aid) { + this.oid = this.#aid; + } else { + console.error('解析稍后再看出错~'); + } + }) + break; + } + case ROUTER.MEDIALIST: { + const path = url.pathname.split('/'); + const ml = +path[2].slice(2); + if (ml) { + favResourceList(ml).then(({ medias }) => { + this.#aid = Number(url.searchParams.get('aid')) || medias[0].id; + if (this.#aid) { + this.oid = this.#aid; + } else { + console.error('解析播放列表出错~'); + } + }) + } else { + console.error('解析播放列表出错~'); + } + break; + } + } + } + init( oid?: number | string, pn?: number, @@ -384,6 +505,9 @@ export class Comment extends HTMLDivElement { } private identify = () => { + this.#aid = 0; + this.#ssid = 0; + this.#epid = 0; this.#oid = 0; this.#pn = 1; this.#sort = 2; diff --git a/src/main/bilibili/desc/index.ts b/src/main/bilibili/desc/index.ts index 0def8f7..298db65 100644 --- a/src/main/bilibili/desc/index.ts +++ b/src/main/bilibili/desc/index.ts @@ -1,11 +1,15 @@ +import { ROUTER } from ".."; import { pgcAppSeason } from "../../../io/com/bilibili/api/pgc/view/v2/app/season"; import { IEpisode, pgcSection } from "../../../io/com/bilibili/api/pgc/view/web/season/user/section"; import { followAdd } from "../../../io/com/bilibili/api/pgc/web/follow/add"; import { followDel } from "../../../io/com/bilibili/api/pgc/web/follow/del"; -import { ICardsOut } from "../../../io/com/bilibili/api/x/article/cards"; +import { cards, ICardsOut } from "../../../io/com/bilibili/api/x/article/cards"; +import { toviewWeb } from "../../../io/com/bilibili/api/x/v2/history/toview/web"; +import { favResourceList } from "../../../io/com/bilibili/api/x/v3/fav/resource/list"; import { detail } from "../../../io/com/bilibili/api/x/web-interface/view/detail"; import svg_heart from "../../../player/assets/svg/heart.svg"; import { customElement } from "../../../utils/Decorator/customElement"; +import { AV } from "../../../utils/av"; import { cookie } from "../../../utils/cookie"; import { Element } from "../../../utils/element"; import { Format } from "../../../utils/fomat"; @@ -65,6 +69,14 @@ export class Desc extends HTMLDivElement { private $detail = Element.add('div', { class: 'bangumi-detail' }, this.$info); + #aid = 0; + + #cid = 0; + + #ssid = 0; + + #epid = 0; + constructor() { super(); this.insertAdjacentHTML('beforeend', ``); @@ -94,7 +106,153 @@ export class Desc extends HTMLDivElement { }); } - update(data: Awaited>) { + async navigate(router: ROUTER, url: URL | Location) { + this.#aid = 0; + this.#cid = 0; + this.#ssid = 0; + this.#epid = 0; + url instanceof Location && (url = new URL(url.href)); + switch (router) { + case ROUTER.AV: { + const path = url.pathname.split('/'); + switch (true) { + case /^av\d+$/i.test(path[2]): { + this.#aid = +path[2].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[2]): { + this.#aid = +AV.fromBV(path[2]); + break; + } + } + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.update(de); + } else { + this.desc(card); + } + } + }); + } else { + console.error('解析av号出错~'); + } + break; + } + case ROUTER.BANGUMI: { + const path = url.pathname.split('/'); + switch (true) { + case /^ss\d+$/i.test(path[3]): { + this.#ssid = +path[3].slice(2); + break; + } + case /^ep\d+$/i.test(path[3]): { + this.#epid = +path[3].slice(2); + break; + } + } + if (this.#ssid || this.#epid) { + pgcAppSeason(this.#ssid ? { season_id: this.#ssid } : { ep_id: this.#epid }) + .then(season => { + this.#ssid || (this.#ssid = season.season_id); + season.modules.forEach(d => { + switch (d.style) { + case "positive": + case "section": { + this.#epid || (this.#epid = d.data.episodes[0]?.ep_id); + break; + } + } + }); + this.bangumi(season, this.#epid).finally(async () => { + if (this.#ssid) { + const d = await pgcSection(this.#ssid); + const eps = d.main_section.episodes.concat(...d.section.map(d => d.episodes)); + const ep = this.#epid ? eps.find(d => d.id === this.#epid) : eps[0]; + if (ep) { + this.#epid = ep.id; + this.banggumiEpisode(eps, this.#epid); + } + } + }); + }); + } else { + console.error('解析Bangumi出错~'); + } + break; + } + case ROUTER.TOVIEW: { + const path = url.hash.split('/'); + switch (true) { + case /^av\d+$/i.test(path[1]): { + this.#aid = +path[1].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[1]): { + this.#aid = +AV.fromBV(path[1]); + break; + } + } + toviewWeb().then(toview => { + this.#aid || (toview.length && (this.#aid = toview[0].aid)); + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.update(de); + } else { + this.desc(card); + } + } + }); + } else { + console.error('解析稍后再看出错~'); + } + }) + break; + } + case ROUTER.MEDIALIST: { + const path = url.pathname.split('/'); + const ml = +path[2].slice(2); + if (ml) { + favResourceList(ml).then(({ medias }) => { + this.#aid = Number(url.searchParams.get('aid')) || medias[0].id; + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.update(de); + } else { + this.desc(card); + } + } + }); + } else { + console.error('解析播放列表出错~'); + } + }) + } else { + console.error('解析播放列表出错~'); + } + break; + } + } + } + + private update(data: Awaited>) { this.desc(data.View); let p = ''; data.Tags.forEach(d => { @@ -103,12 +261,12 @@ export class Desc extends HTMLDivElement { this.$tag.innerHTML = p; } - desc(data: ICardsOut) { + private desc(data: ICardsOut) { this.identify(); this.$m.innerHTML = Format.superLink(data.desc); } - async bangumi(data: Awaited>, epid?: number) { + private async bangumi(data: Awaited>, epid?: number) { this.identify(); this.$desc.classList.add('bangumi'); this.$cover.href = this.$a.href = `//www.bilibili.com/bangumi/media/md${data.media_id}`; @@ -140,7 +298,7 @@ export class Desc extends HTMLDivElement {

${data.evaluate}

`; } - async banggumiEpisode(eps: IEpisode[], epid?: number) { + private async banggumiEpisode(eps: IEpisode[], epid?: number) { this.$episode.insertAdjacentHTML('beforeend', eps.map(d => { return `${d.long_title}${d.badge_info.text}` }).join('')); diff --git a/src/main/bilibili/header/index.ts b/src/main/bilibili/header/index.ts index d444735..6d6c92a 100644 --- a/src/main/bilibili/header/index.ts +++ b/src/main/bilibili/header/index.ts @@ -27,6 +27,7 @@ import { dynamic_num } from "../../../io/com/bilibili/vc/api/dynamic_svr/v1/dyna import { toviewWeb } from "../../../io/com/bilibili/api/x/v2/history/toview/web"; import { medialistRecent } from "../../../io/com/bilibili/api/medialist/gateway/coll/resource/recent"; import { history } from "../../../io/com/bilibili/api/x/v2/history"; +import { ROUTER } from ".."; /** 顶栏 */ @customElement('div') @@ -423,6 +424,25 @@ export class Header extends HTMLDivElement { private past(tsp: number) { return tsp <= 0 ? "今日" : tsp > 0 && tsp <= 864e5 ? "昨日" : tsp > 864e5 && tsp <= 6048e5 ? "近1周" : tsp > 6048e5 && tsp <= 2592e6 ? "1周前" : tsp > 2592e6 && tsp <= 7776e6 ? "1个月前" : "last"; } + + async navigate(router: ROUTER, url: URL | Location) { + this.identify(); + url instanceof Location && (url = new URL(url.href)); + switch (router) { + case ROUTER.AV: + case ROUTER.BANGUMI: + case ROUTER.HOME: + case ROUTER.TOVIEW: + case ROUTER.MEDIALIST: { + this.resource_id = 142; + break; + } + } + } + + private identify = () => { + this.classList.remove('mini'); + } } //////////////////////////// 全局增强 //////////////////////////// diff --git a/src/main/bilibili/index.ts b/src/main/bilibili/index.ts index 2c59192..678d470 100644 --- a/src/main/bilibili/index.ts +++ b/src/main/bilibili/index.ts @@ -2,10 +2,6 @@ import { pgcAppSeason } from "../../io/com/bilibili/api/pgc/view/v2/app/season"; import { pgcSection } from "../../io/com/bilibili/api/pgc/view/web/season/user/section"; import { pugvSeason } from "../../io/com/bilibili/api/pugv/view/web/season"; import { cards } from "../../io/com/bilibili/api/x/article/cards"; -import { pagelist } from "../../io/com/bilibili/api/x/player/pagelist"; -import { toviewWeb } from "../../io/com/bilibili/api/x/v2/history/toview/web"; -import { favResourceList } from "../../io/com/bilibili/api/x/v3/fav/resource/list"; -import { detail } from "../../io/com/bilibili/api/x/web-interface/view/detail"; import { video } from "../../player/area/wrap/video"; import { ev, PLAYER_EVENT } from "../../player/event-target"; import { PLAYER_MODE, PLAYER_STATE } from "../../player/state"; @@ -191,74 +187,11 @@ export class Router { document.body.replaceChildren(this.$header, this.$info, this.$player, this.$desc, this.$comment, this.$footer); this.#p_router = router; } - this.$header.resource_id = 142; - const path = url.pathname.split('/'); - switch (true) { - case /^av\d+$/i.test(path[2]): { - this.aid = +path[2].slice(2); - break; - } - case /^bv1[a-z0-9]{9}$/i.test(path[2]): { - this.aid = +AV.fromBV(path[2]); - break; - } - } - if (this.aid) { - Promise.allSettled([cards({ av: this.aid }), pagelist(this.aid), detail(this.aid)]) - .then(([cards, pagelist, detail]) => { - const d = cards.status === "fulfilled" && cards.value; - const page = pagelist.status === "fulfilled" && pagelist.value; - const de = detail.status === "fulfilled" && detail.value; - if (d) { - const card = d[`av${this.aid}`]; - card.cid && (this.cid = card.cid); - if (page) { - const p = Number(url.searchParams.get('p')) || 1; - this.cid = page[p - 1].cid; - } - if (card.redirect_url) { - const path = card.redirect_url.split('/'); - switch (true) { - case /^ep\d+$/i.test(path[6]): { - this.epid = +path[6].slice(2); - break; - } - case /^ss\d+$/i.test(path[6]): { - this.ssid = +path[6].slice(2); - break; - } - } - } - if (this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid); - (de && de.View.ugc_season) ? this.$player.partUgcSeason(de) : de ? this.$player.getRelated(de.Related.map(d => { - return { - src: d.pic + '@.webp', - title: d.title, - duration: d.duration, - view: d.stat.view, - danmaku: d.stat.danmaku, - author: d.owner.name, - callback() { - navigation?.navigate(`/video/av${d.aid}`); - }, - } - })) : this.$player.getRelated(); - if (de && de.View) { - this.$info.avDetail(de); - this.$desc.update(de); - } else { - this.$info.avCards(card); - this.$desc.desc(card); - } - page && this.$player.partAv(page); - } - } - }); - this.$comment.oid = this.aid; - } else { - console.error('解析av号出错~'); - } + this.$header.navigate(router, url); + this.$info.navigate(router, url); + this.$player.navigate(router, url); + this.$desc.navigate(router, url); + this.$comment.navigate(router, url); break; } case ROUTER.BANGUMI: { @@ -267,62 +200,11 @@ export class Router { document.body.replaceChildren(this.$header, this.$info, this.$player, this.$desc, this.$comment, this.$footer); this.#p_router = router; } - this.$header.resource_id = 142; - const path = url.pathname.split('/'); - switch (true) { - case /^ss\d+$/i.test(path[3]): { - this.ssid = +path[3].slice(2); - break; - } - case /^ep\d+$/i.test(path[3]): { - this.epid = +path[3].slice(2); - break; - } - } - if (this.ssid || this.epid) { - pgcAppSeason(this.ssid ? { season_id: this.ssid } : { ep_id: this.epid }) - .then(async season => { - this.ssid || (this.ssid = season.season_id); - season.modules.forEach(d => { - switch (d.style) { - case "positive": - case "section": { - this.epid || (this.epid = d.data.episodes[0]?.ep_id); - if (this.epid) { - const ep = d.data.episodes.find(d => d.ep_id === this.epid); - if (ep) { - this.aid = ep.aid; - this.cid = ep.cid; - this.$info.bangumi(season, ep); - } - } - break; - } - } - }); - this.$desc.bangumi(season, this.epid); - if (!this.cid && this.ssid) { - const d = await pgcSection(this.ssid); - const eps = d.main_section.episodes.concat(...d.section.map(d => d.episodes)); - const ep = this.epid ? eps.find(d => d.id === this.epid) : eps[0]; - if (ep) { - this.epid = ep.id; - this.aid = ep.aid; - this.cid = ep.cid; - this.$info.bangumi(season, ep); - this.$desc.banggumiEpisode(eps, this.epid); - } - } - if (this.epid && this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid); - this.$player.getRelated(); - this.aid && (this.$comment.oid = this.aid); - } - this.$player.partBangumi(season); - }); - } else { - console.error('解析Bangumi出错~'); - } + this.$header.navigate(router, url); + this.$info.navigate(router, url); + this.$player.navigate(router, url); + this.$desc.navigate(router, url); + this.$comment.navigate(router, url); break; } case ROUTER.HOME: { @@ -331,7 +213,7 @@ export class Router { document.body.replaceChildren(this.$header, this.$home, this.$footer); this.#p_router = router; } - this.$header.resource_id = 142; + this.$header.navigate(router, url); break; } case ROUTER.TOVIEW: { @@ -340,64 +222,11 @@ export class Router { document.body.replaceChildren(this.$header, this.$info, this.$player, this.$desc, this.$comment, this.$footer); this.#p_router = router; } - this.$header.resource_id = 142; - const path = url.hash.split('/'); - switch (true) { - case /^av\d+$/i.test(path[1]): { - this.aid = +path[1].slice(2); - break; - } - case /^bv1[a-z0-9]{9}$/i.test(path[1]): { - this.aid = +AV.fromBV(path[1]); - break; - } - } - toviewWeb().then(toview => { - this.aid || (toview.length && (this.aid = toview[0].aid)); - if (this.aid) { - Promise.allSettled([cards({ av: this.aid }), pagelist(this.aid), detail(this.aid)]) - .then(([cards, pagelist, detail]) => { - const d = cards.status === "fulfilled" && cards.value; - const page = pagelist.status === "fulfilled" && pagelist.value; - const de = detail.status === "fulfilled" && detail.value; - if (d) { - const card = d[`av${this.aid}`]; - card.cid && (this.cid = card.cid); - if (page && path[2]) { - const p = +path[2].slice(1); - this.cid = page[p - 1].cid; - } - if (card.redirect_url) { - const path = card.redirect_url.split('/'); - switch (true) { - case /^ep\d+$/i.test(path[6]): { - this.epid = +path[6].slice(2); - break; - } - case /^ss\d+$/i.test(path[6]): { - this.ssid = +path[6].slice(2); - break; - } - } - } - if (this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid); - page ? this.$player.partToView(toview, page) : this.$player.partToView(toview); - if (de && de.View) { - this.$info.avDetail(de); - this.$desc.update(de); - } else { - this.$info.avCards(card); - this.$desc.desc(card); - } - } - } - }); - this.$comment.oid = this.aid; - } else { - console.error('解析稍后再看出错~'); - } - }) + this.$header.navigate(router, url); + this.$info.navigate(router, url); + this.$player.navigate(router, url); + this.$desc.navigate(router, url); + this.$comment.navigate(router, url); break; } case ROUTER.MEDIALIST: { @@ -406,70 +235,11 @@ export class Router { document.body.replaceChildren(this.$header, this.$info, this.$player, this.$desc, this.$comment, this.$footer); this.#p_router = router; } - this.$header.resource_id = 142; - const path = url.pathname.split('/'); - const ml = +path[2].slice(2); - if (ml) { - favResourceList(ml).then(({ medias, has_more }) => { - this.aid = Number(url.searchParams.get('aid')) || medias[0].id; - if (this.aid) { - Promise.allSettled([cards({ av: this.aid }), pagelist(this.aid), detail(this.aid)]) - .then(([cards, pagelist, detail]) => { - const d = cards.status === "fulfilled" && cards.value; - const page = pagelist.status === "fulfilled" && pagelist.value; - const de = detail.status === "fulfilled" && detail.value; - if (d) { - const card = d[`av${this.aid}`]; - card.cid && (this.cid = card.cid); - if (page) { - const p = Number(url.searchParams.get('p')) || 1; - this.cid = page[p - 1].cid; - } - if (card.redirect_url) { - const path = card.redirect_url.split('/'); - switch (true) { - case /^ep\d+$/i.test(path[6]): { - this.epid = +path[6].slice(2); - break; - } - case /^ss\d+$/i.test(path[6]): { - this.ssid = +path[6].slice(2); - break; - } - } - } - if (this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid); - page ? this.$player.partMedialist(medias, page) : this.$player.partMedialist(medias); - if (de && de.View) { - this.$info.avDetail(de); - this.$desc.update(de); - } else { - this.$info.avCards(card); - this.$desc.desc(card); - } - } - } - - // 请求更多媒体 - let pn = 2; - const getMore = () => { - favResourceList(ml, pn).then(({ medias, has_more }) => { - pn++; - this.$player.partMedialist(medias); - has_more && getMore(); - }) - } - has_more && getMore(); - }); - this.$comment.oid = this.aid; - } else { - console.error('解析稍后再看出错~'); - } - }) - } else { - console.error('解析播放列表出错~'); - } + this.$header.navigate(router, url); + this.$info.navigate(router, url); + this.$player.navigate(router, url); + this.$desc.navigate(router, url); + this.$comment.navigate(router, url); break; } } @@ -568,7 +338,7 @@ export class Router { } } if (this.epid && this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid, true, GroupKind.Pugv); + this.$player.connect(this.aid, this.cid, this.ssid, this.epid, GroupKind.Pugv); } }); } else { @@ -605,7 +375,7 @@ export class Router { } } if (this.epid && this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid, true); + this.$player.connect(this.aid, this.cid, this.ssid, this.epid); this.$player.getRelated(); } }); @@ -627,7 +397,7 @@ export class Router { } } if (this.cid) { - this.$player.connect(this.aid, this.cid, this.ssid, this.epid, true); + this.$player.connect(this.aid, this.cid, this.ssid, this.epid); this.$player.getRelated(); } }) @@ -784,8 +554,6 @@ export class Router { this.cid = 0; this.ssid = 0; this.epid = 0; - this.$player.classList.remove('nano'); - this.$header.classList.remove('mini'); } } diff --git a/src/main/bilibili/info/index.ts b/src/main/bilibili/info/index.ts index 91d7712..ab1d855 100644 --- a/src/main/bilibili/info/index.ts +++ b/src/main/bilibili/info/index.ts @@ -1,13 +1,16 @@ +import { ROUTER } from ".."; import { pgcAppSeason } from "../../../io/com/bilibili/api/pgc/view/v2/app/season"; -import { IEpisode } from "../../../io/com/bilibili/api/pgc/view/web/season/user/section"; +import { IEpisode, pgcSection } from "../../../io/com/bilibili/api/pgc/view/web/season/user/section"; import { status } from "../../../io/com/bilibili/api/pgc/view/web/season/user/status"; import { followAdd } from "../../../io/com/bilibili/api/pgc/web/follow/add"; import { followDel } from "../../../io/com/bilibili/api/pgc/web/follow/del"; -import { ICardsOut } from "../../../io/com/bilibili/api/x/article/cards"; +import { cards, ICardsOut } from "../../../io/com/bilibili/api/x/article/cards"; import { folder } from "../../../io/com/bilibili/api/x/v2/fav/folder"; import { favAdd } from "../../../io/com/bilibili/api/x/v2/fav/video/add"; import { favDel } from "../../../io/com/bilibili/api/x/v2/fav/video/del"; import { favoured } from "../../../io/com/bilibili/api/x/v2/fav/video/favoured"; +import { toviewWeb } from "../../../io/com/bilibili/api/x/v2/history/toview/web"; +import { favResourceList } from "../../../io/com/bilibili/api/x/v3/fav/resource/list"; import { coins } from "../../../io/com/bilibili/api/x/web-interface/archive/coins"; import { like as hasLike } from "../../../io/com/bilibili/api/x/web-interface/archive/has/like"; import { like } from "../../../io/com/bilibili/api/x/web-interface/archive/like"; @@ -23,6 +26,7 @@ import svg_icon_played from "../../../player/assets/svg/icon-played.svg"; import svg_like_number from "../../../player/assets/svg/like-number.svg"; import svg_message from "../../../player/assets/svg/message.svg"; import { customElement } from "../../../utils/Decorator/customElement"; +import { AV } from "../../../utils/av"; import { cookie } from "../../../utils/cookie"; import { Element } from "../../../utils/element"; import { Format } from "../../../utils/fomat"; @@ -126,6 +130,12 @@ export class Info extends HTMLDivElement { #aid = 0; + #cid = 0; + + #ssid = 0; + + #epid = 0; + #fid_add = new Set(); #fid_del = new Set(); @@ -226,7 +236,156 @@ export class Info extends HTMLDivElement { }); } - avCards(card: ICardsOut) { + async navigate(router: ROUTER, url: URL | Location) { + this.#aid = 0; + this.#cid = 0; + this.#ssid = 0; + this.#epid = 0; + url instanceof Location && (url = new URL(url.href)); + switch (router) { + case ROUTER.AV: { + const path = url.pathname.split('/'); + switch (true) { + case /^av\d+$/i.test(path[2]): { + this.#aid = +path[2].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[2]): { + this.#aid = +AV.fromBV(path[2]); + break; + } + } + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.avDetail(de); + } else { + this.avCards(card); + } + } + }); + } else { + console.error('解析av号出错~'); + } + break; + } + case ROUTER.BANGUMI: { + const path = url.pathname.split('/'); + switch (true) { + case /^ss\d+$/i.test(path[3]): { + this.#ssid = +path[3].slice(2); + break; + } + case /^ep\d+$/i.test(path[3]): { + this.#epid = +path[3].slice(2); + break; + } + } + if (this.#ssid || this.#epid) { + pgcAppSeason(this.#ssid ? { season_id: this.#ssid } : { ep_id: this.#epid }) + .then(async season => { + this.#ssid || (this.#ssid = season.season_id); + season.modules.forEach(d => { + switch (d.style) { + case "positive": + case "section": { + this.#epid || (this.#epid = d.data.episodes[0]?.ep_id); + if (this.#epid) { + const ep = d.data.episodes.find(d => d.ep_id === this.#epid); + if (ep) { + this.#cid = ep.cid; + this.bangumi(season, ep); + } + } + break; + } + } + }); + if (!this.#cid && this.#ssid) { + const d = await pgcSection(this.#ssid); + const eps = d.main_section.episodes.concat(...d.section.map(d => d.episodes)); + const ep = this.#epid ? eps.find(d => d.id === this.#epid) : eps[0]; + if (ep) { + this.bangumi(season, ep); + } + } + }); + } else { + console.error('解析Bangumi出错~'); + } + break; + } + case ROUTER.TOVIEW: { + const path = url.hash.split('/'); + switch (true) { + case /^av\d+$/i.test(path[1]): { + this.#aid = +path[1].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[1]): { + this.#aid = +AV.fromBV(path[1]); + break; + } + } + toviewWeb().then(toview => { + this.#aid || (toview.length && (this.#aid = toview[0].aid)); + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.avDetail(de); + } else { + this.avCards(card); + } + } + }); + } else { + console.error('解析稍后再看出错~'); + } + }) + break; + } + case ROUTER.MEDIALIST: { + const path = url.pathname.split('/'); + const ml = +path[2].slice(2); + if (ml) { + favResourceList(ml).then(({ medias }) => { + this.#aid = Number(url.searchParams.get('aid')) || medias[0].id; + if (this.#aid) { + Promise.allSettled([cards({ av: this.#aid }), detail(this.#aid)]) + .then(([cards, detail]) => { + const d = cards.status === "fulfilled" && cards.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.#aid}`]; + if (de && de.View) { + this.avDetail(de); + } else { + this.avCards(card); + } + } + }); + } else { + console.error('解析播放列表出错~'); + } + }) + } else { + console.error('解析播放列表出错~'); + } + } + } + } + + private avCards(card: ICardsOut) { this.identify(); this.#aid = card.aid; navigator.mediaSession.metadata = new MediaMetadata({ @@ -273,7 +432,7 @@ ${card.stat.his_rank ? `${d.name}`).join(''))); } - async bangumi(data: Awaited>, ep: IEpisode) { + private async bangumi(data: Awaited>, ep: IEpisode) { this.identify(); this.#aid = ep.aid; navigator.mediaSession.metadata = new MediaMetadata({ @@ -302,7 +461,7 @@ ${card.stat.his_rank ? ` { + const d = cards.status === "fulfilled" && cards.value; + const page = pagelist.status === "fulfilled" && pagelist.value; + const de = detail.status === "fulfilled" && detail.value; + if (d) { + const card = d[`av${this.aid}`]; + card.cid && (this.cid = card.cid); + if (page) { + const p = Number(url.searchParams.get('p')) || 1; + this.cid = page[p - 1].cid; + } + if (card.redirect_url) { + const path = card.redirect_url.split('/'); + switch (true) { + case /^ep\d+$/i.test(path[6]): { + this.epid = +path[6].slice(2); + break; + } + case /^ss\d+$/i.test(path[6]): { + this.ssid = +path[6].slice(2); + break; + } + } + } + if (this.cid) { + this.connect(this.aid, this.cid, this.ssid, this.epid); + (de && de.View.ugc_season) ? this.partUgcSeason(de) : de ? this.getRelated(de.Related.map(d => { + return { + src: d.pic + '@.webp', + title: d.title, + duration: d.duration, + view: d.stat.view, + danmaku: d.stat.danmaku, + author: d.owner.name, + callback() { + navigation?.navigate(`/video/av${d.aid}`); + }, + } + })) : this.getRelated(); + page && this.partAv(page); + } + } + }); + } else { + console.error('解析av号出错~'); + } + break; + } + case ROUTER.BANGUMI: { + const path = url.pathname.split('/'); + switch (true) { + case /^ss\d+$/i.test(path[3]): { + this.ssid = +path[3].slice(2); + break; + } + case /^ep\d+$/i.test(path[3]): { + this.epid = +path[3].slice(2); + break; + } + } + if (this.ssid || this.epid) { + pgcAppSeason(this.ssid ? { season_id: this.ssid } : { ep_id: this.epid }) + .then(async season => { + this.ssid || (this.ssid = season.season_id); + season.modules.forEach(d => { + switch (d.style) { + case "positive": + case "section": { + this.epid || (this.epid = d.data.episodes[0]?.ep_id); + if (this.epid) { + const ep = d.data.episodes.find(d => d.ep_id === this.epid); + if (ep) { + this.aid = ep.aid; + this.cid = ep.cid; + } + } + break; + } + } + }); + if (!this.cid && this.ssid) { + const d = await pgcSection(this.ssid); + const eps = d.main_section.episodes.concat(...d.section.map(d => d.episodes)); + const ep = this.epid ? eps.find(d => d.id === this.epid) : eps[0]; + if (ep) { + this.epid = ep.id; + this.aid = ep.aid; + this.cid = ep.cid; + } + } + if (this.epid && this.cid) { + this.connect(this.aid, this.cid, this.ssid, this.epid); + this.getRelated(); + } + this.partBangumi(season); + }); + } else { + console.error('解析Bangumi出错~'); + } + break; + } + case ROUTER.TOVIEW: { + const path = url.hash.split('/'); + switch (true) { + case /^av\d+$/i.test(path[1]): { + this.aid = +path[1].slice(2); + break; + } + case /^bv1[a-z0-9]{9}$/i.test(path[1]): { + this.aid = +AV.fromBV(path[1]); + break; + } + } + toviewWeb().then(toview => { + this.aid || (toview.length && (this.aid = toview[0].aid)); + if (this.aid) { + Promise.allSettled([cards({ av: this.aid }), pagelist(this.aid)]) + .then(([cards, pagelist]) => { + const d = cards.status === "fulfilled" && cards.value; + const page = pagelist.status === "fulfilled" && pagelist.value; + if (d) { + const card = d[`av${this.aid}`]; + card.cid && (this.cid = card.cid); + if (page && path[2]) { + const p = +path[2].slice(1); + this.cid = page[p - 1].cid; + } + if (card.redirect_url) { + const path = card.redirect_url.split('/'); + switch (true) { + case /^ep\d+$/i.test(path[6]): { + this.epid = +path[6].slice(2); + break; + } + case /^ss\d+$/i.test(path[6]): { + this.ssid = +path[6].slice(2); + break; + } + } + } + if (this.cid) { + this.connect(this.aid, this.cid, this.ssid, this.epid); + page ? this.partToView(toview, page) : this.partToView(toview); + } + } + }); + } else { + console.error('解析稍后再看出错~'); + } + }) + break; + } + case ROUTER.MEDIALIST: { + const path = url.pathname.split('/'); + const ml = +path[2].slice(2); + if (ml) { + favResourceList(ml).then(({ medias, has_more }) => { + this.aid = Number(url.searchParams.get('aid')) || medias[0].id; + if (this.aid) { + Promise.allSettled([cards({ av: this.aid }), pagelist(this.aid)]) + .then(([cards, pagelist]) => { + const d = cards.status === "fulfilled" && cards.value; + const page = pagelist.status === "fulfilled" && pagelist.value; + if (d) { + const card = d[`av${this.aid}`]; + card.cid && (this.cid = card.cid); + if (page) { + const p = Number(url.searchParams.get('p')) || 1; + this.cid = page[p - 1].cid; + } + if (card.redirect_url) { + const path = card.redirect_url.split('/'); + switch (true) { + case /^ep\d+$/i.test(path[6]): { + this.epid = +path[6].slice(2); + break; + } + case /^ss\d+$/i.test(path[6]): { + this.ssid = +path[6].slice(2); + break; + } + } + } + if (this.cid) { + this.connect(this.aid, this.cid, this.ssid, this.epid); + page ? this.partMedialist(medias, page) : this.partMedialist(medias); + } + } + + // 请求更多媒体 + let pn = 2; + const getMore = () => { + favResourceList(ml, pn).then(({ medias, has_more }) => { + pn++; + this.partMedialist(medias); + has_more && getMore(); + }) + } + has_more && getMore(); + }); + } else { + console.error('解析播放列表出错~'); + } + }) + } else { + console.error('解析播放列表出错~'); + } + break; + } + } + } + connect( aid: number, cid: number, ssid?: number, epid?: number, - force = false, kind?: GroupKind, ) { - if (this.cid !== cid || force) { - this.identify(); - Reflect.set(self, 'aid', this.aid = aid); - Reflect.set(self, 'cid', this.cid = cid); - ssid && (this.ssid = ssid); - epid && (this.epid = epid); - this.qn = +cookie.get('CURRENT_QUALITY') || 0; - if (kind === GroupKind.Pugv && epid) { - pugvPlayurl(aid, cid, epid, this.qn) - .then(d => { - this.attachMedia(d); - d.is_preview && ev.trigger(PLAYER_EVENT.TOAST, '正在观看预览'); - }) - .finally(() => { - video.addEventListener('canplay', () => { - this.getDanmaku(); - this.getUser(); - this.getVideoShot(); - }, { once: true }); - }); - } else if (epid) { - pgcPlayurl(aid, cid, epid, this.qn).then(d => { + this.identify(); + Reflect.set(self, 'aid', this.aid = aid); + Reflect.set(self, 'cid', this.cid = cid); + ssid && (this.ssid = ssid); + epid && (this.epid = epid); + this.qn = +cookie.get('CURRENT_QUALITY') || 0; + if (kind === GroupKind.Pugv && epid) { + pugvPlayurl(aid, cid, epid, this.qn) + .then(d => { this.attachMedia(d); - d.record_info?.record && this.$area.$wrap.$record.addRecord(d.record_info.record); d.is_preview && ev.trigger(PLAYER_EVENT.TOAST, '正在观看预览'); - }).finally(() => { + }) + .finally(() => { + video.addEventListener('canplay', () => { + this.getDanmaku(); + this.getUser(); + this.getVideoShot(); + }, { once: true }); + }); + } else if (epid) { + pgcPlayurl(aid, cid, epid, this.qn).then(d => { + this.attachMedia(d); + d.record_info?.record && this.$area.$wrap.$record.addRecord(d.record_info.record); + d.is_preview && ev.trigger(PLAYER_EVENT.TOAST, '正在观看预览'); + }).finally(() => { + video.addEventListener('canplay', () => { + this.getDanmaku(); + this.getUser(); + this.getVideoShot(); + }, { once: true }); + }); + } else { + playurl(aid, cid, this.qn) + .then(this.attachMedia) + .finally(() => { video.addEventListener('canplay', () => { this.getDanmaku(); this.getUser(); this.getVideoShot(); }, { once: true }); }); - } else { - playurl(aid, cid, this.qn) - .then(this.attachMedia) - .finally(() => { - video.addEventListener('canplay', () => { - this.getDanmaku(); - this.getUser(); - this.getVideoShot(); - }, { once: true }); - }); - } } } @@ -430,7 +661,7 @@ export class BilibiliPlayer extends Player { * @param success 成功获取对应画质的回调 * @param fail 获取对应画质失败回调 */ - updateSource(qn?: number, success?: Function, fail?: Function) { + private updateSource(qn?: number, success?: Function, fail?: Function) { const ajax = this.epid ? pgcPlayurl(this.aid, this.cid, this.epid, this.qn) : playurl(this.aid, this.cid, this.qn); ajax.then(d => { if (d) { @@ -470,7 +701,7 @@ export class BilibiliPlayer extends Player { } /** 选择画质 */ - setQualityFor(qn = 0) { + private setQualityFor(qn = 0) { if (qn === 0) { this.dashPlayer?.setAutoSwitchQualityFor('video', true); } else { @@ -587,7 +818,7 @@ export class BilibiliPlayer extends Player { * @param page 分P数据 * @param toview 是否稍后再看页面 */ - partAv(page: Awaited>) { + private partAv(page: Awaited>) { this.$area.$control.$next.update(page.map((d, i) => `/video/av${this.aid}?p=${i + 1}`), page.findIndex(d => d.cid === this.cid) || 0); this.#part.update(page, this.aid, this.cid); } @@ -597,7 +828,7 @@ export class BilibiliPlayer extends Player { * * @param page Bangumi数据 */ - async partBangumi(page: Awaited>) { + private async partBangumi(page: Awaited>) { page.modules.forEach(d => { switch (d.style) { case "positive": { @@ -618,7 +849,7 @@ export class BilibiliPlayer extends Player { * * @param page 合集数据 */ - partUgcSeason(page: Awaited>) { + private partUgcSeason(page: Awaited>) { if (page.View.ugc_season) { this.$auxiliary.$recommend.add(page.View.ugc_season.sections[0].episodes.map(d => { return { @@ -638,7 +869,7 @@ export class BilibiliPlayer extends Player { } /** 稍后再看分P管理 */ - partToView(page: Awaited>, part?: Awaited>) { + private partToView(page: Awaited>, part?: Awaited>) { const ids: string[] = []; let ci = 0; this.$auxiliary.$recommend.add(page.map(d => { @@ -669,7 +900,7 @@ export class BilibiliPlayer extends Player { } /** 播放列表分P管理 */ - partMedialist(page: Awaited>['medias'], part?: Awaited>) { + private partMedialist(page: Awaited>['medias'], part?: Awaited>) { const ids: string[] = []; let ci = 0; this.$auxiliary.$recommend.add(page.map(d => { @@ -723,6 +954,7 @@ export class BilibiliPlayer extends Player { this.style.backgroundImage = ''; this.style.backgroundSize = ''; this.$auxiliary.$filter.$recommend.textContent = '推荐视频'; + this.classList.remove('nano'); } }