2022-04-03 00:26:53 +00:00
function sortChange ( sortValue ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { sort _order : sortValue } ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
location . reload ( ) ;
return false ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
// Updates video watch status when passed a video id and it's current state (ex if the video was unwatched but you want to mark it as watched you will pass "unwatched")
function updateVideoWatchStatus ( input1 , videoCurrentWatchStatus ) {
2022-04-06 18:48:12 +00:00
if ( videoCurrentWatchStatus ) {
videoId = input1 ;
} else if ( input1 . getAttribute ( "data-id" ) ) {
videoId = input1 . getAttribute ( "data-id" ) ;
videoCurrentWatchStatus = input1 . getAttribute ( "data-status" ) ;
}
postVideoProgress ( videoId , 0 ) ; // Reset video progress on watched/unwatched;
removeProgressBar ( videoId ) ;
if ( videoCurrentWatchStatus == "watched" ) {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "unwatched" ) ;
var payload = JSON . stringify ( { un _watched : videoId } ) ;
sendPost ( payload ) ;
} else if ( videoCurrentWatchStatus == "unwatched" ) {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "watched" ) ;
var payload = JSON . stringify ( { watched : videoId } ) ;
sendPost ( payload ) ;
}
2022-04-03 00:26:53 +00:00
2022-04-06 18:48:12 +00:00
var watchButtons = document . getElementsByClassName ( "watch-button" ) ;
for ( let i = 0 ; i < watchButtons . length ; i ++ ) {
if ( watchButtons [ i ] . getAttribute ( "data-id" ) == videoId ) {
watchButtons [ i ] . outerHTML = watchStatusIndicator ;
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
2022-04-03 00:26:53 +00:00
}
// Creates a watch status indicator when passed a video id and the videos watch status
function createWatchStatusIndicator ( videoId , videoWatchStatus ) {
2022-04-06 18:48:12 +00:00
if ( videoWatchStatus == "watched" ) {
var seen = "seen" ;
var title = "Mark as unwatched" ;
} else if ( videoWatchStatus == "unwatched" ) {
var seen = "unseen" ;
var title = "Mark as watched" ;
}
var watchStatusIndicator = ` <img src="/static/img/icon- ${ seen } .svg" alt=" ${ seen } -icon" data-id=" ${ videoId } " data-status=" ${ videoWatchStatus } " onclick="updateVideoWatchStatus(this)" class="watch-button" title=" ${ title } "> ` ;
return watchStatusIndicator ;
2022-04-03 00:26:53 +00:00
}
// function isWatched(youtube_id) {
// var payload = JSON.stringify({'watched': youtube_id});
// sendPost(payload);
// var seenIcon = document.createElement('img');
// seenIcon.setAttribute('src', "/static/img/icon-seen.svg");
// seenIcon.setAttribute('alt', 'seen-icon');
// seenIcon.setAttribute('id', youtube_id);
// seenIcon.setAttribute('title', "Mark as unwatched");
// seenIcon.setAttribute('onclick', "isUnwatched(this.id)");
// seenIcon.classList = 'seen-icon';
// document.getElementById(youtube_id).replaceWith(seenIcon);
// }
// Removes the progress bar when passed a video id
function removeProgressBar ( videoId ) {
2022-04-06 18:48:12 +00:00
setProgressBar ( videoId , 0 , 1 ) ;
2022-04-03 00:26:53 +00:00
}
function isWatchedButton ( button ) {
2022-04-06 18:48:12 +00:00
youtube _id = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { watched : youtube _id } ) ;
button . remove ( ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
location . reload ( ) ;
return false ;
} , 1000 ) ;
2022-04-03 00:26:53 +00:00
}
// function isUnwatched(youtube_id) {
// postVideoProgress(youtube_id, 0); // Reset video progress on unwatched;
// var payload = JSON.stringify({'un_watched': youtube_id});
// sendPost(payload);
// var unseenIcon = document.createElement('img');
// unseenIcon.setAttribute('src', "/static/img/icon-unseen.svg");
// unseenIcon.setAttribute('alt', 'unseen-icon');
// unseenIcon.setAttribute('id', youtube_id);
// unseenIcon.setAttribute('title', "Mark as watched");
// unseenIcon.setAttribute('onclick', "isWatched(this.id)");
// unseenIcon.classList = 'unseen-icon';
// document.getElementById(youtube_id).replaceWith(unseenIcon);
// }
function unsubscribe ( id _unsub ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { unsubscribe : id _unsub } ) ;
sendPost ( payload ) ;
var message = document . createElement ( "span" ) ;
message . innerText = "You are unsubscribed." ;
document . getElementById ( id _unsub ) . replaceWith ( message ) ;
2022-04-03 00:26:53 +00:00
}
function subscribe ( id _sub ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { subscribe : id _sub } ) ;
sendPost ( payload ) ;
var message = document . createElement ( "span" ) ;
message . innerText = "You are subscribed." ;
document . getElementById ( id _sub ) . replaceWith ( message ) ;
2022-04-03 00:26:53 +00:00
}
function changeView ( image ) {
2022-04-06 18:48:12 +00:00
var sourcePage = image . getAttribute ( "data-origin" ) ;
var newView = image . getAttribute ( "data-value" ) ;
var payload = JSON . stringify ( { change _view : sourcePage + ":" + newView } ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
location . reload ( ) ;
return false ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
function toggleCheckbox ( checkbox ) {
2022-04-06 18:48:12 +00:00
// pass checkbox id as key and checkbox.checked as value
var toggleId = checkbox . id ;
var toggleVal = checkbox . checked ;
var payloadDict = { } ;
payloadDict [ toggleId ] = toggleVal ;
var payload = JSON . stringify ( payloadDict ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
var currPage = window . location . pathname ;
window . location . replace ( currPage ) ;
return false ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
// download page buttons
function rescanPending ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { rescan _pending : true } ) ;
animate ( "rescan-icon" , "rotate-img" ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
checkMessages ( ) ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
function dlPending ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { dl _pending : true } ) ;
animate ( "download-icon" , "bounce-img" ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
checkMessages ( ) ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
function toIgnore ( button ) {
2022-04-06 18:48:12 +00:00
var youtube _id = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { ignore : youtube _id } ) ;
sendPost ( payload ) ;
document . getElementById ( "dl-" + youtube _id ) . remove ( ) ;
2022-04-03 00:26:53 +00:00
}
function downloadNow ( button ) {
2022-04-06 18:48:12 +00:00
var youtube _id = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { dlnow : youtube _id } ) ;
sendPost ( payload ) ;
document . getElementById ( youtube _id ) . remove ( ) ;
setTimeout ( function ( ) {
checkMessages ( ) ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
function forgetIgnore ( button ) {
2022-04-06 18:48:12 +00:00
var youtube _id = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { forgetIgnore : youtube _id } ) ;
sendPost ( payload ) ;
document . getElementById ( "dl-" + youtube _id ) . remove ( ) ;
2022-04-03 00:26:53 +00:00
}
function addSingle ( button ) {
2022-04-06 18:48:12 +00:00
var youtube _id = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { addSingle : youtube _id } ) ;
sendPost ( payload ) ;
document . getElementById ( "dl-" + youtube _id ) . remove ( ) ;
setTimeout ( function ( ) {
checkMessages ( ) ;
} , 500 ) ;
2022-04-03 00:26:53 +00:00
}
function deleteQueue ( button ) {
2022-04-06 18:48:12 +00:00
var to _delete = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { deleteQueue : to _delete } ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
location . reload ( ) ;
return false ;
} , 1000 ) ;
2022-04-03 00:26:53 +00:00
}
function stopQueue ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { queue : "stop" } ) ;
sendPost ( payload ) ;
document . getElementById ( "stop-icon" ) . remove ( ) ;
2022-04-03 00:26:53 +00:00
}
function killQueue ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { queue : "kill" } ) ;
sendPost ( payload ) ;
document . getElementById ( "kill-icon" ) . remove ( ) ;
2022-04-03 00:26:53 +00:00
}
// settings page buttons
function manualImport ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { "manual-import" : true } ) ;
sendPost ( payload ) ;
// clear button
var message = document . createElement ( "p" ) ;
message . innerText = "processing import" ;
var toReplace = document . getElementById ( "manual-import" ) ;
toReplace . innerHTML = "" ;
toReplace . appendChild ( message ) ;
2022-04-03 00:26:53 +00:00
}
function reEmbed ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { "re-embed" : true } ) ;
sendPost ( payload ) ;
// clear button
var message = document . createElement ( "p" ) ;
message . innerText = "processing thumbnails" ;
var toReplace = document . getElementById ( "re-embed" ) ;
toReplace . innerHTML = "" ;
toReplace . appendChild ( message ) ;
2022-04-03 00:26:53 +00:00
}
function dbBackup ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { "db-backup" : true } ) ;
sendPost ( payload ) ;
// clear button
var message = document . createElement ( "p" ) ;
message . innerText = "backing up archive" ;
var toReplace = document . getElementById ( "db-backup" ) ;
toReplace . innerHTML = "" ;
toReplace . appendChild ( message ) ;
2022-04-03 00:26:53 +00:00
}
function dbRestore ( button ) {
2022-04-06 18:48:12 +00:00
var fileName = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { "db-restore" : fileName } ) ;
sendPost ( payload ) ;
// clear backup row
var message = document . createElement ( "p" ) ;
message . innerText = "restoring from backup" ;
var toReplace = document . getElementById ( fileName ) ;
toReplace . innerHTML = "" ;
toReplace . appendChild ( message ) ;
2022-04-03 00:26:53 +00:00
}
function fsRescan ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { "fs-rescan" : true } ) ;
sendPost ( payload ) ;
// clear button
var message = document . createElement ( "p" ) ;
message . innerText = "File system scan in progress" ;
var toReplace = document . getElementById ( "fs-rescan" ) ;
toReplace . innerHTML = "" ;
toReplace . appendChild ( message ) ;
2022-04-03 00:26:53 +00:00
}
function resetToken ( ) {
2022-04-06 18:48:12 +00:00
var payload = JSON . stringify ( { "reset-token" : true } ) ;
sendPost ( payload ) ;
var message = document . createElement ( "p" ) ;
message . innerText = "Token revoked" ;
document . getElementById ( "text-reveal" ) . replaceWith ( message ) ;
2022-04-03 00:26:53 +00:00
}
// delete from file system
function deleteConfirm ( ) {
2022-04-06 18:48:12 +00:00
to _show = document . getElementById ( "delete-button" ) ;
document . getElementById ( "delete-item" ) . style . display = "none" ;
to _show . style . display = "block" ;
2022-04-03 00:26:53 +00:00
}
function deleteVideo ( button ) {
2022-04-06 18:48:12 +00:00
var to _delete = button . getAttribute ( "data-id" ) ;
var to _redirect = button . getAttribute ( "data-redirect" ) ;
var payload = JSON . stringify ( { "delete-video" : to _delete } ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
var redirect = "/channel/" + to _redirect ;
window . location . replace ( redirect ) ;
return false ;
} , 1000 ) ;
2022-04-03 00:26:53 +00:00
}
function deleteChannel ( button ) {
2022-04-06 18:48:12 +00:00
var to _delete = button . getAttribute ( "data-id" ) ;
var payload = JSON . stringify ( { "delete-channel" : to _delete } ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
window . location . replace ( "/channel/" ) ;
return false ;
} , 1000 ) ;
2022-04-03 00:26:53 +00:00
}
function deletePlaylist ( button ) {
2022-04-06 18:48:12 +00:00
var playlist _id = button . getAttribute ( "data-id" ) ;
var playlist _action = button . getAttribute ( "data-action" ) ;
var payload = JSON . stringify ( {
"delete-playlist" : {
"playlist-id" : playlist _id ,
"playlist-action" : playlist _action ,
} ,
} ) ;
sendPost ( payload ) ;
setTimeout ( function ( ) {
window . location . replace ( "/playlist/" ) ;
return false ;
} , 1000 ) ;
2022-04-03 00:26:53 +00:00
}
function cancelDelete ( ) {
2022-04-06 18:48:12 +00:00
document . getElementById ( "delete-button" ) . style . display = "none" ;
document . getElementById ( "delete-item" ) . style . display = "block" ;
2022-04-03 00:26:53 +00:00
}
// player
function createPlayer ( button ) {
2022-04-06 18:48:12 +00:00
var videoId = button . getAttribute ( "data-id" ) ;
var videoData = getVideoData ( videoId ) ;
var videoProgress = getVideoProgress ( videoId ) . position ;
var videoName = videoData . data . title ;
var videoTag = createVideoTag ( videoData , videoProgress ) ;
var playlist = "" ;
var videoPlaylists = videoData . data . playlist ; // Array of playlists the video is in
if ( typeof videoPlaylists != "undefined" ) {
var subbedPlaylists = getSubbedPlaylists ( videoPlaylists ) ; // Array of playlist the video is in that are subscribed
if ( subbedPlaylists . length != 0 ) {
var playlistData = getPlaylistData ( subbedPlaylists [ 0 ] ) ; // Playlist data for first subscribed playlist
var playlistId = playlistData . playlist _id ;
var playlistName = playlistData . playlist _name ;
var playlist = ` <h5><a href="/playlist/ ${ playlistId } /"> ${ playlistName } </a></h5> ` ;
}
}
var videoViews = formatNumbers ( videoData . data . stats . view _count ) ;
var channelId = videoData . data . channel . channel _id ;
var channelName = videoData . data . channel . channel _name ;
removePlayer ( ) ;
// document.getElementById(videoId).outerHTML = ''; // Remove watch indicator from video info
// If cast integration is enabled create cast button
var castButton = "" ;
if ( videoData . config . application . enable _cast ) {
var castButton = ` <google-cast-launcher id="castbutton"></google-cast-launcher> ` ;
}
// Watched indicator
if ( videoData . data . player . watched ) {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "watched" ) ;
} else {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "unwatched" ) ;
}
var playerStats = ` <div class="thumb-icon player-stats"><img src="/static/img/icon-eye.svg" alt="views icon"><span> ${ videoViews } </span> ` ;
if ( videoData . data . stats . like _count ) {
var likes = formatNumbers ( videoData . data . stats . like _count ) ;
playerStats += ` <span>|</span><img src="/static/img/icon-thumb.svg" alt="thumbs-up"><span> ${ likes } </span> ` ;
}
if (
videoData . data . stats . dislike _count &&
videoData . config . downloads . integrate _ryd
) {
var dislikes = formatNumbers ( videoData . data . stats . dislike _count ) ;
playerStats += ` <span>|</span><img class="dislike" src="/static/img/icon-thumb.svg" alt="thumbs-down"><span> ${ dislikes } </span> ` ;
}
playerStats += "</div>" ;
const markup = `
2022-04-03 00:26:53 +00:00
< div class = "video-player" data - id = "${videoId}" >
$ { videoTag }
< div class = "player-title boxed-content" >
< img class = "close-button" src = "/static/img/icon-close.svg" alt = "close-icon" data = "${videoId}" onclick = "removePlayer()" title = "Close player" >
$ { watchStatusIndicator }
$ { castButton }
$ { playerStats }
< div class = "player-channel-playlist" >
< h3 > < a href = "/channel/${channelId}/" > $ { channelName } < / a > < / h 3 >
$ { playlist }
< / d i v >
< a href = "/video/${videoId}/" > < h2 id = "video-title" > $ { videoName } < / h 2 > < / a >
< / d i v >
< / d i v >
` ;
2022-04-06 18:48:12 +00:00
const divPlayer = document . getElementById ( "player" ) ;
divPlayer . innerHTML = markup ;
2022-04-03 00:26:53 +00:00
}
// Add video tag to video page when passed a video id, function loaded on page load `video.html (115-117)`
function insertVideoTag ( videoData , videoProgress ) {
2022-04-06 18:48:12 +00:00
var videoTag = createVideoTag ( videoData , videoProgress ) ;
var videoMain = document . getElementsByClassName ( "video-main" ) ;
videoMain [ 0 ] . innerHTML = videoTag ;
2022-04-03 00:26:53 +00:00
}
// Generates a video tag with subtitles when passed videoData and videoProgress.
function createVideoTag ( videoData , videoProgress ) {
2022-04-06 18:48:12 +00:00
var videoId = videoData . data . youtube _id ;
var videoUrl = videoData . data . media _url ;
var videoThumbUrl = videoData . data . vid _thumb _url ;
var subtitles = "" ;
var videoSubtitles = videoData . data . subtitles ; // Array of subtitles
if (
typeof videoSubtitles != "undefined" &&
videoData . config . downloads . subtitle
) {
for ( var i = 0 ; i < videoSubtitles . length ; i ++ ) {
let label = videoSubtitles [ i ] . name ;
if ( videoSubtitles [ i ] . source == "auto" ) {
label += " - auto" ;
}
subtitles += ` <track label=" ${ label } " kind="subtitles" srclang=" ${ videoSubtitles [ i ] . lang } " src=" ${ videoSubtitles [ i ] . media _url } "> ` ;
}
}
var videoTag = `
2022-04-03 00:26:53 +00:00
< video poster = "${videoThumbUrl}" ontimeupdate = "onVideoProgress()" onpause = "onVideoPause()" onended = "onVideoEnded()" controls autoplay width = "100%" playsinline id = "video-item" >
< source src = "${videoUrl}#t=${videoProgress}" type = "video/mp4" id = "video-source" videoid = "${videoId}" >
$ { subtitles }
< / v i d e o >
` ;
2022-04-06 18:48:12 +00:00
return videoTag ;
2022-04-03 00:26:53 +00:00
}
// Gets video tag
function getVideoPlayer ( ) {
2022-04-06 18:48:12 +00:00
var videoElement = document . getElementById ( "video-item" ) ;
return videoElement ;
2022-04-03 00:26:53 +00:00
}
// Gets the video source tag
function getVideoPlayerVideoSource ( ) {
2022-04-06 18:48:12 +00:00
var videoPlayerVideoSource = document . getElementById ( "video-source" ) ;
return videoPlayerVideoSource ;
2022-04-03 00:26:53 +00:00
}
// Gets the current progress of the video currently in the player
function getVideoPlayerCurrentTime ( ) {
2022-04-06 18:48:12 +00:00
var videoElement = getVideoPlayer ( ) ;
if ( videoElement != null ) {
return videoElement . currentTime ;
}
2022-04-03 00:26:53 +00:00
}
// Gets the video id of the video currently in the player
function getVideoPlayerVideoId ( ) {
2022-04-06 18:48:12 +00:00
var videoPlayerVideoSource = getVideoPlayerVideoSource ( ) ;
if ( videoPlayerVideoSource != null ) {
return videoPlayerVideoSource . getAttribute ( "videoid" ) ;
}
2022-04-03 00:26:53 +00:00
}
// Gets the duration of the video currently in the player
function getVideoPlayerDuration ( ) {
2022-04-06 18:48:12 +00:00
var videoElement = getVideoPlayer ( ) ;
if ( videoElement != null ) {
return videoElement . duration ;
}
2022-04-03 00:26:53 +00:00
}
// Gets current watch status of video based on watch button
function getVideoPlayerWatchStatus ( ) {
2022-04-06 18:48:12 +00:00
var videoId = getVideoPlayerVideoId ( ) ;
var watched = false ;
var watchButtons = document . getElementsByClassName ( "watch-button" ) ;
for ( let i = 0 ; i < watchButtons . length ; i ++ ) {
if (
watchButtons [ i ] . getAttribute ( "data-id" ) == videoId &&
watchButtons [ i ] . getAttribute ( "data-status" ) == "watched"
) {
watched = true ;
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
return watched ;
2022-04-03 00:26:53 +00:00
}
// Runs on video playback, marks video as watched if video gets to 90% or higher, sends position to api
function onVideoProgress ( ) {
2022-04-06 18:48:12 +00:00
var videoId = getVideoPlayerVideoId ( ) ;
var currentTime = getVideoPlayerCurrentTime ( ) ;
var duration = getVideoPlayerDuration ( ) ;
if ( ( currentTime % 10 ) . toFixed ( 1 ) <= 0.2 ) {
// Check progress every 10 seconds or else progress is checked a few times a second
postVideoProgress ( videoId , currentTime ) ;
if ( ! getVideoPlayerWatchStatus ( ) ) {
// Check if video is already marked as watched
if ( watchedThreshold ( currentTime , duration ) ) {
updateVideoWatchStatus ( videoId , "unwatched" ) ;
}
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
2022-04-03 00:26:53 +00:00
}
// Runs on video end, marks video as watched
function onVideoEnded ( ) {
2022-04-06 18:48:12 +00:00
var videoId = getVideoPlayerVideoId ( ) ;
if ( ! getVideoPlayerWatchStatus ( ) ) {
// Check if video is already marked as watched
updateVideoWatchStatus ( videoId , "unwatched" ) ;
}
2022-04-03 00:26:53 +00:00
}
function watchedThreshold ( currentTime , duration ) {
2022-04-06 18:48:12 +00:00
var watched = false ;
if ( duration <= 1800 ) {
// If video is less than 30 min
if ( currentTime / duration >= 0.9 ) {
// Mark as watched at 90%
var watched = true ;
}
} else {
// If video is more than 30 min
if ( currentTime >= duration - 120 ) {
// Mark as watched if there is two minutes left
var watched = true ;
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
return watched ;
2022-04-03 00:26:53 +00:00
}
// Runs on video pause. Sends current position.
function onVideoPause ( ) {
2022-04-06 18:48:12 +00:00
var videoId = getVideoPlayerVideoId ( ) ;
var currentTime = getVideoPlayerCurrentTime ( ) ;
postVideoProgress ( videoId , currentTime ) ;
2022-04-03 00:26:53 +00:00
}
// Format numbers for frontend
function formatNumbers ( number ) {
2022-04-06 18:48:12 +00:00
var numberUnformatted = parseFloat ( number ) ;
if ( numberUnformatted > 999999999 ) {
var numberFormatted =
( numberUnformatted / 1000000000 ) . toFixed ( 1 ) . toString ( ) + "B" ;
} else if ( numberUnformatted > 999999 ) {
var numberFormatted =
( numberUnformatted / 1000000 ) . toFixed ( 1 ) . toString ( ) + "M" ;
} else if ( numberUnformatted > 999 ) {
var numberFormatted =
( numberUnformatted / 1000 ) . toFixed ( 1 ) . toString ( ) + "K" ;
} else {
var numberFormatted = numberUnformatted ;
}
return numberFormatted ;
2022-04-03 00:26:53 +00:00
}
// Gets video data when passed video ID
function getVideoData ( videoId ) {
2022-04-06 18:48:12 +00:00
var apiEndpoint = "/api/video/" + videoId + "/" ;
var videoData = apiRequest ( apiEndpoint , "GET" ) ;
return videoData ;
2022-04-03 00:26:53 +00:00
}
// Gets channel data when passed channel ID
function getChannelData ( channelId ) {
2022-04-06 18:48:12 +00:00
var apiEndpoint = "/api/channel/" + channelId + "/" ;
var channelData = apiRequest ( apiEndpoint , "GET" ) ;
return channelData . data ;
2022-04-03 00:26:53 +00:00
}
// Gets playlist data when passed playlist ID
function getPlaylistData ( playlistId ) {
2022-04-06 18:48:12 +00:00
var apiEndpoint = "/api/playlist/" + playlistId + "/" ;
var playlistData = apiRequest ( apiEndpoint , "GET" ) ;
return playlistData . data ;
2022-04-03 00:26:53 +00:00
}
// Get video progress data when passed video ID
function getVideoProgress ( videoId ) {
2022-04-06 18:48:12 +00:00
var apiEndpoint = "/api/video/" + videoId + "/progress/" ;
var videoProgress = apiRequest ( apiEndpoint , "GET" ) ;
return videoProgress ;
2022-04-03 00:26:53 +00:00
}
// Given an array of playlist ids it returns an array of subbed playlist ids from that list
function getSubbedPlaylists ( videoPlaylists ) {
2022-04-06 18:48:12 +00:00
var subbedPlaylists = [ ] ;
for ( var i = 0 ; i < videoPlaylists . length ; i ++ ) {
if ( getPlaylistData ( videoPlaylists [ i ] ) . playlist _subscribed ) {
subbedPlaylists . push ( videoPlaylists [ i ] ) ;
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
return subbedPlaylists ;
2022-04-03 00:26:53 +00:00
}
// Send video position when given video id and progress in seconds
function postVideoProgress ( videoId , videoProgress ) {
2022-04-06 18:48:12 +00:00
var apiEndpoint = "/api/video/" + videoId + "/progress/" ;
var duartion = getVideoPlayerDuration ( ) ;
if ( ! isNaN ( videoProgress ) && duartion != "undefined" ) {
var data = {
position : videoProgress ,
} ;
if ( videoProgress == 0 ) {
apiRequest ( apiEndpoint , "DELETE" ) ;
// console.log("Deleting Video Progress for Video ID: " + videoId + ", Progress: " + videoProgress);
} else if ( ! getVideoPlayerWatchStatus ( ) ) {
apiRequest ( apiEndpoint , "POST" , data ) ;
// console.log("Saving Video Progress for Video ID: " + videoId + ", Progress: " + videoProgress);
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
2022-04-03 00:26:53 +00:00
}
// Makes api requests when passed an endpoint and method ("GET", "POST", "DELETE")
function apiRequest ( apiEndpoint , method , data ) {
2022-04-06 18:48:12 +00:00
const xhttp = new XMLHttpRequest ( ) ;
var sessionToken = getCookie ( "sessionid" ) ;
xhttp . open ( method , apiEndpoint , false ) ;
xhttp . setRequestHeader ( "X-CSRFToken" , getCookie ( "csrftoken" ) ) ; // Used for video progress POST requests
xhttp . setRequestHeader ( "Authorization" , "Token " + sessionToken ) ;
xhttp . setRequestHeader ( "Content-Type" , "application/json" ) ;
xhttp . send ( JSON . stringify ( data ) ) ;
return JSON . parse ( xhttp . responseText ) ;
2022-04-03 00:26:53 +00:00
}
// Gets origin URL
function getURL ( ) {
2022-04-06 18:48:12 +00:00
return window . location . origin ;
2022-04-03 00:26:53 +00:00
}
function removePlayer ( ) {
2022-04-06 18:48:12 +00:00
var currentTime = getVideoPlayerCurrentTime ( ) ;
var duration = getVideoPlayerDuration ( ) ;
var videoId = getVideoPlayerVideoId ( ) ;
postVideoProgress ( videoId , currentTime ) ;
setProgressBar ( videoId , currentTime , duration ) ;
var playerElement = document . getElementById ( "player" ) ;
if ( playerElement . hasChildNodes ( ) ) {
var youtubeId = playerElement . childNodes [ 1 ] . getAttribute ( "data-id" ) ;
var playedStatus = document . createDocumentFragment ( ) ;
var playedBox = document . getElementById ( youtubeId ) ;
if ( playedBox ) {
playedStatus . appendChild ( playedBox ) ;
}
playerElement . innerHTML = "" ;
// append played status
var videoInfo = document . getElementById ( "video-info-" + youtubeId ) ;
videoInfo . insertBefore ( playedStatus , videoInfo . firstChild ) ;
}
2022-04-03 00:26:53 +00:00
}
// Sets the progress bar when passed a video id, video progress and video duration
function setProgressBar ( videoId , currentTime , duration ) {
2022-04-06 18:48:12 +00:00
var progressBarWidth = ( currentTime / duration ) * 100 + "%" ;
var progressBars = document . getElementsByClassName ( "video-progress-bar" ) ;
for ( let i = 0 ; i < progressBars . length ; i ++ ) {
if ( progressBars [ i ] . id == "progress-" + videoId ) {
if ( ! getVideoPlayerWatchStatus ( ) ) {
progressBars [ i ] . style . width = progressBarWidth ;
} else {
progressBars [ i ] . style . width = "0%" ;
}
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
2022-04-03 00:26:53 +00:00
2022-04-06 18:48:12 +00:00
// progressBar = document.getElementById("progress-" + videoId);
2022-04-03 00:26:53 +00:00
}
// multi search form
function searchMulti ( query ) {
2022-04-06 18:48:12 +00:00
if ( query . length > 1 ) {
var payload = JSON . stringify ( { multi _search : query } ) ;
var http = new XMLHttpRequest ( ) ;
http . onreadystatechange = function ( ) {
if ( http . readyState === 4 ) {
allResults = JSON . parse ( http . response ) . results ;
populateMultiSearchResults ( allResults ) ;
}
} ;
http . open ( "POST" , "/process/" , true ) ;
http . setRequestHeader ( "X-CSRFToken" , getCookie ( "csrftoken" ) ) ;
http . setRequestHeader ( "Content-type" , "application/json" ) ;
http . send ( payload ) ;
}
2022-04-03 00:26:53 +00:00
}
function getViewDefaults ( view ) {
2022-04-06 18:48:12 +00:00
var defaultView = document . getElementById ( "id_" + view ) . value ;
return defaultView ;
2022-04-03 00:26:53 +00:00
}
function populateMultiSearchResults ( allResults ) {
2022-04-06 18:48:12 +00:00
// videos
var defaultVideo = getViewDefaults ( "home" ) ;
var allVideos = allResults . video _results ;
var videoBox = document . getElementById ( "video-results" ) ;
videoBox . innerHTML = "" ;
for ( let index = 0 ; index < allVideos . length ; index ++ ) {
const video = allVideos [ index ] . source ;
const videoDiv = createVideo ( video , defaultVideo ) ;
videoBox . appendChild ( videoDiv ) ;
}
// channels
var defaultChannel = getViewDefaults ( "channel" ) ;
var allChannels = allResults . channel _results ;
var channelBox = document . getElementById ( "channel-results" ) ;
channelBox . innerHTML = "" ;
for ( let index = 0 ; index < allChannels . length ; index ++ ) {
const channel = allChannels [ index ] . source ;
const channelDiv = createChannel ( channel , defaultChannel ) ;
channelBox . appendChild ( channelDiv ) ;
}
// playlists
var defaultPlaylist = getViewDefaults ( "playlist" ) ;
var allPlaylists = allResults . playlist _results ;
var playlistBox = document . getElementById ( "playlist-results" ) ;
playlistBox . innerHTML = "" ;
for ( let index = 0 ; index < allPlaylists . length ; index ++ ) {
const playlist = allPlaylists [ index ] . source ;
const playlistDiv = createPlaylist ( playlist , defaultPlaylist ) ;
playlistBox . appendChild ( playlistDiv ) ;
}
2022-04-03 00:26:53 +00:00
}
function createVideo ( video , viewStyle ) {
2022-04-06 18:48:12 +00:00
// create video item div from template
const videoId = video . youtube _id ;
const mediaUrl = video . media _url ;
const thumbUrl = "/cache/" + video . vid _thumb _url ;
const videoTitle = video . title ;
const videoPublished = video . published ;
const videoDuration = video . player . duration _str ;
if ( video . player . watched ) {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "watched" ) ;
} else {
var watchStatusIndicator = createWatchStatusIndicator ( videoId , "unwatched" ) ;
}
const channelId = video . channel . channel _id ;
const channelName = video . channel . channel _name ;
// build markup
const markup = `
2022-04-03 00:26:53 +00:00
< a href = "#player" data - src = "/media/${mediaUrl}" data - thumb = "${thumbUrl}" data - title = "${videoTitle}" data - channel = "${channelName}" data - channel - id = "${channelId}" data - id = "${videoId}" onclick = "createPlayer(this)" >
< div class = "video-thumb-wrap ${viewStyle}" >
< div class = "video-thumb" >
< img src = "${thumbUrl}" alt = "video-thumb" >
< / d i v >
< div class = "video-play" >
< img src = "/static/img/icon-play.svg" alt = "play-icon" >
< / d i v >
< / d i v >
< / a >
< div class = "video-desc ${viewStyle}" >
< div class = "video-desc-player" id = "video-info-${videoId}" >
$ { watchStatusIndicator }
< span > $ { videoPublished } | $ { videoDuration } < / s p a n >
< / d i v >
< div >
< a href = "/channel/${channelId}/" > < h3 > $ { channelName } < / h 3 > < / a >
< a class = "video-more" href = "/video/${videoId}/" > < h2 > $ { videoTitle } < / h 2 > < / a >
< / d i v >
< / d i v >
` ;
2022-04-06 18:48:12 +00:00
const videoDiv = document . createElement ( "div" ) ;
videoDiv . setAttribute ( "class" , "video-item " + viewStyle ) ;
videoDiv . innerHTML = markup ;
return videoDiv ;
2022-04-03 00:26:53 +00:00
}
function createChannel ( channel , viewStyle ) {
2022-04-06 18:48:12 +00:00
// create channel item div from template
const channelId = channel . channel _id ;
const channelName = channel . channel _name ;
const channelSubs = channel . channel _subs ;
const channelLastRefresh = channel . channel _last _refresh ;
if ( channel . channel _subscribed ) {
var button = ` <button class="unsubscribe" type="button" id=" ${ channelId } " onclick="unsubscribe(this.id)" title="Unsubscribe from ${ channelName } ">Unsubscribe</button> ` ;
} else {
var button = ` <button type="button" id=" ${ channelId } " onclick="subscribe(this.id)" title="Subscribe to ${ channelName } ">Subscribe</button> ` ;
}
// build markup
const markup = `
2022-04-03 00:26:53 +00:00
< div class = "channel-banner ${viewStyle}" >
< a href = "/channel/${channelId}/" >
< img src = "/cache/channels/${channelId}_banner.jpg" alt = "${channelId}-banner" >
< / a >
< / d i v >
< div class = "info-box info-box-2 ${viewStyle}" >
< div class = "info-box-item" >
< div class = "round-img" >
< a href = "/channel/${channelId}/" >
< img src = "/cache/channels/${channelId}_thumb.jpg" alt = "channel-thumb" >
< / a >
< / d i v >
< div >
< h3 > < a href = "/channel/${channelId}/" > $ { channelName } < / a > < / h 3 >
< p > Subscribers : $ { channelSubs } < / p >
< / d i v >
< / d i v >
< div class = "info-box-item" >
< div >
< p > Last refreshed : $ { channelLastRefresh } < / p >
$ { button }
< / d i v >
< / d i v >
< / d i v >
` ;
2022-04-06 18:48:12 +00:00
const channelDiv = document . createElement ( "div" ) ;
channelDiv . setAttribute ( "class" , "channel-item " + viewStyle ) ;
channelDiv . innerHTML = markup ;
return channelDiv ;
2022-04-03 00:26:53 +00:00
}
function createPlaylist ( playlist , viewStyle ) {
2022-04-06 18:48:12 +00:00
// create playlist item div from template
const playlistId = playlist . playlist _id ;
const playlistName = playlist . playlist _name ;
const playlistChannelId = playlist . playlist _channel _id ;
const playlistChannel = playlist . playlist _channel ;
const playlistLastRefresh = playlist . playlist _last _refresh ;
if ( playlist . playlist _subscribed ) {
var button = ` <button class="unsubscribe" type="button" id=" ${ playlistId } " onclick="unsubscribe(this.id)" title="Unsubscribe from ${ playlistName } ">Unsubscribe</button> ` ;
} else {
var button = ` <button type="button" id=" ${ playlistId } " onclick="subscribe(this.id)" title="Subscribe to ${ playlistName } ">Subscribe</button> ` ;
}
const markup = `
2022-04-03 00:26:53 +00:00
< div class = "playlist-thumbnail" >
< a href = "/playlist/${playlistId}/" >
< img src = "/cache/playlists/${playlistId}.jpg" alt = "${playlistId}-thumbnail" >
< / a >
< / d i v >
< div class = "playlist-desc ${viewStyle}" >
< a href = "/channel/${playlistChannelId}/" > < h3 > $ { playlistChannel } < / h 3 > < / a >
< a href = "/playlist/${playlistId}/" > < h2 > $ { playlistName } < / h 2 > < / a >
< p > Last refreshed : $ { playlistLastRefresh } < / p >
$ { button }
< / d i v >
` ;
2022-04-06 18:48:12 +00:00
const playlistDiv = document . createElement ( "div" ) ;
playlistDiv . setAttribute ( "class" , "playlist-item " + viewStyle ) ;
playlistDiv . innerHTML = markup ;
return playlistDiv ;
2022-04-03 00:26:53 +00:00
}
// generic
function sendPost ( payload ) {
2022-04-06 18:48:12 +00:00
var http = new XMLHttpRequest ( ) ;
http . open ( "POST" , "/process/" , true ) ;
http . setRequestHeader ( "X-CSRFToken" , getCookie ( "csrftoken" ) ) ;
http . setRequestHeader ( "Content-type" , "application/json" ) ;
http . send ( payload ) ;
2022-04-03 00:26:53 +00:00
}
function getCookie ( c _name ) {
2022-04-06 18:48:12 +00:00
if ( document . cookie . length > 0 ) {
c _start = document . cookie . indexOf ( c _name + "=" ) ;
if ( c _start != - 1 ) {
c _start = c _start + c _name . length + 1 ;
c _end = document . cookie . indexOf ( ";" , c _start ) ;
if ( c _end == - 1 ) c _end = document . cookie . length ;
return unescape ( document . cookie . substring ( c _start , c _end ) ) ;
2022-04-03 00:26:53 +00:00
}
2022-04-06 18:48:12 +00:00
}
return "" ;
2022-04-03 00:26:53 +00:00
}
// animations
function textReveal ( ) {
2022-04-06 18:48:12 +00:00
var textBox = document . getElementById ( "text-reveal" ) ;
var button = document . getElementById ( "text-reveal-button" ) ;
var textBoxHeight = textBox . style . height ;
if ( textBoxHeight === "unset" ) {
textBox . style . height = "0px" ;
button . innerText = "Show" ;
} else {
textBox . style . height = "unset" ;
button . innerText = "Hide" ;
}
2022-04-03 00:26:53 +00:00
}
function showForm ( ) {
2022-04-06 18:48:12 +00:00
var formElement = document . getElementById ( "hidden-form" ) ;
var displayStyle = formElement . style . display ;
if ( displayStyle === "" ) {
formElement . style . display = "block" ;
} else {
formElement . style . display = "" ;
}
animate ( "animate-icon" , "pulse-img" ) ;
2022-04-03 00:26:53 +00:00
}
function showOverwrite ( ) {
2022-04-06 18:48:12 +00:00
var overwriteDiv = document . getElementById ( "overwrite-form" ) ;
if ( overwriteDiv . classList . contains ( "hidden-overwrite" ) ) {
overwriteDiv . classList . remove ( "hidden-overwrite" ) ;
} else {
overwriteDiv . classList . add ( "hidden-overwrite" ) ;
}
2022-04-03 00:26:53 +00:00
}
function animate ( elementId , animationClass ) {
2022-04-06 18:48:12 +00:00
var toAnimate = document . getElementById ( elementId ) ;
if ( toAnimate . className !== animationClass ) {
toAnimate . className = animationClass ;
} else {
toAnimate . classList . remove ( animationClass ) ;
}
2022-04-03 00:26:53 +00:00
}