Add 'batchFilenameFormat' option

This commit is contained in:
the1812 2020-01-14 16:22:39 +08:00
parent 24c21f2dcc
commit bab5ee0466
18 changed files with 83 additions and 43 deletions

View File

@ -369,6 +369,7 @@ declare global {
videoScreenshot: boolean,
cache: {} | { version: string } | undefined,
filenameFormat: string,
batchFilenameFormat: string,
sideBarOffset: number,
noLiveAutoplay: boolean,
hideHomeLive: boolean,

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

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@
"auto-continue.min.js": "96CD47C367D7397CE1467A69764409BAEFF16E8F535BC8E15523CD0B8A86687E",
"auto-draw.min.js": "AE72CF2623DF2D15AD4AF82D125FFAF7EF5B1E6B36D9E9AC646AC98AA6AA8698",
"auto-play.min.js": "DC9938AC15DADDC9D88DCA0C9BE64BE142C37D32CB85E42E23DAB2A7378531E5",
"batch-download.min.js": "A06E470DD7BE64AC1A576F3FC22BB081D6A5E1F2F4A04748BE6C9B9271DDB47D",
"batch-download.min.js": "B7ADE150F26243B9529C2F0E2EC06695ACD27678E07902A8E6EABA767BBE3DD0",
"biliplus-redirect.min.js": "9882D14DAC5C103212A101A5168883C41B4B3B2737FD5F222DC343D0304FF8AF",
"blackboard.min.js": "8BB9CCDE72302AE7DE39D66F9231EFB82BA27DDA799BA4AAAC06F6DE802661BF",
"blackboard.vue.min.js": "84A30D5A6F322A3C083FC1100E9FF51233ECD08AFBD89A6449AD2388ACCC8522",
@ -90,8 +90,8 @@
"full-page-title.min.js": "5399D56E21336A2A4473F75167755EA3DE7B0146A9285D2B8FB201E44972B921",
"full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764",
"full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37",
"gui-settings.min.css": "8B53DF450716B71AE93735D45386DC443F6CC9716A5D78A5316A8E0FDFECE44D",
"gui-settings.min.html": "E67A78E2614A4647C9F8892A45F90F5EA08BF80C7EAC4E54334EA3643BC82918",
"gui-settings.min.css": "EC9E2C5DEA4D65CC2763676F4172520BA809BCC1FDC82D0A6B1080D19BF576D3",
"gui-settings.min.html": "B14E3E4B72F943299A5641479651BC9922CFC331DFB23E660B7B63FDD184CA70",
"gui-settings.min.js": "029562CA0C0DEFCCBFF38C662C56C651C09847CDB78A99873E3ABA9936B428BA",
"haruna-scale.min.js": "D046864416831B101582DD87E602AE21309FDE2DB64A8F24D57B6ADBE67E6D7B",
"hide-bangumi-reviews.min.js": "7265C0CE994FDA926355A9A4F9B207E7E68E749D47332F3C537EF93E97927A23",
@ -182,7 +182,7 @@
"superchat-translate.min.js": "0317213CDA236990C6A393B00E35165D17704041EBB29C3B08640D95F7FABE02",
"text-validate.min.js": "3F523485A3EAB6F5BB5C81570A8F4796F13EA00E4A229CFD24CB10DC5B5B61C0",
"theme-colors.min.js": "3001D5DAD0EFBAEC7F96C51FD3BE2C4677E358AD70D8DD019D2280EA450A34E7",
"title.min.js": "340C0A454E4717E5A61F24EBCAC2F67B8B1B1C821FCA86A2ADC5FFA486F1862E",
"title.min.js": "C23079AC419781D9400BBD14BB73265542AF8FB711BE67A5D6F20A43B2FE16CA",
"toast.min.css": "954BFF7E23F80710EF241182DBA67B37A1BDAAC1F31B71E0C6A58986E1209CE2",
"toast.min.js": "C430883AC04400A04AFCEDF51ECB7BDB8961812917CD552E71ACF97C19C9F7A4",
"touch-move.min.js": "96072732F8BB29A4B8EF79D5942ED13EF80C0EF209A3ECE6FDAD5D65E9E08655",

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
min/title.min.js vendored
View File

@ -1 +1 @@
(()=>{return(e,t)=>{function i(e=true){const t=document.title.replace("_番剧_bilibili_哔哩哔哩","").replace("_电影_bilibili_哔哩哔哩","").replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace(" - 哔哩哔哩直播,二次元弹幕直播平台","").replace(/[\/\\:\*\?"<>\|]/g," ").trim();if(!e||document.URL.indexOf("/bangumi")!==-1){return t}else{const e=document.querySelector("#multi_page .cur-list>ul li.on a");if(e===null){return t}else{const i=e.getAttribute("title");return t+" - "+i}}}function l(e,t=true){const i=new Date;const l={title:document.title.replace(t?/([^]+?)_番剧_bilibili_哔哩哔哩/:"_番剧_bilibili_哔哩哔哩","").replace(t?/([^]+?)_国创_bilibili_哔哩哔哩/:"_国创_bilibili_哔哩哔哩","").replace(t?/([^]+?)_电影_bilibili_哔哩哔哩/:"_电影_bilibili_哔哩哔哩","").replace(t?/([^]+?)_纪录片_bilibili_哔哩哔哩/:"_纪录片_bilibili_哔哩哔哩","").replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace(/(.*?) - (.*?) - 哔哩哔哩直播,二次元弹幕直播平台/,"$1").trim(),ep:(()=>{if(!t){return null}const e=dq("#eplist_module li.cursor .ep-title");if(e!==null){return e.innerText}const i=document.querySelector("#multi_page .cur-list>ul li.on a");if(i!==null){return i.getAttribute("title")}return null})(),aid:unsafeWindow.aid,cid:unsafeWindow.cid,lid:document.URL.replace(/https:\/\/live\.bilibili\.com\/(\d+).*/,"$1"),y:i.getFullYear().toString(),M:(i.getMonth()+1).toString().padStart(2,"0"),d:i.getDate().toString().padStart(2,"0"),h:i.getHours().toString().padStart(2,"0"),m:i.getMinutes().toString().padStart(2,"0"),s:i.getSeconds().toString().padStart(2,"0"),ms:i.getMilliseconds().toString().substr(0,3)};const r=Object.keys(l).reduce((e,t)=>{return e.replace(new RegExp(`\\[([^\\[\\]]*?)${t}([^\\[\\]]*?)\\]`,"g"),l[t]?`$1${l[t]}$2`:"")},e);return r.replace(/[\/\\:\*\?"<>\|]/g," ")}function r(t=true){if(e.filenameFormat===undefined){return i(t)}return l(e.filenameFormat,t)}return{export:{getFriendlyTitle:r,formatTitle:l}}}})();
(()=>{return(e,t)=>{function i(e=true){const t=document.title.replace("_番剧_bilibili_哔哩哔哩","").replace("_电影_bilibili_哔哩哔哩","").replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace(" - 哔哩哔哩直播,二次元弹幕直播平台","").replace(/[\/\\:\*\?"<>\|]/g," ").trim();if(!e||document.URL.indexOf("/bangumi")!==-1){return t}else{const e=document.querySelector("#multi_page .cur-list>ul li.on a");if(e===null){return t}else{const i=e.getAttribute("title");return t+" - "+i}}}function r(e,t=true,i={}){const r=new Date;const l={title:document.title.replace(/([^]+?)_番剧_bilibili_哔哩哔哩/,"").replace(/([^]+?)_国创_bilibili_哔哩哔哩/,"").replace(/([^]+?)_电影_bilibili_哔哩哔哩/,"").replace(/([^]+?)_纪录片_bilibili_哔哩哔哩/,"").replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace(/(.*?) - (.*?) - 哔哩哔哩直播,二次元弹幕直播平台/,"$1").trim(),ep:(()=>{if(!t){return null}const e=dq("#eplist_module li.cursor .ep-title");if(e!==null){return e.innerText}const i=document.querySelector("#multi_page .cur-list>ul li.on a");if(i!==null){return i.getAttribute("title")}return null})(),aid:unsafeWindow.aid,cid:unsafeWindow.cid,lid:document.URL.replace(/https:\/\/live\.bilibili\.com\/(\d+).*/,"$1"),y:r.getFullYear().toString(),M:(r.getMonth()+1).toString().padStart(2,"0"),d:r.getDate().toString().padStart(2,"0"),h:r.getHours().toString().padStart(2,"0"),m:r.getMinutes().toString().padStart(2,"0"),s:r.getSeconds().toString().padStart(2,"0"),ms:r.getMilliseconds().toString().substr(0,3)};Object.assign(l,i);const n=Object.keys(l).reduce((e,t)=>{return e.replace(new RegExp(`\\[([^\\[\\]]*?)${t}([^\\[\\]]*?)\\]`,"g"),l[t]?`$1${l[t]}$2`:"")},e);return n.replace(/[\/\\:\*\?"<>\|]/g," ")}function l(t=true){if(e.filenameFormat===undefined){return i(t)}return r(e.filenameFormat,t)}return{export:{getFriendlyTitle:l,formatTitle:r}}}})();

View File

@ -477,7 +477,8 @@ Resource.manifest = {
title: {
path: 'title.min.js',
displayNames: {
filenameFormat: '文件命名格式'
filenameFormat: '文件命名格式',
batchFilenameFormat: '批量命名格式',
}
},
imageResolution: {

View File

@ -150,6 +150,7 @@ export const settings = {
videoScreenshot: false,
hideBangumiReviews: false,
filenameFormat: '[title][ - ep]',
batchFilenameFormat: '[n - ][title]',
sideBarOffset: 0,
noLiveAutoplay: false,
hideHomeLive: false,

View File

@ -152,6 +152,7 @@
<checkbox indent="1" key="toastInternalError" dependencies="toast"></checkbox>
<!-- <checkbox indent="0" key="useCache" dependencies=""></checkbox> -->
<textbox indent="0" key="filenameFormat" dependencies=""></textbox>
<textbox indent="0" key="batchFilenameFormat" dependencies=""></textbox>
<textbox indent="0" key="sideBarOffset" dependencies=""></textbox>
<checkbox indent="0" key="ajaxHook" dependencies=""></checkbox>
<dropdown indent="0" key="scriptLoadingMode" dependencies=""></dropdown>

View File

@ -227,6 +227,7 @@
&.disabled div {
opacity: 0.5;
}
& input[key="batchFilenameFormat"],
& input[key="filenameFormat"] {
max-width: 500px;
}

View File

@ -1,3 +1,5 @@
import { formatTitle } from '../title'
const fragmentSplitFactor = 12
const dashExtensions = ['.mp4', '.m4a']
@ -5,9 +7,15 @@ export interface BatchExtractorConfig {
itemFilter: (item: BatchItem) => boolean
api?: (aid: number | string, cid: number | string, quality?: number | string) => string
}
export interface BatchTitleParameter {
[key: string]: string
n: string
ep: string
}
interface BatchItem {
aid: number | string
cid: number | string
titleParameters?: BatchTitleParameter
title: string
}
export interface RawItemFragment { length: number, size: number, url: string }
@ -23,6 +31,11 @@ abstract class Batch {
itemList: BatchItem[] = []
abstract async getItemList(): Promise<BatchItem[]>
abstract async collectData(quality: number | string): Promise<string>
formatTitle(parameters: BatchTitleParameter | undefined) {
const format = settings.batchFilenameFormat
const title = formatTitle(format, true, parameters)
return escapeFilename(title, ' ')
}
async getRawItems(quality: number | string): Promise<RawItem[]> {
return JSON.parse(await this.collectData(quality))
}
@ -119,9 +132,13 @@ class VideoEpisodeBatch extends Batch {
this.itemList = pages.map((page: any) => {
return {
title: `P${page.page} ${page.part}`,
titleParameters: {
n: page.page,
ep: page.part
},
cid: page.cid,
aid: unsafeWindow.aid,
}
} as BatchItem
})
return this.itemList
}
@ -150,7 +167,8 @@ class VideoEpisodeBatch extends Batch {
}
result.push({
fragments,
title: item.title.replace(/[\/\\:\*\?"<>\|]/g, ' '),
// title: item.title.replace(/[\/\\:\*\?"<>\|]/g, ' '),
title: this.formatTitle(item.titleParameters),
totalSize: fragments.map(it => it.size).reduce((acc, it) => acc + it),
cid: item.cid,
referer: document.URL.replace(window.location.search, '')
@ -183,11 +201,18 @@ class BangumiBatch extends Batch {
return []
}
this.itemList = json.result.main_section.episodes.map((it: any, index: number) => {
const n: string = it.long_title ? it.title : (index + 1).toString()
const title: string = it.long_title ? it.long_title : it.title
return {
aid: it.aid,
cid: it.cid,
title: it.long_title ? `${it.title} - ${it.long_title}` : `${index + 1} - ${it.title}`,
}
title: `${n} - ${title}`,
// title: it.long_title ? `${it.title} - ${it.long_title}` : `${index + 1} - ${it.title}`,
titleParameters: {
n,
ep: title,
},
} as BatchItem
})
return this.itemList
}
@ -216,7 +241,8 @@ class BangumiBatch extends Batch {
}
result.push({
fragments,
title: item.title.replace(/[\/\\:\*\?"<>\|]/g, ' '),
// title: item.title.replace(/[\/\\:\*\?"<>\|]/g, ' '),
title: this.formatTitle(item.titleParameters),
totalSize: fragments.map(it => it.size).reduce((acc, it) => acc + it),
cid: item.cid,
referer: document.URL.replace(window.location.search, '')

View File

@ -1,2 +1,2 @@
export function getFriendlyTitle(includesPageTitle?: boolean): string;
export function formatTitle(format: string, includesPageTitle?: boolean): string;
export function getFriendlyTitle(includesPageTitle?: boolean): string
export function formatTitle(format: string, includesPageTitle?: boolean, extraData?: { [key: string]: string }): string

View File

@ -18,14 +18,14 @@ function oldGetFriendlyTitle (includesPageTitle = true) {
}
}
}
export function formatTitle (format, includesPageTitle = true) {
export function formatTitle (format, includesPageTitle = true, extraData = {}) {
const now = new Date()
const data = {
title: document.title
.replace(includesPageTitle ? /([^]+?)_番剧_bilibili_哔哩哔哩/ : '_番剧_bilibili_哔哩哔哩', '')
.replace(includesPageTitle ? /([^]+?)_国创_bilibili_哔哩哔哩/ : '_国创_bilibili_哔哩哔哩', '')
.replace(includesPageTitle ? /([^]+?)_电影_bilibili_哔哩哔哩/ : '_电影_bilibili_哔哩哔哩', '')
.replace(includesPageTitle ? /([^]+?)_纪录片_bilibili_哔哩哔哩/ : '_纪录片_bilibili_哔哩哔哩', '')
.replace(/([^]+?)_番剧_bilibili_哔哩哔哩/, '')
.replace(/([^]+?)_国创_bilibili_哔哩哔哩/, '')
.replace(/([^]+?)_电影_bilibili_哔哩哔哩/, '')
.replace(/([^]+?)_纪录片_bilibili_哔哩哔哩/, '')
.replace('_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili', '')
.replace(/(.*?) - (.*?) - 哔哩哔哩直播,二次元弹幕直播平台/, '$1')
.trim(),
@ -55,6 +55,7 @@ export function formatTitle (format, includesPageTitle = true) {
s: now.getSeconds().toString().padStart(2, '0'),
ms: now.getMilliseconds().toString().substr(0, 3)
}
Object.assign(data, extraData)
const filename = Object.keys(data).reduce((result, name) => {
return result.replace(new RegExp(`\\[([^\\[\\]]*?)${name}([^\\[\\]]*?)\\]`, 'g'), data[name] ? `$1${data[name]}$2` : '')
}, format)