// ==UserScript==
// @name TrakTheSources
// @namespace http://tribuadore.github.io/TrakTheSources
// @version 0.5.0
// @author Tribuadore
// @description Sources movies and tv episodes for Trakt.tv
// @domain trakt.tv
// @domain raw.github.com
// @include http://trakt.tv/*
// @include https://trakt.tv/*
// @grant GM_xmlhttpRequest
// @run-at document-end
// @noframes
// @license MIT License
// ==/UserScript==
var aggregators = {};
aggregators.Primewire = {
URL: 'https://www.primewire.ag',
search: function (media) {
httpGet(aggregators.Primewire.URL + '/index.php?search_keywords=' + media.title, aggregators.Primewire.index, media);
},
index: function (doc, media) {
var pages = doc.evaluate('//div[contains(@class, "index_item")]/a[starts-with(@title, "Watch ' + media.title + '")]', null, null, XPathResult.ANY_TYPE);
var matches = 0;
for (var page = pages.iterateNext(); page; page = pages.iterateNext()) {
if ((new RegExp(' \\(' + media.year + '\\)$')).test(page.getAttribute('title'))) {
++matches;
httpGet(aggregators.Primewire.URL + page.getAttribute('href'), media.isEpisode ? aggregators.Primewire.episodes : aggregators.Primewire.sources, media);
}
}
if (matches === 0) {
return actions.searchShortendTitle(aggregators.Primewire.search, media);
}
},
episodes: function (doc, media) {
var episodes = document.evaluate('//div[@class="tv_episode_item"]/a', doc, null, XPathResult.ANY_TYPE);
var seasonNo = parseInt(media.seasonNo, 10);
var episodeNo = parseInt(media.episodeNo, 10);
for (var episode = episodes.iterateNext(); episode; episode = episodes.iterateNext()) {
var href = episode.getAttribute('href');
if ((new RegExp('/[^/]+/season-' + seasonNo + '-episode-' + episodeNo)).test(href)) {
return httpGet(aggregators.Primewire.URL + href, aggregators.Primewire.sources, media);
}
}
return actions.searchShortendTitle(aggregators.Primewire.search, media);
},
sources: function (doc, media) {
var links = document.evaluate('//table[@class="movie_version"]', doc, null, XPathResult.ANY_TYPE);
for (var link = links.iterateNext(); link; link = links.iterateNext()) {
var quality = document.evaluate('.//td[1]/span/@class', link, null, XPathResult.STRING_TYPE).stringValue;
if (quality === 'quality_dvd') {
if (document.evaluate('.//td[3]/span/script/text()', link, null, XPathResult.STRING_TYPE).stringValue !== 'Promo Host') {
return actions.showExternalLink(doc.url, 'PRIMEWIRE');
}
}
}
}
};
aggregators.Icefilms = {
URL: 'https://www.icefilms.info',
search: function (media) {
var letter = media.title.toLowerCase().replace('the ', '').replace('a ', '').replace(' ', '')[0].toUpperCase();
httpGet(aggregators.Icefilms.URL + '/' + (media.isMovie ? 'movies' : 'tv') + '/a-z/' + letter, aggregators.Icefilms.index, media);
},
index: function (doc, media) {
var pages = doc.evaluate('//a[starts-with(text(), "' + media.title + '")]', null, null, XPathResult.ANY_TYPE);
var matches = 0;
for (var page = pages.iterateNext(); page; page = pages.iterateNext()) {
if ((new RegExp(' \\(' + media.year + '\\)$')).test(page.textContent)) {
++matches;
httpGet(aggregators.Icefilms.URL + page.getAttribute('href'), media.isEpisode ? aggregators.Icefilms.episodes : aggregators.Icefilms.sources, media);
}
}
if (matches === 0) {
return actions.searchShortendTitle(aggregators.Icefilms.search, media);
}
},
episodes: function (doc, media) {
var episodes = document.evaluate('//a[starts-with(@href, "/ip\.php\?v=")]', doc, null, XPathResult.ANY_TYPE);
for (var episode = episodes.iterateNext(); episode; episode = episodes.iterateNext()) {
if ((new RegExp('^' + media.seasonNo + 'x' + media.episodeNo + ' ')).test(episode.textContent)) {
return httpGet(aggregators.Icefilms.URL + episode.getAttribute('href'), aggregators.Icefilms.sources, media);
}
}
return actions.searchShortendTitle(aggregators.Icefilms.search, media);
},
sources: function (doc, media) {
if (doc.getElementById('videoframe')) {
actions.showExternalLink(doc.url, 'ICEFILMS');
}
}
};
var actions = {};
actions.showExternalLink = function (url, label) {
var nav = document.evaluate('//section[@id="info-wrapper"]/div[@class="container"]/div[1]/div[1]/div[1]/ul[@class="external"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;
var li = document.createElement('li');
li.innerHTML = '<a href="' + url + '" target="_blank">' + label + '<div class="fa fa-external-link"></div></a>';
nav.appendChild(li);
};
actions.searchShortendTitle = function (search, media) {
var words = media.title.split(' ');
if (words.length > 1) {
words.splice(0, 1);
media.title = words.join(' ');
search(media);
}
};
var httpGet = function (url, onload, data) {
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: function (response) {
if (response.status === 200) {
var doc = document.implementation.createHTMLDocument();
doc.documentElement.innerHTML = response.responseText;
doc.url = url;
onload(doc, data);
}
}
});
};
var traktUrl;
var trakTheSources = function () {
// If URL hasn't change since last check, don't check again
if (traktUrl === window.location.href) return;
traktUrl = window.location.href;
// Remove none VIP Ads
document.querySelector('[id="huckster-desktop-wrapper"]').style.display = 'none';
document.querySelector('[id="huckster-desktop-bottom"]').style.display = 'none';
var media = {
isMovie: /^https?:\/\/trakt\.tv\/movies\//.test(traktUrl),
isEpisode: /^https?:\/\/trakt\.tv\/shows\//.test(traktUrl)
};
if (media.isMovie) {
var title = /^(.*) \((\d+)\)/.exec(document.title);
media.title = title[1];
media.year = title[2];
} else if (media.isEpisode) {
var title = /^(.*) (\d+)x(\d+) ("|")(.*)("|")/.exec(document.title);
media.title = title[1];
media.year = '\\d+';
media.seasonNo = title[2];
media.episodeNo = title[3];
media.episodeName = title[5];
} else {
return;
}
var aggregatorNames = Object.getOwnPropertyNames(aggregators);
for (var nameIndex in aggregatorNames) {
aggregators[aggregatorNames[nameIndex]].search(JSON.parse(JSON.stringify(media)));
}
};
setInterval(trakTheSources, 1000);