您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
(我已经安装了用户样式管理器,让我安装!)
// ==UserScript==
// @name Youtube Timestamp Buttons from FireBase Helper
// @namespace http://gf.qytechs.cn
// @version 0.2
// @description Uses FireBase Helper Function to Call Youtube Data API 3 to get Comments with TimeStamps
// @author 636597
// @include *://*youtube.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
var button_menu_element = false;
var load_button_element = false;
var next_button_element = false;
var previous_button_element = false;
var time_stamp_data_paragraph_parent_element = false;
var time_stamp_data_paragraph_element = false;
var time_stamp_button_elements = [];
var current_video_id = false;
var current_video_duration = false;
var current_playlist_circular_array = false;
var x1_player = undefined;
var window_history_oberver = false;
function load_window_history_observer() {
CustomLog( "Initializing Window History Poller" );
window_history_oberver = setInterval( function() {
if ( !current_video_id ) { return; }
var url_string = null;
var now_playing_id = null;
try {
url_string = x1_player.getVideoUrl();
now_playing_id = url_string.split( "v=" )[ 1 ].split( "&" )[ 0 ];
}
catch( error ) { return; }
if ( now_playing_id !== current_video_id ) {
CustomLog( "Detected New Video ID" );
CustomLog( "Resetting Time Stamps" );
current_video_id = now_playing_id;
setTimeout( function() {
load_comments_from_firebase_helper( { skip: "yes" , override_id: now_playing_id } );
} , 3000 );
}
} , 1000 );
}
function CustomLog( message ) {
console.log( "YoutubeTimestampButtons.js === " + message );
}
function CircularArrayIterator( list , starting_index ) {
if ( !list ) { return false; }
if ( list.length < 1 ) { return false; }
const llen = list.length;
return {
current_index: starting_index || 0 ,
list: list ,
list_length: llen ,
push: function( item , index ) {
if ( !item ) { return; }
if ( index ) {
this.list.splice( index , 0 , item );
}
else {
this.list.push( item );
}
this.list_length += 1;
} ,
pop: function( index ) {
if ( index ) {
this.list.splice( index , 1 );
}
else {
this.list.pop();
}
this.list_length -= 1;
} ,
current: function() {
return this.list[ this.current_index ];
} ,
next: function() {
CustomLog( "next" );
this.current_index += 1;
if ( this.current_index > ( this.list_length - 1 ) ) {
this.current_index = 0;
}
return this.list[ this.current_index ];
} ,
next_index: function() {
CustomLog( "next index" );
this.current_index += 1;
if ( this.current_index > ( this.list_length - 1 ) ) {
this.current_index = 0;
}
return this.current_index;
} ,
previous: function() {
CustomLog( "previous" );
this.current_index -= 1;
if ( this.current_index < 0 ) {
this.current_index = ( this.list_length - 1 );
}
return this.list[ this.current_index ];
} ,
previous_index: function() {
CustomLog( "previous index" );
this.current_index -= 1;
if ( this.current_index < 0 ) {
this.current_index = ( this.list_length - 1 );
}
return this.current_index;
}
};
}
function removeDuplicates(originalArray, prop) {
var newArray = [];
var lookupObject = {};
for( var i in originalArray ) {
lookupObject[originalArray[i][prop]] = originalArray[i];
}
for(i in lookupObject) {
newArray.push(lookupObject[i]);
}
return newArray;
}
// function playlist_next() {
// CustomLog( "NEXT()" );
// if ( !x1_player ) { return; }
// var current_time = x1_player.getCurrentTime();
// if ( !current_time ) { return; }
// current_time = parseInt( current_time );
// CustomLog( "CURRENT TIME === " + current_time.toString() );
// CustomLog( "CURRENT === [ " + ( current_playlist_circular_array.current_index + 1 ).toString() + " ] of " + current_playlist_circular_array.list_length.toString() + " === " + current_playlist_circular_array.list[ current_playlist_circular_array.current_index ].url_seconds.toString() );
// console.log( current_playlist_circular_array.list[ current_playlist_circular_array.current_index ] );
// var current_url_seconds = current_playlist_circular_array.list[ current_playlist_circular_array.current_index ].url_seconds;
// var current_item = current_playlist_circular_array.list[ current_playlist_circular_array.current_index ];
// while ( current_url_seconds <= current_time ) {
// CustomLog( "current_url_seconds <= current_time" );
// CustomLog( current_url_seconds.toString() + " <= " + current_time.toString() );
// CustomLog( "current_index === " + current_playlist_circular_array.current_index.toString() );
// CustomLog( "Current Item === " );
// console.log( current_item );
// CustomLog( "NEXT()" );
// current_playlist_circular_array.next_index();
// current_item = current_playlist_circular_array.list[ current_playlist_circular_array.current_index ];
// current_url_seconds = current_item.url_seconds;
// CustomLog( current_url_seconds.toString() + " <= " + current_time.toString() );
// CustomLog( "current_index === " + current_playlist_circular_array.current_index.toString() );
// CustomLog( "Current Item === " );
// console.log( current_item );
// if ( current_playlist_circular_array.current_index === 0 ) { break; }
// }
// //next = current_playlist_circular_array.next();
// CustomLog( "NEXT()-FINAL === [ " + ( current_playlist_circular_array.current_index + 1 ).toString() + " ] of " + current_playlist_circular_array.list_length.toString() );
// console.log( current_item );
// x1_player.loadVideoById( current_video_id , current_item.url_seconds );
// }
// function playlist_previous() {
// CustomLog( "PREVIOUS()" );
// if ( !x1_player ) { return; }
// var current_time = x1_player.getCurrentTime();
// if ( !current_time ) { return; }
// current_time = parseInt( current_time );
// CustomLog( "CURRENT TIME === " + current_time.toString() );
// CustomLog( "CURRENT === [ " + ( current_playlist_circular_array.current_index + 1 ).toString() + " ] of " + current_playlist_circular_array.list_length.toString() );
// while ( current_time > current_playlist_circular_array.list[ current_playlist_circular_array.current_index ].url_seconds ) {
// CustomLog( "current_time > current_index" );
// current_playlist_circular_array.previous_index();
// CustomLog( "CURRENT === [ " + ( current_playlist_circular_array.current_index + 1 ).toString() + " ] of " + current_playlist_circular_array.list_length.toString() );
// if ( current_playlist_circular_array.current_index === current_playlist_circular_array.list_length ) { break; }
// }
// //next = current_playlist_circular_array.next();
// CustomLog( "CURRENT === [ " + ( current_playlist_circular_array.current_index + 1 ).toString() + " ] of " + current_playlist_circular_array.list_length.toString() );
// x1_player.loadVideoById( current_video_id , current_playlist_circular_array.list[ current_playlist_circular_array.current_index ].url_seconds );
// }
function playlist_seek( seconds ) {
CustomLog( "SEEKING TO === " + seconds.toString() );
x1_player.loadVideoById( current_video_id , seconds );
}
function add_paragraph_with_time_stamp_data() {
time_stamp_data_paragraph_parent_element = document.querySelector( "ytd-comments#comments" );
if ( time_stamp_data_paragraph_parent_element ) {
time_stamp_data_paragraph_parent_element = time_stamp_data_paragraph_parent_element.parentElement;
var reversed = current_playlist_circular_array.list;
reversed.reverse();
for ( var i = 0; i < reversed.length; ++i ) {
var id = "x1_p_ts_entry_" + i.toString();
var p_string = '<button id="' + id + '">' + reversed[ i ].time_string + '</button>';
//CustomLog( p_string );
var template = document.createElement( 'template' );
template.innerHTML = p_string;
var fragment = template.content
//time_stamp_data_paragraph_parent_element.appendChild( fragment );
time_stamp_data_paragraph_parent_element.insertBefore( fragment , time_stamp_data_paragraph_parent_element.childNodes[ 3 ] );
var b_elem = document.body.querySelector( "#" + id );
b_elem.setAttribute( "url_seconds" , current_playlist_circular_array.list[ i ].url_seconds );
//b_elem.setAttribute( "playlist_index" , reversed[ i ].index );
b_elem.addEventListener( "click" , function( event ) {
//current_playlist_circular_array.current_index = parseInt( this.getAttribute( "playlist_index" ) );
playlist_seek( parseInt( this.getAttribute( "url_seconds" ) ) );
});
time_stamp_button_elements.push( b_elem );
}
}
load_button_element.style.visibility = "visible";
if ( !window_history_oberver ) { load_window_history_observer(); }
}
function add_previous_next_buttons() {
if ( button_menu_element ) {
button_menu_element.insertAdjacentHTML( 'beforeend' , '<button id="x1_playlist_previous">Previous</button>' );
previous_button_element = document.body.querySelector( "#x1_playlist_previous" );
previous_button_element.addEventListener( "click" , playlist_previous );
button_menu_element.insertAdjacentHTML( 'beforeend' , '<button id="x1_playlist_next">Next</button>' );
next_button_element = document.body.querySelector( "#x1_playlist_next" );
next_button_element.addEventListener( "click" , playlist_next );
}
}
function load_keyboard_watchers() {
add_previous_next_buttons();
add_paragraph_with_time_stamp_data();
// TODO: Need To figure out Javscript Circular List, COGGERS FailFish
/*
document.body.addEventListener( "keydown" , function( event ) {
if ( event.key === "n" ) {
playlist_next();
}
else if ( event.key === "b" ) {
playlist_previous();
}
});
*/
}
function get_video_stats() {
var url_string = x1_player.getVideoUrl();
current_video_id = url_string.split( "v=" )[ 1 ].split( "&" )[ 0 ];
current_video_duration = x1_player.getDuration();
/*
current_playlist_id = url_string.split( "list=" );
if ( current_playlist_id ) {
if ( current_playlist_id.length > 1 ) {
current_playlist_id = current_playlist_id[ 1 ].split( "&" )[ 0 ];
current_playlist_index = x1_player.getPlaylistIndex();
CustomLog( current_playlist_id );
CustomLog( current_playlist_index );
}
}
*/
CustomLog( current_video_id );
}
function parse_firebase_helper( comments ) {
CustomLog( "Parsing Recieved Comment Data" );
let final = [];
for ( let i = 0; i < comments.length; ++i ) {
final.push( ...comments[ i ].time_stamp_parts );
}
let uniqueArray = removeDuplicates( final , "url_seconds" );
uniqueArray = uniqueArray.sort( ( a , b ) => {
b.url_seconds - a.url_seconds
});
uniqueArray = uniqueArray.filter( x => x.url_seconds !== null );
uniqueArray = uniqueArray.filter( x => x.url_seconds !== "null" );
uniqueArray = uniqueArray.filter( x => x.url_seconds < current_video_duration );
current_playlist_circular_array = false;
current_playlist_circular_array = CircularArrayIterator( uniqueArray );
add_paragraph_with_time_stamp_data();
console.log( uniqueArray );
}
var fburlb = atob( 'aHR0cHM6Ly91cy1jZW50cmFsMS1oZWxwZXItZTNkODYuY2xvdWRmdW5jdGlvbnMubmV0L3RpbWVzdGFtcHM/aWQ9' );
function load_comments_from_firebase_helper( options ) {
reset_simple();
var rebuild = true;
if ( options ) {
if ( options.skip ) {
if ( options.skip === "yes" ) {
current_video_id = options.override_id;
}
}
}
x1_player = document.getElementById( "movie_player" );
if ( !x1_player ) { return; }
get_video_stats();
if ( !current_video_id ) { return; }
load_button_element.style.visibility = "hidden";
CustomLog( "Fetching Comments from FireBase Helper" );
// fetch( 'https://us-central1-helper-e3d86.cloudfunctions.net/timestamps?id=' + current_video_id , {
// headers: new Headers({
// 'Access-Control-Allow-Origin': '*' ,
// 'Access-Control-Allow-Headers':'application/json',
// 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
// })
// })
fetch( fburlb + current_video_id )
.then( response => response.json() )
.then( data => {
console.log( data );
parse_firebase_helper( data.top_time_stamp_comments );
})
.catch(error => console.error(error))
}
function add_load_button() {
button_menu_element = document.body.querySelector( "ytd-menu-renderer" );
if ( button_menu_element ) {
button_menu_element.insertAdjacentHTML( 'beforeend' , '<button id="x1_load_ts">Load Timestamps</button>' );
load_button_element = document.body.querySelector( "#x1_load_ts" );
load_button_element.addEventListener( "click" , load_comments_from_firebase_helper );
}
}
function reset_simple() {
try { next_button_element.parentNode.removeChild( next_button_element ); } catch( e ){}
next_button_element = false;
try { previous_button_element.parentNode.removeChild( previous_button_element ); } catch( e ){}
previous_button_element = false;
for ( var i = 0; i < time_stamp_button_elements.length; ++i ) {
try { time_stamp_button_elements[ i ].parentNode.removeChild( time_stamp_button_elements[ i ] ); } catch( e ){}
}
//time_stamp_data_paragraph_parent_element = false;
//time_stamp_data_paragraph_element = false;
time_stamp_button_elements = [];
current_video_id = false;
current_video_duration = false;
// current_playlist_id = false;
// current_playlist_index = 0;
// current_index = 0;
// current_playlist = [];
current_playlist_circular_array = undefined;
x1_player = undefined;
}
function reset_all() {
button_menu_element = false;
try { load_button_element.parentNode.removeChild( load_button_element ); } catch( e ){}
load_button_element = false;
try { next_button_element.parentNode.removeChild( next_button_element ); } catch( e ){}
next_button_element = false;
try { previous_button_element.parentNode.removeChild( previous_button_element ); } catch( e ){}
previous_button_element = false;
try { time_stamp_data_paragraph_parent_element.parentNode.removeChild( time_stamp_data_paragraph_parent_element ); } catch( e ){}
time_stamp_data_paragraph_parent_element = false;
time_stamp_data_paragraph_element = false;
time_stamp_button_elements = [];
current_video_id = false;
current_video_duration = false;
//current_playlist_id = false;
//current_playlist_index = 0;
//current_index = 0;
//current_playlist = [];
current_playlist_circular_array = undefined;
x1_player = undefined;
}
function init() {
reset_all();
CustomLog( "LOADING" );
setTimeout(function(){
add_load_button();
//CustomLog( "LOADED" );
} , 3000 );
}
(function() {
window.addEventListener ( "load", init );
})();