Add batch limit & warnings

This commit is contained in:
the1812 2020-08-16 11:06:25 +08:00
parent 8ea7ca6c4c
commit 19df697199
11 changed files with 65 additions and 15 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,7 @@
- 能够下载的清晰度取决于当前登录的账号, 例如`高清 1080P60`需要已登录大会员账号.
- 如果以您的账号权限无法观看某些视频(地区限制, 大会员专享等), 就算使用了类似[解除B站区域限制](https://greasyfork.org/zh-CN/scripts/25718-%E8%A7%A3%E9%99%A4b%E7%AB%99%E5%8C%BA%E5%9F%9F%E9%99%90%E5%88%B6)的脚本也是无法下载的, 除非您有对应节点的梯子.
- 直接下载过程中所有数据都存在内存里, 内存占用很大的话会导致系统卡顿. 可以考虑使用`显示链接`转给IDM或浏览器下载, 或使用[导出 aria2](aria2-notice.md)来进行下载.
- 短时间内大量下载(错误代码为412, 多发于批量导出某某教程/课程的全套视频)会遭到b站的暂时封禁, 需要等待一段时间后才能恢复, 这期间脚本的下载视频功能也会停用.
<!-- - 使用`复制链接`得到的链接并不是直接就能用的, 因为**下载时的请求Header必须包含`Referer=https://www.bilibili.com`和正确的`User-Agent`**, 直接粘贴在浏览器里是打不开的. [详细信息](https://github.com/the1812/Bilibili-Evolved/wiki/使用下载视频的复制链接) -->

1
min/batch-warning.min.js vendored Normal file
View File

@ -0,0 +1 @@
(()=>{return(r,o)=>{const n=32;const t=412;const e=r=>{Toast.info(`为防止短时间内大量下载导致封禁, 请不要选择超过${n}的集数.`,r,5e3)};const s=()=>{throw new Error(`为防止短时间内大量下载导致封禁, 请不要选择超过${n}的集数.`)};const a=()=>{throw new Error(`短时间内下载量过大, 请过段时间再试.`)};return{export:{MaxBatchSize:n,BannedResponse:t,showBatchWarning:e,throwBatchError:s,throwBannedError:a}}}})();

View File

@ -13,6 +13,7 @@
"auto-play.min.js": "DC9938AC15DADDC9D88DCA0C9BE64BE142C37D32CB85E42E23DAB2A7378531E5",
"bangumi-timeline.vue.min.js": "3A02A24CA45655763C3A568F618A10F4009747FB67FCD002EAEBE256F03CEDC4",
"batch-download.min.js": "E205A4C855A77B2940C5747384E0750CF50CD7A19A4D4EA623B3AD835D4692BB",
"batch-warning.min.js": "C4D35814CBCFAD0EFB166D0F34B6F37E034DC59E09719BC3656520120E493475",
"biliplus-redirect.min.js": "8446444A9E9974EB32C766CB0CD3826E9F85BAA2B5F09048EBA8F3FEEAE9FA6F",
"blackboard.min.js": "5F50F1DDA203AC0C54AB52868881AA43B22007EAEF042618B1A093BBAFFDEE5B",
"blackboard.vue.min.js": "84A30D5A6F322A3C083FC1100E9FF51233ECD08AFBD89A6449AD2388ACCC8522",
@ -85,7 +86,7 @@
"download-subtitle.min.js": "EAD1F63E53C5A0A9877EBF655B68FB3438601D2869F31D0D4A2F7BD2A215E5F3",
"download-video.min.css": "3739711E755A4C7050343337AA59C235D19CC0D75FEF1B39DD1FE471AF19C811",
"download-video.min.html": "F1DBAF7AC697CA28D7B0C0807160B4D5A33DDCDFA9ADB4DFCD511C685FDC0277",
"download-video.min.js": "6937EE9C8ED782FFD07D7B6FFF2F2D59BA05FB436E3F5C9C2A48CEF7C0987607",
"download-video.min.js": "64F89AAB04D098A7E9B71D13F37B7B7AFADA9142DC1F553814039A4A9B246DF0",
"download-video-package.min.js": "79C0338420F6B388B1F5FFB50DB8333CD8DBF253DFF564F143AA0C01E79EF518",
"dpi-img.vue.min.js": "11DF7577B754D8C01E8331E4FDAC9494E72523099845A0D6B0D897849CD841D6",
"expand-danmaku.min.js": "B21658C40085AEA8DC49652AE62EB8610BB2EBEAF7A9C9AF69EF3B11E08EEC8D",

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
export const MaxBatchSize = 32
export const BannedResponse = 412
export const showBatchWarning = (title: string) => {
Toast.info(`为防止短时间内大量下载导致封禁, 请不要选择超过${MaxBatchSize}的集数.`, title, 5000)
}
export const throwBatchError = () => {
throw new Error(`为防止短时间内大量下载导致封禁, 请不要选择超过${MaxBatchSize}的集数.`)
}
export const throwBannedError = () => {
throw new Error(`短时间内下载量过大, 请过段时间再试.`)
}
export default {
export: {
MaxBatchSize,
BannedResponse,
showBatchWarning,
throwBatchError,
throwBannedError,
}
}

View File

@ -158,13 +158,21 @@ class VideoFormat {
return await VideoFormat.filterFormats(VideoFormat.parseFormats(data))
}
static async getAvailableFormats(): Promise<VideoFormat[]> {
const url = await pageData.entity.getUrl()
const json = await Ajax.getJsonWithCredentials(url)
if (json.code !== 0) {
throw new Error('获取清晰度信息失败.')
const { BannedResponse, throwBannedError } = await import('./batch-warning')
try {
const url = await pageData.entity.getUrl()
const json = await Ajax.getJsonWithCredentials(url)
if (json.code !== 0) {
throw new Error('获取清晰度信息失败.')
}
const data = json.data || json.result || json
return await VideoFormat.filterFormats(VideoFormat.parseFormats(data))
} catch (error) {
if ((error as Error).message.includes(`status of ${BannedResponse}`)) {
throwBannedError()
}
throw error
}
const data = json.data || json.result || json
return await VideoFormat.filterFormats(VideoFormat.parseFormats(data))
}
}
const allFormats: VideoFormat[] = [
@ -806,6 +814,10 @@ async function loadPanel() {
return
}
const format = this.getFormat() as VideoFormat
if (format.quality === 120) {
Toast.info('4K视频不支持直接下载, 请使用下方的导出选项.', '下载视频', 5000)
return
}
const videoDownloader = await format.downloadInfo(this.dash)
videoDownloader.subtitle = this.subtitle
switch (type) {
@ -871,10 +883,15 @@ async function loadPanel() {
},
async exportBatchData(type: ExportType) {
const episodeList = this.episodeList as EpisodeItem[]
const { MaxBatchSize, showBatchWarning } = await import('./batch-warning')
if (episodeList.every(item => item.checked === false)) {
Toast.info('请至少选择1集或以上的数量!', '批量导出', 3000)
return
}
if (episodeList.length > MaxBatchSize) {
showBatchWarning('批量导出')
return
}
const episodeFilter = (item: EpisodeItem) => {
const match = episodeList.find((it: EpisodeItem) => it.cid === item.cid) as EpisodeItem | undefined
if (match === undefined) {
@ -1036,10 +1053,15 @@ async function loadPanel() {
}
},
async exportManualData(type: ExportType) {
const { MaxBatchSize, showBatchWarning } = await import('./batch-warning')
if (this.manualInputItems.length === 0) {
Toast.info('请至少输入一个有效的视频链接!', '手动输入', 3000)
return
}
if (this.manualInputItems.length > MaxBatchSize) {
showBatchWarning('手动输入')
return
}
const { ManualInputBatch } = await import('./batch-download')
const batch = new ManualInputBatch({
api: await (new Video().getApiGenerator(this.dash)),
@ -1147,6 +1169,7 @@ async function loadPanel() {
return
}
const { BatchExtractor } = await import('batch-download')
const { MaxBatchSize } = await import('./batch-warning')
if (await BatchExtractor.test() !== true) {
this.batch = false
this.episodeList = []
@ -1161,7 +1184,7 @@ async function loadPanel() {
title: item.title,
titleParameters: item.titleParameters,
index,
checked: true,
checked: index < MaxBatchSize,
} as EpisodeItem
})
},