diff --git a/amaz.giveaway.user.js b/amaz.giveaway.user.js index 7969356..3d3b308 100644 --- a/amaz.giveaway.user.js +++ b/amaz.giveaway.user.js @@ -4,59 +4,66 @@ // @description Allow removal of visited links on Amazon Giveaway Listing // @include https://smile.amazon.com/ga/giveaways* // @include https://www.amazon.com/ga/giveaways* -// @version 1.8.0 +// @version 1.9.2 // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js // ==/UserScript== -var checked = false; -var regex_hide; +/* global jQuery */ +/* jshint esversion: 6 */ -var getSmallUrl = function(fullUrl) { - return fullUrl.split('?')[0]; -}; +(function ($) { + 'use strict'; -var hideOne = function(el) { - $(el).parents('.giveawayItemContainer').css('display', checked ? 'none' : 'block'); -}; + var checked = false; + var regex_hide; -var hideVisited = function(evt) { - checked = $(this).prop('checked'); - var $links = $('#giveaway-grid a[href*="amazon.com/ga"]'); + var getSmallUrl = function(fullUrl) { + return fullUrl.split('?')[0]; + }; - var hide = regex_hide ? new RegExp(regex_hide, 'i') : null; + var hideOne = function(el) { + $(el).parents('.listing-item').css('display', checked ? 'none' : 'block'); + }; - $links.each(function() { - var href = getSmallUrl($(this).attr('href')); - if (localStorage.getItem(href)) { + var hideVisited = function(evt) { + checked = $(this).prop('checked'); + var $links = $('.listing-info-container a[href*="/ga"]'); + + var hide = regex_hide ? new RegExp(regex_hide, 'i') : null; + + $links.each(function() { + var href = getSmallUrl($(this).attr('href')); + if (localStorage.getItem(href)) { + hideOne(this); + } + + var title = $(this).find('.prize-title').text(); + if (hide && title && hide.test(title)) { + hideOne(this); + } + }); + }; + + $(document).ready(function() { + $('.listing-info-container').on('click', 'a[href*="/ga"]', function(evt) { + var href = getSmallUrl($(this).attr('href')); + localStorage[href] = "visited"; hideOne(this); - } + }); - var title = $(this).find('.giveawayPrizeNameContainer').text(); - if (hide && title && hide.test(title)) { - hideOne(this); - } - }); -}; + $('.listing-info-container a[href*="/ga"]').attr('target', '_blank'); -$(document).ready(function() { - $('head').append(''); + regex_hide = localStorage.getItem('regex_hide') || ''; - $('#giveaway-grid').on('click', 'a[href*="amazon.com/ga"]', function(evt) { + $('#giveaway-numbers-container') + .append('') + .append(``); - var href = getSmallUrl($(this).attr('href')); - localStorage[href] = "visited"; - hideOne(this); + $('#hide_visited').on('click', hideVisited); + $('#hide_regex').on('change', function() { + regex_hide = $(this).val(); + localStorage.regex_hide = regex_hide; + }); }); - regex_hide = localStorage.getItem('regex_hide') || ''; - - $('#giveaway-result-info-bar-content') - .append('') - .append(``); - - $('#hide_visited').on('click', hideVisited); - $('#hide_regex').on('change', function() { - regex_hide = $(this).val(); - localStorage.regex_hide = regex_hide; - }); -}); +})(jQuery); diff --git a/comicextra.user.js b/comicextra.user.js new file mode 100644 index 0000000..fe17dd5 --- /dev/null +++ b/comicextra.user.js @@ -0,0 +1,89 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name Comic Extra Scraper +// @namespace danielrayjones +// @version 0.0.6 +// @description Scrape comics from comicextra.com +// @author Dan Jones +// @match https://www.comicextra.com/* +// @grant none +// @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js +// @require https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js +// @require https://bowercdn.net/c/jszip-3.1.5/dist/jszip.min.js +// ==/UserScript== + +/* global jQuery, JSZip */ +/* jshint esversion: 6 */ + +console.log('will scrape comics'); + +(function($) { + 'use strict'; + + $(window).konami({ + code: [71,69,84], + cheat: getStuff + }); + + function getStuff() { + let i = 0; + + let path = location.pathname.split('/'); + let end = path.pop(); + while (!end && path.length) { + end = path.pop(); + } + + if (end !== 'full') { + alert('Must have the full comic'); + return; + } + + let chapter = path.pop(); + let match; + if ((match = chapter.match(/^chapter-([0-9]+)/))) { + chapter = match[1]; + } + + let name = path.pop(); + + console.log(`Getting ${name} ${chapter}`); + + let imgs = $('.chapter-main .chapter_img').toArray(); + console.log(imgs); + + let cbz = new JSZip(); + + function downloadCbz() { + cbz.generateAsync({type: 'blob'}) + .then(blob => { + let title = name.replace(/-/g, ' ') + ' ' + chapter; + + let $el = $(''); + $(document.body).append($el); + $el.attr('href', URL.createObjectURL(blob)); + $el.attr('download', `${title} (comicextra) (Danjones).cbz`); + $el.get(0).click(); + }); + } + + function getOne() { + if (!imgs || !imgs.length) { + downloadCbz(); + return; + } + + let img = imgs.shift(); + console.log(img.src); + + fetch(`//cors-anywhere.herokuapp.com/${img.src}`).then(resp => resp.blob()).then(blob => { + cbz.file(name + '-' + (i < 10 ? '00' : '0' ) + i + '.jpg', blob); + + i = i+1; + setTimeout(getOne, 0); + }); + } + + getOne(); + } +})(jQuery); diff --git a/cookie.clicker.user.js b/cookie.clicker.user.js new file mode 100644 index 0000000..27dbfe5 --- /dev/null +++ b/cookie.clicker.user.js @@ -0,0 +1,45 @@ +// ==UserScript== +// @name Auto Cookie Clicker +// @namespace danielrayjones +// @description Plays Cookie Clicker for you +// @include http://orteil.dashnet.org/cookieclicker/ +// @version 0.0.4 +// ==/UserScript== + +/* jshint esversion: 6 */ + +let AutoClicker = {stop: false}; +unsafeWindow.AutoClicker = AutoClicker; + +window.addEventListener('load', function () { + 'use strict'; + + let cookie = document.getElementById('bigCookie'); + let shimmers = document.getElementById('shimmers'); + + function clickCookie() { + AutoClicker.cookie.click(); + if (!AutoClicker.stop) { + setTimeout(clickCookie, 5); + } + } + + let shimmerObserver = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + mutation.addedNodes.forEach(function (shimmer) { + console.log('clicking', shimmer); + shimmer.click(); + }); + }); + }); + shimmerObserver.observe(shimmers, { childList: true}); + + AutoClicker.cookie = cookie; + AutoClicker.shimmers = shimmers; + AutoClicker.clickCookie = clickCookie; + AutoClicker.shimmerObserver = shimmerObserver; + + for (let i = 0; i < 20; i++) { + clickCookie(); + } +}); diff --git a/fullcomic.user.js b/fullcomic.user.js new file mode 100644 index 0000000..aa8cd87 --- /dev/null +++ b/fullcomic.user.js @@ -0,0 +1,85 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name Full Comic Scraper +// @namespace danielrayjones +// @version 0.0.5 +// @description Scrape comics from fullcomic.pro +// @author Dan Jones +// @match http://fullcomic.pro/* +// @grant none +// @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js +// @require https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js +// @require https://bowercdn.net/c/jszip-3.1.5/dist/jszip.min.js +// ==/UserScript== + +/* global jQuery, JSZip */ +/* jshint esversion: 6 */ + +console.log('will scrape comics'); + +(function($) { + 'use strict'; + + $(window).konami({ + code: [71,69,84], + cheat: getStuff + }); + + function getStuff() { + let i = 0; + + let title = $('.title h1').text(); + + let regex = /Issue #([0-9]+)/; + let match; + if ((match = title.match(regex))) { + let issue = match[1]; + while (issue.length < 3) { + issue = '0' + issue; + } + + title = title.replace(regex, issue); + } + + console.log(`Getting ${title}`); + + let imgs = $('#imgPages img').toArray(); + console.log(imgs); + + let cbz = new JSZip(); + + function downloadCbz() { + cbz.generateAsync({type: 'blob'}) + .then(blob => { + let fileTitle = title.replace(/: /g, ' - '); + + let $el = $(''); + $(document.body).append($el); + $el.attr('href', URL.createObjectURL(blob)); + $el.attr('download', `${fileTitle} (fullcomic) (Danjones).cbz`); + $el.get(0).click(); + }); + } + + function getOne() { + if (!imgs || !imgs.length) { + downloadCbz(); + return; + } + + let img = imgs.shift(); + console.log(img.src); + + fetch(`//cors-anywhere.herokuapp.com/${img.src}`).then(resp => resp.blob()).then(blob => { + let name = title.replace(/[^A-Za-z0-9]+/g, '-'); + + cbz.file(name + '-' + (i < 10 ? '00' : '0' ) + i + '.jpg', blob); + + i = i+1; + setTimeout(getOne, 0); + }); + } + + getOne(); + } +})(jQuery); diff --git a/giveaway.hide.crap.user.js b/giveaway.hide.crap.user.js index 85ca0a6..6d8646c 100644 --- a/giveaway.hide.crap.user.js +++ b/giveaway.hide.crap.user.js @@ -3,11 +3,12 @@ // @namespace danielrayjones // @description Remove stuff I don't like from Amazon Giveaway Listing // @include https://giveawaylisting.com/ -// @version 1.0 +// @version 1.0.1 // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js // ==/UserScript== /* global $ */ +/* jshint esversion: 6 */ var hide = function(text) { $('#giveaways a:contains("' + text +'")') diff --git a/giveaway.user.js b/giveaway.user.js index a07fba6..406e7f2 100644 --- a/giveaway.user.js +++ b/giveaway.user.js @@ -3,10 +3,12 @@ // @namespace danielrayjones // @description Allow removal of visited links on Amazon Giveaway Listing // @include https://giveawaylisting.com/ -// @version 1.3 +// @version 1.3.1 // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js // ==/UserScript== +/* jshint esversion: 6 */ + var checked = false; var hideOne = function(el) { diff --git a/infinite-craft-plus.user.js b/infinite-craft-plus.user.js new file mode 100644 index 0000000..ec95fde --- /dev/null +++ b/infinite-craft-plus.user.js @@ -0,0 +1,143 @@ +// ==UserScript== +// @name Infinite Craft Plus +// @namespace danielrayjones +// @match https://neal.fun/infinite-craft/ +// @grant none +// @version 0.0.1 +// @author Dan Jones +// @description 2024-01-06T14:13:00-0500 +// ==/UserScript== + +/* global window, localStorage, FileReader */ + +(function () { + const key = "infinite-craft-data"; + + function getData() { + return localStorage.getItem(key); + } + + function downloadData() { + const data = getData(); + + const dl = document.createElement('a'); + dl.href = 'data:application/json,' + data; + dl.download = 'infinite-craft.json'; + + dl.click(); + } + + function getParsedData() { + return JSON.parse(getData()); + } + + function getElements() { + return getParsedData().elements; + } + + function overwriteElements(newElements) { + const data = getParsedData(); + const old = data.elements; + data.elements = newElements; + + localStorage.setItem(key, JSON.stringify(data)); + + return old; + } + + function addElements(newElements) { + const els = getElements(); + + for (let i = 0; i < newElements.length; i++) { + const newEl = newElements[i]; + const found = els.find(el => el.text === newEl.text); + if (found) { + continue; + } + + console.log('Adding', newEl); + + els.push(newEl); + } + + return overwriteElements(els); + } + + function uploadElements(evt) { + evt.preventDefault(); + const files = evt.target.uploads.files; + + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const read = new FileReader(); + read.addEventListener('load', function () { + const body = read.result; + const els = JSON.parse(body)?.elements; + addElements(els); + }); + read.readAsText(file); + } + + const sub = evt.target.lastChild; + sub.disabled = true; + sub.setAttribute('value', '✅'); + } + + function getUploadButton() { + const f = document.createElement('form'); + f.style.display = 'inline'; + + const ups = document.createElement('input'); + ups.setAttribute('type', 'file'); + ups.setAttribute('name', 'uploads'); + ups.setAttribute('accept', '.json'); + ups.setAttribute('required', true); + f.appendChild(ups); + + f.addEventListener('submit', uploadElements); + + const sub = document.createElement('input'); + sub.setAttribute('type', 'submit'); + sub.setAttribute('value', 'Upload'); + f.appendChild(sub); + + return f; + } + + function getDownloadButton() { + const butt = document.createElement('button'); + butt.innerText = '⤵️'; + butt.addEventListener('click', downloadData); + + return butt; + } + + function addButtons() { + const target = document.querySelector('.site-title')?.parentElement; + if (!target) { + console.log("Can't find .site-title"); + return null; + } + + const span = document.createElement('span'); + const down = getDownloadButton(); + const up = getUploadButton(); + span.appendChild(down); + span.appendChild(up); + + const next = target.nextElementSibling; + console.log('inserting', span, 'before', next); + target.style.display = 'none'; + + return target.parentElement.insertBefore(span, next); + } + + window.Game = window.Game || {}; + + window.Game.getData = getElements; + window.Game.download = downloadData; + + window.addEventListener('load', () => console.log(addButtons())); + +})(); + diff --git a/old-reddit-expando.user.js b/old-reddit-expando.user.js new file mode 100644 index 0000000..1eea2a4 --- /dev/null +++ b/old-reddit-expando.user.js @@ -0,0 +1,46 @@ +// ==UserScript== +// @name Old Reddit Image Expander +// @namespace danielrayjones +// @description Allow removal of visited links on Amazon Giveaway Listing +// @include https://old.reddit.com* +// @version 1.0.3 +// ==/UserScript== + +(function() { + const listing = document.getElementById('siteTable'); + + if (!listing) { + return; + } + + let para = document.createElement('p'); + let exButton = document.createElement('button'); + exButton.innerText = 'Expand'; + exButton = para.appendChild(exButton); + exButton.addEventListener('click', () => document.querySelectorAll('.expando-button.collapsed').forEach(e => e.click())); + + let deButton = document.createElement('button'); + deButton.innerText = 'Collapse'; + deButton = para.appendChild(deButton); + deButton.addEventListener('click', () => document.querySelectorAll('.expando-button.expanded').forEach(e => e.click())); + + para = listing.insertBefore(para, listing.firstChild); + + const proxyThumbClicks = function(evt) { + let thing = evt.target; + while (!thing.classList.contains('thing') && thing != document.body) { + thing = thing.parentElement; + } + if (!thing.classList.contains('thing')) { + console.log("Couldn't find thing"); + return true; + } + evt.preventDefault(); + + thing.querySelector('.expando-button')?.click(); + + return false; + }; + + listing.querySelectorAll('.thumbnail').forEach(e => e.addEventListener('click', proxyThumbClicks)); +})(); diff --git a/readcomiconline.user.js b/readcomiconline.user.js new file mode 100644 index 0000000..14dbfdb --- /dev/null +++ b/readcomiconline.user.js @@ -0,0 +1,89 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name Read Comic Online Scraper +// @namespace danielrayjones +// @version 0.0.4 +// @description Scrape comics from readcomiconline.to +// @author Dan Jones +// @match https://readcomiconline.to/* +// @grant none +// @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js +// @require https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js +// @require https://bowercdn.net/c/jszip-3.1.5/dist/jszip.min.js +// ==/UserScript== + +/* global jQuery, JSZip */ +/* jshint esversion: 6 */ + +(function($) { + 'use strict'; + + console.log('This does not work'); + return; + + $(window).konami({ + code: [71,69,84], + cheat: getStuff + }); + + function getStuff() { + let i = 0; + + let path = location.pathname.split('/'); + let chapter = path.pop(); + while (!chapter && path.length) { + chapter = path.pop(); + } + + let match; + if ((match = chapter.match(/^Issue-([0-9]+)/))) { + chapter = match[1]; + } + + let name = path.pop(); + + if (path.pop() !== 'Comic') { + alert('Not on a comic page'); + return; + } + + console.log(`Getting ${name} ${chapter}`); + + let imgs = $('#divImage img').toArray(); + console.log(imgs); + + let cbz = new JSZip(); + + function downloadCbz() { + cbz.generateAsync({type: 'blob'}) + .then(blob => { + let title = name.replace(/-/g, ' ') + ' ' + chapter; + + let $el = $(''); + $(document.body).append($el); + $el.attr('href', URL.createObjectURL(blob)); + $el.attr('download', `${title} (readcomiconline) (Danjones).cbz`); + $el.get(0).click(); + }); + } + + function getOne() { + if (!imgs || !imgs.length) { + downloadCbz(); + return; + } + + let img = imgs.shift(); + console.log(img.src); + + fetch(`//cors-anywhere.herokuapp.com/${img.src}`).then(resp => resp.blob()).then(blob => { + cbz.file(name + '-' + (i < 10 ? '00' : '0' ) + i + '.jpg', blob); + + i = i+1; + setTimeout(getOne, 0); + }); + } + + getOne(); + } +})(jQuery); diff --git a/trakt.clear-store.user.js b/trakt.clear-store.user.js new file mode 100644 index 0000000..9a4ad94 --- /dev/null +++ b/trakt.clear-store.user.js @@ -0,0 +1,37 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name Trakt Storage Clearer +// @namespace danielrayjones +// @version 0.0.1 +// @description +// @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'; + + const clearStorage = () => localStorage.clear(); + + /* todo + $(window).konami({ + code: [80, 73, 67, 75], + cheat: clearStorage + }); + */ + + function addPickButton() { + const $leftNav = $('.subnav-wrapper .container .left'); + const $found = $leftNav.find('.clear-store'); + if (!$found.length) { + $leftNav.append('X') + .find('.clear-store').on('click', clearStorage); + } + } + +})(); diff --git a/trakt.pick-show.user.js b/trakt.pick-show.user.js new file mode 100644 index 0000000..b425424 --- /dev/null +++ b/trakt.pick-show.user.js @@ -0,0 +1,111 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name Trakt Show Picker +// @namespace danielrayjones +// @version 0.0.10 +// @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'; + + let watched_shows; + + $(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('') + .find('.pick-episode').on('click', pickShow); + } + } + + function refreshPage() { + addPickButton(); + $('div[data-type="show"]') + .on('click', unghost); + } + + refreshPage(); + const observer = new MutationObserver(refreshPage); + observer.observe(document.head.parentElement, {childList: true}); + + 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)'); + } + +})(); diff --git a/trakt.scraper.user.js b/trakt.scraper.user.js index c5c6fff..c2b81dd 100644 --- a/trakt.scraper.user.js +++ b/trakt.scraper.user.js @@ -2,28 +2,30 @@ // ==UserScript== // @name Trakt Scraper // @namespace danielrayjones -// @version 0.0.2 +// @version 0.0.8 // @description Scrape lists of shows/movies from Trakt and download a JSON file // @author Dan Jones // @match https://trakt.tv/* // @grant none -// @require https://raw.githubusercontent.com/tommcfarlin/konami-code/master/src/jquery.konami.min.js +// @require https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js // ==/UserScript== +/* global $, compressedCache, localStorage */ +/* jshint esversion: 6 */ + (function() { 'use strict'; $(window).konami({ code: [71,69,84], - eventName: 'konami.get' + cheat: getStuff }); - $(window).on('konami.get', getStuff); - String.prototype.lpad = function(padString, length) { let str = this; - while (str.length < length) + while (str.length < length) { str = padString + str; + } return str; }; @@ -34,13 +36,14 @@ let $ep = $(that); let $series = $ep.find('[itemtype="http://schema.org/TVSeries"]'); + let this_ep = $ep.data(); + if ($series.length < 1) { $series = $('[itemtype="http://schema.org/TVSeries"]'); } let series = $ep.data('show-id'); let ep = $ep.data('episode-id'); - //let url = $ep.data('url'); let url = $ep.children('[itemprop="url"]').attr('content'); let series_title = $series.children('[itemprop="name"]').attr('content'); @@ -50,41 +53,68 @@ $ep_title = $ep.find('[itemprop="name"]'); } + let released = $ep.data('released') || null; + if (released) { + released = (new Date(released)).getTime()/1000; + } + let ep_title = $ep_title.attr('content'); let ep_number = $ep.find('[itemprop="episodeNumber"]').attr('content'); let season_number = $ep.data('season-number'); - //let title = $ep.data('title'); - let title = series_title + " " + season_number + "x" + String(ep_number).lpad("0", 2) + ' "' + ep_title + '"'; + + if (!season_number) { + let $title_ep = $ep.find('.main-title-sxe'); + if ($title_ep.length && $title_ep.text()) { + let match = /([0-9+])x[0-9]+/.exec($title_ep.text()); + if (match) { + season_number = match[1]; + } + } + } + + if (!season_number) { + season_number = 0; + } + + let title = series_title + " " + String(season_number) + "x" + String(ep_number).lpad("0", 2) + ' "' + ep_title + '"'; let watched = watched_shows[series] ? watched_shows[series].e[ep] : null; - let this_ep = { - series_id: series, - episode_id: ep, - title, - url, - watches: watched ? watched[1] : 0, - last_watched: watched ? watched[0] : null, - }; + let $img = $ep.find('[itemprop="image"]'); + if ($img.length > 0) { + this_ep['image'] = $img.attr('content'); + } + + this_ep['series_id'] = series; + this_ep['episode_id'] = ep; + this_ep['title'] = title; + this_ep['url'] = url; + this_ep['released'] = released; + this_ep['watches'] = watched ? watched[1] : 0; + this_ep['last_watched'] = watched ? watched[0] : null; return this_ep; } function processMovie(that) { let $mov = $(that); + let this_mov = $mov.data(); let id = $mov.data('movie-id'); let title = $mov.children('[itemprop="name"]').attr('content'); let url = $mov.children('[itemprop="url"]').attr('content'); let watched = watched_movies[id]; - let this_mov = { - id, - title, - url, - watches: watched ? watched[1] : 0, - last_watched: watched ? watched[0] : null, - }; + let $img = $mov.find('[itemprop="image"]'); + if ($img.length > 0) { + this_mov['image'] = $img.attr('content'); + } + + this_mov['id'] = id; + this_mov['title'] = title; + this_mov['url'] = url; + this_mov['watches'] = watched ? watched[1] : 0; + this_mov['last_watched'] = watched ? watched[0] : null; return this_mov; } diff --git a/trakt.simplifier.user.js b/trakt.simplifier.user.js index 4e04746..455372f 100644 --- a/trakt.simplifier.user.js +++ b/trakt.simplifier.user.js @@ -2,13 +2,15 @@ // ==UserScript== // @name Trakt Simplifier // @namespace danielrayjones -// @version 0.0.2 +// @version 0.0.3 // @description Strip out eps/movies from trakt lists based on a query string // @author Dan Jones // @match https://trakt.tv/* // @grant none // ==/UserScript== +/* jshint esversion: 6 */ + (function() { 'use strict'; diff --git a/viewcomic.scraper.user.js b/viewcomic.scraper.user.js index 4ced591..7a0ac98 100644 --- a/viewcomic.scraper.user.js +++ b/viewcomic.scraper.user.js @@ -2,27 +2,27 @@ // ==UserScript== // @name Viewcomic Scraper // @namespace danielrayjones -// @version 0.0.6 +// @version 0.0.10 // @description Scrape comics from viewcomic.com // @author Dan Jones // @match http://viewcomic.com/* // @grant none // @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js -// @require https://raw.githubusercontent.com/tommcfarlin/konami-code/master/src/jquery.konami.min.js +// @require https://bowercdn.net/c/konami-code-1.3.2/src/jquery.konami.min.js +// @require https://bowercdn.net/c/jszip-3.1.5/dist/jszip.min.js // ==/UserScript== -/* global jQuery */ +/* global jQuery, JSZip */ +/* jshint esversion: 6 */ (function($) { 'use strict'; $(window).konami({ code: [71,69,84], - eventName: 'konami.get' + cheat: getStuff }); - $(window).on('konami.get', getStuff); - function getStuff() { let i = 0; @@ -36,23 +36,38 @@ let imgs = $('div.pinbin-copy img.picture, div.pinbin-copy img.hoverZoomLink').toArray(); console.log(imgs); + let cbz = new JSZip(); + + function downloadCbz() { + cbz.generateAsync({type: 'blob'}) + .then(blob => { + let title = name.replace(/-/g, ' ').replace(/\b([0-9]{4})\b/, '($1)'); + + let $el = $(''); + $(document.body).append($el); + $el.attr('href', URL.createObjectURL(blob)); + $el.attr('download', `${title} (viewcomic) (Danjones).cbz`); + $el.get(0).click(); + }); + } + function getOne() { - if (!imgs) return; + if (!imgs || !imgs.length) { + downloadCbz(); + return; + } + let img = imgs.shift(); console.log(img.src); fetch(img.src).then(resp => resp.blob()).then(blob => { - let $el = $(''); - $(document.body).append($el); - $el.attr('href', URL.createObjectURL(blob)); - $el.attr('download', name + '-' + (i < 10 ? '00' : '0' ) + i + '.jpg'); - $el.get(0).click(); + cbz.file(name + '-' + (i < 10 ? '00' : '0' ) + i + '.jpg', blob); i = i+1; - setTimeout(getOne, 1000); + setTimeout(getOne, 0); }); } + getOne(); } - })(jQuery); diff --git a/wheniwork.hours.user.js b/wheniwork.hours.user.js new file mode 100644 index 0000000..41d49af --- /dev/null +++ b/wheniwork.hours.user.js @@ -0,0 +1,67 @@ +// -*- tab-width: 4; js-indent-level: 4; -*- +// ==UserScript== +// @name WhenIWork True Total Worked +// @namespace danielrayjones +// @description Adds the Total hours worked, including today +// @include https://app.wheniwork.com/payroll/ +// @version 0.2.1 +// @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js +// ==/UserScript== + +/* global $ */ +/* jshint esversion: 6 */ + +$(document).ready(function() { + 'use strict'; + + // Filter out this event from iframes + if (!this.body.classList.contains("controller-payroll")) { + return; + } + + let currentHourSum = 0; + + function updateHours(hours) { + currentHourSum = hours; + + let weekPlusDayTotal = $('#week-plus-day-total'); + let span = `Total with Today${hours}`; + + if (weekPlusDayTotal.length === 0) { + $('#header-summary-container .stats').append( + `
${span}
` + ); + } else { + weekPlusDayTotal.html(span); + } + + // In case this ran while the page was loading, let's try again in two seconds. + return setTimeout(addHours, 2000); + } + + function addHours() { + let hourSum = 0; + $('.times-list .col-worked .text-input[data-total]').each(function () { + hourSum += parseFloat($(this).text()) || 0; + }); + + // Adjust for floating point errors + hourSum = Math.round(hourSum*100)/100; + + console.log(`got ${hourSum} hours`); + + // AJAX request hasn't finished yet. Let's wait some more. + if (currentHourSum === 0 && hourSum === 0) return setTimeout(addHours, 2000); + + if (currentHourSum !== hourSum && hourSum > 0) { + return updateHours(hourSum); + } + + return null; + } + + // The hours don't show up until after an AJAX request completes. + // Let's wait two seconds for it to finish. + setTimeout(addHours, 2000); + +});