2021-11-21 03:17:10 +00:00
// ==UserScript==
// @name AnimeBytes Mediainfo Improvements
// @author WeebDataHoarder
2024-04-03 15:59:50 +00:00
// @version 1.32.1
2021-11-21 03:17:10 +00:00
// @downloadURL https://git.gammaspectra.live/WeebDataHoarder/userscripts/raw/branch/master/AnimeBytes/ab-mediainfo.user.js
// @updateURL https://git.gammaspectra.live/WeebDataHoarder/userscripts/raw/branch/master/AnimeBytes/ab-mediainfo.user.js
// @description AnimeBytes Mediainfo Improvements. Adds several listing and matching releases against mediainfo utilities. MIT license
// @match https://animebytes.tv/torrents.php?*id=*
2021-11-29 23:31:17 +00:00
// @match https://animebytes.tv/torrents2.php?*id=*
2021-12-09 08:56:14 +00:00
// @exclude https://animebytes.tv/torrents*groupid=*
2021-11-29 18:02:16 +00:00
// @match https://animebytes.tv/user.php?action=edit
2021-12-10 07:05:25 +00:00
// @match https://animebytes.tv/upload.php*
2024-02-27 12:19:10 +00:00
// @icon https://mei.kuudere.pw/jEBHMictkaa.png
2021-11-25 18:53:41 +00:00
// @grant GM_addStyle
2021-11-29 18:02:16 +00:00
// @grant GM_setValue
// @grant GM_getValue
2021-12-10 07:31:13 +00:00
// @require deps/compat.js?1
2022-04-24 18:53:25 +00:00
// @require deps/resources.js?2
2021-12-10 07:31:13 +00:00
// @require deps/settings.js?1
2023-11-20 08:43:12 +00:00
// @require deps/mediainfo.js?17
2021-12-10 07:31:13 +00:00
// @require deps/ab-class.js?1
2021-11-21 03:17:10 +00:00
// @run-at document-end
// ==/UserScript==
2021-12-02 16:26:08 +00:00
function getComparisonLine ( tags , legacy = true ) {
2021-11-21 03:17:10 +00:00
let entries = [ ] ;
2021-12-02 16:26:08 +00:00
entries . push ( getLineTagEntry ( tags . source , legacy ) ) ;
entries . push ( getLineTagEntry ( tags . container , legacy ) + ( "region" in tags ? " (" + tags . region + ")" : "" ) ) ;
2021-11-21 03:17:10 +00:00
if ( "aspectRatio" in tags ) {
entries . push ( tags . aspectRatio ) ;
}
2021-11-25 18:07:42 +00:00
if ( "videoCodec" in tags && ! (
2021-12-02 16:26:08 +00:00
getLineTagEntry ( tags . source , legacy ) . match ( /^DVD[59]$/ ) !== null
2021-11-25 18:07:42 +00:00
) ) {
2021-12-02 16:26:08 +00:00
entries . push ( getLineTagEntry ( tags . videoCodec , legacy ) ) ;
2021-11-21 03:17:10 +00:00
}
2021-12-16 14:48:21 +00:00
entries . push ( getLineTagEntry ( tags . resolution , legacy ) ) ;
2021-11-21 03:17:10 +00:00
2021-12-09 08:56:14 +00:00
entries . push ( getLineTagEntry ( tags . audioCodec , legacy ) + " " + Mediainfo . getAudioChannels ( tags . audioChannels ) ) ;
2021-11-30 09:07:11 +00:00
if ( ( ! ( "audioLanguages" in tags ) || "English" in tags . audioLanguages ) && tags . audioCount > 1 ) {
2021-11-21 03:17:10 +00:00
entries . push ( "Dual Audio" ) ;
}
2021-12-02 16:26:08 +00:00
entries . push ( ( "subtitleType" in tags ? getLineTagEntry ( tags . subtitleType , legacy ) : "RAW" ) + ( "group" in tags ? " (" + tags . group + ")" : "" ) ) ;
2021-11-21 03:17:10 +00:00
return entries . join ( " | " ) ;
}
2022-04-24 18:53:25 +00:00
function wrap ( ... e ) {
let span = document . createElement ( "span" ) ;
e . forEach ( ( i ) => {
span . append ( i ) ;
} )
return span ;
}
function wrapStyleClass ( e , classType ) {
let span = document . createElement ( "span" ) ;
2022-04-27 13:01:20 +00:00
let value ;
if ( typeof e === 'string' ) {
value = e ;
} else {
value = e . textContent ;
if ( value === "" ) {
value = e . getAttribute ( "alt" ) ;
}
}
if ( value === "" ) {
return e ;
}
2022-04-24 18:53:25 +00:00
if ( settings . getSetting ( "script_evaHighlightEmulation" ) || settings . getSetting ( "script_abHighlights2Emulation" ) ) {
2022-04-27 13:01:20 +00:00
span . setAttribute ( "data-" + classType , value ) ;
2022-04-24 18:53:25 +00:00
}
if ( settings . getSetting ( "script_abHighlights2Emulation" ) ) {
span . classList . add ( "userscript-highlight" , "torrent-field" ) ;
2022-04-27 13:01:20 +00:00
span . setAttribute ( "data-field" , value ) ;
2022-04-24 18:53:25 +00:00
}
span . append ( e ) ;
return span ;
}
2021-12-09 15:04:39 +00:00
function getEntryLine ( tags , messages ) {
2021-11-25 18:07:42 +00:00
// Source + container + remux | Codec / Resolution / HDR | Audio + Dual + commentary | Text | OtherTags | icons
let entries = {
source : [ ] ,
video : [ ] ,
audio : [ ] ,
text : [ ] ,
other : [ ] ,
icons : [ ]
} ;
2021-11-30 05:06:09 +00:00
2022-04-24 18:53:25 +00:00
entries . source . push ( wrap (
wrapStyleClass ( getLineTagEntry ( tags . source , false ) , "media" ) ,
( "sourceName" in tags ? wrap ( " (" , wrapStyleClass ( tags . sourceName , "source" ) , ")" ) : "" )
) ) ;
entries . source . push ( wrap (
wrapStyleClass ( getLineTagEntry ( tags . container , false ) , "container" ) ,
( "region" in tags ? wrap ( " (" , wrapStyleClass ( tags . region , "region" ) , ")" ) : "" )
) ) ;
2021-11-25 18:07:42 +00:00
2021-12-02 16:26:08 +00:00
if ( "videoCodec" in tags ) {
2021-11-30 08:40:15 +00:00
let span = document . createElement ( "span" ) ;
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "debug_flagUnknownCodec" ) && typeof tags . videoCodec !== "object" ) {
2021-11-30 08:40:15 +00:00
span . append ( "NOID-" ) ;
}
let codec = document . createElement ( "span" ) ;
codec . classList . add ( "entry_codec" ) ;
codec . textContent = getLineTagEntry ( tags . videoCodec , false ) ;
2022-04-24 18:53:25 +00:00
span . append ( wrapStyleClass ( codec , "codec" ) ) ;
2021-12-09 08:56:14 +00:00
if ( "videoEncoder" in tags && settings . getSetting ( "showEncodingDetails" ) ) {
2022-04-24 18:53:25 +00:00
span . append ( wrap (
" (" ,
wrapStyleClass ( tags . videoEncoder , "encoder" ) ,
( "videoEncodeMode" in tags ? wrap ( " " , wrapStyleClass ( tags . videoEncodeMode , "encode-mode" ) ) : "" ) ,
( "videoEncodeRateControl" in tags ? wrap ( " " , wrapStyleClass ( tags . videoEncodeRateControl , "encode-rc" ) ) : "" ) ,
")"
) ) ;
2021-11-30 08:40:15 +00:00
}
entries . video . push ( span ) ;
}
2022-04-24 18:53:25 +00:00
entries . video . push ( wrap (
wrapStyleClass ( getLineTagEntry ( tags . resolution , false ) , "resolution" ) ,
( "aspectRatio" in tags ? wrap ( " " , wrapStyleClass ( tags . aspectRatio , "aspect-ratio" ) ) : "" )
/* ("videoFrameRate" in tags ? " @ " + tags.videoFrameRate : "")*/
) ) ;
2021-11-21 03:17:10 +00:00
if ( "videoHDR" in tags ) {
2022-04-24 18:53:25 +00:00
entries . video . push ( wrapStyleClass ( getLineTagEntry ( tags . videoHDR , false ) , "hdr" ) ) ;
2021-11-21 03:17:10 +00:00
}
2021-11-26 09:28:35 +00:00
if ( tags . videoCount > 1 ) {
2022-04-24 18:53:25 +00:00
entries . video . push ( wrapStyleClass ( tags . videoCount === 2 ? "Dual" : "Multi (" + tags . videoCount + ")" , "dual-video" ) ) ;
2021-11-26 09:28:35 +00:00
}
2021-11-21 03:17:10 +00:00
2021-11-30 08:40:15 +00:00
{
let span = document . createElement ( "span" ) ;
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "debug_flagUnknownCodec" ) && typeof tags . audioCodec !== "object" ) {
2021-11-30 08:40:15 +00:00
span . append ( "NOID-" ) ;
}
let codec = document . createElement ( "span" ) ;
codec . classList . add ( "entry_codec" ) ;
codec . textContent = getLineTagEntry ( tags . audioCodec , false ) ;
2022-04-24 18:53:25 +00:00
span . append ( wrapStyleClass ( codec , "audio-codec" ) ) ;
2021-12-24 16:23:05 +00:00
if ( settings . getSetting ( "showAudioDetails" ) && "audioBitrate" in tags ) {
2022-04-24 18:53:25 +00:00
span . append ( " " , wrapStyleClass ( tags . audioBitrate , "audio-bitrate" ) ) ;
2021-12-24 16:23:05 +00:00
}
2022-04-24 18:53:25 +00:00
span . append ( " " , wrapStyleClass ( Mediainfo . getAudioChannels ( tags . audioChannels ) , "audio-channels" ) ) ;
2021-11-30 08:40:15 +00:00
entries . audio . push ( span ) ;
}
2021-11-21 03:17:10 +00:00
if ( tags . audioCount > 1 ) {
2021-11-30 09:07:11 +00:00
if ( ( ! ( "audioLanguages" in tags ) || "English" in tags . audioLanguages ) ) {
2022-04-24 18:53:25 +00:00
entries . audio . push ( wrapStyleClass ( tags . audioCount === 2 ? "Dual" : "Dual Multi (" + ( "audioLanguages" in tags ? Object . keys ( tags . audioLanguages ) . length + "x" : "" ) + tags . audioCount + ")" , "dual-audio" ) ) ;
2021-11-30 09:07:11 +00:00
} else {
2022-04-24 18:53:25 +00:00
entries . audio . push ( wrapStyleClass ( "Multi (" + ( "audioLanguages" in tags ? Object . keys ( tags . audioLanguages ) . length + "x" : "" ) + tags . audioCount + ")" , "dual-audio" ) ) ;
2021-11-30 09:07:11 +00:00
}
2021-11-21 03:17:10 +00:00
}
2021-11-21 13:15:27 +00:00
if ( "audioCommentary" in tags && tags . audioCommentary ) {
2022-04-24 18:53:25 +00:00
entries . audio . push ( wrapStyleClass ( "Commentary" , "audio-commentary" ) ) ;
2021-11-21 13:15:27 +00:00
}
2021-11-21 14:41:03 +00:00
if ( "remux" in tags ) {
if ( tags . remux === true ) {
2022-04-24 18:53:25 +00:00
entries . source . push ( wrapStyleClass ( "REMUX" , "remux" ) ) ;
2021-11-21 14:41:03 +00:00
} else if ( tags . remux === "probably" ) {
2022-04-24 18:53:25 +00:00
entries . source . push ( wrapStyleClass ( "REMUX*" , "remux" ) ) ;
2021-11-21 14:41:03 +00:00
}
}
2022-04-27 13:01:20 +00:00
entries . text . push ( wrap (
wrapStyleClass ( ( "subtitleCodec" in tags ? tags . subtitleCodec + " " : "" ) , "subbing-codec" ) ,
wrapStyleClass ( ( "subtitleType" in tags ? getLineTagEntry ( tags . subtitleType , false ) : "RAW" ) , "subbing" ) ,
( "group" in tags ? wrap ( " (" , wrapStyleClass ( tags . group , "group" ) , ")" ) : "" ) ,
) ) ;
2021-12-01 07:32:10 +00:00
2021-11-21 13:15:27 +00:00
if ( tags . remastered ) {
2021-12-09 08:56:14 +00:00
entries . other . push ( createImage ( "remastered" ) ) ;
2021-11-21 13:15:27 +00:00
}
2021-12-01 07:32:10 +00:00
if ( tags . censoredHentai ) {
2021-12-09 08:56:14 +00:00
entries . other . push ( createImage ( "hentaic" ) ) ;
2021-12-01 07:32:10 +00:00
} else if ( tags . uncensoredHentai ) {
2021-12-09 08:56:14 +00:00
entries . other . push ( createImage ( "hentai" ) ) ;
2021-12-01 07:32:10 +00:00
}
2021-11-21 13:15:27 +00:00
if ( tags . freeleech ) {
2022-04-24 18:53:25 +00:00
entries . other . push ( wrapStyleClass ( createImage ( "freeleech" ) , "freeleech" ) ) ;
2021-11-25 18:07:42 +00:00
}
if ( "chapters" in tags ) {
entries . other . push ( tags . chapters === "ordered" ? "Ordered Chapters" : "Chapters" ) ;
}
2021-12-09 08:56:14 +00:00
if ( tags . openFormat && settings . getSetting ( "openFormats" ) ) {
2021-11-29 22:41:33 +00:00
entries . other . push ( "Open Format" ) ;
}
2021-11-25 18:07:42 +00:00
if ( tags . snatched ) {
entries . other . push ( "Snatched" ) ;
2021-11-21 13:15:27 +00:00
}
2021-11-30 03:48:57 +00:00
if ( tags . pruned ) {
entries . other . push ( "Pruned" ) ;
}
2022-01-03 14:54:50 +00:00
if ( tags . reported ) {
entries . other . push ( "Reported" ) ;
}
2021-12-09 15:04:39 +00:00
let messageCount = 0 ;
2021-11-25 18:07:42 +00:00
2021-12-09 15:04:39 +00:00
let span = document . createElement ( "span" ) ;
span . classList . add ( "emoji" , "icons" ) ;
2021-11-25 18:07:42 +00:00
2021-12-09 15:04:39 +00:00
for ( const [ key , value ] of Object . entries ( messages ) ) {
if ( value . length > 0 ) {
for ( let v of value ) {
if ( Array . isArray ( v ) ) {
switch ( v [ 0 ] ) {
case "info" :
span . append ( createIcon ( "ℹ " , null , key + ": " + v [ 1 ] ) ) ;
break ;
case "warning" :
span . append ( createIcon ( "⚠" , "#ffff00" , key + ": " + v [ 1 ] ) ) ;
break ;
case "danger" :
span . append ( createIcon ( "❌" , "#ff0000" , key + ": " + v [ 1 ] ) ) ;
break ;
case "mediainfo" :
span . append ( createIcon ( "📄" , "#ff0000" , key + ": " + v [ 1 ] ) ) ;
break ;
}
} else {
span . append ( createIcon ( "⚠" , "#ffff00" , key + ": " + v ) ) ;
}
++ messageCount ;
}
2021-11-25 18:07:42 +00:00
}
2021-12-09 15:04:39 +00:00
}
if ( messageCount > 0 ) {
2021-11-25 18:07:42 +00:00
entries . icons . unshift ( span ) ;
}
2021-11-21 13:15:27 +00:00
return entries ;
2021-11-21 03:17:10 +00:00
}
2021-12-16 15:04:39 +00:00
function extractTagsFromFilename ( fileName , sourceTags , source = "" ) {
2021-12-10 07:05:25 +00:00
let tags = {
} ;
2023-05-22 15:44:32 +00:00
let cleanName = fileName . replace ( /\.[^/.]+$/ , "" )
cleanName = cleanName . replace ( /\[[A-F0-9]{8}\]$/i , "" )
cleanName = cleanName . replace ( /\([A-F0-9]{8}\)$/i , "" )
2021-12-10 07:05:25 +00:00
//handle file tags
2023-05-22 15:44:32 +00:00
cleanName . split ( "." ) . forEach ( ( p ) => {
2021-12-16 14:48:21 +00:00
const pCase = p . toUpperCase ( ) ;
if ( pCase === "NF" || pCase === "NETFLIX" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Netflix" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "CR" || pCase === "CRUNCHYROLL" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Crunchyroll" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "ITUNES" ) {
tags . sourceName = "Apple iTunes" ;
} else if ( pCase === "ATVP" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Apple TV+" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "DSNP" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Disney Plus" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "AMZN" || pCase === "AMAZON" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Amazon Prime Video" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "FUNI" || pCase === "FUNIMATION" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Funimation" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "WAKANIM" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Wakanim" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "ANIMELAB" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "AnimeLab" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "HIDIVE" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Hidive" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "VRV" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "VRV" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "HULU" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Hulu" ;
} else if ( p === "HDR" ) {
tags . videoHDR = "HDR" ;
} else if ( p === "HDR10" ) {
tags . videoHDR = "HDR10" ;
} else if ( p === "DV" ) {
tags . videoHDR = "HDR DV" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "REMUX" ) {
2021-12-10 07:05:25 +00:00
tags . remux = true ;
2021-12-16 14:48:21 +00:00
} else if ( p . match ( /^(bd|(blu-?ray))(-?rip)?$/i ) !== null ) {
2023-05-22 15:44:32 +00:00
tags . source = ( cleanName . match ( /(4K|2160|3840|UHD)/ ) !== null || sourceTags . source === "UHD Blu-ray" ) ? "UHD Blu-ray" : "Blu-ray" ;
2021-12-16 14:48:21 +00:00
} else if ( p . match ( /^dvd(-?rip)?$/i ) !== null ) {
tags . source = "DVD" ;
} else if ( p . match ( /^web(-?(rip|dl))?$/i ) !== null ) {
tags . source = "Web" ;
2021-12-10 07:05:25 +00:00
}
2023-04-13 09:37:58 +00:00
// negative match known rips to not be flagged by REMUX* later
if ( p . match ( /^(bd|(blu-?ray))(-?rip)$/i ) !== null ) {
tags . remux = false ;
} else if ( p . match ( /^(dvd)(-?rip)$/i ) !== null ) {
tags . remux = false ;
}
2021-12-10 07:05:25 +00:00
} ) ;
2023-05-22 15:44:32 +00:00
cleanName . split ( /[ _\[(\])]/ ) . forEach ( ( p ) => {
2021-12-16 14:48:21 +00:00
const pCase = p . toUpperCase ( ) ;
if ( source === "Web" && ( pCase === "NF" || pCase === "NETFLIX" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Netflix" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase === "ITUNES" ) {
tags . sourceName = "Apple iTunes" ;
} else if ( source === "Web" && ( pCase === "CR" || pCase === "CRUNCHYROLL" || pCase === "CR-DUB" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Crunchyroll" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && ( pCase === "AMZN" || pCase === "AMAZON" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Amazon Prime Video" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && pCase === "HULU" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Hulu" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && ( pCase === "FUNIMATION" || pCase === "FUNI" || pCase === "FUNIDUB" || pCase === "FUNI-DUB" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Funimation" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && ( pCase === "HIDIVE" || pCase === "HIDIVE-DUB" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Hidive" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && pCase === "VRV" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "VRV" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "TV" && pCase === "SSTV" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Space Shower TV" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "TV" && pCase === "SSTV+" ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "Space Shower TV+" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "TV" && ( pCase === "M-ON" || pCase === "M-ON!" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "MUSIC ON! TV" ;
2021-12-16 14:48:21 +00:00
} else if ( source === "Web" && ( pCase === "WETV" ) ) {
2021-12-10 07:05:25 +00:00
tags . sourceName = "WeTV" ;
2022-05-05 11:18:27 +00:00
} else if ( source === "TV" && pCase === "MX" ) {
tags . sourceName = "TOKYO MX" ;
} else if ( source === "TV" && pCase === "CX" ) {
tags . sourceName = "Fuji TV" ;
} else if ( source === "TV" && pCase === "TX" ) {
tags . sourceName = "TX Network" ;
} else if ( source === "TV" && pCase === "NTV" ) {
tags . sourceName = "NIPPON TV" ;
} else if ( source === "TV" && pCase === "ABC" ) {
tags . sourceName = "ABC" ;
} else if ( source === "TV" && pCase === "RKC" ) {
tags . sourceName = "RKC" ;
} else if ( source === "TV" && pCase === "CS3" ) {
tags . sourceName = "CS3" ;
} else if ( source === "TV" && pCase === "BS6" ) {
tags . sourceName = "BS6" ;
} else if ( source === "TV" && pCase === "RKC" ) {
tags . sourceName = "RKC" ;
} else if ( source === "TV" && pCase === "EX-BS" ) {
tags . sourceName = "EX-BS" ;
} else if ( source === "TV" && pCase === "TBS" ) {
tags . sourceName = "TBS Television" ;
} else if ( source === "TV" && pCase === "EX" ) {
tags . sourceName = "TV Asahi" ;
} else if ( source === "TV" && pCase === "TVA" ) {
tags . sourceName = "TV Aichi" ;
} else if ( source === "TV" && pCase === "QAB" ) {
tags . sourceName = "QAB" ;
} else if ( source === "TV" && pCase === "TVQ" ) {
tags . sourceName = "TVQ Kyushu Broadcasting" ;
} else if ( source === "TV" && pCase === "KBC" ) {
tags . sourceName = "KBC" ;
} else if ( source === "TV" && pCase === "BS4" ) {
tags . sourceName = "BS Nippon TV" ;
} else if ( source === "TV" && pCase === "BS11" ) {
tags . sourceName = "BS11" ;
} else if ( source === "TV" && ( pCase === "AT-X" || pCase === "ATX" ) ) {
tags . sourceName = "AT-X" ;
} else if ( source === "TV" && pCase === "WOWOW" ) {
tags . sourceName = "WOWOW" ;
} else if ( source === "TV" && pCase === "YTV" ) {
tags . sourceName = "Yomiuri TV" ;
2021-12-10 07:05:25 +00:00
} else if ( p === "HDR" ) {
tags . videoHDR = "HDR" ;
} else if ( p === "HDR10" ) {
tags . videoHDR = "HDR10" ;
} else if ( p === "DV" ) {
tags . videoHDR = "HDR DV" ;
2021-12-16 14:48:21 +00:00
} else if ( pCase . indexOf ( "REMUX" ) !== - 1 ) {
2021-12-10 07:05:25 +00:00
tags . remux = true ;
2021-12-16 14:48:21 +00:00
} else if ( p . match ( /^(bd|(blu-?ray))(-?rip)?$/i ) !== null ) {
2023-05-22 15:44:32 +00:00
tags . source = ( cleanName . match ( /(4K|2160|3840|UHD)/ ) !== null || sourceTags . source === "UHD Blu-ray" ) ? "UHD Blu-ray" : "Blu-ray" ;
2021-12-16 14:48:21 +00:00
} else if ( p . match ( /^dvd(-?rip)?$/i ) !== null ) {
tags . source = "DVD" ;
} else if ( p . match ( /^web(-?(rip|dl))?$/i ) !== null ) {
tags . source = "Web" ;
2021-12-10 07:05:25 +00:00
}
2023-04-13 09:37:58 +00:00
// negative match known rips to not be flagged by REMUX* later
if ( p . match ( /^(bd|(blu-?ray))(-?rip)$/i ) !== null ) {
tags . remux = false ;
} else if ( p . match ( /^(dvd)(-?rip)$/i ) !== null ) {
tags . remux = false ;
}
2021-12-10 07:05:25 +00:00
} ) ;
return tags ;
}
2021-12-10 10:50:30 +00:00
function extractFromMediainfo ( tags , mediainfo , warnings , fileName , fileList , sourceTags , isLiveActionType = false ) {
2021-12-10 07:05:25 +00:00
2021-12-10 10:50:30 +00:00
tags . openFormat = false ;
2022-04-24 18:53:25 +00:00
2021-12-10 07:05:25 +00:00
let japaneseAudio = null ;
let otherAudio = null ;
let defaultAudio = null ;
let englishSubs = null ;
let defaultSubs = null ;
const fversions = ( "format_version" in mediainfo . general ? mediainfo . general . format _version . replace ( /[^0-9 ]+/g , "" ) . split ( " " ) . filter ( ( a ) => a ) : [ ] ) ;
const fversion = fversions . length > 0 ? " v" + fversions . join ( "." ) : "" ;
switch ( mediainfo . general . format ) {
case "Matroska" :
tags . container = {
name : "MKV" + ( settings . getSetting ( "showContainerVersions" ) ? fversion : "" ) ,
legacy : "MKV"
} ;
tags . openFormat = true ;
break ;
case "WebM" :
tags . container = {
name : "WebM" + ( settings . getSetting ( "showContainerVersions" ) ? fversion : "" ) ,
legacy : "MKV"
} ;
tags . openFormat = true ;
break ;
case "Ogg" :
tags . container = "OGM" ;
tags . openFormat = true ;
break ;
case "MPEG-4" :
tags . container = "MP4" ;
break ;
case "MPEG-PS" :
let baseContainer = "MPG" ;
if ( fileName . split ( "." ) . slice ( - 1 ) [ 0 ] . toUpperCase ( ) === "VOB" ) {
baseContainer = "VOB"
}
if ( sourceTags . container . match ( / IFO$/ ) !== null ) {
baseContainer += " IFO" ;
}
tags . container = {
name : sourceTags . container === "ISO" ? "ISO-" + baseContainer : baseContainer ,
legacy : sourceTags . container === "ISO" ? "ISO" : baseContainer
} ;
break ;
case "MPEG-TS" :
tags . container = "TS" ;
if ( "original_network_name" in mediainfo . general ) {
tags . sourceName = mediainfo . general . original _network _name ;
}
break ;
case "Flash Video" :
tags . container = "FLV" ;
break ;
case "AVI" :
tags . container = "AVI" ;
break ;
2022-04-28 22:02:28 +00:00
case "RealMedia" :
tags . container = "RMVB" ;
break ;
2021-12-10 07:05:25 +00:00
case "Windows Media" :
tags . container = "WMV" ;
break ;
case "BDAV" :
tags . container = {
name : sourceTags . container === "ISO" ? "ISO-M2TS" : "M2TS" ,
legacy : sourceTags . container === "ISO" ? "ISO" : "M2TS"
} ;
break ;
}
2023-09-02 14:07:36 +00:00
let isHandbrake = false ;
if ( "general" in mediainfo ) {
if ( "writing_application" in mediainfo . general ) {
if ( mediainfo . general . writing _application . match ( /^HandBrake / ) !== null ) {
if ( settings . getSetting ( "warning_handbrakeEncoder" ) ) {
warnings . general . push ( [ "info" , "Found HandBrake encoder" ] ) ;
}
isHandbrake = true ;
}
}
}
2021-12-10 07:05:25 +00:00
let video = null ;
mediainfo . video . forEach ( ( v ) => {
Mediainfo . makeVideoObject ( v ) ;
if ( ! ( "open" in v . _ _videoCodec ) || ! v . _ _videoCodec . open ) {
tags . openFormat = false ;
}
if ( video !== null && "default" in v && v . default === "Yes" ) {
video = v ;
}
} ) ;
if ( video === null && mediainfo . video . length > 0 ) {
video = mediainfo . video [ 0 ] ;
}
tags . videoCount = mediainfo . video . length ;
if ( video !== null ) {
tags . videoCodec = Mediainfo . matchCodec ( Mediainfo . videoCodecs , video , sourceTags . videoCodec ? sourceTags . videoCodec : video . _ _videoCodec ) ;
if ( "frame_rate" in video ) {
tags . videoFrameRate = video . frame _rate . split ( " " ) [ 0 ] ;
} else if ( "original_frame_rate" in video ) {
tags . videoFrameRate = video . original _frame _rate . split ( " " ) [ 0 ] ;
}
2022-05-10 08:14:34 +00:00
if ( "videoFrameRate" in tags && tags . videoFrameRate > settings . getSetting ( "warning_progressiveFpsTooHigh" ) && ( ! ( "scan_type" in video ) || video . scan _type === "Progressive" ) ) {
2021-12-10 07:05:25 +00:00
warnings . video . push ( [ "danger" , "Progressive Frame Rate too high! Found " + tags . videoFrameRate + " > " + settings . getSetting ( "warning_progressiveFpsTooHigh" ) ] ) ;
}
let width = parseInt ( video . width . replace ( /[^0-9]/g , "" ) ) ;
let height = parseInt ( video . height . replace ( /[^0-9]/g , "" ) ) ;
2022-03-29 07:40:24 +00:00
2021-12-10 07:05:25 +00:00
let ar = width / height ;
2022-03-29 07:40:24 +00:00
//Handle anamorphic video
2022-03-29 07:45:16 +00:00
if ( "display_aspect_ratio" in video && settings . getSetting ( "handleAnamorphicVideo" ) ) {
2022-03-29 07:40:24 +00:00
let params = video . display _aspect _ratio . replace ( "/" , ":" ) . split ( ":" ) ;
if ( params . length === 2 ) {
let dar = params [ 0 ] / params [ 1 ] ;
2022-03-29 14:58:01 +00:00
if ( Math . abs ( ar - dar ) >= 0.02 ) {
2022-03-29 07:40:24 +00:00
warnings . video . push ( [ "info" , "Anamorphic video found: " + width + "x" + height + " -> " + Math . floor ( height * dar ) + "x" + height ] ) ;
width = Math . floor ( height * dar ) ;
}
ar = width / height ;
}
}
2021-12-16 14:48:21 +00:00
let scanTypeLetter = "p" ;
if ( "scan_type" in video ) {
if ( video . scan _type . toUpperCase ( ) === "MBAFF" ) {
scanTypeLetter = "i" ;
2021-12-16 17:23:13 +00:00
warnings . video . push ( [ "info" , "MBAFF found as video storage method. Content might still be Progressive" ] ) ;
2021-12-16 14:48:21 +00:00
} else if ( video . scan _type . toUpperCase ( ) === "INTERLACED" ) {
scanTypeLetter = "i" ;
} else if ( video . scan _type . toUpperCase ( ) === "PROGRESSIVE" ) {
scanTypeLetter = "p" ;
}
}
2021-12-10 07:05:25 +00:00
//TODO: make this % offset from expected
if ( ar < 1.4 ) { //Closer to 4:3, including crop
if ( width <= 1008 && width >= 900 && height >= 540 && height <= 730 ) {
2021-12-16 14:48:21 +00:00
tags . resolution = {
name : "720" + scanTypeLetter ,
legacy : "720p" /* + ((scanTypeLetter !== "p" && scanTypeLetter !== "i") ? "i" : scanTypeLetter)*/
} ;
2021-12-10 07:05:25 +00:00
} else if ( width <= 1580 && width >= 1340 && height > 720 && height <= 1080 ) {
2021-12-16 14:48:21 +00:00
tags . resolution = {
name : "1080" + scanTypeLetter ,
legacy : "1080" + ( ( scanTypeLetter !== "p" && scanTypeLetter !== "i" ) ? "i" : scanTypeLetter )
} ;
2021-12-10 07:05:25 +00:00
} else if ( width <= 2900 && width >= 2800 && height > 1100 && height <= 2160 ) {
tags . resolution = "4K" ;
} else {
tags . resolution = width + "x" + height ;
}
} else { //Closer to 16:9, including crop
if ( width <= 1290 && width >= 1200 && height >= 540 && height <= 720 ) {
2021-12-16 14:48:21 +00:00
tags . resolution = {
name : "720" + scanTypeLetter ,
legacy : "720p" /* + ((scanTypeLetter !== "p" && scanTypeLetter !== "i") ? "i" : scanTypeLetter)*/
} ;
2022-03-29 14:58:01 +00:00
} else if ( width <= 1940 && width >= 1820 && height > 720 && height <= 1084 ) {
2021-12-16 14:48:21 +00:00
tags . resolution = {
name : "1080" + scanTypeLetter ,
legacy : "1080" + ( ( scanTypeLetter !== "p" && scanTypeLetter !== "i" ) ? "i" : scanTypeLetter )
} ;
2022-03-29 14:58:01 +00:00
} else if ( width <= 3850 && width >= 3640 && height > 1084 && height <= 2160 ) {
2021-12-10 07:05:25 +00:00
tags . resolution = "4K" ;
} else {
tags . resolution = width + "x" + height ;
}
}
if ( "display_aspect_ratio" in video ) {
tags . aspectRatio = video . display _aspect _ratio . replace ( "/" , ":" ) ;
}
if ( "color_primaries" in video && ( video . color _primaries === "BT.2020" || video . color _primaries === "BT.2100" ) ) {
tags . videoHDR = "HDR" ;
}
if ( "hdr_format" in video ) {
if ( video . hdr _format . match ( /Dolby Vision/ ) !== null ) {
tags . videoHDR = "HDR DV" ;
} else if ( video . hdr _format . match ( /SMPTE ST 2086/ ) !== null && video . hdr _format . match ( /HDR10/ ) !== null ) {
tags . videoHDR = "HDR10" ;
} else if ( video . hdr _format . match ( /SMPTE ST 2094-40/ ) !== null && video . hdr _format . match ( /HDR10/ ) !== null ) {
tags . videoHDR = "HDR10+" ;
} else if ( video . hdr _format . match ( /SL-HDR1/ ) !== null ) {
tags . videoHDR = "SL-HDR1" ;
} else if ( video . hdr _format . match ( /SL-HDR2/ ) !== null ) {
tags . videoHDR = "SL-HDR2" ;
}
}
if ( ! ( "videoHDR" in tags ) && "commercial_name" in video ) {
if ( video . commercial _name . match ( /HDR10/ ) !== null ) {
tags . videoHDR = "HDR10" ;
}
}
if ( "writing_library" in video ) {
if ( video . writing _library . match ( /^x265/ ) !== null ) {
tags . videoEncoder = "x265" ;
let versionMatch = video . writing _library . match ( /^x265 (?<version>[0-9+]+(-[a-f0-9]+)?):/ )
if ( versionMatch !== null ) {
tags . videoEncoderVersion = parseInt ( versionMatch . groups . version ) ;
}
} else if ( video . writing _library . match ( /x264/ ) !== null ) {
tags . videoEncoder = "x264" ;
let versionMatch = video . writing _library . match ( / r(?<version>[0-9]+) / )
if ( versionMatch !== null ) {
tags . videoEncoderVersion = parseInt ( versionMatch . groups . version ) ;
}
} else if ( video . writing _library . match ( /^ATEME/ ) !== null ) {
tags . videoEncoder = "ATEME" ;
2022-08-03 11:57:33 +00:00
} else if ( video . writing _library . match ( /www\.letv\.com/ ) !== null || video . writing _library . match ( /letv cloud/ ) !== null ) {
tags . videoEncoder = "letv" ;
let versionMatch = video . writing _library . match ( /-V (?<version>[0-9.\-]+)$/ )
if ( versionMatch !== null ) {
tags . videoEncoderVersion = parseInt ( versionMatch . groups . version ) ;
}
} else if ( video . writing _library . match ( /^BiliBili/ ) !== null ) {
tags . videoEncoder = "BiliBili" ;
let versionMatch = video . writing _library . match ( /v(?<version>[0-9.\-]+)$/ )
if ( versionMatch !== null ) {
tags . videoEncoderVersion = parseInt ( versionMatch . groups . version ) ;
}
2021-12-10 07:05:25 +00:00
} else if ( video . writing _library . match ( /libaom/ ) !== null ) {
tags . videoEncoder = "libaom" ;
} else if ( video . writing _library . match ( /_nvenc/ ) !== null ) {
tags . videoEncoder = "NVENC" ;
if ( settings . getSetting ( "warning_hwEncoder" ) ) {
warnings . video . push ( [ "danger" , "Found NVENC hardware-encoded stream" ] ) ;
}
} else if ( video . writing _library . match ( /_qsv/ ) !== null ) {
tags . videoEncoder = "QuickSync" ;
if ( settings . getSetting ( "warning_hwEncoder" ) ) {
warnings . video . push ( [ "danger" , "Found QuickSync hardware-encoded stream" ] ) ;
}
} else if ( video . writing _library . match ( /_vaapi/ ) !== null ) {
tags . videoEncoder = "VAAPI" ;
if ( settings . getSetting ( "warning_hwEncoder" ) ) {
warnings . video . push ( [ "danger" , "Found VAAPI hardware-encoded stream" ] ) ;
}
2022-01-01 01:39:20 +00:00
} else if ( video . writing _library . trim ( ) . match ( /[^0-9A-F]/i ) !== null ) {
2021-12-10 07:05:25 +00:00
[ tags . videoEncoder ] = video . writing _library . split ( " " ) ;
}
2023-09-02 14:07:36 +00:00
} else if ( isHandbrake ) {
// HandBrake removes NVenc tags when using Hardware Encoder, at least on H.264 and H.265
tags . videoEncoder = "HandBrake HW" ;
if ( settings . getSetting ( "warning_hwEncoder" ) ) {
warnings . video . push ( [ "danger" , "Found probable HandBrake hardware-encoded stream" ] ) ;
}
2021-12-10 07:05:25 +00:00
}
2022-06-17 07:34:07 +00:00
//Detect probably H262 remuxes
try {
if (
! ( "remux" in tags )
&& ! ( "encoding_settings" in video ) && ! ( "writing_library" in video )
&& video . codec _id === "V_MPEG2" && video . format _profile === "Main@Main"
&& ( ( video . width === "720 pixels" && video . height === "480 pixels" ) || ( video . width === "720 pixels" && video . height === "576 pixels" ) )
&& ( ! ( "original_source_medium" in video ) || video . original _source _medium === "DVD-Video" )
&& ( ! ( "bits_pixel_frame" in video ) || parseFloat ( video . bits _pixel _frame ) > 0.5 )
) {
tags . remux = "probably" ;
}
} catch ( e ) {
}
2021-12-10 07:05:25 +00:00
//Detect probably H264 remuxes
try {
if (
! ( "remux" in tags ) &&
! ( "encoding_settings" in video ) && ! ( "writing_library" in video ) &&
video . codec _id === "V_MPEG4/ISO/AVC" && video . format _profile === "High@L4.1" &&
2021-12-26 14:27:27 +00:00
(
( "format_settings" in video && video . format _settings . match ( /CABAC \/ [234] Ref Frames/ ) !== null ) ||
( video . format _settings _cabac === "Yes" && "format_settings_reframes" in video && video . format _settings _reframes . match ( /^[234] frames/ ) !== null )
)
&& width === 1920 && height === 1080 &&
2021-12-10 07:05:25 +00:00
video . frame _rate _mode === "Constant" &&
2021-12-27 16:54:53 +00:00
( ! ( "bits_pixel_frame" in video ) || parseFloat ( video . bits _pixel _frame ) > 0.4 )
2021-12-10 07:05:25 +00:00
) {
tags . remux = "probably" ;
}
} catch ( e ) {
}
//Detect probably H265 4K remuxes
try {
if (
! ( "remux" in tags ) &&
(
//TODO: add more if found
( ! ( "encoding_settings" in video ) && ! ( "writing_library" in video ) ) ||
( ! ( "encoding_settings" in video ) && video . writing _library . match ( /^ATEME/ ) !== null ) ||
( ( ! ( "encoding_settings" in video ) || ( video . encoding _settings . match ( /crf=[0-9]+/ ) === null ) ) && video . writing _library . match ( /^x265/ ) !== null )
) &&
video . codec _id === "V_MPEGH/ISO/HEVC" && video . format _profile === "Main 10@L5.1@High" &&
width === 3840 && height === 2160 &&
video . frame _rate _mode === "Constant" &&
( ! ( "bits_pixel_frame" in video ) || parseFloat ( video . bits _pixel _frame ) > 0.2 )
) {
tags . remux = "probably" ;
}
} catch ( e ) {
}
if ( "encoding_settings" in video ) {
let match = null ;
2021-12-27 16:54:53 +00:00
if ( ( match = video . encoding _settings . match ( / rc=(?<rc>[0-9a-z]+)/i ) ) !== null ) {
tags . videoEncodeMode = match . groups . rc . toLowerCase ( ) ;
2021-12-27 15:05:17 +00:00
}
2021-12-10 07:05:25 +00:00
if ( ( match = video . encoding _settings . match ( /crf=(?<crf>[0-9.]+)/ ) ) !== null ) {
2021-12-27 16:54:53 +00:00
tags . videoEncodeMode = "crf" ;
tags . videoEncodeRateControl = parseFloat ( match . groups . crf ) . toFixed ( 1 ) ;
2021-12-27 15:05:17 +00:00
} else if ( video . encoding _settings . match ( /rc=cqp/ ) !== null && ( match = video . encoding _settings . match ( / qp=(?<qp>[0-9.]+)/ ) ) !== null ) {
2021-12-27 16:54:53 +00:00
tags . videoEncodeMode = "cqp" ;
tags . videoEncodeRateControl = parseFloat ( match . groups . qp ) . toFixed ( 1 ) ;
2021-12-27 15:05:17 +00:00
if ( settings . getSetting ( "warning_encodeSettings" ) ) {
warnings . video . push ( [ "info" , "Found encode using rc=cqp (Constant QP) mode on encoding settings" ] ) ;
}
} else if ( ( match = video . encoding _settings . match ( /bitrate=(?<bitrate>[0-9.]+)/ ) ) !== null ) {
2021-12-27 16:54:53 +00:00
tags . videoEncodeRateControl = parseInt ( match . groups . bitrate ) + "k" ;
2021-12-10 07:05:25 +00:00
}
if ( video . encoding _settings . match ( /rc=2pass/ ) !== null ) {
2021-12-27 16:54:53 +00:00
tags . videoEncodeMode = "2pass" ;
2021-12-10 07:05:25 +00:00
}
2021-12-27 15:05:17 +00:00
2021-12-10 07:05:25 +00:00
if ( ! ( "remux" in tags ) && video . codec _id === "V_MPEG4/ISO/AVC" && ( match = video . format _profile . match ( /(?<profile>(baseline|main)[ 0-9]*)@/i ) ) !== null ) {
if ( settings . getSetting ( "warning_encodeProfile" ) ) {
warnings . video . push ( [ "warning" , "Found encode using profile=" + match . groups . profile + " on encoding settings" ] ) ;
}
}
if ( video . encoding _settings . match ( /cabac=0/ ) !== null && settings . getSetting ( "warning_encodeSettings" ) ) {
warnings . video . push ( [ "info" , "Found encode with CABAC disabled" ] ) ;
}
if ( video . encoding _settings . match ( /mbtree=0/ ) !== null && settings . getSetting ( "warning_encodeSettings" ) ) {
warnings . video . push ( [ "info" , "Found encode with mbtree disabled" ] ) ;
}
if ( video . encoding _settings . match ( /bframes=0/ ) !== null && settings . getSetting ( "warning_encodeSettings" ) ) {
warnings . video . push ( [ "info" , "Found encode with bframes disabled" ] ) ;
}
if ( video . encoding _settings . match ( /me=dia/ ) !== null && settings . getSetting ( "warning_encodeSettings" ) ) {
warnings . video . push ( [ "info" , "Found encode with me=dia" ] ) ;
}
}
}
let audioLanguages = { } ;
let audioCount = 0 ;
mediainfo . audio . forEach ( ( audio , index ) => {
Mediainfo . makeAudioObject ( audio ) ;
if ( ! ( "open" in audio . _ _audioCodec ) || ! audio . _ _audioCodec . open ) {
tags . openFormat = false ;
}
const isDescriptionEntry = ( "title" in audio ) ? audio . title . match ( /descript/i ) !== null : false ;
const isCommentary = "title" in audio && audio . title . match ( /comment/i ) !== null ;
const isDefault = audio . default === "Yes" ;
2024-04-03 15:59:50 +00:00
let audioLang = "language" in audio ? audio . language : "Unknown" ;
//Pick first default audio
if ( isDefault && defaultAudio == null ) {
2021-12-10 07:05:25 +00:00
defaultAudio = audio ;
}
2024-04-03 15:59:50 +00:00
if ( audioLang !== "Japanese" && audioLang !== "Unknown" && ( isDefault && defaultAudio === audio ) && ! isLiveActionType && settings . getSetting ( "warning_defaultAudioNotJapanese" ) ) {
warnings . audio . push ( [ "info" , "First default audio #" + ( index + 1 ) + " is not in Japanese" ] ) ;
2021-12-10 07:05:25 +00:00
}
if ( isCommentary ) {
tags . audioCommentary = true ;
}
if ( ! isCommentary && ! isDescriptionEntry ) {
++ audioCount ;
if ( ! ( audioLang in audioLanguages ) ) {
audioLanguages [ audioLang ] = 0 ;
}
audioLanguages [ audioLang ] ++ ;
}
if ( ! isDescriptionEntry && ! isCommentary && audioLang === "Japanese" ) {
if ( japaneseAudio === null ) { // Pick first
japaneseAudio = audio ;
} else {
if ( audio . channels > japaneseAudio . channels || (
audio . channels === japaneseAudio . channels && ( // Alternate upgrade path
( [ "AAC-LC" , "HE-AAC" , "AAC-Main" , "AC3" , "Vorbis" , "MP2" , "MP3" , "DTS" ] . includes ( japaneseAudio . _ _audioCodec . name ) && [ "E-AC3" , "E-AC3 Atmos" , "DTS-HD" , "DTS-ES" ] . includes ( audio . _ _audioCodec . name ) ) ||
( ! japaneseAudio . _ _audioCodec . lossless && audio . _ _audioCodec . lossless === true )
)
) ) {
japaneseAudio = audio ;
}
}
} else if ( ! isDescriptionEntry && ! isCommentary && audioLang === "Unknown" ) {
if ( japaneseAudio === null && ( mediainfo . audio . length === 1 || ( Object . keys ( audioLanguages ) . length === 1 && "Unknown" in audioLanguages ) ) ) {
japaneseAudio = audio ;
} else if ( japaneseAudio !== null && ( ! ( "language" in japaneseAudio ) || japaneseAudio . language === "Unknown" ) ) {
if ( audio . channels > japaneseAudio . channels || (
audio . channels === japaneseAudio . channels && ( // Alternate upgrade path
( [ "AAC-LC" , "HE-AAC" , "AAC-Main" , "AC3" , "Vorbis" , "MP2" , "MP3" , "DTS" ] . includes ( japaneseAudio . _ _audioCodec . name ) && [ "E-AC3" , "E-AC3 Atmos" , "DTS-HD" , "DTS-ES" ] . includes ( audio . _ _audioCodec . name ) ) ||
( ! japaneseAudio . _ _audioCodec . lossless && audio . _ _audioCodec . lossless === true )
)
) ) {
japaneseAudio = audio ;
}
}
} else if ( ! isDescriptionEntry && ! isCommentary ) {
if ( otherAudio === null ) { // Pick first
otherAudio = audio ;
} else {
if ( audio . channels > otherAudio . channels ) {
otherAudio = audio ;
}
}
}
let ratio = null ;
if ( "stream_size" in audio ) {
try {
ratio = parseFloat ( audio . stream _size . match ( /\((?<percentage>[0-9.]+)%\)$/ ) . groups . percentage ) ;
} catch ( e ) {
}
}
2022-05-12 07:50:05 +00:00
const isRemuxOrRawSource = ( "remux" in tags || getLineTagEntry ( sourceTags . container , true ) . match ( /^(ISO|M2TS|DVD|(VOB IFO))/ ) !== null ) ;
2021-12-10 07:05:25 +00:00
if ( ! isRemuxOrRawSource && audio . format === "PCM" && settings . getSetting ( "warning_bloatPCM" ) ) {
warnings . audio . push ( [ "warning" , "BLOAT: Audio track #" + ( index + 1 ) + " is uncompressed PCM." ] ) ;
}
2021-12-24 16:23:05 +00:00
if ( ! isRemuxOrRawSource && ( audio . format === "FLAC" || audio . format . match ( /^DTS/ ) !== null ) && ( ratio === null || ( ratio > 10 ) ) && settings . getSetting ( "warning_bloatg16bit" ) && "bit_depth" in audio ) {
2021-12-10 07:05:25 +00:00
let bitDepth = parseInt ( audio . bit _depth . replace ( /[^0-9]/g , "" ) ) ;
if ( bitDepth > 16 ) {
warnings . audio . push ( [ "warning" , "BLOAT: Audio track #" + ( index + 1 ) + " is " + audio . _ _audioCodec . name + " with bit depth greater than 16-bit, found " + bitDepth + "-bit." ] ) ;
}
}
} ) ;
if ( Object . keys ( audioLanguages ) . length > 1 || ! ( "Unknown" in audioLanguages ) ) {
tags . audioCount = audioCount ;
tags . audioLanguages = audioLanguages ;
}
let audio = japaneseAudio !== null ? japaneseAudio : ( defaultAudio !== null ? defaultAudio : otherAudio ) ;
if ( audio !== null ) {
tags . audioChannels = audio . channels ;
tags . audioCodec = Mediainfo . matchCodec ( Mediainfo . audioCodecs , audio , sourceTags . audioCodec ? sourceTags . audioCodec : audio . _ _audioCodec ) ;
2021-12-24 16:23:05 +00:00
if ( tags . audioCodec . lossless ) {
if ( "bit_depth" in audio ) {
2021-12-25 14:33:02 +00:00
let bitDepth = parseInt ( audio . bit _depth . split ( "/" ) [ 0 ] . replace ( /[^0-9]/g , "" ) ) ;
2021-12-24 16:23:05 +00:00
tags . audioBitrate = bitDepth + "-bit" ;
}
} else {
if ( "bit_rate" in audio ) {
2021-12-26 14:20:37 +00:00
let bitRate = parseInt ( audio . bit _rate . split ( "/" ) [ 0 ] . replace ( /[^0-9.]/g , "" ) ) ;
2021-12-24 16:23:05 +00:00
tags . audioBitrate = bitRate + "k" ;
}
}
2021-12-10 07:05:25 +00:00
}
if ( "text" in mediainfo ) {
mediainfo . text . forEach ( ( text , index ) => {
const isSignsEntry = ( "title" in text ) ? ( text . title . match ( /sign/i ) !== null && text . title . match ( /(text|full|dialogue)/i ) === null ) : false ;
const isDefault = text . default === "Yes" ;
if ( isSignsEntry && isDefault && settings . getSetting ( "warning_signsDefault" ) ) {
2021-12-16 14:48:21 +00:00
warnings . text . push ( [ "warning" , "Default Subtitles track #" + ( index + 1 ) + " is a Signs track" ] ) ;
2021-12-10 07:05:25 +00:00
}
if ( isDefault ) {
defaultSubs = text ;
}
if ( ! isSignsEntry && ( text . language === "English" || ( englishSubs === null && "title" in text && text . title . match ( /english/i ) !== null ) ) ) {
if ( englishSubs === null ) {
englishSubs = text ;
} else {
if ( text . codec _id === "S_TEXT/ASS" && englishSubs . codec _id !== "S_TEXT/ASS" ) {
englishSubs = text ;
}
}
} else if ( ! isSignsEntry && mediainfo . text . length === 1 && ( text . language === "Unknown" || ! ( "language" in text ) ) ) {
englishSubs = text ;
} else if ( englishSubs === null && ! isSignsEntry && text . language === "Japanese" && ( "title" in text && text . title . match ( /(text|full|dialogue|english)/i ) !== null ) ) {
englishSubs = text ;
if ( settings . getSetting ( "warning_textLabeling" ) ) {
warnings . text . push ( [ "warning" , "Subtitles track #" + ( index + 1 ) + " is labeled as Japanese, but is not Japanese" ] ) ;
}
}
2021-12-16 14:48:21 +00:00
2021-12-27 15:05:17 +00:00
if ( ! isSignsEntry && isDefault && text !== englishSubs && text . language !== "English" && sourceTags . subtitleType === "Softsubs" ) {
2021-12-16 14:48:21 +00:00
warnings . text . push ( [ "warning" , "Default Subtitles track #" + ( index + 1 ) + " is not in English" ] ) ;
}
2021-12-10 07:05:25 +00:00
} ) ;
}
let text = englishSubs !== null ? englishSubs : ( defaultSubs !== null ? defaultSubs : ( ( "text" in mediainfo && mediainfo . text . length > 0 && ( ! ( "language" in mediainfo . text [ 0 ] ) || mediainfo . text [ 0 ] . language === "Unknown" || mediainfo . text [ 0 ] . language === "Japanese" ) ) ? mediainfo . text [ 0 ] : null ) ) ;
let isTrackExternal = false ;
let externalTrackFormat = null ;
fileList . every ( ( file ) => {
const ext = file . path . split ( "." ) . slice ( - 1 ) [ 0 ] . toUpperCase ( ) ;
if ( ext === "ASS" || ext === "SRT" || ext === "SSA" || ext === "MKS" || ext === "VTT" || ext === "SUB" ) {
isTrackExternal = true ;
externalTrackFormat = ext ;
}
return ! isTrackExternal ;
} ) ;
if ( sourceTags . subtitleType === "Guess" ) {
if ( englishSubs !== null ) {
sourceTags . subtitleType = "Softsubs" ;
} else {
sourceTags . subtitleType = "" ;
}
}
if ( text !== null ) {
switch ( text . format ) {
case "EIA-608" :
tags . subtitleCodec = "CC SRT" ;
break ;
case "UTF-8" :
tags . subtitleCodec = text . codec _id === "S_TEXT/UTF8" ? "SRT" : text . format ;
break ;
case "Subrip" :
tags . subtitleCodec = "SRT" ;
break ;
case "RLE" :
tags . subtitleCodec = "VobSub" ;
break ;
default :
tags . subtitleCodec = text . format ;
}
tags . subtitleTitle = "title" in text ? text . title : "" ;
if ( isTrackExternal === false && sourceTags . subtitleType === "Softsubs" && englishSubs === null ) {
warnings . text . push ( [ "warning" , "Could not find English labeled subtitles, but labeled Softsubs" ] ) ;
} else {
if ( ! ( "subtitleType" in sourceTags ) || sourceTags . subtitleType !== "Softsubs" ) {
if ( settings . getSetting ( "warning_textLabeling" ) ) {
warnings . text . push ( [ "warning" , "Found " + tags . subtitleCodec + " Softsubs, but labeled " + ( ! ( "subtitleType" in sourceTags ) ? "RAW" : sourceTags . subtitleType ) ] ) ;
}
}
}
}
if ( ( tags . subtitleType === "Softsubs" || sourceTags . subtitleType === "Softsubs" ) && ( text === null || englishSubs === null ) ) {
if ( isTrackExternal ) {
tags . subtitleType = "Softsubs" ;
tags . subtitleCodec = "External " + externalTrackFormat ;
if ( settings . getSetting ( "warning_externalSubs" ) ) {
warnings . text . push ( [ "info" , "Subtitle track is external" ] ) ;
}
} else if ( "subtitleType" in sourceTags && sourceTags . subtitleType !== "Hardsubs" && ( text === null || ( "language" in text && text . language !== "Unknown" ) ) ) {
warnings . text . push ( [ "warning" , "Could not find subtitles either on file listing or disk, probably hardsubbed?" ] ) ;
}
}
if ( "menu" in mediainfo ) {
//Check for chapters and ordered chapters
let chapterCount = 0 ;
for ( const [ key , value ] of Object . entries ( mediainfo . menu ) ) {
let entryCount = 0 ;
value . split ( " / " ) . forEach ( ( i ) => {
i = i . trim ( ) ;
if ( i . indexOf ( ":" ) !== - 1 ) {
entryCount ++ ;
}
} ) ;
2022-04-24 14:05:21 +00:00
if ( chapterCount === 0 && entryCount > 1 && ! ( "chapters" in tags ) ) {
2021-12-10 07:05:25 +00:00
tags . chapters = "ordered" ;
if ( settings . getSetting ( "warning_orderedChapters" ) ) {
warnings . general . push ( [ "warning" , "Found Ordered Chapters" ] ) ;
}
}
++ chapterCount ;
}
if ( ! ( "chapters" in tags ) && chapterCount > 1 ) {
tags . chapters = chapterCount
}
}
matchSet . forEach ( ( entry ) => {
try {
let match = true ;
let set = Object . assign ( { } , entry . set ) ;
let m = null ;
for ( const [ k , v ] of Object . entries ( entry . match ) ) {
let ob = null ;
if ( k === "tags" ) {
ob = { } ;
for ( const [ key , value ] of Object . entries ( tags ) ) {
if ( ! ( key in ob ) ) {
ob [ key ] = value ;
}
}
for ( const [ key , value ] of Object . entries ( sourceTags ) ) {
if ( ! ( key in ob ) ) {
ob [ key ] = value ;
}
}
} else if ( k === "video" ) {
ob = video ;
} else if ( k === "audio" ) {
ob = audio ;
} else if ( k === "text" ) {
ob = text ;
} else if ( k === "custom" && typeof v === 'function' ) {
m = v ( sourceTags , mediainfo , tags , video , audio , text ) ;
if ( m === null || m === false ) {
match = false ;
break ;
}
if ( typeof m === "object" && "groups" in m && typeof m . groups === "object" ) {
for ( const [ k2 , v2 ] of Object . entries ( m . groups ) ) {
if ( typeof v2 !== "undefined" ) {
for ( const [ k3 , v3 ] of Object . entries ( set ) ) {
if ( typeof v3 === 'string' ) {
set [ k3 ] = v3 . replace ( '$' + k2 , v2 ) ;
}
}
} else {
for ( const [ k3 , v3 ] of Object . entries ( set ) ) {
if ( typeof v3 === 'string' ) {
set [ k3 ] = v3 . replace ( '$' + k2 , "" ) ;
}
}
}
}
}
continue ;
}
if ( ob === null ) {
match = false ;
break ;
}
for ( const [ key , value ] of Object . entries ( v ) ) {
if ( value === null ) {
if ( key in ob ) {
match = false ;
break ;
}
continue ;
}
if ( ! ( key in ob ) ) {
match = false ;
break ;
} else if ( value instanceof RegExp ) {
if ( ( m = ob [ key ] . match ( value ) ) === null ) {
match = false ;
break ;
}
if ( "groups" in m && typeof m . groups === "object" ) {
for ( const [ k2 , v2 ] of Object . entries ( m . groups ) ) {
if ( typeof v2 !== "undefined" ) {
for ( const [ k3 , v3 ] of Object . entries ( set ) ) {
if ( typeof v3 === 'string' ) {
set [ k3 ] = v3 . replace ( '$' + k2 , v2 ) ;
}
}
} else {
for ( const [ k3 , v3 ] of Object . entries ( set ) ) {
if ( typeof v3 === 'string' ) {
set [ k3 ] = v3 . replace ( '$' + k2 , "" ) ;
}
}
}
}
}
} else if ( ob [ key ] !== value ) {
match = false ;
break ;
}
}
}
if ( match ) {
for ( const [ k , v ] of Object . entries ( set ) ) {
if ( v === null ) {
delete tags [ k ] ;
} else {
tags [ k ] = v . trim ( ) ;
}
}
}
} catch ( e ) {
console . log ( e ) ;
}
} ) ;
2022-04-24 18:53:25 +00:00
2021-12-10 07:05:25 +00:00
return tags ;
}
2021-12-09 15:04:39 +00:00
function createIcon ( text , color = null , title = null ) {
let e = document . createElement ( "span" ) ;
if ( color ) {
e . style [ "color" ] = color ;
}
if ( title ) {
e . setAttribute ( "title" , title ) ;
}
e . append ( text ) ;
return e ;
}
2021-11-21 03:17:10 +00:00
2021-12-09 08:56:14 +00:00
const imageTypes = {
freeleech : {
src : "/static/common/flicon.png" ,
alt : "Freeleech!" ,
title : "This torrent is freeleech. Remember to seed!"
2021-11-21 17:35:27 +00:00
} ,
2021-12-09 08:56:14 +00:00
remastered : {
src : "/static/common/rmstr.png" ,
alt : "Remastered" ,
title : "This torrent is from a remastered source!"
2021-11-30 07:37:23 +00:00
} ,
2021-12-09 08:56:14 +00:00
hentaic : {
src : "/static/common/hentaic.svg" ,
alt : "Hentai" ,
title : "This torrent is of censored hentai (18+) material!"
2021-11-21 17:35:27 +00:00
} ,
2021-12-09 08:56:14 +00:00
hentai : {
src : "/static/common/hentai.svg" ,
alt : "Hentai" ,
title : "This torrent is of uncensored hentai (18+) material!"
2021-11-30 07:37:23 +00:00
} ,
2021-12-09 08:56:14 +00:00
script _warning : {
src : "/static/common/symbols/warned.png"
2021-11-21 17:35:27 +00:00
} ,
2021-12-09 08:56:14 +00:00
script _danger : {
src : "/static/common/symbols/disabled.png"
2021-11-21 03:17:10 +00:00
}
2021-12-09 08:56:14 +00:00
}
2021-11-30 05:06:09 +00:00
2021-12-09 08:56:14 +00:00
function createImage ( type ) {
if ( ! ( type in imageTypes ) ) {
throw "Unknown image type " + type ;
}
2021-11-21 03:17:10 +00:00
2021-12-09 08:56:14 +00:00
const i = imageTypes [ type ] ;
2021-11-30 07:37:23 +00:00
2021-12-09 08:56:14 +00:00
let img = document . createElement ( "img" ) ;
img . src = i . src ;
if ( "alt" in i ) {
img . alt = i . alt ;
}
if ( "title" in i ) {
img . title = i . title ;
}
2021-11-30 07:37:23 +00:00
2021-12-09 08:56:14 +00:00
return img ;
2021-11-30 07:37:23 +00:00
}
2021-11-29 16:42:55 +00:00
2021-12-09 08:56:14 +00:00
/ * *
* @ param v
* @ param legacy
* @ returns String
* /
function getLineTagEntry ( v , legacy ) {
if ( typeof v === 'object' ) {
2021-12-10 07:15:59 +00:00
return ( legacy && "legacy" in v ) ? v . legacy : v . name ;
2021-12-09 08:56:14 +00:00
}
2021-11-30 05:06:09 +00:00
2021-12-09 08:56:14 +00:00
return v ;
2021-11-29 16:42:55 +00:00
}
2021-12-09 08:56:14 +00:00
2021-11-25 22:32:46 +00:00
const matchSet = [
{
2023-04-03 08:21:41 +00:00
//Hidive 480p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
height : /^(480) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 148" ,
encoding _settings : new RegExp ( "cabac=1 / ref=[36] / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(15) / lookahead_threads=[2] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=90 / keyint_min=9 / scenecut=0 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=22\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=(3500) / vbv_bufsize=(7680) / crf_max=0\\.0 / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:1\\.00" )
}
} ,
set : {
sourceName : "Hidive"
}
} ,
{
//Hidive 720p/1080p
2021-11-25 22:32:46 +00:00
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
2021-11-25 23:14:12 +00:00
codec _id : /^A_AAC/
2021-11-25 23:11:24 +00:00
} ,
video : {
height : /^(720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 148" ,
encoding _settings : new RegExp ( "cabac=1 / ref=[36] / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(22|34) / lookahead_threads=[35] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=90 / keyint_min=9 / scenecut=0 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=22\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=(11100|13500) / vbv_bufsize=(111000|135000) / crf_max=0\\.0 / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:1\\.00" )
}
} ,
set : {
sourceName : "Hidive"
}
} ,
2023-08-19 05:42:04 +00:00
{
//Crunchyroll Aug 2023 encoding settings for 480p/720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
height : /^(480|720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 164" ,
2023-08-19 05:50:27 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=[46] / deblock=1:1:1 / analyse=(0x1:0x111|0x3:0x113) / me=hex / subme=8 / psy=1 / psy_rd=0\\.40:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=2 / 8x8dct=[01] / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(1|9|12) / lookahead_threads=[12] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=2 / keyint=(96|120) / keyint_min=(48|60) / scenecut=40 / intra_refresh=0 / rc_lookahead=(48|60) / rc=2pass / mbtree=1 / bitrate=(2000|4000|8000) / ratetol=1\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=(3000|6000|12000) / vbv_bufsize=(4500|9000|18000) / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:0\\.60" )
2023-08-19 05:42:04 +00:00
}
} ,
set : {
sourceName : "Crunchyroll"
}
} ,
2023-04-03 08:21:41 +00:00
{
//Crunchyroll Jan 2023 encoding settings for 480p/720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
height : /^(480|720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
2023-04-03 08:28:38 +00:00
writing _library : "x264 core 164" ,
2023-04-03 08:26:05 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=[46] / deblock=1:1:1 / analyse=(0x1:0x111|0x3:0x113) / me=hex / subme=8 / psy=1 / psy_rd=0\\.40:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=2 / 8x8dct=[01] / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(15|22|34) / lookahead_threads=[235] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=2 / keyint=(96|120) / keyint_min=(48|60) / scenecut=40 / intra_refresh=0 / rc_lookahead=(48|60) / rc=2pass / mbtree=1 / bitrate=(2000|4000|8000) / ratetol=1\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=(3000|6000|12000) / vbv_bufsize=(4500|9000|18000) / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:0\\.60" )
2023-04-03 08:21:41 +00:00
}
} ,
set : {
sourceName : "Crunchyroll"
}
} ,
2021-11-25 23:11:24 +00:00
{
//Crunchyroll new encoding settings for 480p/720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
2021-11-25 23:14:12 +00:00
codec _id : /^A_AAC/
2021-11-25 22:32:46 +00:00
} ,
video : {
height : /^(480|720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 142" ,
2021-11-30 11:01:01 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=[46] / deblock=1:1:1 / analyse=(0x1:0x111|0x3:0x113) / me=umh / subme=8 / psy=1 / psy_rd=0\\.40:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=[01] / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(6|10|12) / lookahead_threads=[12] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=2 / keyint=(96|120) / keyint_min=(48|60) / scenecut=40 / intra_refresh=0 / rc_lookahead=(48|60) / rc=2pass / mbtree=1 / bitrate=(2000|4000|8000) / ratetol=1\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=(3000|6000|12000) / vbv_bufsize=(4500|9000|18000) / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:0\\.60" )
2021-11-25 22:32:46 +00:00
}
} ,
set : {
sourceName : "Crunchyroll"
}
} ,
2021-11-26 04:42:57 +00:00
{
//Crunchyroll new crf encoding settings for 720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
height : /^(720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 142" ,
2021-11-30 09:33:38 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=[46] / deblock=1:1:1 / analyse=0x3:0x113 / me=umh / subme=8 / psy=1 / psy_rd=0\\.40:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(10|12|16) / lookahead_threads=[12] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=(48|96) / keyint_min=(24|48) / scenecut=40 / intra_refresh=0 / rc_lookahead=48 / rc=crf / mbtree=1 / crf=(15\\.0|16\\.0) / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=(4000|8000) / vbv_bufsize=(6000|12000) / crf_max=0\\.0 / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:0\\.60" )
2021-11-26 04:42:57 +00:00
}
} ,
set : {
sourceName : "Crunchyroll"
}
} ,
2021-11-25 22:32:46 +00:00
{
//Crunchyroll old encoding settings for 480p/720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
2021-11-25 23:14:12 +00:00
codec _id : /^A_AAC/
2021-11-25 22:32:46 +00:00
} ,
video : {
height : /^(480|720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 120 r2120 0c7dab9" ,
2021-11-26 04:42:57 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=[46] / deblock=1:1:1 / analyse=(0x1:0x111|0x3:0x113) / me=umh / subme=8 / psy=1 / psy_rd=0\\.40:0\\.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=[01] / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=[48] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=(23|25) / scenecut=40 / intra_refresh=0 / rc_lookahead=50 / rc=2pass / mbtree=1 / bitrate=(768|1776|3072|3088) / ratetol=1\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=(1536|3552|6144|6176) / vbv_bufsize=(3840|8880|15360|15440) / nal_hrd=none / ip_ratio=1\\.40 / aq=1:0\\.60" )
2021-11-25 22:32:46 +00:00
}
} ,
set : {
sourceName : "Crunchyroll"
}
} ,
2021-11-26 04:42:57 +00:00
{
//Funimation 360p/720p/1080p
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
height : /^(360|720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
writing _library : "x264 core 157 r2948 dada181" ,
encoding _settings : new RegExp ( "cabac=[01] / ref=1 / deblock=1:0:0 / analyse=(0x1:0x111|0x3:0x113) / me=hex / subme=7 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=[01] / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=(11|12|22|24) / lookahead_threads=[1-4] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=[02] / ((b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / )|)weightp=[02] / keyint=48 / keyint_min=4 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=cbr / mbtree=1 / bitrate=(1200|3500|8000) / ratetol=1\\.0 / qcomp=0\\.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=(1200|3500|8000) / vbv_bufsize=(3600|10500|24000) / nal_hrd=none / filler=0 / ip_ratio=1\\.40 / aq=1:1\\.00" )
}
} ,
set : {
sourceName : "Funimation"
}
} ,
2022-08-03 11:57:33 +00:00
{
//letv
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_AAC/
} ,
video : {
writing _library : /letv.*codec -V [0-9.\-]+$/ ,
encoding _settings : null
}
} ,
set : {
sourceName : "letv"
}
} ,
2021-11-25 23:11:24 +00:00
{
//bilibili
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
2021-11-25 23:14:12 +00:00
codec _id : /^A_AAC/
2021-11-25 23:11:24 +00:00
} ,
video : {
frame _rate _mode : "Constant" ,
writing _library : /^BiliBili H264 Encoder v[0-9.\-]+$/ ,
encoding _settings : null
}
} ,
set : {
sourceName : "bilibili"
}
} ,
2021-11-30 07:37:23 +00:00
{
//Google/YouTube
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
video : {
frame _rate _mode : "Constant" ,
title : /^ISO Media file produced by Google Inc/ ,
encoding _settings : null
}
} ,
set : {
sourceName : "YouTube"
}
} ,
2021-11-30 10:29:33 +00:00
{
//Le.com / LeTV / Leshi Video
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
video : {
frame _rate _mode : "Constant" ,
writing _library : /^Provided by www\.letv\.com/ ,
encoding _settings : null
}
} ,
set : {
sourceName : "Leshi Video" ,
videoEncoder : null ,
}
} ,
2021-11-29 21:56:16 +00:00
{
2022-07-13 13:36:35 +00:00
//Netflix 2pass old?
2021-11-29 21:56:16 +00:00
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : "A_EAC3" ,
} ,
video : {
height : /^(720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
bit _rate _mode : "Variable" ,
writing _library : /^x264 core 118$/ ,
encoding _settings : new RegExp ( "cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=umh / subme=10 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=[68] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=2 / b_pyramid=0 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=48 / keyint_min=(23|24|25) / scenecut=0 / intra_refresh=0 / rc_lookahead=0 / rc=2pass / mbtree=1 / bitrate=[0-9]+ / ratetol=1\\.0 / qcomp=0\\.50 / qpmin=6 / qpmax=51 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=[0-9]+ / vbv_bufsize=[0-9]+ / nal_hrd=vbr / ip_ratio=1\\.40 / aq=1:1\\.00" )
}
} ,
set : {
sourceName : "Netflix*"
}
} ,
2021-11-25 23:11:24 +00:00
{
2022-07-13 13:36:35 +00:00
//Netflix 2pass?
2021-11-25 23:11:24 +00:00
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
2021-11-26 05:14:37 +00:00
codec _id : /^A_E?AC3$/ ,
2021-11-25 23:11:24 +00:00
} ,
video : {
height : /^(720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
bit _rate _mode : "Variable" ,
2021-11-26 05:14:37 +00:00
writing _library : /^x264 core 148 r[0-9]+ [0-9a-f]+$/ ,
2021-11-29 21:56:16 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=umh / subme=10 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=[68] / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / stitchable=1 / constrained_intra=0 / bframes=2 / b_pyramid=0 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=(48|250) / keyint_min=(23|24|25) / scenecut=0 / intra_refresh=0 / rc_lookahead=48 / rc=2pass / mbtree=1 / bitrate=[0-9]+ / ratetol=1\\.0 / qcomp=0\\.50 / qpmin=6 / qpmax=51 / qpstep=4 / cplxblur=20\\.0 / qblur=0\\.5 / vbv_maxrate=[0-9]+ / vbv_bufsize=[0-9]+ / nal_hrd=vbr / filler=0 / ip_ratio=1\\.40 / aq=1:1\\.00" )
2021-11-25 23:11:24 +00:00
}
} ,
set : {
sourceName : "Netflix*"
}
} ,
2021-11-30 10:29:33 +00:00
{
2022-07-13 13:36:35 +00:00
//Netflix crf 18/20?
2021-11-30 10:29:33 +00:00
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^A_E?AC3$/ ,
} ,
video : {
height : /^(720|(1 080)) pixels$/ ,
frame _rate _mode : "Constant" ,
bit _rate _mode : "Variable" ,
writing _library : /^x264 core 148 r[0-9]+ [0-9a-f]+$/ ,
2022-07-13 13:36:35 +00:00
encoding _settings : new RegExp ( "cabac=1 / ref=4 / deblock=1:0:0 / analyse=0x3:0x111 / me=umh / subme=10 / psy=1 / psy_rd=1\\.00:0\\.00 / mixed_ref=1 / me_range=120 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=[68] / lookahead_threads=[12] / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / stitchable=1 / constrained_intra=0 / bframes=16 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=(240) / keyint_min=(121) / scenecut=0 / intra_refresh=0 / rc_lookahead=240 / rc=crf / mbtree=1 / crf=(18\\.0|19\\.0|20\\.0|21\\.0) / qcomp=0\\.50 / qpmin=6 / qpmax=51 / qpstep=4 / vbv_maxrate=(14000|20000) / vbv_bufsize=(14000|25000) / crf_max=0\\.0 / nal_hrd=vbr / filler=0 / ip_ratio=1\\.40 / aq=1:0\\.80" )
2021-11-30 10:29:33 +00:00
}
} ,
set : {
sourceName : "Netflix*"
}
} ,
2021-11-26 04:42:57 +00:00
{
//Amazon Prime Video?
match : {
tags : {
sourceName : null ,
source : "Web"
} ,
audio : {
codec _id : /^(A_AAC|A_EAC3$)/
} ,
video : {
codec _id : "V_MPEG4/ISO/AVC" ,
format _profile : /^((High@(L4|L3\.1))|Main@L3)$/ ,
format _settings _cabac : "Yes" ,
frame _rate _mode : "Constant" ,
writing _library : null ,
encoding _settings : null ,
color _range : "Limited" ,
color _primaries : "BT.709" ,
transfer _characteristics : "BT.709" ,
2021-11-30 07:37:23 +00:00
matrix _coefficients : "BT.709" ,
codec _configuration _box : null ,
2021-11-26 04:42:57 +00:00
} ,
2021-12-10 07:05:25 +00:00
custom : ( sourceTags , mediainfo , tags , video , audio , text ) => {
2021-11-29 16:42:55 +00:00
let match = ( mediainfo . audio . length === 1 && "codec_id" in mediainfo . audio [ 0 ] && mediainfo . audio [ 0 ] . codec _id . match ( /^A_EAC3$/ ) !== null ) ||
2021-11-30 10:29:33 +00:00
( mediainfo . audio . length === 2 && "codec_id" in mediainfo . audio [ 0 ] && "codec_id" in mediainfo . audio [ 1 ] && ( ( mediainfo . audio [ 0 ] . codec _id . match ( /^(A_AAC|^A_EAC3$)/ ) !== null && mediainfo . audio [ 1 ] . codec _id . match ( /^A_EAC3$/ ) !== null ) || ( mediainfo . audio [ 1 ] . codec _id . match ( /^(A_AAC|^A_EAC3$)/ ) !== null && mediainfo . audio [ 0 ] . codec _id . match ( /^A_EAC3$/ ) !== null ) ) ) ;
2021-11-26 04:42:57 +00:00
if ( match ) {
let eac3Track = mediainfo . audio [ 0 ] . codec _id . match ( /^A_EAC3$/ ) !== null ? mediainfo . audio [ 0 ] : ( ( mediainfo . audio . length > 1 && mediainfo . audio [ 1 ] . codec _id . match ( /^A_EAC3$/ ) !== null ) ? mediainfo . audio [ 1 ] : null ) ;
if ( eac3Track === null ) {
match = false ;
}
if ( "bit_rate_mode" in video && video . bit _rate _mode !== "Constant" ) {
match = false ;
}
switch ( parseInt ( video . width . replace ( /[^0-9]/g , "" ) ) ) {
case 1920 :
if ( "nominal_bit_rate" in video && video . nominal _bit _rate !== "10 000 kb/s" ) {
match = false ;
}
if ( video . format _profile !== "High@L4" ) {
match = false ;
}
if ( ( "format_settings_reframes" in video && video . format _settings _reframes !== "4 frames" ) || ( "format_settings_reference_frames" in video && video . format _settings _reference _frames !== "4 frames" ) ) {
match = false ;
}
break ;
case 1280 :
2021-11-30 10:29:33 +00:00
if ( "nominal_bit_rate" in video && video . nominal _bit _rate !== "4 000 kb/s" && video . nominal _bit _rate !== "6 000 kb/s" ) {
2021-11-26 04:42:57 +00:00
match = false ;
}
if ( video . format _profile !== "High@L3.1" ) {
match = false ;
}
2021-11-30 10:29:33 +00:00
if ( ( "format_settings_reframes" in video && video . format _settings _reframes !== "5 frames" && video . format _settings _reframes !== "4 frames" ) || ( "format_settings_reference_frames" in video && video . format _settings _reference _frames !== "5 frames" && video . format _settings _reference _frames !== "4 frames" ) ) {
2021-11-26 04:42:57 +00:00
match = false ;
}
break ;
case 720 :
/ * i f ( " n o m i n a l _ b i t _ r a t e " i n v i d e o & & v i d e o . n o m i n a l _ b i t _ r a t e ! = = " 4 0 0 0 k b / s " ) {
match = false ;
} * /
if ( video . format _profile !== "Main@L3" ) {
match = false ;
}
if ( ( "format_settings_reframes" in video && video . format _settings _reframes !== "5 frames" ) || ( "format_settings_reference_frames" in video && video . format _settings _reference _frames !== "5 frames" ) ) {
match = false ;
}
break ;
default :
match = false ;
}
2021-11-29 16:42:55 +00:00
switch ( eac3Track . channels ) {
2021-11-26 04:42:57 +00:00
case 2 :
if ( "bit_rate_mode" in eac3Track && eac3Track . bit _rate _mode !== "Constant" ) {
match = false ;
}
if ( "bit_rate" in eac3Track && eac3Track . bit _rate !== "224 kb/s" ) {
match = false ;
}
if ( "number_of_dynamic_objects" in eac3Track ) { //No Atmos
match = false ;
}
break ;
case 6 :
if ( "bit_rate_mode" in eac3Track && eac3Track . bit _rate _mode !== "Constant" ) {
match = false ;
}
if ( "bit_rate" in eac3Track && eac3Track . bit _rate !== "640 kb/s" ) {
match = false ;
}
if ( "number_of_dynamic_objects" in eac3Track ) { //No Atmos
match = false ;
}
break ;
default :
match = false ;
}
}
return match ;
} ,
} ,
set : {
sourceName : "Amazon Prime Video*"
}
} ,
2021-11-29 16:42:55 +00:00
] ;
2021-12-09 15:04:39 +00:00
const settings = new ScriptSettings ( "" ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "handleMusicVideos" , "Process Music" , "Process Video formats under Music categories. Example: DVD, PV, Live" , "bool" , true ) ;
2021-12-10 07:05:25 +00:00
settings . addSetting ( "handleUploadAutofill" , "Autofill Upload Details" , "Parse Mediainfo on upload and autofill details." , "bool" , true ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "enhanceTags" , "Enhance Tags" , "Entries will have their tags replaced/extended. Formats (like Atmos, HDR, higher bitDepth, chroma) and detected Sources will be labeled accordingly. Disabling this removes most of this scripts functions." , "bool" , true ) ;
settings . addSetting ( "openFormats" , "Label Open Formats" , "Entries that are composed fully of known Open Formats/Codecs will be labeled as such." , "bool" , true ) ;
settings . addSetting ( "showContainerVersions" , "Show Container Versions" , "Display container versions. Currently implemented for Matroska / WebM" , "bool" , false ) ;
2021-12-10 07:05:25 +00:00
settings . addSetting ( "showEncodingDetails" , "Show Encoding Details" , "Display encoding details such as encoder, mode, CRF, and bitrate" , "bool" , true ) ;
2021-12-24 16:23:05 +00:00
settings . addSetting ( "showAudioDetails" , "Show Audio Details" , "Display extra audio details such as bit-depth, bitrate." , "bool" , false ) ;
2022-03-29 07:45:16 +00:00
settings . addSetting ( "handleAnamorphicVideo" , "Handle Anamorphic Video" , "Use Display Aspect Ratio information to calculate display resolution." , "bool" , true ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "regexpFilter" , "RegExp Filter" , "Any entry that matches one of these RegExp (without delimiters) will be filtered out. Can enter a different one per line. Empty to disable" , "text" , "" ) ;
2022-04-27 10:16:55 +00:00
settings . addSetting ( "extraStyles" , "CSS Styles" , "Extra CSS styles to add to Torrent pages. Empty to disable. Enter a single style rule per line." , "text" , "" ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "script_deliciousCompatMode" , "Enable Delicious Compatibility" , "Enable workarounds to make output compatible with AnimeBytes Delicious user scripts Bundle" , "bool" , true ) ;
2022-04-24 18:53:25 +00:00
settings . addSetting ( "script_evaHighlightEmulation" , "Enable Eva's torrent highlighter emulation" , "Create classes and data tags similar to Eva's torrent highlighter, without breaking this script functions." , "bool" , true ) ;
settings . addSetting ( "script_abHighlights2Emulation" , "Enable AB Highlights 2 emulation" , "Create classes and data tags similar to AB Highlights 2, without breaking this script functions." , "bool" , true ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "warning_mediainfoSource" , "General: Mediainfo Source" , "Alert when Mediainfo was found on Description and not on Mediainfo tab." , "bool" , true ) ;
settings . addSetting ( "warning_mediainfoInvalid" , "General: Mediainfo not found" , "Alert when Mediainfo was not found or invalid" , "bool" , true ) ;
settings . addSetting ( "warning_tagMismatch" , "General: Mismatched Tags" , "Alert when site tags differ from calculated tags" , "bool" , true ) ;
settings . addSetting ( "warning_orderedChapters" , "General: Ordered Chapters" , "Warn when Ordered Chapters are found" , "bool" , true ) ;
settings . addSetting ( "warning_japaneseNumbering" , "General: Japanese Episode Numbering" , "Inform when episodes are labeled in Japanese. Example: 第02話" , "bool" , true ) ;
2023-09-02 13:58:32 +00:00
settings . addSetting ( "warning_handbrakeEncoder" , "General: HandBrake Encode" , "Inform when HandBrake is found on a release." , "bool" , true ) ;
2021-12-09 08:56:14 +00:00
settings . addSetting ( "warning_hwEncoder" , "Video: Hardware Encoded" , "Alert when a hardware encoder is found on a release." , "bool" , true ) ;
settings . addSetting ( "warning_encodeProfile" , "Video: Low Profile" , "Warn when low encoding profile is found on encode settings." , "bool" , true ) ;
settings . addSetting ( "warning_encodeSettings" , "Video: Settings Information" , "Show extra information messages about encode settings." , "bool" , true ) ;
settings . addSetting ( "warning_progressiveFpsTooHigh" , "Video: High FPS Threshold" , "Alert when fps for progressive scan encodes is above this number." , "int" , 30 ) ;
settings . addSetting ( "warning_defaultAudioNotJapanese" , "Audio: Default not Japanese" , "Inform when Default audio is not Japanese (Does not apply to Live Action)" , "bool" , true ) ;
settings . addSetting ( "warning_bloatPCM" , "Audio: bloat, PCM" , "Warn when any audio track is left as PCM (Does not apply to remux or raw sources)" , "bool" , true ) ;
settings . addSetting ( "warning_bloatg16bit" , "Audio: bloat, >16-bit" , "Warn when specific lossless audio has bit depth larger than 16-bit (Does not apply to remux or raw sources)" , "bool" , true ) ;
settings . addSetting ( "warning_signsDefault" , "Text: Default is Signs" , "Warn when Default track is a known Signs track" , "bool" , true ) ;
settings . addSetting ( "warning_textLabeling" , "Text: Wrongly Labeled Subtitles" , "Warn when tracks are believed not their Language labeled not English." , "bool" , true ) ;
settings . addSetting ( "warning_externalSubs" , "Text: External Subtitles" , "Warn when only external subtitles are present" , "bool" , true ) ;
settings . addSetting ( "debug_printGroup" , "Print Torrent Groups" , "Outputs the torrent group result of matching and parsing on console for inspection." , "bool" , false ) ;
settings . addSetting ( "debug_flagUnknownCodec" , "Flag Unknown Codecs" , "Flags unknown codecs that have not been matched internally." , "bool" , false ) ;
2021-11-30 05:06:09 +00:00
2021-11-29 18:02:16 +00:00
const torrentTypeImage = document . querySelector ( "a.scaledImg > img" ) ;
const torrentType = torrentTypeImage ? torrentTypeImage . getAttribute ( "title" ) : null ;
2021-11-29 23:31:17 +00:00
const torrentTypeHeader = document . querySelector ( "#content .thin > h2" ) ;
const torrentTypeMusic = torrentTypeHeader ? torrentTypeHeader . textContent . split ( /[()\[\]\-]/g ) . filter ( ( a ) => a ) . slice ( - 1 ) [ 0 ] : null ;
2021-11-25 18:07:42 +00:00
const torrentTableColspan = 6 ;
2021-11-29 18:02:16 +00:00
2021-11-29 23:31:17 +00:00
if (
2021-12-09 08:56:14 +00:00
( torrentType !== null && ABClass . videoTypes . indexOf ( torrentType . replace ( "Live Action " , "" ) ) !== - 1 ) ||
( settings . getSetting ( "handleMusicVideos" ) && torrentTypeMusic !== null && ABClass . musicVideoTypes . indexOf ( torrentTypeMusic ) !== - 1 )
2021-11-29 23:31:17 +00:00
) {
2021-11-25 18:07:42 +00:00
2021-12-09 08:56:14 +00:00
const isMusicType = torrentTypeMusic !== null && ABClass . musicVideoTypes . indexOf ( torrentTypeMusic ) !== - 1 ;
2021-11-29 23:31:17 +00:00
const isLiveActionType = torrentType !== null && torrentType . match ( /Live Action/ ) !== null ;
console . log ( "Found entry type " + ( isMusicType ? torrentTypeMusic : torrentType ) ) ;
2021-11-29 18:02:16 +00:00
2021-11-21 03:17:10 +00:00
let episodeCount = 0 ;
document . querySelectorAll ( "ul.stats > li" ) . forEach ( ( item ) => {
let strongItem = item . querySelector ( "strong" ) ;
if ( strongItem !== null && strongItem . textContent === "Episodes:" ) {
episodeCount = parseInt ( item . querySelector ( "a" ) . textContent ) ;
}
} ) ;
2021-11-30 07:37:23 +00:00
if ( episodeCount === 0 && torrentType !== null && torrentType . match ( /Movie$/ ) !== null ) {
2021-11-21 03:17:10 +00:00
episodeCount = 1 ;
}
let torrentListing = [ ] ;
document . querySelectorAll ( ".group_torrent" ) . forEach ( ( item ) => {
2021-11-29 23:31:17 +00:00
const downloadLink = item . querySelector ( "td > span a[title^='Download']" ) ;
const linkSection = downloadLink . closest ( "td" ) ;
2021-11-21 03:17:10 +00:00
const [ torrentEntry ] = Array . from ( linkSection . querySelectorAll ( "a" ) ) . slice ( - 1 ) ;
const torrentId = parseInt ( downloadLink . getAttribute ( "href" ) . match ( /\/torrent\/(?<torrent_id>[0-9]+)\/download/ ) . groups . torrent _id ) ;
2021-11-25 21:12:43 +00:00
if ( ! torrentEntry ) {
//Skip unknown entries
return ;
}
2021-11-21 03:17:10 +00:00
let tags = {
audioCount : 1 ,
2021-11-21 13:15:27 +00:00
freeleech : torrentEntry . querySelector ( "img[alt^='Freeleech!']" ) !== null ,
remastered : torrentEntry . querySelector ( "img[alt^='Remastered']" ) !== null ,
2024-03-30 18:14:05 +00:00
censoredHentai : torrentEntry . querySelector ( "img[src*='/hentaic-']" ) !== null ,
uncensoredHentai : torrentEntry . querySelector ( "img[src*='/hentai-']" ) !== null ,
2022-01-03 14:54:50 +00:00
snatched : torrentEntry . textContent . match ( /- Snatched/ ) !== null ,
reported : torrentEntry . textContent . match ( /- Reported/ ) !== null ,
pruned : torrentEntry . textContent . match ( /- Pruned!/ ) !== null
2021-11-21 03:17:10 +00:00
} ;
2022-01-03 14:54:50 +00:00
torrentEntry . textContent . replace ( "»" , "" ) . replace ( /- (Snatched|Pruned!|Reported)/g , "" ) . split ( /( \| | \/ )/ ) . forEach ( ( t ) => {
2021-11-21 03:17:10 +00:00
let tagEntry = t . trim ( ) ;
if ( tagEntry === "" ) {
return ;
}
let match = null ;
2021-12-09 08:56:14 +00:00
if ( ! ( "source" in tags ) && ABClass . sources . indexOf ( tagEntry ) !== - 1 ) {
2021-11-21 03:17:10 +00:00
tags . source = tagEntry ;
2021-12-09 08:56:14 +00:00
} else if ( ! ( "container" in tags ) && ABClass . containers . some ( ( i ) => tagEntry . startsWith ( i ) ) ) {
2021-11-21 03:17:10 +00:00
if ( ( match = tagEntry . match ( /^(?<container>[^(]+) \((?<region>[^)]+)\)$/ ) ) !== null ) {
tags . container = match . groups . container ;
tags . region = match . groups . region ;
} else {
tags . container = tagEntry ;
}
2021-12-09 08:56:14 +00:00
} else if ( ! ( "videoCodec" in tags ) && ABClass . videoCodecs . some ( ( i ) => tagEntry . startsWith ( i ) ) ) {
2021-11-21 03:17:10 +00:00
tags . videoCodec = tagEntry ;
2021-12-09 08:56:14 +00:00
} else if ( ! ( "audioCodec" in tags ) && ABClass . audioCodecs . some ( ( i ) => tagEntry . startsWith ( i ) ) ) {
2021-11-21 03:17:10 +00:00
match = tagEntry . match ( /^(?<codec>.+) (?<channels>[0-9.]+)$/ )
tags . audioCodec = match . groups . codec ;
tags . audioChannels = match . groups . channels . split ( "." ) . reduce ( ( p , c ) => parseInt ( p ) + parseInt ( c ) ) ;
} else if ( tagEntry . match ( /^[0-9]+:[0-9]+$/ ) !== null ) {
tags . aspectRatio = tagEntry ;
2021-11-29 20:30:18 +00:00
} else if ( tagEntry . match ( /^[0-9]+x[0-9]+$/i ) !== null || tagEntry . match ( /^(720p|1080p|1080i|4K)$/i ) !== null ) {
tags . resolution = tagEntry . toLowerCase ( ) ;
2021-11-21 03:17:10 +00:00
} else if ( tagEntry === "Dual Audio" ) {
tags . audioCount = 2 ;
} else if ( ( match = tagEntry . match ( /^(?<kind>(RAW|Hardsubs|Softsubs))( \()?(?<group>[^)]*)(\))?$/ ) ) !== null ) {
if ( match . groups . kind !== "RAW" ) {
tags . subtitleType = match . groups . kind ;
}
if ( match . groups . group !== "" ) {
tags . group = match . groups . group ;
}
} else {
//console.log(tagEntry);
}
} ) ;
let torrent = {
id : torrentId ,
tags : tags ,
elements : {
item : item ,
entry : torrentEntry ,
link : downloadLink ,
} ,
} ;
const dataSection = document . getElementById ( "torrent_" + torrentId ) ;
if ( dataSection !== null ) {
2021-11-25 18:07:42 +00:00
torrent . elements . data = dataSection ;
2021-11-21 03:17:10 +00:00
const descriptionSection = document . getElementById ( torrentId + "_description" ) ;
const filelistSection = document . getElementById ( torrentId + "_filelist" ) ;
const mediaInfoSection = document . getElementById ( torrentId + "_mediainfo" ) ;
if ( descriptionSection !== null ) {
torrent . elements . description = descriptionSection . querySelector ( "blockquote" ) ;
torrent . description = torrent . elements . description . textContent ;
}
if ( filelistSection !== null ) {
torrent . elements . filelist = filelistSection . querySelector ( "table" ) ;
torrent . filelist = [ ] ;
torrent . elements . filelist . querySelectorAll ( "tr" ) . forEach ( ( tableRow ) => {
if ( tableRow . querySelector ( "td > strong" ) !== null ) {
//Skip header
return ;
}
torrent . filelist . push ( {
path : tableRow . querySelector ( "td" ) . textContent ,
size : tableRow . querySelector ( "td:last-of-type" ) . textContent //TODO: convert back to bytes
} )
} ) ;
}
if ( mediaInfoSection !== null ) {
torrent . elements . mediainfo = mediaInfoSection ;
let m _list = [ ] ;
torrent . elements . mediainfo . querySelectorAll ( "pre" ) . forEach ( ( mediainfoItem ) => {
2021-11-30 07:37:23 +00:00
let t = mediainfoItem . textContent . trim ( ) ;
let index = t . indexOf ( "General" ) ;
if ( index !== - 1 ) {
2021-12-09 08:56:14 +00:00
let m = Mediainfo . parseText ( t . substr ( index ) ) ;
2021-11-30 07:37:23 +00:00
if ( m !== null ) {
m _list . push ( m ) ;
}
2021-11-21 03:17:10 +00:00
}
} ) ;
if ( m _list . length > 0 ) {
torrent . mediainfo = m _list ;
2021-11-21 14:06:34 +00:00
torrent . mediainfoSource = "mediainfo" ;
}
} else if ( descriptionSection !== null ) {
//Find mediainfo tags
torrent . elements . description . querySelectorAll ( "input.spoilerButton" ) . forEach ( ( e ) => {
2022-07-23 10:44:50 +00:00
let ee = e . parentElement . querySelector ( "div.spoiler" ) ;
let tt = ee . querySelector ( "pre" ) ;
if ( ! tt ) {
tt = ee ;
}
let t = tt . textContent . trim ( )
2021-11-30 07:37:23 +00:00
let index = t . indexOf ( "General" ) ;
if ( index !== - 1 ) {
2021-12-09 08:56:14 +00:00
let m = Mediainfo . parseText ( t . substr ( index ) ) ;
2021-11-21 14:06:34 +00:00
if ( m !== null ) {
if ( ! ( "mediainfo" in torrent ) ) {
torrent . mediainfo = [ ] ;
torrent . mediainfoSource = "description spoiler" ;
}
torrent . mediainfo . push ( m ) ;
}
}
} ) ;
2021-11-21 14:51:42 +00:00
if ( ! ( "mediainfo" in torrent ) ) {
//Fallback, find General tag
let t = torrent . elements . description . parentElement . textContent . trim ( ) ;
let index = t . indexOf ( "General" ) ;
if ( index !== - 1 ) {
2021-12-09 08:56:14 +00:00
let m = Mediainfo . parseText ( t . substr ( index ) ) ;
2021-11-21 14:51:42 +00:00
if ( m !== null ) {
if ( ! ( "mediainfo" in torrent ) ) {
torrent . mediainfo = [ ] ;
torrent . mediainfoSource = "description" ;
}
torrent . mediainfo . push ( m ) ;
2021-11-21 14:06:34 +00:00
}
}
2021-11-21 03:17:10 +00:00
}
}
torrentListing . push ( torrent ) ;
}
} ) ;
2021-11-25 18:07:42 +00:00
{
{
2021-11-25 21:27:21 +00:00
let parentTd = document . querySelector ( "table.torrent_table tr > td[width*='%']" ) ;
2021-11-25 18:07:42 +00:00
parentTd . insertAdjacentElement ( "beforebegin" , document . createElement ( "td" ) ) ;
// Source + container + remux | Codec / Resolution / HDR | Audio + Dual + commentary | Text | OtherTags | Icons
parentTd . setAttribute ( "colspan" , torrentTableColspan . toString ( ) ) ;
document . querySelectorAll ( "table.torrent_table tr.edition_info > td" ) . forEach ( ( e ) => {
2021-12-24 16:23:05 +00:00
e . setAttribute ( "colspan" , ( parseInt ( e . getAttribute ( "colspan" ) ) + torrentTableColspan ) . toString ( ) ) ;
2021-11-25 18:07:42 +00:00
} ) ;
}
torrentListing . forEach ( ( torrent ) => {
2021-11-29 23:31:17 +00:00
let parent = torrent . elements . link . closest ( "span:not(.download_link)" ) ;
2021-11-25 18:07:42 +00:00
let td = document . createElement ( "td" ) ;
2021-11-25 21:27:21 +00:00
let element = torrent . elements . data . querySelector ( "td" ) ;
2021-12-24 16:23:05 +00:00
element . setAttribute ( "colspan" , ( parseInt ( element . getAttribute ( "colspan" ) ) + torrentTableColspan ) . toString ( ) ) ;
2021-11-25 18:07:42 +00:00
2021-11-29 23:31:17 +00:00
parent . closest ( "td" ) . insertAdjacentElement ( "beforebegin" , td ) ;
2021-11-25 18:07:42 +00:00
parent . style [ "white-space" ] = "nowrap" ;
td . append ( parent ) ;
Array . from ( parent . childNodes ) . forEach ( ( e ) => {
if ( e . nodeType === Node . TEXT _NODE && [ "[" , "]" ] . includes ( e . textContent . trim ( ) ) ) {
e . remove ( ) ;
}
} ) ;
} ) ;
}
2021-12-09 15:04:39 +00:00
2022-04-27 10:36:27 +00:00
GM _addStyle ( "#content{ width: -moz-fit-content; width: fit-content; max-width: calc(100% - 50px); }" ) ;
2021-12-09 15:04:39 +00:00
GM _addStyle ( `
@ font - face {
font - family : 'EmojiSymbols' ; /*This is what your font will be named*/
src : local ( 'EmojiSymbols-Regular' ) ,
url ( '`+ getResource("EmojiSymbols") + `' )
format ( 'woff' ) ;
}
` );
GM _addStyle ( ".emoji{ font-family: 'EmojiSymbols'; }" ) ;
GM _addStyle ( ".group_torrent .icons { font-weight: normal; font-style: normal; font-size: 16px; text-shadow: 0px 0px 2px #000;}" ) ;
2022-04-27 10:36:27 +00:00
GM _addStyle ( "#content{ max-width: calc(100% - 50px); width: -moz-fit-content; width: fit-content; }" ) ;
GM _addStyle ( "table.torrent_table { width: -moz-fit-content; width: fit-content; min-width: calc(950px - 240px); }" ) ;
GM _addStyle ( "table.torrent_table tr > td[width*='%'] { width: -moz-fit-content; width: fit-content; max-width: 80%;" ) ;
2021-11-25 19:16:58 +00:00
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "script_deliciousCompatMode" ) ) {
2021-12-02 16:26:08 +00:00
//Fix delicious user scripts
2022-04-27 10:36:27 +00:00
GM _addStyle ( "div.torrent_filter_box { width: -moz-fit-content !important; width: fit-content !important; float: none !important; min-width: calc(950px - 240px); }" ) ;
2021-12-02 16:26:08 +00:00
}
2021-11-25 18:53:41 +00:00
2022-04-27 10:16:55 +00:00
settings . getSetting ( "extraStyles" ) . split ( "\n" ) . forEach ( ( s ) => {
if ( s . trim ( ) === "" ) {
return ;
}
GM _addStyle ( s ) ;
} ) ;
2021-11-30 08:40:15 +00:00
2021-11-25 18:53:41 +00:00
const torrentTableElement = document . querySelector ( "div#content table.torrent_table" ) ;
const resizeCallback = ( ) => {
2021-11-29 23:36:05 +00:00
document . querySelectorAll ( isMusicType ? "#torrents2 div.main_column > table:not(.torrent_table), #torrents2 div.main_column > div" : "#torrents div.main_column > table:not(.torrent_table), #torrents div.main_column > div" ) . forEach ( ( e ) => {
2021-11-25 18:53:41 +00:00
e . style [ "width" ] = torrentTableElement . offsetWidth + "px" ;
} ) ;
} ;
const tableResizeObserver = new ResizeObserver ( resizeCallback ) ;
tableResizeObserver . observe ( torrentTableElement ) ;
resizeCallback ( ) ;
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "debug_printGroup" ) ) {
2021-11-30 05:06:09 +00:00
console . log ( torrentListing ) ;
}
2021-11-25 18:53:41 +00:00
2021-11-21 03:17:10 +00:00
torrentListing . forEach ( ( torrent ) => {
try {
2021-11-25 18:07:42 +00:00
let tags = {
2022-04-24 18:53:25 +00:00
2021-11-25 18:07:42 +00:00
} ;
2022-04-24 18:53:25 +00:00
2021-11-25 18:07:42 +00:00
let warnings = {
general : [ ] ,
audio : [ ] ,
video : [ ] ,
text : [ ]
}
let fileName = null ;
2021-11-30 08:08:30 +00:00
if ( "mediainfo" in torrent && torrent . mediainfo . length > 0 && "complete_name" in torrent . mediainfo [ 0 ] . general ) {
2021-12-16 14:48:21 +00:00
[ fileName ] = torrent . mediainfo [ 0 ] . general . complete _name . split ( /[/\\]/g ) . slice ( - 1 ) ;
2021-11-25 18:07:42 +00:00
} else {
2021-11-30 08:08:30 +00:00
torrent . filelist . every ( ( f ) => {
[ f ] = f . path . split ( "/" ) . slice ( - 1 ) ;
const ext = f . split ( "." ) . slice ( - 1 ) [ 0 ] . toUpperCase ( ) ;
if ( ext === "ISO" || ext === "MKV" || ext === "MP4" || ext === "OGM" || ext === "AVI" ) {
fileName = f ;
}
return fileName === null ;
} ) ;
if ( fileName === null ) {
[ fileName ] = torrent . filelist [ 0 ] . path . split ( "/" ) . slice ( - 1 ) ;
}
2021-11-25 18:07:42 +00:00
}
2021-11-25 18:13:36 +00:00
let japaneseEpisodeMatch = fileName . match ( /第[0-9.]+話/u ) ;
2021-12-09 08:56:14 +00:00
if ( japaneseEpisodeMatch !== null && settings . getSetting ( "warning_japaneseNumbering" ) ) {
2021-11-25 18:16:02 +00:00
warnings . general . push ( [ "info" , "Episode numbering is in Japanese format: example " + japaneseEpisodeMatch [ 0 ] ] ) ;
2021-11-25 18:13:36 +00:00
}
2021-12-16 15:04:39 +00:00
for ( const [ key , value ] of Object . entries ( extractTagsFromFilename ( fileName , torrent . tags , torrent . tags . source ) ) ) {
2021-12-10 07:05:25 +00:00
tags [ key ] = value ;
}
2022-03-29 07:40:24 +00:00
if ( "mediainfo" in torrent && torrent . mediainfo . length > 0 && torrent . mediainfo [ 0 ] . video && torrent . mediainfo [ 0 ] . video . length > 0 ) {
2021-11-21 03:17:10 +00:00
let mediainfo = torrent . mediainfo [ 0 ] ;
2021-12-09 08:56:14 +00:00
if ( torrent . mediainfoSource !== "mediainfo" && settings . getSetting ( "warning_mediainfoSource" ) ) {
2021-12-09 15:04:39 +00:00
warnings . general . push ( [ "mediainfo" , "Mediainfo sourced from " + torrent . mediainfoSource + ". Consider reporting the torrent and providing it." ] )
2021-11-21 14:06:34 +00:00
}
2021-11-21 03:17:10 +00:00
2021-12-16 14:48:21 +00:00
let isFileMatch = false ;
const fileNameToMatch = fileName . toLowerCase ( ) . replace ( /[ \t\r\n]/g , "" ) ;
torrent . filelist . every ( ( file ) => {
if ( file . path . split ( "/" ) . slice ( - 1 ) [ 0 ] . toLowerCase ( ) . replace ( /[ \t\r\n]/g , "" ) === fileNameToMatch ) {
isFileMatch = true ;
}
return ! isFileMatch ;
} ) ;
if ( ! isFileMatch ) {
warnings . general . push ( [ "warning" , "Source file \"" + fileName + "\" not found on torrent file list. It might be part of an archive." ] ) ;
}
2021-12-10 10:50:30 +00:00
extractFromMediainfo ( tags , mediainfo , warnings , fileName , torrent . filelist , torrent . tags , isLiveActionType ) ;
2022-04-24 18:53:25 +00:00
2021-11-25 18:07:42 +00:00
} else {
torrent . elements . item . style [ "font-style" ] = "italic" ;
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "warning_mediainfoInvalid" ) ) {
2021-12-09 15:04:39 +00:00
warnings . text . push ( [ "mediainfo" , "No valid mediainfo section found. Report torrent with MediaInfo." ] ) ;
2021-11-29 18:02:16 +00:00
}
2021-11-25 18:07:42 +00:00
}
2021-11-21 15:26:00 +00:00
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
for ( const [ key , value ] of Object . entries ( torrent . tags ) ) {
if ( ! ( key in tags ) ) {
tags [ key ] = value ;
2021-11-21 13:15:27 +00:00
}
2021-11-25 18:07:42 +00:00
}
2021-11-21 13:15:27 +00:00
2021-11-25 18:07:42 +00:00
if ( ! ( "aspectRatio" in torrent . tags ) && "aspectRatio" in tags ) {
torrent . tags . aspectRatio = tags . aspectRatio ;
}
2021-11-21 15:26:00 +00:00
2021-11-29 16:42:55 +00:00
//console.log(tags);
2021-11-25 18:07:42 +00:00
let oldTagLine = getComparisonLine ( torrent . tags ) ;
let newTagLine = getComparisonLine ( tags ) ;
2021-11-21 15:26:00 +00:00
2021-12-09 08:56:14 +00:00
if ( newTagLine . toLowerCase ( ) !== oldTagLine . toLowerCase ( ) && settings . getSetting ( "warning_tagMismatch" ) ) {
2021-11-25 18:07:42 +00:00
warnings . general . push ( [ "danger" , "Tag mismatch:\nold: " + oldTagLine + " !=\nnew: " + newTagLine ] ) ;
}
2021-11-21 15:26:00 +00:00
2021-11-25 18:07:42 +00:00
let messages = document . createElement ( "div" ) ;
messages . append ( document . createElement ( "br" ) ) ;
2021-11-21 15:26:00 +00:00
2021-12-09 15:04:39 +00:00
let messageCount = 0 ;
2021-11-25 18:07:42 +00:00
for ( const [ key , value ] of Object . entries ( warnings ) ) {
if ( value . length > 0 ) {
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
let h3 = document . createElement ( "h3" ) ;
2021-11-29 21:39:09 +00:00
h3 . textContent = key . toUpperCase ( ) + " MESSAGES" ;
2021-11-25 18:07:42 +00:00
messages . append ( h3 ) ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
let messageList = document . createElement ( "ul" ) ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
for ( let v of value ) {
let li = document . createElement ( "li" ) ;
li . style . float = "inherit" ;
let value = "" ;
if ( Array . isArray ( v ) ) {
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
switch ( v [ 0 ] ) {
case "info" :
value = "info: " + v [ 1 ] ;
break ;
case "warning" :
value = "warning: " + v [ 1 ] ;
break ;
case "danger" :
value = "danger: " + v [ 1 ] ;
break ;
2021-12-09 15:04:39 +00:00
case "mediainfo" :
value = "mediainfo: " + v [ 1 ] ;
break ;
2021-11-25 18:07:42 +00:00
}
} else {
value = v ;
}
2021-12-09 15:04:39 +00:00
++ messageCount ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
if ( value . includes ( "\n" ) ) {
let pre = document . createElement ( "pre" ) ;
pre . textContent = value ;
li . append ( pre ) ;
} else {
li . textContent = value ;
}
2021-11-21 03:43:15 +00:00
2021-11-25 18:07:42 +00:00
messageList . append ( li ) ;
}
2021-11-21 13:15:27 +00:00
2021-11-25 18:07:42 +00:00
messages . append ( messageList ) ;
messages . append ( document . createElement ( "br" ) ) ;
}
}
messages . append ( document . createElement ( "hr" ) ) ;
2021-11-21 13:15:27 +00:00
2021-12-09 15:04:39 +00:00
if ( messageCount > 0 ) {
2021-11-25 18:07:42 +00:00
if ( "description" in torrent . elements ) {
torrent . elements . description . prepend ( messages ) ;
}
}
2021-11-21 13:15:27 +00:00
2021-11-25 18:07:42 +00:00
/ * w h i l e ( t o r r e n t . e l e m e n t s . e n t r y . f i r s t C h i l d ) {
torrent . elements . entry . firstChild . remove ( ) ;
} * /
torrent . elements . entry . parentElement . remove ( ) ;
2021-11-21 13:15:27 +00:00
2021-12-09 15:04:39 +00:00
let entries = getEntryLine ( settings . getSetting ( "enhanceTags" ) === false ? torrent . tags : tags , warnings ) ;
2021-11-21 13:15:27 +00:00
2021-11-29 23:31:17 +00:00
let lastTd = torrent . elements . link . closest ( "td" ) ;
2021-11-21 13:15:27 +00:00
2021-11-25 18:07:42 +00:00
let onclickFn = ( e ) => {
torrent . elements . data . classList . toggle ( "hide" ) ;
e . preventDefault ( ) ;
} ;
2021-11-21 13:15:27 +00:00
2021-11-29 21:38:12 +00:00
let entryText = [ ] ;
2022-04-24 19:03:03 +00:00
let fields = [ ] ;
2021-11-25 18:07:42 +00:00
[ "icons" , "source" , "video" , "audio" , "text" , "other" ] . forEach ( ( k ) => {
let td = document . createElement ( "td" ) ;
2021-11-25 18:53:41 +00:00
td . style [ "max-width" ] = "calc(80% / " + torrentTableColspan + ")" ;
2021-11-25 18:07:42 +00:00
if ( k !== "other" ) {
2021-11-25 19:24:56 +00:00
td . style [ "width" ] = "fit-content" ;
2021-11-25 18:07:42 +00:00
}
2021-12-09 15:04:39 +00:00
if ( k === "icons" ) {
td . style [ "padding" ] = "0px 5px" ;
}
2021-11-25 18:07:42 +00:00
td . style [ "cursor" ] = "pointer" ;
2021-11-21 13:15:27 +00:00
2021-11-25 18:07:42 +00:00
let a = document . createElement ( "a" ) ;
if ( tags . snatched ) {
a . classList . add ( "snatched-torrent" ) ;
2021-11-21 03:17:10 +00:00
}
2022-04-24 18:53:25 +00:00
2021-11-25 18:07:42 +00:00
a . setAttribute ( "href" , torrent . elements . entry . href ) ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
a . addEventListener ( "click" , ( e ) => e . preventDefault ( ) ) ;
td . addEventListener ( "click" , onclickFn ) ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
entries [ k ] . forEach ( ( e ) => {
if ( a . firstChild ) {
a . append ( " / " ) ;
2021-11-21 03:43:15 +00:00
}
2021-11-25 18:07:42 +00:00
a . append ( e ) ;
} ) ;
2021-11-21 14:51:42 +00:00
2022-04-24 18:53:25 +00:00
if ( settings . getSetting ( "script_evaHighlightEmulation" ) ) {
a . classList . add ( "userscript-highlight" ) ;
}
if ( settings . getSetting ( "script_abHighlights2Emulation" ) ) {
a . classList . add ( "userscript-highlight" , "torrent-page" ) ;
a . querySelectorAll ( "span.userscript-highlight" ) . forEach ( ( e ) => {
e . getAttributeNames ( ) . forEach ( ( name ) => {
2022-04-24 19:04:22 +00:00
if ( name . match ( /^data-/ ) !== null && name !== "data-field" ) {
2022-04-24 18:53:25 +00:00
let attr = e . getAttribute ( name ) ;
a . setAttribute ( name , e . getAttribute ( name ) ) ;
fields . push ( attr ) ;
}
} ) ;
} ) ;
}
2021-11-25 18:07:42 +00:00
td . append ( a ) ;
2021-11-21 03:17:10 +00:00
2021-11-25 18:07:42 +00:00
lastTd . insertAdjacentElement ( "afterend" , td )
lastTd = td ;
2021-11-29 21:38:12 +00:00
entryText . push ( td . textContent . trim ( ) ) ;
2021-11-25 18:07:42 +00:00
} ) ;
2021-11-21 03:17:10 +00:00
2022-04-24 19:03:03 +00:00
if ( settings . getSetting ( "script_abHighlights2Emulation" ) ) {
lastTd . parentElement . querySelectorAll ( "td > a.userscript-highlight" ) . forEach ( ( e ) => {
e . setAttribute ( "data-fields" , fields . join ( " " ) )
} )
}
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "script_deliciousCompatMode" ) ) {
2021-12-02 16:26:08 +00:00
let hiddenParent = torrent . elements . link . closest ( "td" ) ;
let span = document . createElement ( "span" ) ;
span . style [ "display" ] = "none" ;
span . classList . add ( "fix_delicious_metadata" ) ;
2021-12-09 08:56:14 +00:00
span . append ( getComparisonLine ( settings . getSetting ( "enhanceTags" ) === false ? torrent . tags : tags , false ) ) ;
2021-12-02 16:26:08 +00:00
hiddenParent . append ( span ) ;
}
2021-11-30 08:40:15 +00:00
entryText = entryText . join ( " | " ) ;
2021-12-09 08:56:14 +00:00
settings . getSetting ( "regexpFilter" ) . split ( "\n" ) . every ( ( regexpFilter ) => {
2021-11-30 08:40:15 +00:00
regexpFilter = regexpFilter . trim ( ) ;
if ( regexpFilter !== "" && entryText . match ( new RegExp ( regexpFilter ) ) !== null ) {
//Filter out, only if not directly linked
if ( ! window . location . href . includes ( "torrentid=" + torrent . id ) ) {
torrent . elements . item . style [ "display" ] = "none" ;
torrent . elements . data . style [ "display" ] = "none" ;
}
return false ;
2021-11-29 18:02:16 +00:00
}
2021-11-30 08:40:15 +00:00
return true ;
} ) ;
2021-11-29 18:02:16 +00:00
2021-11-21 03:17:10 +00:00
} catch ( e ) {
console . log ( "Error:" , e ) ;
console . log ( torrent ) ;
2021-11-25 20:00:23 +00:00
//Fix entries
torrent . elements . entry . parentElement . setAttribute ( "colspan" , torrentTableColspan . toString ( ) ) ;
2021-11-21 03:17:10 +00:00
}
} ) ;
2021-12-10 07:05:25 +00:00
} else if ( window . location . href . match ( /upload\.php/ ) !== null && settings . getSetting ( "handleUploadAutofill" ) ) {
let mediainfoField = document . getElementById ( "mediainfo_desc" ) ;
if ( mediainfoField !== null ) {
let errorField = document . createElement ( "p" ) ;
errorField . style [ "font-weight" ] = "bold" ;
errorField . style [ "display" ] = "none" ;
mediainfoField . closest ( "dd" ) . append ( errorField ) ;
const eventHandler = ( ) => {
let text = mediainfoField . value ;
let mediainfo = null ;
errorField . style [ "display" ] = "none" ;
try {
let index = text . indexOf ( "General" ) ;
if ( index !== - 1 ) {
let m = Mediainfo . parseText ( text . substr ( index ) ) ;
if ( m !== null ) {
mediainfo = m ;
}
}
} catch ( e ) {
}
if ( mediainfo === null ) {
if ( text . trim ( ) !== "" ) {
errorField . textContent = "Could not parse Mediainfo. Maybe it is invalid / not English / not Mediainfo?"
errorField . style [ "display" ] = "" ;
}
} else {
let sourceElement = document . getElementById ( "media" ) ;
let containerElement = document . getElementById ( "containers_anime" ) ;
let videoCodecElement = document . getElementById ( "codecs" ) ;
let resolutionListElement = document . getElementById ( "resolution_anime" ) ;
let resolutionOtherElement = document . getElementById ( "other_resolution_anime" ) ;
let regionElement = document . getElementById ( "region_anime" ) ;
let arElement = document . getElementById ( "aspectratio_anime" ) ;
let audioCodecElement = document . getElementById ( "audio" ) ;
let audioChannelsElement = document . getElementById ( "audiochannels" ) ;
let dualAudioElement = document . getElementById ( "dual_audio" ) ;
let subbingElement = document . getElementById ( "subbing" ) ;
let isLiveActionType = false ;
let sourceTags = {
source : sourceElement . value ,
container : containerElement . value ,
videoCodec : videoCodecElement . value ,
resolution : resolutionListElement . value !== "OTHER" ? resolutionListElement . value : resolutionOtherElement . value ,
region : regionElement . value ,
aspectRatio : arElement . value ,
audioCodec : audioCodecElement . value ,
audioChannels : audioChannelsElement . value . split ( "." ) . reduce ( ( p , c ) => parseInt ( p ) + parseInt ( c ) ) ,
audioCount : dualAudioElement . checked ? 2 : 1 ,
} ;
if ( subbingElement . value === "Softsubs" || subbingElement . value === "Hardsubs" ) {
sourceTags . subtitleType = subbingElement . value ;
} else {
sourceTags . subtitleType = "Guess" ;
}
let tags = {
} ;
let warnings = {
general : [ ] ,
audio : [ ] ,
video : [ ] ,
text : [ ]
}
try {
2021-12-16 14:48:21 +00:00
let fileName = "complete_name" in mediainfo . general ? mediainfo . general . complete _name . split ( /[/\\]/g ) . slice ( - 1 ) [ 0 ] : "" ;
2021-12-16 15:04:39 +00:00
for ( const [ key , value ] of Object . entries ( extractTagsFromFilename ( fileName , sourceTags , sourceTags . source ) ) ) {
2021-12-10 07:05:25 +00:00
tags [ key ] = value ;
}
2021-12-10 10:50:30 +00:00
extractFromMediainfo ( tags , mediainfo , warnings , fileName , [ { path : fileName , size : 0 } ] , sourceTags , isLiveActionType ) ;
2021-12-10 07:05:25 +00:00
for ( const [ key , value ] of Object . entries ( sourceTags ) ) {
if ( ! ( key in tags ) ) {
tags [ key ] = value ;
}
}
2021-12-16 14:48:21 +00:00
let resolution = getLineTagEntry ( tags . resolution , true ) ;
if ( resolution === "4K" || resolution === "1080p" || resolution === "1080i" || resolution === "720p" ) {
resolutionListElement . value = resolution ;
2021-12-10 07:05:25 +00:00
resolutionOtherElement . value = "" ;
resolutionOtherElement . closest ( "dd" ) . style [ "display" ] = "none" ;
} else {
resolutionListElement . value = "OTHER" ;
2021-12-16 14:48:21 +00:00
resolutionOtherElement . value = resolution ;
2021-12-10 07:05:25 +00:00
resolutionOtherElement . closest ( "dd" ) . style [ "display" ] = "" ;
}
const addMessage = ( fieldElement , text ) => {
let parentDD = fieldElement . closest ( "dd" ) ;
let e = parentDD . querySelector ( "p.mediainfo" ) ;
if ( e === null ) {
e = document . createElement ( "p" ) ;
e . classList . add ( "mediainfo" ) ;
parentDD . append ( e ) ;
}
e . textContent = "Detected: " + text ;
} ;
sourceElement . value = getLineTagEntry ( tags . source , true ) ;
containerElement . value = getLineTagEntry ( tags . container , true ) ;
addMessage ( containerElement , getLineTagEntry ( tags . container , false ) ) ;
if ( containerElement . value === "ISO" || containerElement . value === "VOB IFO" || containerElement . value === "M2TS" ) {
regionElement . closest ( "dd" ) . style [ "display" ] = "" ;
arElement . closest ( "dd" ) . style [ "display" ] = "" ;
} else {
regionElement . closest ( "dd" ) . style [ "display" ] = "none" ;
arElement . closest ( "dd" ) . style [ "display" ] = "none" ;
}
videoCodecElement . value = getLineTagEntry ( tags . videoCodec , true ) ;
addMessage ( videoCodecElement , getLineTagEntry ( tags . videoCodec , false ) ) ;
if ( regionElement . closest ( "dd" ) . style [ "display" ] !== "none" ) {
regionElement . value = getLineTagEntry ( tags . region , true ) ;
}
if ( arElement . closest ( "dd" ) . style [ "display" ] !== "none" ) {
arElement . value = getLineTagEntry ( tags . aspectRatio , true ) ;
addMessage ( arElement , getLineTagEntry ( tags . aspectRatio , false ) ) ;
}
audioCodecElement . value = getLineTagEntry ( tags . audioCodec , true ) ;
addMessage ( audioCodecElement , getLineTagEntry ( tags . audioCodec , false ) ) ;
audioChannelsElement . value = Mediainfo . getAudioChannels ( getLineTagEntry ( tags . audioChannels , true ) ) ;
addMessage ( audioChannelsElement , Mediainfo . getAudioChannels ( getLineTagEntry ( tags . audioChannels , false ) ) ) ;
subbingElement . value = getLineTagEntry ( tags . subtitleType , true ) ;
addMessage ( subbingElement , ( "subtitleCodec" in tags ? tags . subtitleCodec + " " : "" ) + getLineTagEntry ( tags . subtitleType , false ) ) ;
if ( ( ! ( "audioLanguages" in tags ) || "English" in tags . audioLanguages ) && tags . audioCount > 1 ) {
dualAudioElement . checked = 1 ;
} else {
dualAudioElement . checked = 0 ;
}
} catch ( e ) {
errorField . textContent = e ;
errorField . style [ "display" ] = "" ;
}
}
} ;
mediainfoField . addEventListener ( "input" , eventHandler ) ;
mediainfoField . addEventListener ( "change" , eventHandler ) ;
mediainfoField . addEventListener ( "keyup" , eventHandler ) ;
}
2021-11-29 18:02:16 +00:00
} else if ( window . location . href . match ( /user\.php\?action=edit/ ) !== null ) {
let tabs = document . querySelector ( "ul.ue_tabs" ) ;
let sections = document . getElementById ( "tabs" ) ;
2021-12-02 16:26:08 +00:00
let sectionsHandle = sections . querySelector ( "p > input[type='submit']" ) . closest ( "p" ) ;
2021-11-29 18:02:16 +00:00
let section = document . createElement ( "div" ) ;
section . id = "mediainfo_settings" ;
2021-12-02 16:26:08 +00:00
section . style [ "display" ] = "none" ;
2021-11-29 18:02:16 +00:00
let e = document . createElement ( "div" ) ;
e . classList . add ( "head" , "colhead_dark" , "strong" ) ;
e . textContent = "Mediainfo Userscript Settings" ;
section . append ( e ) ;
let ul = document . createElement ( "ul" ) ;
ul . classList . add ( "nobullet" , "ue_list" ) ;
section . append ( ul ) ;
e = document . createElement ( "div" ) ;
e . classList . add ( "head" , "colhead_dark" , "strong" ) ;
2021-11-29 21:39:09 +00:00
e . textContent = "Mediainfo Userscript Messages" ;
2021-11-29 18:02:16 +00:00
section . append ( e ) ;
let ul _warn = document . createElement ( "ul" ) ;
ul _warn . classList . add ( "nobullet" , "ue_list" ) ;
section . append ( ul _warn ) ;
2021-11-30 05:06:09 +00:00
e = document . createElement ( "div" ) ;
e . classList . add ( "head" , "colhead_dark" , "strong" ) ;
e . textContent = "Mediainfo Userscript Debugging" ;
section . append ( e ) ;
let ul _debug = document . createElement ( "ul" ) ;
ul _debug . classList . add ( "nobullet" , "ue_list" ) ;
section . append ( ul _debug ) ;
2021-12-09 08:56:14 +00:00
Object . values ( settings . settings ) . forEach ( ( setting ) => {
2021-11-29 18:02:16 +00:00
let li = document . createElement ( "li" ) ;
let name = document . createElement ( "span" ) ;
name . classList . add ( "ue_left" , "strong" ) ;
name . textContent = setting . name ;
li . append ( name ) ;
let entry = document . createElement ( "span" ) ;
entry . classList . add ( "ue_right" ) ;
2021-11-30 08:40:15 +00:00
let input = setting . type === "text" ? document . createElement ( "textarea" ) : document . createElement ( "input" ) ;
2021-11-29 18:02:16 +00:00
input . id = "mediainfo_" + setting . id ;
switch ( setting . type ) {
case "bool" :
input . setAttribute ( "type" , "checkbox" ) ;
input . checked = setting . value ;
break ;
2021-11-30 08:40:15 +00:00
case "text" :
input . setAttribute ( "type" , "text" ) ;
input . value = setting . value ;
input . style [ "min-width" ] = "300px" ;
input . style [ "min-height" ] = "60px" ;
break ;
2021-11-29 18:02:16 +00:00
case "string" :
input . setAttribute ( "type" , "text" ) ;
input . value = setting . value ;
break ;
case "int" :
input . setAttribute ( "type" , "number" ) ;
input . value = setting . value ;
break ;
}
const eventHandler = ( ) => {
switch ( setting . type ) {
case "bool" :
2021-12-09 08:56:14 +00:00
settings . setSetting ( setting . id , input . checked ) ;
2021-11-29 18:02:16 +00:00
break ;
2021-11-30 08:40:15 +00:00
case "text" :
2021-12-09 08:56:14 +00:00
settings . setSetting ( setting . id , input . value ) ;
2021-11-30 08:40:15 +00:00
break ;
2021-11-29 18:02:16 +00:00
case "string" :
2021-12-09 08:56:14 +00:00
settings . setSetting ( setting . id , input . value ) ;
2021-11-29 18:02:16 +00:00
break ;
case "int" :
2021-12-09 08:56:14 +00:00
settings . setSetting ( setting . id , parseInt ( input . value ) ) ;
2021-11-29 18:02:16 +00:00
break ;
}
} ;
2021-11-30 08:40:15 +00:00
input . addEventListener ( "input" , eventHandler ) ;
2021-11-29 18:02:16 +00:00
input . addEventListener ( "change" , eventHandler ) ;
input . addEventListener ( "keyup" , eventHandler ) ;
entry . append ( input ) ;
2021-11-30 08:40:15 +00:00
if ( setting . type === "text" ) {
entry . append ( document . createElement ( "br" ) ) ;
}
2021-11-29 18:02:16 +00:00
let desc = document . createElement ( "label" ) ;
desc . setAttribute ( "for" , input . id ) ;
desc . textContent = " " + setting . description ;
entry . append ( desc ) ;
li . append ( entry ) ;
if ( setting . id . match ( /^warning_/ ) !== null ) {
ul _warn . append ( li ) ;
2021-11-30 05:06:09 +00:00
} else if ( setting . id . match ( /^debug_/ ) !== null ) {
ul _debug . append ( li ) ;
2021-11-29 18:02:16 +00:00
} else {
ul . append ( li ) ;
}
} ) ;
2021-12-02 16:26:08 +00:00
sectionsHandle . insertAdjacentElement ( 'beforebegin' , section ) ;
2021-12-09 08:56:14 +00:00
if ( settings . getSetting ( "script_deliciousCompatMode" ) ) {
2021-12-02 16:26:08 +00:00
let div = document . getElementById ( "#potatoes_setting" ) ;
if ( div ) {
//Fix their styling so it defaults to hidden
div . style [ "display" ] = "none" ;
sectionsHandle . insertAdjacentElement ( 'beforebegin' , div ) ;
} else {
}
}
2021-11-29 18:02:16 +00:00
let tab = document . createElement ( "li" ) ;
let a = document . createElement ( "a" ) ;
a . href = "#" + section . id ;
a . textContent = "Mediainfo Settings" ;
tab . append ( "•" ) ;
tab . append ( a ) ;
tabs . append ( tab ) ;
2021-11-21 03:17:10 +00:00
}