106 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // -*- tab-width: 4; js-indent-level: 4; -*-
 | |
| // ==UserScript==
 | |
| // @name         Trakt Show Picker
 | |
| // @namespace    danielrayjones
 | |
| // @version      0.0.9
 | |
| // @description  Pick a show from progress page
 | |
| // @author       Dan Jones
 | |
| // @match        https://trakt.tv/users/*/progress*
 | |
| // @grant        none
 | |
| // @require      https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js
 | |
| // ==/UserScript==
 | |
| 
 | |
| /* global $, compressedCache, localStorage, MutationObserver */
 | |
| /* jshint esversion: 6 */
 | |
| 
 | |
| (function() {
 | |
|     'use strict';
 | |
| 
 | |
|     $(window).konami({
 | |
|         code: [80, 73, 67, 75],
 | |
|         cheat: pickShow
 | |
|     });
 | |
| 
 | |
|     function unghost() {
 | |
|         $(this).removeClass('sortable-ghost');
 | |
|     }
 | |
| 
 | |
|     function addPickButton() {
 | |
|         const $leftNav = $('.subnav-wrapper .container .left');
 | |
|         const $found = $leftNav.find('.pick-episode');
 | |
|         if (!$found.length) {
 | |
|             $leftNav.append('<span class="filter-dropdown toggle-simple-progress pick-episode" title="Pick Episode"><span class="icon trakt-icon-wand"></span></span>')
 | |
|                 .find('.pick-episode').on('click', pickShow);
 | |
|         }
 | |
| 
 | |
|         $('div[data-type="show"]').on('click', unghost);
 | |
|     }
 | |
|     addPickButton();
 | |
|     const observer = new MutationObserver(addPickButton);
 | |
|     observer.observe(document.head.parentElement, {childList: true});
 | |
| 
 | |
|     let watched_shows;
 | |
| 
 | |
|     function getWeightedIndex(total) {
 | |
|         const opts = [];
 | |
|         for ( let idx = 0; idx < total; idx++) {
 | |
|             for (let idxInst = 0; idxInst < total - idx; idxInst++) {
 | |
|                 opts.push(idx);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         const totalWeights = opts.length;
 | |
|         const which = Math.floor(Math.random() * totalWeights);
 | |
| 
 | |
|         return opts[which];
 | |
|     }
 | |
| 
 | |
|     function pickShow() {
 | |
| 
 | |
|         if ('compressedCache' in window) {
 | |
|             watched_shows = compressedCache.get('watched_shows');
 | |
|         } else {
 | |
|             watched_shows = JSON.parse(localStorage.watched_shows);
 | |
|         }
 | |
| 
 | |
|         let $shows = $('div[data-type="show"]');
 | |
|         $shows.removeClass('sortable-ghost');
 | |
|         $shows = filterShows($shows);
 | |
| 
 | |
|         let picked = getWeightedIndex($shows.length);
 | |
|         let $picked = $shows.eq(picked);
 | |
| 
 | |
|         $shows.addClass('sortable-ghost');
 | |
|         $picked.removeClass('sortable-ghost').insertAfter($picked.parent().find('.pagination-top'));
 | |
| 
 | |
|     }
 | |
| 
 | |
|     function filterShows($shows) {
 | |
| 
 | |
|         // Milliseconds in two days
 | |
|         const twoDays = 2 * 24 * 60 * 60 * 1000;
 | |
|         const twoDaysAgo = (new Date()) - twoDays;
 | |
| 
 | |
|         $shows.each(function (i, show) {
 | |
| 
 | |
|             const showId = Number.parseInt(show.dataset.showId);
 | |
|             const showInfo = watched_shows[showId];
 | |
|             if (!showInfo) return;
 | |
| 
 | |
|             const lastWatch = showInfo.ts*1000;
 | |
|             // Skip ones we've watched in the last two days
 | |
|             if (lastWatch > twoDaysAgo) {
 | |
|                 show.classList.add('sortable-ghost');
 | |
|             }
 | |
| 
 | |
|             const percentage = show.dataset.percentage;
 | |
| 
 | |
|             if (percentage == 100) {
 | |
|                 show.classList.add('sortable-ghost');
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         return $shows.filter(':not(.sortable-ghost)');
 | |
|     }
 | |
| 
 | |
| })();
 |