1
+ // ==UserScript==
2
+ // @name Bangumi Episode On Air
3
+ // @namespace moe.willian.bangumi.ep-onAir
4
+ // @version 0.0.1
5
+ // @description Identify if a scheduled episode is still on air from play history
6
+ // @author Willian
7
+ // @include /^https?://(bangumi\.tv|bgm\.tv|chii\.in)//
8
+ // @run -at document-end
9
+ // ==/UserScript==
10
+
11
+ const lowerLimit = 3 ;
12
+ const factor = 5 ;
13
+
14
+ // median
15
+ function median ( values ) {
16
+ values = values . slice ( 0 ) . sort ( function ( a , b ) { return a - b ; } ) ;
17
+
18
+ return middle ( values ) ;
19
+ }
20
+
21
+ function middle ( values ) {
22
+ var len = values . length ;
23
+ var half = Math . floor ( len / 2 ) ;
24
+
25
+ if ( len % 2 )
26
+ return ( values [ half - 1 ] + values [ half ] ) / 2.0 ;
27
+ else
28
+ return values [ half ] ;
29
+ }
30
+
31
+ // 本番
32
+ /* jshint jquery: false */
33
+ function onAir ( ) {
34
+ const $ = q => document . querySelector ( q ) ;
35
+ const $All = q => document . querySelectorAll ( q ) ;
36
+
37
+ const getComment = function getCommentCountFromRel ( rel ) {
38
+ return + $ ( rel ) . querySelector ( 'span.tip > .cmt > .na' ) . textContent . slice ( 1 , - 1 ) ;
39
+ // throw Error(`Cannot get comments from rel: ${rel}`);
40
+ } ;
41
+
42
+ const callObserveForChange = ( observee , selectors , func , args , should_not_call_rightaway = false ) => {
43
+ if ( ! should_not_call_rightaway ) {
44
+ let images = observee . querySelectorAll ( selectors ) ;
45
+ func . apply ( null , [ images ] . concat ( args ) ) ;
46
+ }
47
+
48
+ if ( window . MutationObserver ) {
49
+ let observer = new MutationObserver ( ( mutationsList , observer ) => {
50
+ for ( let mutation of mutationsList ) {
51
+ if ( mutation . type == 'childList' ) {
52
+ images = observee . querySelectorAll ( selectors ) ;
53
+ func . apply ( null , [ images ] . concat ( args ) ) ;
54
+ }
55
+ }
56
+ } ) ;
57
+
58
+ const config = { attributes : false , childList : true , subtree : false } ;
59
+ observer . observe ( observee , config ) ;
60
+
61
+ window . addEventListener ( 'beforeunload' , ( event ) => {
62
+ observer . disconnect ( ) ;
63
+ } ) ;
64
+ }
65
+ } ;
66
+ if ( ! window . MutationObserver ) {
67
+ console . warn ( '[moe.willian.bangumi.retina] Browser does not support MutationObserver!' ) ;
68
+ }
69
+
70
+ const onLoad = function onLoad ( ) {
71
+ /* jshint jquery: true */
72
+ const programs = $All ( '.prg_list' ) ;
73
+ for ( const prg of programs ) {
74
+ const buttoms = Array . from ( prg . querySelectorAll ( 'li > .load-epinfo' ) ) ;
75
+ const airs = buttoms . filter ( b => b . classList . contains ( 'epBtnAir' ) ) ;
76
+ if ( airs . length > 0 ) {
77
+ console . log ( 'should detect on air' , prg ) ;
78
+ const medium = middle (
79
+ buttoms
80
+ . filter ( b => b . classList . contains ( 'epBtnWatched' ) || b . classList . contains ( 'epBtnAir' ) )
81
+ . filter ( b => b . hasAttribute ( 'rel' ) )
82
+ . map ( b => getComment ( b . getAttribute ( 'rel' ) ) )
83
+ . sort ( )
84
+ )
85
+ const threshold = Math . min ( medium / factor , lowerLimit ) ;
86
+
87
+ for ( const btn of airs ) {
88
+ console . log ( getComment ( btn . getAttribute ( 'rel' ) ) , threshold ) ;
89
+
90
+ if ( getComment ( btn . getAttribute ( 'rel' ) ) < threshold ) {
91
+ btn . classList . add ( 'willian-epBtnOnAir' ) ;
92
+ }
93
+ }
94
+ }
95
+
96
+ }
97
+ }
98
+ onLoad ( ) ;
99
+ }
100
+ $ ( document ) . ready ( onAir ) ;
0 commit comments