您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动提取 TMDb 信息、识别编码格式和下拉选项
// ==UserScript== // @name DolbyAutoTools 助手 // @namespace https://www.hddolby.com/ // @version 1.0.17 // @description 自动提取 TMDb 信息、识别编码格式和下拉选项 // @match https://www.hddolby.com/upload.php // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; function createButton() { const descrBox = document.querySelector('#descr'); if (!descrBox) return; const row = descrBox.closest('td'); const button = document.createElement('button'); button.textContent = '处理信息'; button.type = 'button'; button.style.margin = '5px 0'; button.style.padding = '4px 10px'; button.addEventListener('click', handleClick); row.appendChild(button); } function selectByMap(map, selectName) { let name = document.querySelector('#name')?.value?.toLowerCase() || ''; const select = document.querySelector(`select[name="${selectName}"]`); if (!select) return; // 针对 team_sel,只识别最后一个'-'后面的内容 if (selectName === 'team_sel') { // 匹配最后一个'-'后面的非空白字符 const teamMatch = name.match(/-([^\s-]+)$/); if (teamMatch) { const teamKey = teamMatch[1]; for (const [key, value] of Object.entries(map)) { if (teamKey.includes(key)) { select.value = value; break; } } return; } } // 其他情况保持原有逻辑 for (const [key, value] of Object.entries(map)) { if (name.includes(key)) { select.value = value; break; } } } function handleClick() { const descrBox = document.querySelector('#descr'); let text = descrBox.value.trimStart(); const titleMatch = text.match(/TMDb Title:\s*(.+)/); const urlMatch = text.match(/TMDb URL:\s*(.+)/); if (titleMatch) { const title = titleMatch[1].trim(); const smallDescr = document.querySelector('input[name="small_descr"]'); if (smallDescr) smallDescr.value = title; } if (urlMatch) { const url = urlMatch[1].trim(); const tmdbUrl = document.querySelector('input[name="tmdb_url"]'); if (tmdbUrl) tmdbUrl.value = url; } text = text // 删除 TMDb Format: 及其前面所有内容 .replace(/[\s\S]*TMDb Format:.*\n?/i, ''); descrBox.value = text.trimStart(); // 自动识别其他选项 const resolutionMap = { '4320p': '6', '8k': '6', '2160p': '1', '4k': '1', '1080p': '2', '1080i': '3', '720p': '4', }; const codecMap = { 'h.265': '2', 'hevc': '2', 'h.264': '1', 'avc': '1', 'vvc': '13', 'av1': '11', 'vp9': '12', 'avs3': '14', 'avs+': '15', 'avs2': '16', 'vc-1': '5', 'mpeg-2': '6', }; const audioCodecMap = { 'dts-hd ma': '1', 'dts-hd': '1', 'truehd': '2', 'dts-x': '15', 'lpcm': '3', 'dts': '4', 'eac3': '14', 'ddp': '14', 'ac3': '5', 'dd': '5', 'aac': '6', 'opus': '13', 'flac': '7', 'ape': '8', 'wav': '9', 'mp3': '10', 'm4a': '11', 'av3a': '16', 'avsa': '17', 'mpeg': '18', }; const teamMap = { 'dream': '1', 'dbtv': '10', 'qhstudio': '12', 'cornermv': '13', 'telesto': '14', 'mteam': '2', 'wiki': '4', 'frds': '7', 'hdo': '9', 'beast': '11', 'chd': '5', 'cmct': '6', 'pthome': '3', }; const mediumMap = { 'remux': '3', 'uhd': '1', 'blu-ray': '2', 'bluray': '2', 'bdrip': '2', 'encode': '10', 'web-dl': '6', 'webrip': '7', 'webdl': '6', 'feed': '12', 'hdtv': '5', 'hd dvd': '4', 'hddvd': '4', 'dvd': '8', 'cd': '9', }; selectByMap(resolutionMap, 'standard_sel'); selectByMap(codecMap, 'codec_sel'); selectByMap(audioCodecMap, 'audiocodec_sel'); selectByMap(teamMap, 'team_sel'); selectByMap(mediumMap, 'medium_sel'); // 处理 name 字段中的音频声道格式,比如 AAC 2 0- => AAC 2.0- const nameInput = document.querySelector('#name'); if (nameInput && nameInput.value) { // 匹配常见音频编码后跟 2 0 或 5 1 等,替换为 2.0、5.1 nameInput.value = nameInput.value.replace( /\b([a-z0-9]+)\s+([2-8])\s([01])(?=[^\d]|$)/ig, (match, codec, ch1, ch2) => `${codec} ${ch1}.${ch2}` ); } // 官方制作组自动勾选 const name = document.querySelector('#name')?.value?.toLowerCase() || ''; const officialTeams = ['dream', 'dbtv', 'qhstudio', 'cornermv']; const officialCheckbox = document.querySelector('input[name="officialteam"]'); if (officialCheckbox) { const checked = officialTeams.some(team => name.includes(team)); officialCheckbox.checked = checked; const tagGfCheckbox = document.querySelector('input#tag_gf[name="tags[]"][value="gf"]'); if (tagGfCheckbox) tagGfCheckbox.checked = checked; } // 勾选 tag_wj 如果 name 包含 complete const tagWjCheckbox = document.querySelector('input#tag_wj[name="tags[]"][value="wj"]'); if (tagWjCheckbox) tagWjCheckbox.checked = name.includes('complete'); // 勾选 tag_hdrm 如果 name 包含 HDR10+ 或 HDR10P(不区分大小写) const tagHdrmCheckbox = document.querySelector('input#tag_hdrm[name="tags[]"][value="hdrm"]'); let hdr10PlusChecked = false; if (tagHdrmCheckbox) { const lowerName = name.toLowerCase(); hdr10PlusChecked = lowerName.includes('hdr10+') || lowerName.includes('hdr10p'); tagHdrmCheckbox.checked = hdr10PlusChecked; } // 勾选 tag_hdr10 如果 name 包含 HDR 或 HDR10(不区分大小写),且未勾选 HDR10+ const tagHdr10Checkbox = document.querySelector('input#tag_hdr10[name="tags[]"][value="hdr10"]'); if (tagHdr10Checkbox && !hdr10PlusChecked) { const lowerName = name.toLowerCase(); tagHdr10Checkbox.checked = lowerName.includes('hdr'); } // 勾选 tag_zz 如果简介里字幕含有 zh const tagZzCheckbox = document.querySelector('input#tag_zz[name="tags[]"][value="zz"]'); if (tagZzCheckbox) { // 检查 descrBox.value 里是否有 "Subtitles" 或 "字幕" 行包含 "zh" const descrText = descrBox.value.toLowerCase(); // 匹配 "subtitles" 或 "字幕" 开头的行,且包含 "zh" const hasZhSubtitle = descrText.split('\n').some(line => (line.includes('subtitles') || line.includes('字幕')) && (line.includes('zh') || line.includes('cmn')) ); tagZzCheckbox.checked = hasZhSubtitle; } // 勾选 tag_ko 如果简介中 audio 行包含 ko const tagKoCheckbox = document.querySelector('input#tag_ko[name="tags[]"][value="ko"]'); if (tagKoCheckbox) { const descrText = descrBox.value.toLowerCase(); tagKoCheckbox.checked = descrText.split('\n').some(line => (line.startsWith('audio') || line.includes('音频')) && line.includes('ko') ); } // 勾选 tag_ja 如果简介中 audio 行包含 ja const tagJaCheckbox = document.querySelector('input#tag_ja[name="tags[]"][value="ja"]'); if (tagJaCheckbox) { const descrText = descrBox.value.toLowerCase(); tagJaCheckbox.checked = descrText.split('\n').some(line => (line.startsWith('audio') || line.includes('音频')) && line.includes('ja') ); } // 检测视频码率并勾选高码率标签 const descrText = descrBox.value; const bitrateMatch = descrText.match(/Video.*?(\d+\.\d+)\s*Mb\/s/i); if (bitrateMatch && !isNaN(bitrateMatch[1])) { const bitrate = parseFloat(bitrateMatch[1]); const tagHqCheckbox = document.querySelector('input#tag_hq[name="tags[]"][value="hq"]'); if (tagHqCheckbox) { tagHqCheckbox.checked = bitrate > 10; } } // 如果简介中类别匹配到“纪录”,则选择 Documentaries纪录片 const typeSelect = document.querySelector('select[name="type"]#browsecat'); if (typeSelect) { const descrText = descrBox.value; const tmdbUrlInput = document.querySelector('input[name="tmdb_url"]'); const tmdbUrl = tmdbUrlInput ? tmdbUrlInput.value : ''; // 只遍历一次,收集所有类别行 const categoryLines = descrText.split('\n').filter(line => line.includes('◎类 别') || line.includes('类别') ).join(' '); // 统一小写处理 const categoryText = categoryLines.toLowerCase(); // 优先级顺序:纪录片 > 动画 > 剧情+tv > 真人秀 > 电影 if (categoryText.includes('纪录')) { typeSelect.value = "404"; } else if (categoryText.includes('动画')) { typeSelect.value = "405"; } else if (categoryText.includes('真人秀')) { typeSelect.value = "403"; } else { const tvKeywords = ['剧情', '喜剧', 'Sci-Fi & Fantasy', '犯罪']; const isTVSeries = tvKeywords.some(keyword => categoryText.includes(keyword)); if (isTVSeries && /\/tv\//.test(tmdbUrl)) { typeSelect.value = "402"; } else { // 不包含 真人秀/纪录/动画 且 tmdbUrl 含 /movie/ const excludeKeywords = ['真人秀', '纪录', '动画']; const hasExclude = excludeKeywords.some(keyword => categoryText.includes(keyword)); if (!hasExclude && /\/movie\//.test(tmdbUrl)) { typeSelect.value = "401"; } } } } } // 初始化按钮 window.addEventListener('load', createButton); })();