diff --git a/packages/unblock-area-limit/src/api/bilibili.ts b/packages/unblock-area-limit/src/api/bilibili.ts index 90602da6..774bbbb5 100644 --- a/packages/unblock-area-limit/src/api/bilibili.ts +++ b/packages/unblock-area-limit/src/api/bilibili.ts @@ -35,23 +35,23 @@ export interface AppSeasonInfo { title: string } alias: string - all_buttons: { + all_buttons?: { watch_fornal: string } - all_up_infos: any + all_up_infos?: any areas: [{ id: number name: string }] - badge: string - badge_info: { + badge?: string + badge_info?: { bg_color: string bg_color_night: string text: string } cover: string detail: string - dialog: { + dialog?: { code: number config: any image: { @@ -66,28 +66,28 @@ export interface AppSeasonInfo { type: string } dynamic_subtitle: string - earphone_conf: { + earphone_conf?: { sp_phones: any[] } - enable_vt: boolean + enable_vt?: boolean evaluate: string - icon_font: { + icon_font?: { name: string text: string } link: string - media_badge_info: any - media_id: number + media_badge_info?: any + media_id?: number mode: number modules: any[] new_ep: { - desc: string + desc?: string id: number - is_new: number - more: string + is_new?: number + more?: string title: string } - new_keep_activity_material: { + new_keep_activity_material?: { activityId: number } origin_name: string @@ -102,12 +102,12 @@ export interface AppSeasonInfo { vip_discount_price: string vip_promotion: string } | undefined - play_strategy: { + play_strategy?: { auto_play_toast: string recommend_show_strategy: number strategies: any[] } - premieres: any[] + premieres?: any[] publish: { is_finish: number is_started: number @@ -116,34 +116,34 @@ export interface AppSeasonInfo { release_date_show: string time_length_show: string unknow_pub_date: number - update_info_desc: string + update_info_desc?: string weekday: number } - record: string + record?: string refine_cover: string - reserve: { + reserve?: { episodes: any[] tip: string } rights: { allow_bp: number allow_bp_rank: number - allow_download: number + allow_download?: number allow_review: number area_limit: number ban_area_show: number can_watch: number copyright: string - forbid_pre: number - freya_white: number - is_cover_show: number + forbid_pre?: number + freya_white?: number + is_cover_show?: number is_preview: number - only_vip_download: number - resource: string - watch_platform: number + only_vip_download?: number + resource?: string + watch_platform?: number } season_id: number - season_title: string + season_title?: string series: { display_type: number series_id: number @@ -152,7 +152,7 @@ export interface AppSeasonInfo { share_copy: string share_url: string short_link: string - show_season_type: number + show_season_type?: number square_cover: string staff: { info: string @@ -161,7 +161,7 @@ export interface AppSeasonInfo { stat: { coins: number danmakus: number - favorite: number + favorite?: number favorites: number followers: string likes: number @@ -169,7 +169,7 @@ export interface AppSeasonInfo { reply: number share: number views: number - vt: number + vt?: number } status: number jp_title?: string | undefined @@ -177,7 +177,7 @@ export interface AppSeasonInfo { name: string }] subtitle: string - test_switch: { + test_switch?: { channel_entrance_exp_action: number enable_ep_vt: boolean hide_ep_vv_vt_dm: number @@ -197,9 +197,9 @@ export interface AppSeasonInfo { title: string total: number type: number - type_desc: string + type_desc?: string type_name: string - user_status: { + user_status?: { follow: number follow_bubble: number follow_status: number @@ -221,7 +221,7 @@ export interface AppSeasonInfo { } season_status?: number | undefined is_paster_ads: number - user_thumbup: { + user_thumbup?: { url_image_ani: string url_image_ani_cut: string url_image_bright: string @@ -246,18 +246,18 @@ export interface AppSeasonInfo { title: string } alias: string - all_buttons: { watch_fornal: string } - all_up_infos: any + all_buttons?: { watch_fornal: string } + all_up_infos?: any areas: [{ id: number, name: string }] - badge: string - badge_info: { + badge?: string + badge_info?: { bg_color: string bg_color_night: string text: string } cover: string detail: string - dialog: { + dialog?: { code: number config: any image: { @@ -272,26 +272,26 @@ export interface AppSeasonInfo { type: string } dynamic_subtitle: string - earphone_conf: { sp_phones: any[] } - enable_vt: boolean + earphone_conf?: { sp_phones: any[] } + enable_vt?: boolean evaluate: string - icon_font: { + icon_font?: { name: string text: string } link: string - media_badge_info: any - media_id: number + media_badge_info?: any + media_id?: number mode: number modules: any[] new_ep: { - desc: string + desc?: string id: number - is_new: number - more: string + is_new?: number + more?: string title: string } - new_keep_activity_material: { activityId: number } + new_keep_activity_material?: { activityId: number } origin_name: string payment?: { dialog: any @@ -302,12 +302,12 @@ export interface AppSeasonInfo { vip_discount_price: string vip_promotion: string } - play_strategy: { + play_strategy?: { auto_play_toast: string recommend_show_strategy: number strategies: any[] } - premieres: any[] + premieres?: any[] publish: { is_finish: number is_started: number @@ -316,34 +316,34 @@ export interface AppSeasonInfo { release_date_show: string time_length_show: string unknow_pub_date: number - update_info_desc: string + update_info_desc?: string weekday: number } - record: string + record?: string refine_cover: string - reserve: { + reserve?: { episodes: any[] tip: string } rights: { allow_bp: number allow_bp_rank: number - allow_download: number + allow_download?: number allow_review: number area_limit: number ban_area_show: number can_watch: number copyright: string - forbid_pre: number - freya_white: number - is_cover_show: number + forbid_pre?: number + freya_white?: number + is_cover_show?: number is_preview: number - only_vip_download: number - resource: string - watch_platform: number + only_vip_download?: number + resource?: string + watch_platform?: number } season_id: number - season_title: string + season_title?: string series: { display_type: number series_id: number @@ -352,7 +352,7 @@ export interface AppSeasonInfo { share_copy: string share_url: string short_link: string - show_season_type: number + show_season_type?: number square_cover: string staff: { info: string @@ -361,7 +361,7 @@ export interface AppSeasonInfo { stat: { coins: number danmakus: number - favorite: number + favorite?: number favorites: number followers: string likes: number @@ -369,7 +369,7 @@ export interface AppSeasonInfo { reply: number share: number views: number - vt: number + vt?: number } status: number jp_title?: string @@ -377,7 +377,7 @@ export interface AppSeasonInfo { name: string }] subtitle: string - test_switch: { + test_switch?: { channel_entrance_exp_action: number enable_ep_vt: boolean hide_ep_vv_vt_dm: number @@ -397,9 +397,9 @@ export interface AppSeasonInfo { title: string total: number type: number - type_desc: string + type_desc?: string type_name: string - user_status: { + user_status?: { follow: number follow_bubble: number follow_status: number @@ -421,7 +421,7 @@ export interface AppSeasonInfo { } season_status?: number is_paster_ads: number - user_thumbup: { + user_thumbup?: { url_image_ani: string url_image_ani_cut: string url_image_bright: string @@ -494,15 +494,60 @@ export interface EpisodeInfo { interface SeasonInfoOnThailand { code: number + message: string result: { actor: { info: string + title: string + } + alias: string + areas: [{ id: number, name: string }] + cover: string + detail: string + dynamic_subtitle: string + evaluate: string + link: string + mode: number + publish: { + is_finish: number + is_started: number + pub_time: string + pub_time_show: string + release_date_show: string + time_length_show: string + unknow_pub_date: number + weekday: number } + refine_cover: string + series: any + share_copy: string + share_url: string + short_link: string + square_cover: string + staff: any + stat: { + coins: number + danmakus: number + favorites: number + followers: string + hot: number + likes: number + play: string + reply: number + series_play: string + share: number + views: number + } + subtitle: string + total: number + type: number + type_name: string actors?: string origin_name: string jp_title?: string new_ep: { id: number + new_ep_display: string title: string } newest_ep?: { @@ -516,6 +561,16 @@ interface SeasonInfoOnThailand { season_id: number rights: { watch_platform?: number + allow_bp: number + allow_bp_rank: number + allow_review: number + area_limit: number + ban_area_show: number + can_watch: number + copyright: string + forbidPre: number + is_preview: number + onlyVipDownload: number } is_paster_ads: number total_ep: number diff --git a/packages/unblock-area-limit/src/api/biliplus.ts b/packages/unblock-area-limit/src/api/biliplus.ts index b8e3ddd5..bda37692 100644 --- a/packages/unblock-area-limit/src/api/biliplus.ts +++ b/packages/unblock-area-limit/src/api/biliplus.ts @@ -1,6 +1,7 @@ import { balh_config } from "../feature/config"; import { Async } from "../util/async"; -import { Converters } from "../util/converters"; +import { Converters, uposMap } from "../util/converters"; +import { addNoRefererHost } from "../util/inject-xhr"; import { access_key_param_if_exist } from "./bilibili-utils"; function convertPlayUrl(originUrl: string) { @@ -113,8 +114,10 @@ export async function fixMobiPlayUrlJson(originJson: object) { minBufferTime: number min_buffer_time: number video: [{ - backupUrl: string[] - baseUrl: string + backupUrl?: string[] + baseUrl?: string + backup_url: string[] + base_url: string codecs: string sar: string startWithSAP: number @@ -136,8 +139,10 @@ export async function fixMobiPlayUrlJson(originJson: object) { } }] audio: [{ - backupUrl: string[] - baseUrl: string + backupUrl?: string[] + baseUrl?: string + backup_url: string[] + base_url: string codecs: string startWithSAP: number start_with_sap: number @@ -235,6 +240,7 @@ export async function fixMobiPlayUrlJson(originJson: object) { } function getSegmentBase(url: string, id: string, range: string = '5000') { + addNoRefererHost(url) return new Promise((resolve, reject) => { // 从 window 中读取已有的值 if (window.__segment_base_map__) { @@ -265,7 +271,7 @@ export async function fixMobiPlayUrlJson(originJson: object) { window.__segment_base_map__[id] = result } - // console.log('get SegmentBase ', result, 'id=', id); + // console.log('get SegmentBase', result, 'id=', id); resolve(result); } xhr.send(null) // 发送请求 @@ -291,24 +297,17 @@ export async function fixMobiPlayUrlJson(originJson: object) { } // 乱猜 range 导致泡面番播不出 result.dash.video.forEach((video) => { - if (video.backupUrl.length > 0 && video.backupUrl[0].indexOf('akamaized.net') > -1) { - // 有时候返回 bcache 地址, 直接访问 bcache CDN 会报 403,如果备用地址有 akam,替换为 akam - video.baseUrl = video.backupUrl[0] - } - taskList.push(getSegmentBase(video.baseUrl, getId(video.baseUrl, '30080', true), range.toString())) + taskList.push(getSegmentBase(video.base_url, getId(video.base_url, '30080', true), range.toString())) }) result.dash.audio.forEach((audio) => { - if (audio.backupUrl.length > 0 && audio.backupUrl[0].indexOf('akamaized.net') > -1) { - audio.baseUrl = audio.backupUrl[0] - } - taskList.push(getSegmentBase(audio.baseUrl, getId(audio.baseUrl, '30080', true), range.toString())) + taskList.push(getSegmentBase(audio.base_url, getId(audio.base_url, '30080', true), range.toString())) }) await Promise.all(taskList) if (window.__segment_base_map__) segmentBaseMap = window.__segment_base_map__ // 填充视频流数据 result.dash.video.forEach((video) => { - let video_id = getId(video.baseUrl, '30280') + let video_id = getId(video.base_url, '30280') if (!codecsMap.hasOwnProperty(video_id)) { // https://github.com/ipcjs/bilibili-helper/issues/775 // 泰区的视频URL不包含 id 了 @@ -317,7 +316,7 @@ export async function fixMobiPlayUrlJson(originJson: object) { video.codecs = codecsMap[video_id] - let segmentBaseId = getId(video.baseUrl, '30280', true) + let segmentBaseId = getId(video.base_url, '30280', true) video.segment_base = { initialization: segmentBaseMap[segmentBaseId][0], index_range: segmentBaseMap[segmentBaseId][1] @@ -341,14 +340,14 @@ export async function fixMobiPlayUrlJson(originJson: object) { // 填充音频流数据 result.dash.audio.forEach((audio) => { - let audio_id = getId(audio.baseUrl, '30280') + let audio_id = getId(audio.base_url, '30280') if (!codecsMap.hasOwnProperty(audio_id)) { // https://github.com/ipcjs/bilibili-helper/issues/775 // 泰区的音频URL不包含 id 了 audio_id = audio.id.toString() } - let segmentBaseId = getId(audio.baseUrl, '30280', true) + let segmentBaseId = getId(audio.base_url, '30280', true) audio.segment_base = { initialization: segmentBaseMap[segmentBaseId][0], index_range: segmentBaseMap[segmentBaseId][1] @@ -429,12 +428,31 @@ export async function fixThailandPlayUrlJson(originJson: object) { 'min_buffer_time': 0.0, 'audio': [] } + + const upos = uposMap[balh_config.upos_server || 'hw'] ?? uposMap.hw + // 填充音频流数据 origin.data.video_info.dash_audio.forEach((audio) => { - audio.backupUrl = audio.backup_url - audio.backup_url = audio.backup_url - audio.base_url = audio.base_url.includes(':8000') ? audio.backup_url[0] : audio.base_url - audio.baseUrl = audio.base_url + const base_url = audio.base_url + const url = new URL(base_url, document.location.href) + const search = audio.backup_url ? new URL(audio.backup_url[0]).search : url.search + if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(url.hostname)) { + audio.base_url = new URL(url.pathname.replace(/\/v1\/resource\//g, '').replace(/\_/g, `\/`) + search, `https://${upos}`).href + } else if (url.hostname.includes("akamaized.net")) { + audio.base_url = new URL(url.pathname + search, `https://${upos}`).href + } + addNoRefererHost(audio.base_url) + if (audio.backup_url) { + audio.backup_url.forEach(u => { + if (u.includes("akamaized.net")) { + const url = new URL(u) + u = new URL(url.pathname + url.search, `https://${upos}`).href + } + addNoRefererHost(u) + }) + } + if (audio.baseUrl) audio.baseUrl = audio.base_url + if (audio.backupUrl) audio.backupUrl = audio.backup_url dash.audio.push(audio) }) // 填充视频流数据 @@ -443,16 +461,32 @@ export async function fixThailandPlayUrlJson(originJson: object) { let support_formats = [] let dash_video = [] origin.data.video_info.stream_list.forEach((stream) => { - support_formats.push(stream.stream_info) - accept_quality.push(stream.stream_info.quality) - accept_description.push(stream.stream_info.new_description) // 只加入有视频链接的数据 if (stream.dash_video && stream.dash_video.base_url) { - stream.dash_video.backupUrl = stream.dash_video.backup_url - stream.dash_video.backup_url = stream.dash_video.backup_url - stream.dash_video.base_url = stream.dash_video.base_url.includes(':8000') ? stream.dash_video.backup_url[0] : stream.dash_video.base_url - stream.dash_video.baseUrl = stream.dash_video.base_url + support_formats.push(stream.stream_info) + accept_quality.push(stream.stream_info.quality) + accept_description.push(stream.stream_info.new_description) stream.dash_video.id = stream.stream_info.quality + const base_url = stream.dash_video.base_url + const url = new URL(base_url, document.location.href) + const search = stream.dash_video.backup_url ? new URL(stream.dash_video.backup_url[0]).search : url.search + if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(url.hostname)) { + stream.dash_video.base_url = new URL(url.pathname.replace(/\/v1\/resource\//g, '').replace(/\_/g, `\/`) + search, `https://${upos}`).href + } else if (url.hostname.includes("akamaized.net")) { + stream.dash_video.base_url = new URL(url.pathname + search, `https://${upos}`).href + } + addNoRefererHost(stream.dash_video.base_url) + if (stream.dash_video.backup_url) { + stream.dash_video.backup_url.forEach(u => { + if (u.includes("akamaized.net")) { + const url = new URL(u) + u = new URL(url.pathname + url.search, `https://${upos}`).href + } + addNoRefererHost(u) + }) + } + if (stream.dash_video.baseUrl) stream.dash_video.baseUrl = stream.dash_video.base_url + if (stream.dash_video.backupUrl) stream.dash_video.backupUrl = stream.dash_video.backup_url dash_video.push(stream.dash_video) } }) @@ -463,7 +497,7 @@ export async function fixThailandPlayUrlJson(originJson: object) { result['support_formats'] = support_formats result['dash'] = dash // 下面参数取自安达(ep359333),总之一股脑塞进去( - result['fnval'] = 80 + result['fnval'] = result.support_formats[0].quality result['fnver'] = 0 result['status'] = 2 result['vip_status'] = 1 diff --git a/packages/unblock-area-limit/src/feature/bili/area_limit_for_vue.ts b/packages/unblock-area-limit/src/feature/bili/area_limit_for_vue.ts index 3137c047..0ae6a860 100644 --- a/packages/unblock-area-limit/src/feature/bili/area_limit_for_vue.ts +++ b/packages/unblock-area-limit/src/feature/bili/area_limit_for_vue.ts @@ -117,7 +117,6 @@ async function fixThailandSeason(ep_id: string, season_id: string) { // https://github.com/yujincheng08/BiliRoaming/issues/112 const thailandApi = new BiliBiliApi(balh_config.server_custom_th) const origin = await thailandApi.getSeasonInfoByEpSsIdOnThailand(ep_id, season_id) - const input_episodes = origin.result.modules[0].data.episodes origin.result.actors = origin.result.actor.info origin.result.is_paster_ads = 0 @@ -125,29 +124,28 @@ async function fixThailandSeason(ep_id: string, season_id: string) { origin.result.newest_ep = origin.result.new_ep origin.result.season_status = origin.result.status origin.result.season_title = origin.result.title - origin.result.total_ep = input_episodes.length origin.result.rights.watch_platform = 1 origin.result.episodes = [] - input_episodes.forEach((ep) => { - ep.episode_status = ep.status - ep.ep_id = ep.id - ep.index = ep.title - ep.index_title = ep.long_title - origin.result.episodes?.push(ep) - }) - + if (origin.result.modules.length > 0) { + origin.result.modules[0].data.episodes.forEach((ep) => { + ep.episode_status = ep.status + ep.ep_id = ep.id + ep.index = ep.title + ep.index_title = ep.long_title + origin.result.episodes?.push(ep) + }) + origin.result.total = origin.result.modules[0].data.episodes.length + } + origin.result.total_ep = origin.result.total origin.result.style = [] origin.result.styles?.forEach((it) => { origin.result.style.push(it.name) }) - - let result: AppSeasonInfo = JSON.parse(JSON.stringify(origin)) - return result + return { code: origin.code, message: origin.message, data: origin.result } } let invalidInitialState: StringAnyObject | undefined - function fixBangumiPlayPage() { util_init(async () => { if (util_page.bangumi_md()) { @@ -189,34 +187,50 @@ function fixBangumiPlayPage() { } }) let seasons: any[] = [] - result.result.modules.forEach((module: { data: { seasons: any[] } }) => { - module.data.seasons.forEach(season => { - seasons.push(season) - }) + + result.result.modules.forEach((module: { data: { seasons?: any[], episodes?: any[] } }) => { + if (module.data.seasons) { + module.data.seasons.forEach(season => { + seasons.push(season) + }) + } else if (module.data.episodes) { + module.data.episodes.forEach(ep => { + seasons.push(ep) + }) + } }) result.result['seasons'] = seasons - let section = await bilibiliApi.getSeasonSectionBySsId(season_id) - result.result['episodes'] = section.result.main_section.episodes - result.result['section'] = section.result.section - result.result['positive'] = { id: section.result.main_section.id, title: section.result.main_section.title } - let episodeInfo = await bilibiliApi.getEpisodeInfoByEpId(result.result.episodes[0].id) - result.result['up_info'] = episodeInfo.data.related_up[0] - result.result.episodes.forEach((ep: { [x: string]: any; id: any }) => { - ep['bvid'] = Converters.aid2bv(ep.aid) - ep['ep_id'] = ep.id - ep['link'] = `https://www.bilibili.com/bangumi/play/ep${ep.id}` - ep['rights'] = { allow_download: 1, area_limit: 0, allow_dm: 1 } - ep['short_link'] = `https://b23.tv/ep${ep.id}` - }) - result.result.section.forEach(section => { - section.episodes.forEach((ep: { [x: string]: any; id: any }) => { + if (!result.result.episodes) { + const section = await bilibiliApi.getSeasonSectionBySsId(season_id) + result.result['episodes'] = section.result.main_section.episodes + result.result['section'] = section.result.section + result.result['positive'] = { id: section.result.main_section.id, title: section.result.main_section.title } + } + + if (result.result.episodes.length > 0) { + const episodeInfo = await bilibiliApi.getEpisodeInfoByEpId(result.result.episodes[0].id) + if (episodeInfo.code = 0) { + result.result['up_info'] = episodeInfo.data.related_up[0] + } + result.result.episodes.forEach((ep: { [x: string]: any; id: any }) => { ep['bvid'] = Converters.aid2bv(ep.aid) ep['ep_id'] = ep.id ep['link'] = `https://www.bilibili.com/bangumi/play/ep${ep.id}` ep['rights'] = { allow_download: 1, area_limit: 0, allow_dm: 1 } ep['short_link'] = `https://b23.tv/ep${ep.id}` }) - }) + } + if (result.result.section) { + result.result.section.forEach(section => { + section.episodes.forEach((ep: { [x: string]: any; id: any }) => { + ep['bvid'] = Converters.aid2bv(ep.aid) + ep['ep_id'] = ep.id + ep['link'] = `https://www.bilibili.com/bangumi/play/ep${ep.id}` + ep['rights'] = { allow_download: 1, area_limit: 0, allow_dm: 1 } + ep['short_link'] = `https://b23.tv/ep${ep.id}` + }) + }) + } const ep = ep_id != '' ? result.result.episodes.find(ep => ep.ep_id === +ep_id) : result.result.episodes[0] if (!ep) { throw `通过bangumi接口未找到${ep_id}对应的视频信息` @@ -236,6 +250,7 @@ function fixBangumiPlayPage() { item.i = index item.link = 'https://www.bilibili.com/bangumi/play/ep' + item.ep_id item.title = item.titleFormat + if (item.jump) item['skip'] = item.jump return item })) let titleForma diff --git a/packages/unblock-area-limit/src/feature/bili/bangumi-play-page-template.html b/packages/unblock-area-limit/src/feature/bili/bangumi-play-page-template.html index deab7c8b..d6fda0c7 100644 --- a/packages/unblock-area-limit/src/feature/bili/bangumi-play-page-template.html +++ b/packages/unblock-area-limit/src/feature/bili/bangumi-play-page-template.html @@ -3,7 +3,7 @@ - + @@ -40,7 +40,7 @@ href="//s1.hdslb.com/bfs/static/pgcv/css/video.1.d78d6e85da752e622f857a963ae79be916fe4c01.css"> - +