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(
+ ``
+ );
+ } 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);
+
+});