mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Merge branch 'preview-fixes'
This commit is contained in:
commit
c9432fc369
@ -4,12 +4,8 @@
|
||||
|
||||
- 需要安装 [Node.js](https://nodejs.org/en/download/) (>= 14.0), [Visual Studio Code](https://code.visualstudio.com/) 和 [yarn](https://yarnpkg.com/getting-started/install#global-install).
|
||||
- 将项目 Fork 至自己账户后, 克隆至本地
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/{{your-name}}/Bilibili-Evolved.git -b preview --single-branch
|
||||
cd Bilibili-Evolved
|
||||
```
|
||||
- 安装依赖
|
||||
- 分支视情况切换或新建, 新功能以 `preview-features` 为基础分支, 功能修复以 `preview-fixes` 为基础分支.
|
||||
- 安装依赖:
|
||||
|
||||
```powershell
|
||||
yarn
|
||||
@ -241,7 +237,7 @@ export const component: ComponentMetadata = {
|
||||
commit message 只需写明改动点, 中英文随意, 也不强求类似 [commit-lint](https://github.com/conventional-changelog/commitlint) 的格式.
|
||||
|
||||
## 发起 PR (合并请求)
|
||||
将你的分支往主仓库的 `preview` 分支合并就行.
|
||||
将你的分支往主仓库的 `preview-features` (新增功能) 或 `preview-fixes` (功能修复) 分支合并就行.
|
||||
|
||||
## 自行保留
|
||||
你可以选择不将功能代码合并到主仓库, 因此也没有 ESLint 的限制. PR 时仅添加指向你的仓库中的组件信息即可, 具体来说, 是在 `registry/lib/docs/third-party.ts` 中, 往对应数组中添加你的功能的相关信息, 当然别忘了把 `owner` 设为你的 GitHub 用户名.
|
||||
|
||||
6
registry/dist/components/video/download.js
vendored
6
registry/dist/components/video/download.js
vendored
File diff suppressed because one or more lines are too long
@ -24,6 +24,7 @@ export const entry: ComponentEntry = async ({ metadata: { name } }) => {
|
||||
const globalFixedExclude = [
|
||||
'https://space.bilibili.com',
|
||||
'https://www.bilibili.com/read',
|
||||
'https://www.bilibili.com/account/history',
|
||||
]
|
||||
if (!globalFixedExclude.some(p => matchUrlPattern(p))) {
|
||||
addComponentListener(`${name}.globalFixed`, value => {
|
||||
|
||||
@ -13,7 +13,8 @@ li.nav-item[report-id="playpage_dynamic"] .i-frame,
|
||||
.bili-header-m .head-banner .head-content .head-logo,
|
||||
#biliMainHeader .mini-header,
|
||||
#biliMainHeader .base-mini-header,
|
||||
.bili-header__bar {
|
||||
.bili-header__bar,
|
||||
.z-top-container {
|
||||
display: none !important;
|
||||
}
|
||||
.van-popover {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="history-list">
|
||||
<div class="custom-navbar-history-list">
|
||||
<div class="header">
|
||||
<div class="header-row">
|
||||
<div class="search">
|
||||
@ -217,7 +217,7 @@ export default Vue.extend({
|
||||
@import "common";
|
||||
@import "../popup";
|
||||
|
||||
.history-list {
|
||||
.custom-navbar-history-list {
|
||||
width: 350px;
|
||||
@include navbar-popup-height();
|
||||
font-size: 12px;
|
||||
|
||||
@ -89,7 +89,7 @@ import {
|
||||
VLoading,
|
||||
} from '@/ui'
|
||||
import { addComponentListener } from '@/core/settings'
|
||||
import { dqa } from '@/core/utils'
|
||||
import { deleteValue, dqa } from '@/core/utils'
|
||||
import { SortableJSLibrary } from '@/core/runtime-library'
|
||||
import { SortableEvent } from 'sortablejs'
|
||||
import { getData } from '@/plugins/data'
|
||||
@ -122,7 +122,7 @@ export default Vue.extend({
|
||||
padding: navbarOptions.padding,
|
||||
rendered,
|
||||
// order: navbarOptions.order,
|
||||
hidden: navbarOptions.hidden,
|
||||
hidden: [...navbarOptions.hidden],
|
||||
loaded: false,
|
||||
}
|
||||
},
|
||||
@ -173,11 +173,13 @@ export default Vue.extend({
|
||||
this.rendered.items = sortItems(rendered.items, ordersMap)
|
||||
},
|
||||
toggleVisible(item: CustomNavbarItem) {
|
||||
if (navbarOptions.hidden.includes(item.name)) {
|
||||
lodash.pull(navbarOptions.hidden, item.name)
|
||||
if (this.hidden.includes(item.name)) {
|
||||
deleteValue(this.hidden, it => it === item.name)
|
||||
deleteValue(navbarOptions.hidden, it => it === item.name)
|
||||
item.hidden = false
|
||||
console.log('delete', item.name)
|
||||
} else {
|
||||
this.hidden.push(item.name)
|
||||
navbarOptions.hidden.push(item.name)
|
||||
item.hidden = true
|
||||
console.log('add', item.name)
|
||||
|
||||
@ -140,7 +140,11 @@ import { getFriendlyTitle } from '@/core/utils/title'
|
||||
import { bangumiBatchInput } from './inputs/bangumi/batch'
|
||||
import { videoBatchInput } from './inputs/video/batch'
|
||||
import { videoSingleInput } from './inputs/video/input'
|
||||
import { videoDashAVC, videoDashHEVC, audioDash } from './apis/dash'
|
||||
import {
|
||||
videoDashAVC,
|
||||
videoDashHEVC,
|
||||
videoAudioDash,
|
||||
} from './apis/dash'
|
||||
import { videoFlv } from './apis/flv'
|
||||
import { toastOutput } from './outputs/toast'
|
||||
import {
|
||||
@ -164,7 +168,7 @@ const [apis] = registerAndGetData(
|
||||
videoFlv,
|
||||
videoDashAVC,
|
||||
videoDashHEVC,
|
||||
audioDash,
|
||||
videoAudioDash,
|
||||
] as DownloadVideoApi[],
|
||||
)
|
||||
const [assets] = registerAndGetData(
|
||||
@ -182,7 +186,7 @@ const { basicConfig } = getComponentSettings('downloadVideo').options as {
|
||||
output: string
|
||||
}
|
||||
}
|
||||
const filterData = (items: { match?: TestPattern }[]) => {
|
||||
const filterData = <T extends { match?: TestPattern }> (items: T[]) => {
|
||||
const matchedItems = items.filter(it => it.match?.some(p => matchUrlPattern(p)) ?? true)
|
||||
return matchedItems
|
||||
}
|
||||
@ -202,7 +206,6 @@ export default Vue.extend({
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const lastApi = basicConfig.api
|
||||
const lastOutput = basicConfig.output
|
||||
return {
|
||||
open: false,
|
||||
@ -219,8 +222,8 @@ export default Vue.extend({
|
||||
selectedQuality: undefined,
|
||||
inputs: [],
|
||||
selectedInput: undefined,
|
||||
apis,
|
||||
selectedApi: apis.find(it => it.name === lastApi) || apis[0],
|
||||
apis: [],
|
||||
selectedApi: undefined,
|
||||
outputs,
|
||||
selectedOutput: outputs.find(it => it.name === lastOutput) || outputs[0],
|
||||
}
|
||||
@ -269,9 +272,20 @@ export default Vue.extend({
|
||||
},
|
||||
mounted() {
|
||||
coreApis.observer.videoChange(() => {
|
||||
this.selectedInput = undefined
|
||||
this.selectedApi = undefined
|
||||
|
||||
const matchedInputs = filterData(inputs)
|
||||
this.inputs = matchedInputs
|
||||
this.selectedInput = matchedInputs[0]
|
||||
const matchedApis = filterData(apis)
|
||||
this.apis = matchedApis
|
||||
const lastApi = matchedApis.find(api => api.name === basicConfig.api)
|
||||
if (lastApi) {
|
||||
this.selectedApi = lastApi
|
||||
} else {
|
||||
this.selectedApi = matchedApis[0]
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
@ -291,7 +305,7 @@ export default Vue.extend({
|
||||
return videoItems
|
||||
},
|
||||
async updateTestVideoInfo() {
|
||||
if (!this.selectedInput) {
|
||||
if (!this.selectedInput || !this.selectedApi) {
|
||||
return
|
||||
}
|
||||
this.testData.videoInfo = null
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||
import { formData } from '@/core/utils'
|
||||
import { formData, matchUrlPattern } from '@/core/utils'
|
||||
import { ascendingSort, descendingSort } from '@/core/utils/sort'
|
||||
import { allQualities, VideoQuality } from '@/components/video/video-quality'
|
||||
import { bangumiUrls } from '@/core/utils/urls'
|
||||
import { compareQuality } from '../error'
|
||||
import {
|
||||
DownloadVideoApi, DownloadVideoFragment, DownloadVideoInfo, DownloadVideoInputItem,
|
||||
} from '../types'
|
||||
|
||||
/* spell-checker: disable */
|
||||
import { bangumiApi, videoApi } from './url'
|
||||
|
||||
/** dash 格式更明确的扩展名 */
|
||||
export const DashExtensions = {
|
||||
@ -75,12 +75,14 @@ export const dashToFragments = (info: {
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
/* spell-checker: disable */
|
||||
const downloadDash = async (
|
||||
input: DownloadVideoInputItem,
|
||||
config: {
|
||||
codec?: DashCodec
|
||||
filters?: DashFilters
|
||||
},
|
||||
} = {},
|
||||
) => {
|
||||
const { codec = 'AVC/H.264', filters } = config
|
||||
const dashFilters = {
|
||||
@ -98,7 +100,8 @@ const downloadDash = async (
|
||||
fnver: 0,
|
||||
fnval: 2000,
|
||||
}
|
||||
const api = `https://api.bilibili.com/x/player/playurl?${formData(params)}`
|
||||
const isBanugmi = bangumiUrls.some(url => matchUrlPattern(url))
|
||||
const api = isBanugmi ? bangumiApi(formData(params)) : videoApi(formData(params))
|
||||
const data = await bilibiliApi(
|
||||
getJsonWithCredentials(api),
|
||||
'获取视频链接失败',
|
||||
@ -184,6 +187,7 @@ const downloadDash = async (
|
||||
compareQuality(input, info)
|
||||
return info
|
||||
}
|
||||
|
||||
export const videoDashAVC: DownloadVideoApi = {
|
||||
name: 'video.dash.avc',
|
||||
displayName: 'dash (AVC/H.264)',
|
||||
@ -196,7 +200,7 @@ export const videoDashHEVC: DownloadVideoApi = {
|
||||
description: '音画分离的 mp4 格式, 编码为 H.265, 体积较小, 兼容性较差. 下载后可以合并为单个 mp4 文件.',
|
||||
downloadVideoInfo: async input => downloadDash(input, { codec: 'HEVC/H.265' }),
|
||||
}
|
||||
export const audioDash: DownloadVideoApi = {
|
||||
export const videoAudioDash: DownloadVideoApi = {
|
||||
name: 'video.dash.audio',
|
||||
displayName: 'dash (仅音频)',
|
||||
description: '仅下载视频中的音频轨道.',
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||
import { formData } from '@/core/utils'
|
||||
import { formData, matchUrlPattern } from '@/core/utils'
|
||||
import { allQualities } from '@/components/video/video-quality'
|
||||
import { bangumiUrls } from '@/core/utils/urls'
|
||||
import { compareQuality } from '../error'
|
||||
import {
|
||||
DownloadVideoApi,
|
||||
DownloadVideoFragment,
|
||||
DownloadVideoInfo,
|
||||
DownloadVideoInputItem,
|
||||
} from '../types'
|
||||
import { bangumiApi, videoApi } from './url'
|
||||
|
||||
const parseInfoFromJson = (data: any, extensions: string[]) => {
|
||||
const getExtension = (index: number) => {
|
||||
@ -32,33 +35,39 @@ const parseInfoFromJson = (data: any, extensions: string[]) => {
|
||||
currentQuality,
|
||||
}
|
||||
}
|
||||
|
||||
/* spell-checker: disable */
|
||||
const downloadFlv = async (
|
||||
input: DownloadVideoInputItem,
|
||||
) => {
|
||||
const { aid, cid, quality } = input
|
||||
const params = {
|
||||
avid: aid,
|
||||
cid,
|
||||
qn: quality?.value ?? '',
|
||||
otype: 'json',
|
||||
fourk: 1,
|
||||
fnver: 0,
|
||||
fnval: 0,
|
||||
}
|
||||
const isBanugmi = bangumiUrls.some(url => matchUrlPattern(url))
|
||||
const api = isBanugmi ? bangumiApi(formData(params)) : videoApi(formData(params))
|
||||
const data = await bilibiliApi(
|
||||
getJsonWithCredentials(api),
|
||||
'获取视频链接失败',
|
||||
)
|
||||
const info = new DownloadVideoInfo({
|
||||
input,
|
||||
jsonData: data,
|
||||
...parseInfoFromJson(data, ['.flv']),
|
||||
})
|
||||
compareQuality(input, info)
|
||||
return info
|
||||
}
|
||||
|
||||
export const videoFlv: DownloadVideoApi = {
|
||||
name: 'video.flv',
|
||||
displayName: 'flv',
|
||||
description: '使用 flv 格式下载, 兼容 H.264 编码.',
|
||||
downloadVideoInfo: async input => {
|
||||
const { aid, cid, quality } = input
|
||||
const params = {
|
||||
avid: aid,
|
||||
cid,
|
||||
qn: quality?.value ?? '',
|
||||
otype: 'json',
|
||||
fourk: 1,
|
||||
fnver: 0,
|
||||
fnval: 0,
|
||||
}
|
||||
const api = `https://api.bilibili.com/x/player/playurl?${formData(params)}`
|
||||
const data = await bilibiliApi(
|
||||
getJsonWithCredentials(api),
|
||||
'获取视频链接失败',
|
||||
)
|
||||
const info = new DownloadVideoInfo({
|
||||
input,
|
||||
jsonData: data,
|
||||
...parseInfoFromJson(data, ['.flv']),
|
||||
})
|
||||
compareQuality(input, info)
|
||||
return info
|
||||
},
|
||||
downloadVideoInfo: input => downloadFlv(input),
|
||||
}
|
||||
|
||||
2
registry/lib/components/video/download/apis/url.ts
Normal file
2
registry/lib/components/video/download/apis/url.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const videoApi = (params: string) => `https://api.bilibili.com/x/player/playurl?${params}`
|
||||
export const bangumiApi = (params: string) => `https://api.bilibili.com/pgc/player/web/playurl?${params}`
|
||||
@ -72,6 +72,8 @@ export class DownloadVideoInfo {
|
||||
export interface DownloadVideoApi extends WithName {
|
||||
downloadVideoInfo: (input: DownloadVideoInputItem) => Promise<DownloadVideoInfo>
|
||||
description?: string
|
||||
/** 网址匹配规则 */
|
||||
match?: TestPattern
|
||||
}
|
||||
/** 表示下载时额外附带的产物, 如弹幕 / 字幕等 */
|
||||
export interface DownloadVideoAssets<AssetsParameter = any> extends VueInstanceInput, WithName {
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="script-links">
|
||||
<a target="_blank" href="https://github.com/the1812/Bilibili-Evolved/tree/v2/" class="homepage script-link">
|
||||
<a target="_blank" href="https://github.com/the1812/Bilibili-Evolved" class="homepage script-link">
|
||||
<VButton>
|
||||
<VIcon icon="mdi-home-outline" :size="20" />
|
||||
主页
|
||||
|
||||
@ -172,7 +172,7 @@ export interface FunctionalMetadata {
|
||||
/** 插件化数据定义 */
|
||||
plugin?: Optional<PluginMinimalData, 'name'>
|
||||
/** 额外想要展示在设置里的选项 UI */
|
||||
extraOptions?: Executable<VueModule>
|
||||
extraOptions?: () => Promise<VueModule>
|
||||
/** 设置匹配的URL, 不匹配则不运行此组件 */
|
||||
urlInclude?: TestPattern
|
||||
/** 设置不匹配的URL, 不匹配则不运行此组件, 优先级高于`urlInclude` */
|
||||
|
||||
@ -88,6 +88,11 @@ export async function getWatchlaterList(): Promise<number[]>
|
||||
export async function getWatchlaterList(raw: true): Promise<RawWatchlaterItem[]>
|
||||
export async function getWatchlaterList(raw: false): Promise<number[]>
|
||||
export async function getWatchlaterList(raw = false): Promise<number[] | RawWatchlaterItem[]> {
|
||||
const { getUID } = await import('@/core/utils')
|
||||
if (!getUID()) {
|
||||
console.warn('[稍后再看列表] 账号未登录')
|
||||
return []
|
||||
}
|
||||
const api = 'https://api.bilibili.com/x/v2/history/toview/web'
|
||||
const { getJsonWithCredentials } = await import('@/core/ajax')
|
||||
const response = await getJsonWithCredentials(api)
|
||||
|
||||
@ -234,6 +234,7 @@ export interface BilibiliApiResponse {
|
||||
msg?: string
|
||||
ttl: number
|
||||
data: any
|
||||
result?: any
|
||||
}
|
||||
/**
|
||||
* 进行 bilibili API 标准响应处理
|
||||
@ -252,5 +253,5 @@ export const bilibiliApi = async <T = any>(
|
||||
logError(error)
|
||||
throw error
|
||||
}
|
||||
return (json.data || {}) as T
|
||||
return (json.data || json.result || {}) as T
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ export const mediaListUrls = [
|
||||
/** 含有普通视频的页面 */
|
||||
export const videoUrls = [
|
||||
'//www.bilibili.com/video/',
|
||||
/\/\/www\.bilibili\.com\/festival\/(\d+)bnj/,
|
||||
...mediaListUrls,
|
||||
]
|
||||
/** 含有番剧的页面 */
|
||||
@ -43,6 +44,7 @@ export const mainSiteUrls = [
|
||||
/^https:\/\/www\.bilibili\.com\/$/,
|
||||
/^https:\/\/www\.bilibili\.com\/([^\/]+)\.html$/,
|
||||
/^https:\/\/www\.bilibili\.com\/watchlater\/#\/list$/,
|
||||
'https://www.bilibili.com/account/',
|
||||
]
|
||||
/** 直播间页面 */
|
||||
export const liveUrls = [
|
||||
|
||||
Loading…
Reference in New Issue
Block a user