CryptalEquine / Flinders Lecture Downloader

// ==UserScript==
// @name          Flinders Lecture Downloader
// @namespace     fld
// @description   Creates a download link for direct video files. Right click and Save As to save the video file itself.
// @license       MIT
// @include       *flo.flinders.edu.au/mod/*
// @include       *flex.flinders.edu.au/items/*
// @include       *drnajeeblectures.com*
// @include       *lecturio.com*
// @require       https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
// @require       https://gist.githubusercontent.com/BrockA/2625891/raw/9c97aa67ff9c5d56be34a55ad6c18a314e5eb548/waitForKeyElements.js
// @version       1.0.13
// @run-at 		   document-end
// @noframes	   true
// @grant         unsafeWindow
// @grant    	   GM_log
// @updateURL     https://openuserjs.org/meta/CryptalEquine/Flinders_Lecture_Downloader.meta.js
// ==/UserScript==


// Helper functions
String.prototype.contains = function(e) { return this.indexOf(e) > -1; };



// FLINDERS: Regular lecture page
if (location.href.contains('flo.flinders.edu.au/mod/lecture/'))
{
   var _found = false;
   
   waitForKeyElements("div[id*='flindersmedia-']", function(e)
   {
      if (_found) return;
      _found = true;
      
      var infoScript = $("body").html().match(/(Y.use\(\'mod_lecture)([A-Za-z0-9\'\,\ \(\)\{\}\\n\\r\n\.\_\"\-]+)/g)[0];
      
      var videoID = infoScript.match(/[0-9]+/g)[0] || null;
      var year = infoScript.match(/[0-9]+/g)[2] || null;
      
      if (videoID && year)
      {
         var topicCode = $('h3.flindersmedia').text().trim() || '';
         var courseName = $('h3.coursetitle').text().trim() || '';
         var courseTitle = $('#page-navbar').find('ul.breadcrumb').find("a[title='" + courseName + "']").text().trim() || '';
         
         var l1 = 'Lecture recording - ';
         var l2 = 'Lecture recording: ';
         var title = document.title.replace(courseTitle + ': ', '').replace(l1, '').replace(l2, '').trim() || '';
         title = title.replace(/[\\\/\:\*\?\"<>\|\;\{\}\^\%\#\@\!\-]/gi, '_').replace(/ /g, '_');
         title = year + '_' + topicCode + '_' + title.replace(/[\_]{2,}/g, '');
         if (!title.contains('.mp4'))
            title = title + '.mp4';
         
         if ($("#flindersmedia-podcast").length > 0)
            $("#flindersmedia-podcast").append('<br><a download="' + title + '" style="font-size: 16pt;" id="downloadVideoFile">Direct video file link</a>');
         else
            $("div[id*='flindersmedia-']").parent().append('<br><a download="' + title + '" style="font-size: 16pt;" id="downloadVideoFile">Direct video file link</a>');
         $("#downloadVideoFile").attr('href', 'http://video.flinders.edu.au/videodl' + year + '/' + videoID + '_adsl.mp4');
      }
   }, true);
}


// FLINDERS: Weird Flex HTML5 video page
if (location.href.contains('flex.flinders.edu.au/items/'))
{
   waitForKeyElements("#html5player_html5_api", function(e)
   {
      var videoID = e.find("source").attr('src') || null;
      
      if (videoID)
      {
         $("#player-container").append('<br><br><a id="downloadVideoFile">Direct video file link</a>');
         $("#downloadVideoFile").attr('href', videoID);
      }
      
   }, true);
}


// FLINDERS: Even weirder pre-recorded stream-type video
if (location.href.contains('flo.flinders.edu.au/mod/page/view.php'))
{
   waitForKeyElements("object[id='mediaspace']", function(e)
   {
      var infoScript = e.parents('#playback').find("script:contains('.mp4')");
      var imageUrl = infoScript.html().match(/\'image\'\:\s*\'([a-zA-Z0-9\:\_\/\.\(\)]+)/g)[0]
                        .replace(/ /g, '').replace("'image':'", '') || null;
      var videoName = infoScript.html().match(/[a-zA-Z0-9\_\&\.]+\.(mp4)/g)[0] || null;
      var videoID = imageUrl.replace(/[a-zA-Z0-9]+\.((png)|(jpg))/g, videoName) || null;
      
      var videoTitle = $("#region-main").find('h2').html().replace('Lecture recording:', '').trim() + '.mp4';
      
      if (videoID)
      {
         var style = 'color: blue; font-size: 20pt;';
         $("#playback").append('<br><br><a download="' + videoTitle + '" id="downloadVideoFile" style="' + style + '">Direct video file link</a>');
         $("#downloadVideoFile").attr('href', videoID);
      }
      
   }, true);
}



// Dr Najeeb Videos
waitForKeyElements("video.rmp", function(e)
{
   var videoID = e.attr('src') || null;
   
   if (videoID)
   {
      $("video.rmp").parent().parent().parent().append('<br><br><a id="downloadVideoFile">Direct video file link</a>');
      $("#downloadVideoFile").attr('href', videoID);
   }
}, true);



// Lecturio Videos
if (location.href.contains('lecturio.com'))
{
   waitForKeyElements("#lecturio_player_media video", function(e)
   {
      var videoID = e.attr('src') || null;
      var title = $('h1.page-heading').contents().not($('h1.page-heading').children()).text().trim();
      
      if (videoID)
      {
         var downloadLinkElement = '<a download="' + title + '.mp4" id="downloadVideoFile">Direct video file link</a>';
         var videoLink = videoID.replace('500.mp4', '700.mp4'); //.match(/[A-Za-z0-9\-\:\\\/\.\_]+/g)[0] to get the non tokenised URL
         $('#lecture-player').append(downloadLinkElement);
         $("#downloadVideoFile").attr('href', videoLink);
      }
   }, true);
   
   var hasRun = false;
   
   waitForKeyElements("ul#course-content", function(e)
   {
      if (hasRun) return;
      hasRun = true;
      
      var subjectField = $( 'h1.header-course-title' ).eq( 0 ).attr( 'data-url' ).replace( '/medical-courses/', '' ).replace( '.course', '' ).trim();
      var videoFileLinks = [], jsonRequests = [];
      var videoLinks = $(e).find('li');
      var attempted = 0, done = 0;
      
      var subCategories = $( 'ul.curriculum-list' ).find( 'li' );
      
      for (var i = 0; i < videoLinks.length; i++)
      {
         var v = videoLinks.eq(i).attr('data-url').split('/').slice(-1)[0].replace('.lecture?autostart=1', '')
         videoFileLinks.push({ name: videoLinks.eq(i).find('a span').eq(0).text() });
         
         ( function(index) {
            attempted++;
            jsonRequests.push(
               $.ajax({
                  url: 'https://app.lecturio.com/api/en/v7/html5/course/' 
                        + subjectField + '/lecture/' + v.replace('.lecture', '') + '.json'
                  ,method: 'GET'
                  ,contentType: 'application/json'
               }).done( function(data)
               {
                  var fsName = ((index + 1) < 10 ? '0' : '') + (index + 1) + ' ' + videoFileLinks[index].name.replace(/\:/g, ' -');
                  fsName = fsName.trim();
                  
                  var dl = '<a style="padding-top: 4px;" download="' + fsName + '.mp4" id="dlvf' + index + '">Download video file (' + fsName + ')</a>';
                  videoLinks.eq(index).find("div[class*='js-progress-bar']").remove();
                  videoLinks.eq(index).append( dl );
                  $("#dlvf" + index).attr('href', data.content.media[1].file);
                  done++;
               })
            );
         } )( i );
      }
      
      function printList()
      {
         if ( done == videoLinks.length )
         {
            var _links = $( "a[id*='dlvf']" );
            var listing = '';
            var renaming = '';
            var directory = $( 'ol.breadcrumb' ).find( 'li' ).text().replace( /  /g, '' ).replace( 'Curriculum', '' ).trim().replace( /\n/g, '/' ).replace( /\/\//g, '\\' );
            
            for ( var i = 0; i < _links.length; i++ )
            {
               var _fn = _links.eq( i ).attr( 'href' ).match( /\/([\w\d\-\_]+)(\.mp4)/g )[ 0 ].replace( '/', '' );
               var _nfn = _links.eq( i ).attr( 'download' ).trim().replace( /\–|\û/g, '-' ).replace( /  /g, ' ' );
               listing += _links.eq( i ).attr( 'href' ) + '\r\n';
               renaming += 'ren ' + '"D:\\Downloads\\' + _fn + '" "' + _nfn + '"\r\n';
               renaming += 'echo f | xcopy "' + _nfn + '" "D:\\OneDrive\\Lecturio\\Video\\' + directory + '\\' + _nfn + '" /Q /R /Y\r\n';
               renaming += 'del /F /Q "' + _nfn + '"\r\n\r\n';
            }
            
            console.log( listing.trim() );
            console.log( renaming.trim() );
         }
         else
            setTimeout( printList, 500 );
      }
      
      setTimeout( printList, 500 );
      
   }, true);
}