Skip to content

Instantly share code, notes, and snippets.

@730730
Last active January 8, 2024 19:33
Show Gist options
  • Save 730730/241caafc5ee60ea83d537a80051aecc4 to your computer and use it in GitHub Desktop.
Save 730730/241caafc5ee60ea83d537a80051aecc4 to your computer and use it in GitHub Desktop.
Tampermonkey script that adds filtering and sorting capabilities to AnimeBytes torrent groups
// ==UserScript==
// @name AB Filter/Sorter
// @version 1.0
// @description Adds a table of filters to AnimeBytes torrent groups and the possibility to sort by size/snatches/seeders/leechers
// @author 730
// @match https://animebytes.tv/torrents.php?id=*
// @updateURL https://gist.githubusercontent.com/730730/241caafc5ee60ea83d537a80051aecc4/raw/ab-filter.user.js
// @downloadURL https://gist.githubusercontent.com/730730/241caafc5ee60ea83d537a80051aecc4/raw/ab-filter.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
/*TODO:
show filter in series page too
create selects dinamically with only the available options out of the existing torrents
hide snatched (checkbox that toggles hiding)
*/
const torrentAttributes = {
"media": {
"TV": 1,
"DVD": 2,
"Blu-ray": 3,
"UHD Blu-ray": 4,
"HD DVD": 5,
"VHS": 6,
"VCD": 7,
"LD": 8,
"Web": 9
},
"container": {
"AVI": 1,
"MKV": 2,
"MP4": 3,
"OGM": 4,
"WMV": 5,
"MPG": 6,
"MPEG": 7,
"ISO": 8,
"VOB": 9,
"VOB IFO": 10,
"TS": 11,
"M2TS": 12
},
"codec": {
"h264": 1,
"h264 10-bit": 2,
"h265": 3,
"h265 10-bit": 4,
"XviD": 5,
"DivX": 6,
"WMV": 7,
"MPEG": 8,
"VC-1": 9,
"MPEG-TS": 10,
"DVD5": 11,
"DVD9": 12
},
"resolution": {
"640x480": 1,
"720x480": 2,
"720x486": 3,
"720x576": 4,
"704x396": 5,
"848x480": 6,
"1024x576": 7,
"720p": 8,
"1080i": 9,
"1080p": 10,
"4K": 11,
"Other": 12
},
"region": {
"R1": 1,
"R2 Japan": 2,
"R2 Europe": 3,
"R3": 4,
"R4": 5,
"R5": 6,
"R6": 7,
"A": 8,
"B": 9,
"C": 10
},
"aspectRatio": {
"4:3": 1,
"16:9": 2,
"1.85:1": 3,
"2.39:1": 4,
"2.4:1": 5
},
"audio": {
"MP3": 1,
"Vorbis": 2,
"Opus": 3,
"AAC": 4,
"AC3": 5,
"TrueHD": 6,
"DTS": 7,
"DTS-ES": 8,
"FLAC": 9,
"PCM": 10,
"WMA": 11,
"Real Audio": 12,
"DTS-HD": 13,
"DTS-HD MA": 14
},
"audioChannels": {
"1.0": 1,
"2.0": 2,
"2.1": 3,
"5.0": 4,
"5.1": 5,
"6.0": 6,
"6.1": 7,
"7.1": 8
},
"subs": {
"Softsubs": 1,
"Hardsubs": 2,
"RAW": 3
},
"dualAudio": {
"Yes": 1,
"No": 2
}
}
const units = {
"MiB": 1024,
"GiB": 1048576,
"TiB": 1073741824
}
function Torrent() {
this.html = null;
this.pad = null;
this.size = null;
this.snatches = null;
this.seeders = null;
this.leechers = null;
this.media = null;
this.container = null;
this.codec = null;
this.resolution = null;
//these 2 exists only when container is ISO/VOB IFO/M2TS
this.region = null;
this.aspectRatio = null;
this.audio = null;
this.audioChannels = null;
this.dualAudio = null;
this.subs = null;
this.subgroup = null;
}
//example: media, container (region), [aspectRatio], codec, resolution,
// audio (audioChannels), [dualAudio], subs (subgroup), [irrelevant]
//INIT SCRAPING
var torrents = $(".group_torrent");
var info = torrents.find("td > a");
var torrentNumbers = torrents.find("td + td");
var pads = $("tr.pad");
//fill info with arrays of each torrent's properties
for (var i = 0; i < info.length; i++) {
info[i] = $(info[i]).text().replace(/[\n\t»]/g, "").split(" | ");
//remove empty info (remaster tag)
for (var j = 0; j < info[i].length; j++) {
if (info[i][j] === "") {
info[i].splice(j, 1);
}
}
}
//fill torrents array with corresponding Torrent objects
for (var i = 0; i < torrents.length; i++) {
var auxTorrent = $(torrents[i]);
torrents[i] = new Torrent();
torrents[i].html = auxTorrent;
torrents[i].pad = $(pads[i]);
let size = parseFloat($(torrentNumbers[(i * 4)]).text().split(" ")[0]);
let unit = $(torrentNumbers[(i * 4)]).text().split(" ")[1];
torrents[i].size = size * units[unit];
torrents[i].snatches = parseInt($(torrentNumbers[(i * 4) + 1]).text().replace(/,/g, ""));
torrents[i].seeders = parseInt($(torrentNumbers[(i * 4) + 2]).text().replace(/,/g, ""));
torrents[i].leechers = parseInt($(torrentNumbers[(i * 4) + 3]).text().replace(/,/g, ""));
torrents[i].media = torrentAttributes.media[info[i][0]];
//ISO/VOB IFO/M2TS route
if (info[i][1].match(/\(/)) { //check if it has a parenthesis
torrents[i].container = torrentAttributes.container[info[i][1].split(" ")[0]];
//match inside of parentheses
torrents[i].region = torrentAttributes.region[info[i][1].match(/\(([^)]+)\)/)[1]];
torrents[i].aspectRatio = torrentAttributes.aspectRatio[info[i][2]];
torrents[i].codec = torrentAttributes.codec[info[i][3]];
torrents[i].resolution = torrentAttributes.resolution[info[i][4]] || 12;
torrents[i].audio = torrentAttributes.audio[info[i][5].split(" ")[0]];
torrents[i].audioChannels = torrentAttributes.audioChannels[info[i][5].split(" ")[1]];
//dual audio route
if (info[i][6] == "Dual Audio") {
torrents[i].dualAudio = 1;
torrents[i].subs = torrentAttributes.subs[info[i][7]];
} else {
//non-dual audio route
torrents[i].dualAudio = 2;
torrents[i].subs = torrentAttributes.subs[info[i][6]];
}
} else {
//non-ISO/VOB IFO/M2TS route
torrents[i].container = torrentAttributes.container[info[i][1]];
torrents[i].codec = torrentAttributes.codec[info[i][2]];
torrents[i].resolution = torrentAttributes.resolution[info[i][3]] || 12;
torrents[i].audio = torrentAttributes.audio[info[i][4].split(" ")[0]];
torrents[i].audioChannels = torrentAttributes.audioChannels[info[i][4].split(" ")[1]];
//dual audio route
if (info[i][5] == "Dual Audio") {
torrents[i].dualAudio = 1;
torrents[i].subs = torrentAttributes.subs[info[i][6].split(" ")[0]];
//torrents[i].subgroup = info[i][6].match(/\(([^)]+)\)/)[1];
} else {
//non-dual audio route
torrents[i].dualAudio = 2;
torrents[i].subs = torrentAttributes.subs[info[i][5].split(" ")[0]];
//torrents[i].subgroup = info[i][5].match(/\(([^)]+)\)/)[1];
}
}
}
//END SCRAPING
//INIT HTML CREATION
var table = $(
`<table id="filter">
<tbody>
<tr>
<td>
<label for="media"><strong>Media</strong></label>
<select id="media">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="resolution"><strong>Resolution</strong></label>
<select id="resolution">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="audio"><strong>Audio</strong></label>
<select id="audio">
<option value="-1" selected>Don't care</option>
</select>
<select id="audioChannels">
<option value="-1" selected>Don't care</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="codec"><strong>Codec</strong></label>
<select id="codec">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="dualAudio"><strong>Dual Audio</strong></label>
<select id="dualAudio">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="subs"><strong>Subs</strong></label>
<select id="subs">
<option value="-1" selected>Don't care</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="container"><strong>Container</strong></label>
<select id="container">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="aspectRatio"><strong>Aspect Ratio</strong></label>
<select id="aspectRatio">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<label for="region"><strong>Region</strong></label>
<select id="region">
<option value="-1" selected>Don't care</option>
</select>
</td>
<td>
<button id="filter-reset" style="width: 70px; height: 30px;">Reset</button>
</td>
</tr>
</tbody>
</table>`);
//add filter table to document
$(".main_column").prepend(table);
//set change handlers for all filtering <select>s
$("#filter select").change(filterTorrents);
//set click handler for "Size" label and change cursor
$(".torrent_table > tbody > tr:first-child > td:nth-child(2) strong").click(function(){sortTorrents(0)});
$(".torrent_table > tbody > tr:first-child > td:nth-child(2) strong").css("cursor", "pointer");
//set click handlers and change cursor for the other 3 icons
$($(".sign img")[0]).click(function(){sortTorrents(1)});
$($(".sign img")[0]).css("cursor", "pointer");
$($(".sign img")[1]).click(function(){sortTorrents(2)});
$($(".sign img")[1]).css("cursor", "pointer");
$($(".sign img")[2]).click(function(){sortTorrents(3)});
$($(".sign img")[2]).css("cursor", "pointer");
//fill filtering <select>s with their corresponding <option>s
for (var attr in torrentAttributes) {
for (var val in torrentAttributes[attr]) {
$("#" + attr).append("<option value='" + torrentAttributes[attr][val] +
"'>" + val + "</option>");
}
}
$("#filter-reset").click(resetFilter);
//END HTML CREATION
function hideTorrent(torrent) {
torrent.html.hide();
torrent.pad.addClass("hide");
}
function showTorrent(torrent) {
torrent.html.show();
}
function getFilterValues() {
let values = new Torrent();
for (var attr in torrentAttributes) {
values[attr] = parseInt($("#" + attr).val());
}
return values;
}
function filterTorrents() {
let filterValues = getFilterValues();
for (var i = 0; i < torrents.length; i++) {
let matches = true;
for (var attr in torrentAttributes) {
if (torrents[i][attr] != filterValues[attr] && filterValues[attr] != -1) {
matches = false;
}
}
if (!matches) {
hideTorrent(torrents[i]);
} else {
showTorrent(torrents[i]);
}
}
}
function sortBySize() {
if (typeof sortBySize.descending == 'undefined') {
sortBySize.descending = false;
}
if (!sortBySize.descending) {
torrents.sort(function (a, b) {
return a.size - b.size;
});
sortBySize.descending = true;
} else {
torrents.sort(function (a, b) {
return b.size - a.size;
});
sortBySize.descending = false;
}
}
function sortBySnatches() {
if (typeof sortBySnatches.descending == 'undefined') {
sortBySnatches.descending = false;
}
if (!sortBySnatches.descending) {
torrents.sort(function (a, b) {
return a.snatches - b.snatches;
});
sortBySnatches.descending = true;
} else {
torrents.sort(function (a, b) {
return b.snatches - a.snatches;
});
sortBySnatches.descending = false;
}
}
function sortBySeeders() {
if (typeof sortBySeeders.descending == 'undefined') {
sortBySeeders.descending = false;
}
if (!sortBySeeders.descending) {
torrents.sort(function (a, b) {
return a.seeders - b.seeders;
});
sortBySeeders.descending = true;
} else {
torrents.sort(function (a, b) {
return b.seeders - a.seeders;
});
sortBySeeders.descending = false;
}
}
function sortByLeechers() {
if (typeof sortByLeechers.descending == 'undefined') {
sortByLeechers.descending = false;
}
if (!sortByLeechers.descending) {
torrents.sort(function (a, b) {
return a.leechers - b.leechers;
});
sortByLeechers.descending = true;
} else {
torrents.sort(function (a, b) {
return b.leechers - a.leechers;
});
sortByLeechers.descending = false;
}
}
function displayTorrents() {
let torrentsHeader = $(".torrent_table > tbody > tr:first-child");
for (var i = 0; i < torrents.length; i++) {
torrentsHeader.after(torrents[i].html);
torrents[i].html.after(torrents[i].pad);
}
}
function sortTorrents(criterion) {
switch (criterion) {
case 0: //size
sortBySize();
break;
case 1: //snatches
sortBySnatches();
break;
case 2: //seeders
sortBySeeders();
break;
case 3: //leechers
sortByLeechers();
break;
}
displayTorrents();
}
function resetFilter() {
for (var attr in torrentAttributes) {
$("#" + attr).val("-1");
}
filterTorrents();
}
})();
@kanjieater
Copy link

Exactly what i was googling for. thanks 730 🙇‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment