// ==UserScript==
// @name TVShow Time Watch Online
// @namespace dannieboi
// @version 0.3
// @description Show links to watch tv shows on To-Watch page
// @author dannieboi
// @match http://www.tvshowtime.com/en
// @grant GM_addStyle
// ==/UserScript==
"format register";
(function(global) {
var defined = {};
// indexOf polyfill for IE8
var indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++)
if (this[i] === item)
return i;
return -1;
}
function dedupe(deps) {
var newDeps = [];
for (var i = 0, l = deps.length; i < l; i++)
if (indexOf.call(newDeps, deps[i]) == -1)
newDeps.push(deps[i])
return newDeps;
}
function register(name, deps, declare, execute) {
if (typeof name != 'string')
throw "System.register provided no module name";
var entry;
// dynamic
if (typeof declare == 'boolean') {
entry = {
declarative: false,
deps: deps,
execute: execute,
executingRequire: declare
};
}
else {
// ES6 declarative
entry = {
declarative: true,
deps: deps,
declare: declare
};
}
entry.name = name;
// we never overwrite an existing define
if (!defined[name])
defined[name] = entry;
entry.deps = dedupe(entry.deps);
// we have to normalize dependencies
// (assume dependencies are normalized for now)
// entry.normalizedDeps = entry.deps.map(normalize);
entry.normalizedDeps = entry.deps;
}
function buildGroups(entry, groups) {
groups[entry.groupIndex] = groups[entry.groupIndex] || [];
if (indexOf.call(groups[entry.groupIndex], entry) != -1)
return;
groups[entry.groupIndex].push(entry);
for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
var depName = entry.normalizedDeps[i];
var depEntry = defined[depName];
// not in the registry means already linked / ES6
if (!depEntry || depEntry.evaluated)
continue;
// now we know the entry is in our unlinked linkage group
var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);
// the group index of an entry is always the maximum
if (depEntry.groupIndex === undefined || depEntry.groupIndex < depGroupIndex) {
// if already in a group, remove from the old group
if (depEntry.groupIndex !== undefined) {
groups[depEntry.groupIndex].splice(indexOf.call(groups[depEntry.groupIndex], depEntry), 1);
// if the old group is empty, then we have a mixed depndency cycle
if (groups[depEntry.groupIndex].length == 0)
throw new TypeError("Mixed dependency cycle detected");
}
depEntry.groupIndex = depGroupIndex;
}
buildGroups(depEntry, groups);
}
}
function link(name) {
var startEntry = defined[name];
startEntry.groupIndex = 0;
var groups = [];
buildGroups(startEntry, groups);
var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
for (var i = groups.length - 1; i >= 0; i--) {
var group = groups[i];
for (var j = 0; j < group.length; j++) {
var entry = group[j];
// link each group
if (curGroupDeclarative)
linkDeclarativeModule(entry);
else
linkDynamicModule(entry);
}
curGroupDeclarative = !curGroupDeclarative;
}
}
// module binding records
var moduleRecords = {};
function getOrCreateModuleRecord(name) {
return moduleRecords[name] || (moduleRecords[name] = {
name: name,
dependencies: [],
exports: {}, // start from an empty module and extend
importers: []
})
}
function linkDeclarativeModule(entry) {
// only link if already not already started linking (stops at circular)
if (entry.module)
return;
var module = entry.module = getOrCreateModuleRecord(entry.name);
var exports = entry.module.exports;
var declaration = entry.declare.call(global, function(name, value) {
module.locked = true;
exports[name] = value;
for (var i = 0, l = module.importers.length; i < l; i++) {
var importerModule = module.importers[i];
if (!importerModule.locked) {
var importerIndex = indexOf.call(importerModule.dependencies, module);
importerModule.setters[importerIndex](exports);
}
}
module.locked = false;
return value;
});
module.setters = declaration.setters;
module.execute = declaration.execute;
if (!module.setters || !module.execute)
throw new TypeError("Invalid System.register form for " + entry.name);
// now link all the module dependencies
for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
var depName = entry.normalizedDeps[i];
var depEntry = defined[depName];
var depModule = moduleRecords[depName];
// work out how to set depExports based on scenarios...
var depExports;
if (depModule) {
depExports = depModule.exports;
}
else if (depEntry && !depEntry.declarative) {
depExports = { 'default': depEntry.module.exports, __useDefault: true };
}
// in the module registry
else if (!depEntry) {
depExports = load(depName);
}
// we have an entry -> link
else {
linkDeclarativeModule(depEntry);
depModule = depEntry.module;
depExports = depModule.exports;
}
// only declarative modules have dynamic bindings
if (depModule && depModule.importers) {
depModule.importers.push(module);
module.dependencies.push(depModule);
}
else
module.dependencies.push(null);
// run the setter for this dependency
if (module.setters[i])
module.setters[i](depExports);
}
}
// An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
function getModule(name) {
var exports;
var entry = defined[name];
if (!entry) {
exports = load(name);
if (!exports)
throw new Error("Unable to load dependency " + name + ".");
}
else {
if (entry.declarative)
ensureEvaluated(name, []);
else if (!entry.evaluated)
linkDynamicModule(entry);
exports = entry.module.exports;
}
if ((!entry || entry.declarative) && exports && exports.__useDefault)
return exports['default'];
return exports;
}
function linkDynamicModule(entry) {
if (entry.module)
return;
var exports = {};
var module = entry.module = { exports: exports, id: entry.name };
// AMD requires execute the tree first
if (!entry.executingRequire) {
for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
var depName = entry.normalizedDeps[i];
var depEntry = defined[depName];
if (depEntry)
linkDynamicModule(depEntry);
}
}
// now execute
entry.evaluated = true;
var output = entry.execute.call(global, function(name) {
for (var i = 0, l = entry.deps.length; i < l; i++) {
if (entry.deps[i] != name)
continue;
return getModule(entry.normalizedDeps[i]);
}
throw new TypeError('Module ' + name + ' not declared as a dependency.');
}, exports, module);
if (output)
module.exports = output;
}
/*
* Given a module, and the list of modules for this current branch,
* ensure that each of the dependencies of this module is evaluated
* (unless one is a circular dependency already in the list of seen
* modules, in which case we execute it)
*
* Then we evaluate the module itself depth-first left to right
* execution to match ES6 modules
*/
function ensureEvaluated(moduleName, seen) {
var entry = defined[moduleName];
// if already seen, that means it's an already-evaluated non circular dependency
if (entry.evaluated || !entry.declarative)
return;
// this only applies to declarative modules which late-execute
seen.push(moduleName);
for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
var depName = entry.normalizedDeps[i];
if (indexOf.call(seen, depName) == -1) {
if (!defined[depName])
load(depName);
else
ensureEvaluated(depName, seen);
}
}
if (entry.evaluated)
return;
entry.evaluated = true;
entry.module.execute.call(global);
}
// magical execution function
var modules = {};
function load(name) {
if (modules[name])
return modules[name];
var entry = defined[name];
// first we check if this module has already been defined in the registry
if (!entry)
throw "Module " + name + " not present.";
// recursively ensure that the module and all its
// dependencies are linked (with dependency group handling)
link(name);
// now handle dependency execution in correct order
ensureEvaluated(name, []);
// remove from the registry
defined[name] = undefined;
var module = entry.declarative ? entry.module.exports : { 'default': entry.module.exports, '__useDefault': true };
// return the defined module object
return modules[name] = module;
};
return function(main, declare) {
var System;
// if there's a system loader, define onto it
if (typeof System != 'undefined' && System.register) {
declare(System);
System['import'](main);
}
// otherwise, self execute
else {
declare(System = {
register: register,
get: load,
set: function(name, module) {
modules[name] = module;
},
newModule: function(module) {
return module;
},
global: global
});
System.set('@empty', System.newModule({}));
load(main);
}
};
})(typeof window != 'undefined' ? window : global)
/* ('mainModule', function(System) {
System.register(...);
}); */
('src/run.tvshowtime', function(System) {
System.register("src/core/TvShowInfo", [], function (_export) {
var _createClass, _classCallCheck, TitleInfo, TvShowInfo;
return {
setters: [],
execute: function () {
"use strict";
_createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
_classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
TitleInfo = (function () {
function TitleInfo(title) {
_classCallCheck(this, TitleInfo);
this.title = title;
}
_createClass(TitleInfo, {
raw: {
get: function () {
return this.title;
}
},
clean: {
get: function () {
return this.title.replace(/[:,'()\.]/g, "").replace("&", "and");
}
},
dash: {
get: function () {
return this.clean.replace(/\s/g, "-").toLowerCase();
}
},
underscore: {
get: function () {
return this.clean.replace(/\s/g, "_").toLowerCase();
}
},
plus: {
get: function () {
return this.clean.replace(/\s/g, "+").toLowerCase();
}
},
space: {
get: function () {
return this.clean.replace(/\s/g, "%20").toLowerCase();
}
}
});
return TitleInfo;
})();
TvShowInfo = (function () {
function TvShowInfo(title, season, episode, year) {
_classCallCheck(this, TvShowInfo);
this.title = title;
this.season = season;
this.episode = episode;
this.year = year;
}
_createClass(TvShowInfo, {
getTitleInfo: {
value: function getTitleInfo() {
return new TitleInfo(this.title);
}
},
getSeasonString: {
value: function getSeasonString(numDigits) {
if (numDigits) {
return this._pad(this.season, numDigits);
}
return this.season.toString();
}
},
getEpisodeString: {
value: function getEpisodeString(numDigits) {
if (numDigits) {
return this._pad(this.episode, numDigits);
}
return this.episode.toString();
}
},
_pad: {
value: function _pad(num, size) {
var s = num + "";
while (s.length < size) s = "0" + s;
return s;
}
}
});
return TvShowInfo;
})();
_export("default", TvShowInfo);
}
};
});
System.register("src/core/TvShowSiteInfo", [], function (_export) {
var _classCallCheck, TvShowSiteInfo;
return {
setters: [],
execute: function () {
"use strict";
_classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
TvShowSiteInfo = function TvShowSiteInfo(siteName, options) {
_classCallCheck(this, TvShowSiteInfo);
this.siteName = siteName;
this.tvShowPageUrl = options.tvShowPageUrl;
this.episodePageUrl = options.episodePageUrl;
this.searchUrl = options.searchUrl;
this.logoUrl = options.logoUrl;
};
_export("default", TvShowSiteInfo);
}
};
});
System.register("src/core/tvShowSitesArray", ["src/core/TvShowSiteInfo"], function (_export) {
var TvShowSiteInfo;
return {
setters: [function (_srcCoreTvShowSiteInfo) {
TvShowSiteInfo = _srcCoreTvShowSiteInfo["default"];
}],
execute: function () {
"use strict";
// tv show sites
_export("default", [
// PutLocker TV Shows
new TvShowSiteInfo("PutLocker TV Shows", {
logoUrl: "http://www.iconj.com/ico/3/s/3s61b5mccc.ico",
tvShowPageUrl: "http://putlockertvshows.me/watch/{TITLE_DASH}/",
episodePageUrl: "http://putlockertvshows.me/watch/{TITLE_DASH}/s{SEASON_2}e{EPISODE_2}.html"
}),
// watch series
new TvShowSiteInfo("Watch Series", {
logoUrl: "http://watchseriesfree.to/favicon.ico",
tvShowPageUrl: "http://watchseriesfree.to/serie/{TITLE_UNDERSCORE}",
episodePageUrl: "http://watchseriesfree.to/episode/{TITLE_UNDERSCORE}_s{SEASON}_e{EPISODE}.html",
searchUrl: "http://watchseriesfree.to/search/{TITLE_RAW}"
}),
// project free tV
new TvShowSiteInfo("Project Free TV", {
logoUrl: "http://cdn4.projectfreetv.so/wp-content/uploads/2015/01/favicon.ico",
tvShowPageUrl: "http://projectfreetv.ch/free/{TITLE_DASH}/",
episodePageUrl: "http://projectfreetv.ch/{TITLE_DASH}-season-{SEASON}-episode-{EPISODE}/",
searchUrl: "http://projectfreetv.ch/search/{TITLE_SPACE}"
}),
// netflix
new TvShowSiteInfo("Netflix", {
logoUrl: "http://www.netflix.com/favicon.ico",
searchUrl: "http://www.netflix.com/search/{TITLE_SPACE}"
}),
// amazon
new TvShowSiteInfo("Amazon", {
logoUrl: "http://www.amazon.com/favicon.ico",
searchUrl: "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dinstant-video&field-keywords={TITLE_PLUS}&rh=n%3A2858778011%2Ck%3A{TITLE_PLUS}"
}),
// hulu
new TvShowSiteInfo("Hulu", {
logoUrl: "http://www.hulu.com/favicon.ico",
searchUrl: "http://www.hulu.com/{TITLE_DASH}"
})]);
}
};
});
System.register("src/renderers/IconRenderer", [], function (_export) {
var _createClass, _classCallCheck, IconRenderer;
return {
setters: [],
execute: function () {
"use strict";
_createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
_classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
//import $ from "jquery";
IconRenderer = (function () {
function IconRenderer() {
_classCallCheck(this, IconRenderer);
}
_createClass(IconRenderer, null, {
render: {
value: function render(tvShowlinks, tvLinksContainSelector) {
var $container = $(tvLinksContainSelector);
var iconsHtml = [];
for (var i = 0; i < tvShowlinks.length; i++) {
var linkData = tvShowlinks[i];
var pageUrl = linkData.episodePageUrl || linkData.tvShowPageUrl || linkData.searchUrl;
var iconHtml = "<a href='" + pageUrl + "' title='" + linkData.siteName + "' class='tv-link' target='_blank'>\n <img src='" + linkData.logoUrl + "'/>\n </a>";
iconsHtml.push(iconHtml);
}
$container.append(iconsHtml.join(""));
}
},
addPageStyles: {
value: function addPageStyles() {
var css = "\n a.tv-link {\n padding-right: 2px;\n }\n\n a.tv-link img {\n width: 16px;\n height: 16px;\n -webkit-filter: grayscale(1);\n -webkit-filter: grayscale(100%);\n filter: grayscale(100%);\n filter: url(#greyscale);\n filter: gray;\n }\n\n a.tv-link img:hover {\n -webkit-filter: none;\n filter: none;\n }\n ";
GM_addStyle(css);
}
}
});
return IconRenderer;
})();
_export("default", IconRenderer);
}
};
});
System.register("src/core/getTvShowLinksFromInfo", ["src/core/TvShowInfo", "src/core/TvShowSiteInfo", "src/core/tvShowSitesArray"], function (_export) {
var TvShowInfo, TvShowSiteInfo, siteInfoArray;
function setTitlePlaceholderData(str, tvShowInfo) {
if (!str) {
return null;
}var titleInfo = tvShowInfo.getTitleInfo();
str = str.replace("{TITLE_PLUS}", titleInfo.plus);
str = str.replace("{TITLE_CLEAN}", titleInfo.clean);
str = str.replace("{TITLE_DASH}", titleInfo.dash);
str = str.replace("{TITLE_UNDERSCORE}", titleInfo.underscore);
str = str.replace("{TITLE_RAW}", titleInfo.raw);
str = str.replace("{TITLE_SPACE}", titleInfo.space);
str = str.replace("{SEASON}", tvShowInfo.getSeasonString());
str = str.replace("{SEASON_2}", tvShowInfo.getSeasonString(2));
str = str.replace("{EPISODE}", tvShowInfo.getEpisodeString());
str = str.replace("{EPISODE_2}", tvShowInfo.getEpisodeString(2));
return str;
}
return {
setters: [function (_srcCoreTvShowInfo) {
TvShowInfo = _srcCoreTvShowInfo["default"];
}, function (_srcCoreTvShowSiteInfo) {
TvShowSiteInfo = _srcCoreTvShowSiteInfo["default"];
}, function (_srcCoreTvShowSitesArray) {
siteInfoArray = _srcCoreTvShowSitesArray["default"];
}],
execute: function () {
"use strict";
_export("default", function (tvShowInfo) {
return siteInfoArray.map(function (value, index, array) {
return new TvShowSiteInfo(value.siteName, {
tvShowPageUrl: setTitlePlaceholderData(value.tvShowPageUrl, tvShowInfo),
episodePageUrl: setTitlePlaceholderData(value.episodePageUrl, tvShowInfo),
searchUrl: setTitlePlaceholderData(value.searchUrl, tvShowInfo),
logoUrl: value.logoUrl
});
});
});
}
};
});
System.register("src/parsers/TvShowTimeParser", ["src/core/getTvShowLinksFromInfo", "src/core/TvShowInfo"], function (_export) {
var getTvShowLinks, TvShowInfo, _createClass, _classCallCheck, TvShowTimeParser;
return {
setters: [function (_srcCoreGetTvShowLinksFromInfo) {
getTvShowLinks = _srcCoreGetTvShowLinksFromInfo["default"];
}, function (_srcCoreTvShowInfo) {
TvShowInfo = _srcCoreTvShowInfo["default"];
}],
execute: function () {
"use strict";
_createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
_classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
TvShowTimeParser = (function () {
function TvShowTimeParser(renderer) {
_classCallCheck(this, TvShowTimeParser);
this.renderer = renderer;
}
_createClass(TvShowTimeParser, {
parse: {
value: function parse() {
this.renderer.addPageStyles();
this._parseElement($("ul.to-watch-list > li[id^='episode-item-']:not(.upcoming)"));
var self = this;
// select the target node
var target = document.querySelector("ul.to-watch-list");
// configuration of the observer:
var config = { childList: true };
// create an observer instance
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
var numAddedNodes = mutation.addedNodes.length;
if (numAddedNodes > 0) {
for (var i = 0; i < numAddedNodes; i++) {
var $node = $(mutation.addedNodes.item(i));
console.dir($node);
if ($node.is("li") && $node.hasClass("episode-item") && !$node.hasClass("upcoming")) {
self._parseElement($node).bind(self, $node)();
}
}
}
});
});
// pass in the target node, as well as the observer options
observer.observe(target, config);
}
},
_parseElement: {
value: function _parseElement($element) {
var _this = this;
$element.each(function (index, li) {
var title, season, episode, year;
var $li = $(li);
var episodeDetails = $li.find("div.episode-details > h2 > a").text();
var regExMatches = episodeDetails.match(/S(\d*)E(\d*)/i);
season = parseInt(regExMatches[1]);
episode = parseInt(regExMatches[2]);
var titleDetails = $li.find("div.episode-details > a").text();
var indexOfYear = titleDetails.lastIndexOf("(");
if (indexOfYear > 0) {
title = titleDetails.substr(0, indexOfYear).trim();
year = parseInt(titleDetails.substring(indexOfYear + 1, titleDetails.lastIndexOf(")")));
} else {
title = titleDetails;
}
$li.find("div.nav").prepend("<div class='tv-links-container' style='float:left; width:157px; height:20px; text-align: left'></div>");
var tvShowInfo = new TvShowInfo(title, season, episode, year);
var tvShowLinks = getTvShowLinks(tvShowInfo);
var tvLinksContainSelector = "#" + $li.attr("id") + "> div.nav > div.tv-links-container";
_this.renderer.render(tvShowLinks, tvLinksContainSelector);
});
}
}
});
return TvShowTimeParser;
})();
_export("default", TvShowTimeParser);
}
};
});
//import $ from "jquery";
System.register("src/run.tvshowtime", ["src/parsers/TvShowTimeParser", "src/renderers/IconRenderer"], function (_export) {
var Parser, renderer;
return {
setters: [function (_srcParsersTvShowTimeParser) {
Parser = _srcParsersTvShowTimeParser["default"];
}, function (_srcRenderersIconRenderer) {
renderer = _srcRenderersIconRenderer["default"];
}],
execute: function () {
"use strict";
new Parser(renderer).parse();
}
};
});
});
//# sourceMappingURL=tvshowtime.js.map