select / Pirate Bay Top 100 Movies IMDb

// ==UserScript==
// @name         Pirate Bay Top 100 Movies IMDb
// @namespace    http://github.com/select
// @version      0.1
// @description  Add imdb ratings to The Priate Bay top 100
// @author       select
// @match        https://thepiratebay.org/search.php?q=top100:*
// @grant        GM_xmlhttpRequest
// @license      MIT
// @copyright    2020, select (https://openuserjs.org/users/select)
// ==/UserScript==

const apiKey = 'XXXXXX'; // please create your api key at http://www.omdbapi.com/
const movieTitleRexEx = /(www\.[^ ]+ -)?(\[\w+\] )*([^(]*)( \()?(\d{4})[^p]/;
const movie_db = initDatabase();

function getImdbInfo(title, year) {
	return new Promise((resolve, reject) => {
		if (title in movie_db) resolve(movie_db[title]);
		let url = `http://www.omdbapi.com/?apiKey=${apiKey}&i=&t=${encodeURIComponent(title)}`;
		if (year) url += `&y=${year}`;
		GM_xmlhttpRequest({
			method: 'GET',
			url,
			onload: (response) => {
				const data = JSON.parse(response.responseText);
				if (data.Response === 'False') {
					movie_db[title] = false;
					reject();
				} else {
					movie_db[title] = data;
					resolve(data);
				}
				localStorage.movie_db = JSON.stringify(movie_db);
			},
			onerror: () => {
				console.warn('request failed: http://www.omdbapi.com/?t=' + title);
				reject();
			},
		});
	});
}

function initDatabase() {
	const c = localStorage.getItem('movie_db');
	return !c ? {} : JSON.parse(c);
}

async function run() {
	'use strict';

	document.body.innerHTML += `<style>.klsdkjf-votes {
	display: flex;
	justify-content: space-between;
	margin: 0 1rem;
}</style>`;

	const entries = await Promise.all(
		[...document.querySelectorAll('.list-entry')].map(async ($el) => {
			const rawTitle = $el.querySelector('.item-title a').textContent;
			const match = movieTitleRexEx.exec(rawTitle);
			const cleanTitle = match ? match[3].replace(/\./g, ' ').trim() : '';
			const year = match ? match[5] : '';
			let imdbInfo = false;
			try {
				imdbInfo = match ? await getImdbInfo(cleanTitle, year) : false;
			} catch (error) {
				console.error('getImdbInfo Errro', error)
			}
			let rating = imdbInfo ? parseFloat(imdbInfo.imdbRating) : 0;
			if (isNaN(rating)) rating = 0;

			const imdbQuery = (t) =>
				`<a href="http://www.imdb.com/find?ref_=nv_sr_fn&q=${t}&s=all" target="_blank">🔎</a>`;
			const $firstField = $el.querySelector('span:first-child');
			if (!(match && match.length)) {
				$firstField.innerHTML = imdbQuery(rawTitle);
			} else if (!imdbInfo) {
				$firstField.innerHTML = imdbQuery(cleanTitle);
			} else {
				$firstField.innerHTML = `<a class="klsdkjf-votes" href="http://www.imdb.com/title/${imdbInfo.imdbID}" target="_blank" title="${imdbInfo.imdbVotes} votes"> <span>${imdbInfo.imdbRating}</span><span>${imdbInfo.imdbVotes}</span>  </a>`;
				if (rating > 7.5) $firstField.style.fontWeight = `bold`;
				const $secondField = $el.querySelector('.item-title');
				$secondField.style.display = 'flex';
				$secondField.style.justifyContent = 'space-between';
				$secondField.innerHTML += `<span style="color: #666; margin-left: 1rem">${imdbInfo.Genre}</span>`;
				if (rating < 7.0) $el.style.opacity = 0.4;
			}
			return {
				$el,
				rating,
			};
		})
	);
	entries.sort((a, b) => (a.rating >= b.rating ? -1 : 1));
	const $parent = document.querySelector('#torrents');
	const $header = $parent.querySelector('.list-header');
	$parent.innerHTML = `${$header.outerHTML}${entries.map(({ $el }) => $el.outerHTML).join(' ')}`;
}

(function () {
	run().then(() => console.log('The End'));
})();