mirror of
https://github.com/mitb-archive/filebot
synced 2024-08-13 17:03:45 -04:00
* lots of testing & improvement for movie auto-detection
* more robust CLI movie-mode
This commit is contained in:
parent
d4b38f918f
commit
a5284ccb40
@ -26,7 +26,7 @@ tsv.text.eachLine{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
movies = movies.findAll{ it[0] <= 9999999 && it[2] >= 1960 && it[1] =~ /^[A-Z0-9]/ && it[1] =~ /[\p{Alpha}]{3}/ }.sort{ it[1] }
|
movies = movies.findAll{ it[0] <= 9999999 && it[2] >= 1930 && it[1] =~ /^[A-Z0-9]/ && it[1] =~ /[\p{Alpha}]{3}/ }.sort{ it[1] }
|
||||||
|
|
||||||
gz(m_out, movies.collect{ [it[0].pad(7), it[1], it[2]].join('\t') })
|
gz(m_out, movies.collect{ [it[0].pad(7), it[1], it[2]].join('\t') })
|
||||||
println "Movie Count: " + movies.size()
|
println "Movie Count: " + movies.size()
|
||||||
|
@ -313,8 +313,9 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
derivatesByMovieFile.put(movieFile, new ArrayList<File>());
|
derivatesByMovieFile.put(movieFile, new ArrayList<File>());
|
||||||
}
|
}
|
||||||
for (File file : orphanedFiles) {
|
for (File file : orphanedFiles) {
|
||||||
|
List<File> orphanParent = listPath(file);
|
||||||
for (File movieFile : movieFiles) {
|
for (File movieFile : movieFiles) {
|
||||||
if (isDerived(file, movieFile)) {
|
if (orphanParent.contains(movieFile.getParentFile()) && isDerived(file, movieFile)) {
|
||||||
derivatesByMovieFile.get(movieFile).add(file);
|
derivatesByMovieFile.get(movieFile).add(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -382,7 +383,11 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
if (movie == null) {
|
if (movie == null) {
|
||||||
CLILogger.fine(format("Auto-detect movie from context: [%s]", file));
|
CLILogger.fine(format("Auto-detect movie from context: [%s]", file));
|
||||||
Collection<Movie> results = detectMovie(file, null, service, locale, strict);
|
Collection<Movie> results = detectMovie(file, null, service, locale, strict);
|
||||||
movie = (Movie) selectSearchResult(query, results, strict).get(0);
|
try {
|
||||||
|
movie = (Movie) selectSearchResult(query, results, strict).get(0);
|
||||||
|
} catch (Exception e) {
|
||||||
|
CLILogger.log(Level.WARNING, String.format("%s: [%s/%s] %s", e.getClass().getSimpleName(), guessMovieFolder(file) != null ? guessMovieFolder(file).getName() : null, file.getName(), e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
if (movie != null) {
|
if (movie != null) {
|
||||||
Analytics.trackEvent(service.getName(), "SearchMovie", movie.toString(), 1);
|
Analytics.trackEvent(service.getName(), "SearchMovie", movie.toString(), 1);
|
||||||
|
@ -15,6 +15,7 @@ import java.net.MalformedURLException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.CollationKey;
|
import java.text.CollationKey;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -301,19 +302,13 @@ public class MediaDetection {
|
|||||||
|
|
||||||
// search by file name or folder name
|
// search by file name or folder name
|
||||||
List<String> terms = new ArrayList<String>();
|
List<String> terms = new ArrayList<String>();
|
||||||
|
|
||||||
// 1. term: try to match movie pattern 'name (year)' or use filename as is
|
// 1. term: try to match movie pattern 'name (year)' or use filename as is
|
||||||
Matcher nameMatcher = compile("^(.+?)[(]((?:19|20)\\d{2})[)]").matcher(movieFile.getName());
|
terms.add(reduceMovieName(getName(movieFile)));
|
||||||
if (nameMatcher.find()) {
|
|
||||||
terms.add(String.format("%s (%s)", nameMatcher.group(1).trim(), nameMatcher.group(2)));
|
|
||||||
} else {
|
|
||||||
terms.add(getName(movieFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. term: first meaningful parent folder
|
// 2. term: first meaningful parent folder
|
||||||
File movieFolder = guessMovieFolder(movieFile);
|
File movieFolder = guessMovieFolder(movieFile);
|
||||||
if (movieFolder != null) {
|
if (movieFolder != null) {
|
||||||
terms.add(getName(movieFolder));
|
terms.add(reduceMovieName(getName(movieFolder)));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Movie> movieNameMatches = matchMovieName(terms, locale, strict);
|
List<Movie> movieNameMatches = matchMovieName(terms, locale, strict);
|
||||||
@ -329,6 +324,11 @@ public class MediaDetection {
|
|||||||
movieNameMatches = matchMovieName(terms, locale, false);
|
movieNameMatches = matchMovieName(terms, locale, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assume name without spacing will mess up any lookup
|
||||||
|
if (movieNameMatches.isEmpty()) {
|
||||||
|
movieNameMatches = matchMovieFromStringWithoutSpacing(terms, new NameSimilarityMetric(), strict ? 0.9f : 0.6f);
|
||||||
|
}
|
||||||
|
|
||||||
// query by file / folder name
|
// query by file / folder name
|
||||||
if (queryLookupService != null) {
|
if (queryLookupService != null) {
|
||||||
options.addAll(queryMovieByFileName(terms, queryLookupService, locale));
|
options.addAll(queryMovieByFileName(terms, queryLookupService, locale));
|
||||||
@ -344,6 +344,15 @@ public class MediaDetection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String reduceMovieName(String name) throws IOException {
|
||||||
|
Matcher reluctantMatcher = compile("^(.+)[\\[\\(]((?:19|20)\\d{2})[\\]\\)]").matcher(name);
|
||||||
|
if (reluctantMatcher.find()) {
|
||||||
|
return String.format("%s %s", reluctantMatcher.group(1).trim(), reluctantMatcher.group(2));
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static File guessMovieFolder(File movieFile) throws IOException {
|
public static File guessMovieFolder(File movieFile) throws IOException {
|
||||||
// first meaningful parent folder (max 2 levels deep)
|
// first meaningful parent folder (max 2 levels deep)
|
||||||
File f = movieFile.getParentFile();
|
File f = movieFile.getParentFile();
|
||||||
@ -357,24 +366,39 @@ public class MediaDetection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<Movie> matchMovieName(final List<String> files, final Locale locale, final boolean strict) throws Exception {
|
private static List<Entry<String, Movie>> movieIndex;
|
||||||
|
|
||||||
|
|
||||||
|
private static synchronized List<Entry<String, Movie>> getMovieIndex() throws IOException {
|
||||||
|
if (movieIndex == null) {
|
||||||
|
Movie[] movies = releaseInfo.getMovieList();
|
||||||
|
movieIndex = new ArrayList<Entry<String, Movie>>(movies.length);
|
||||||
|
for (Movie movie : movies) {
|
||||||
|
movieIndex.add(new SimpleEntry<String, Movie>(normalizePunctuation(movie.getName()).toLowerCase(), movie));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return movieIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Movie> matchMovieName(final List<String> files, final Locale locale, final boolean strict) throws Exception {
|
||||||
// cross-reference file / folder name with movie list
|
// cross-reference file / folder name with movie list
|
||||||
final HighPerformanceMatcher nameMatcher = new HighPerformanceMatcher(3);
|
final HighPerformanceMatcher nameMatcher = new HighPerformanceMatcher(3);
|
||||||
final Map<Movie, String> matchMap = new HashMap<Movie, String>();
|
final Map<Movie, String> matchMap = new HashMap<Movie, String>();
|
||||||
|
|
||||||
for (final Movie movie : releaseInfo.getMovieList()) {
|
for (Entry<String, Movie> movie : getMovieIndex()) {
|
||||||
for (String name : files) {
|
for (String name : files) {
|
||||||
String movieIdentifier = movie.getName();
|
String movieIdentifier = movie.getKey();
|
||||||
String commonName = nameMatcher.matchFirstCommonSequence(name, movieIdentifier);
|
String commonName = nameMatcher.matchFirstCommonSequence(name, movieIdentifier);
|
||||||
if (commonName != null && commonName.length() >= movieIdentifier.length()) {
|
if (commonName != null && commonName.length() >= movieIdentifier.length()) {
|
||||||
String strictMovieIdentifier = movie.getName() + " " + movie.getYear();
|
String strictMovieIdentifier = movie.getKey() + " " + movie.getValue().getYear();
|
||||||
String strictCommonName = nameMatcher.matchFirstCommonSequence(name, strictMovieIdentifier);
|
String strictCommonName = nameMatcher.matchFirstCommonSequence(name, strictMovieIdentifier);
|
||||||
if (strictCommonName != null && strictCommonName.length() >= strictMovieIdentifier.length()) {
|
if (strictCommonName != null && strictCommonName.length() >= strictMovieIdentifier.length()) {
|
||||||
// prefer strict match
|
// prefer strict match
|
||||||
matchMap.put(movie, strictCommonName);
|
matchMap.put(movie.getValue(), strictCommonName);
|
||||||
} else if (!strict) {
|
} else if (!strict) {
|
||||||
// make sure the common identifier is not just the year
|
// make sure the common identifier is not just the year
|
||||||
matchMap.put(movie, commonName);
|
matchMap.put(movie.getValue(), commonName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +418,32 @@ public class MediaDetection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Movie> matchMovieFromStringWithoutSpacing(List<String> files, SimilarityMetric metric, float similarityThreshold) throws IOException {
|
||||||
|
Pattern spacing = Pattern.compile("[\\p{Punct}\\p{Space}]+");
|
||||||
|
|
||||||
|
List<String> terms = new ArrayList<String>(files.size());
|
||||||
|
for (String it : files) {
|
||||||
|
String term = spacing.matcher(it).replaceAll("").toLowerCase();
|
||||||
|
if (term.length() >= 3) {
|
||||||
|
terms.add(term); // only consider words, not just random letters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Movie> movies = new ArrayList<Movie>();
|
||||||
|
for (Entry<String, Movie> it : getMovieIndex()) {
|
||||||
|
String name = spacing.matcher(it.getKey()).replaceAll("").toLowerCase();
|
||||||
|
for (String term : terms) {
|
||||||
|
if (term.contains(name) && metric.getSimilarity(name, term) >= similarityThreshold) {
|
||||||
|
movies.add(it.getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Collection<Movie> queryMovieByFileName(List<String> files, MovieIdentificationService queryLookupService, Locale locale) throws Exception {
|
private static Collection<Movie> queryMovieByFileName(List<String> files, MovieIdentificationService queryLookupService, Locale locale) throws Exception {
|
||||||
// remove blacklisted terms
|
// remove blacklisted terms
|
||||||
Set<String> querySet = new LinkedHashSet<String>();
|
Set<String> querySet = new LinkedHashSet<String>();
|
||||||
|
@ -3,6 +3,7 @@ package net.sourceforge.filebot.media;
|
|||||||
|
|
||||||
|
|
||||||
import static java.util.Arrays.*;
|
import static java.util.Arrays.*;
|
||||||
|
import static java.util.Collections.*;
|
||||||
import static java.util.ResourceBundle.*;
|
import static java.util.ResourceBundle.*;
|
||||||
import static java.util.regex.Pattern.*;
|
import static java.util.regex.Pattern.*;
|
||||||
import static net.sourceforge.filebot.similarity.Normalization.*;
|
import static net.sourceforge.filebot.similarity.Normalization.*;
|
||||||
@ -28,6 +29,7 @@ import java.util.Map;
|
|||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
@ -93,6 +95,7 @@ public class ReleaseInfo {
|
|||||||
public List<String> cleanRelease(Collection<String> items, boolean strict) throws IOException {
|
public List<String> cleanRelease(Collection<String> items, boolean strict) throws IOException {
|
||||||
Set<String> languages = getLanguageMap(Locale.ENGLISH, Locale.getDefault()).keySet();
|
Set<String> languages = getLanguageMap(Locale.ENGLISH, Locale.getDefault()).keySet();
|
||||||
|
|
||||||
|
Pattern clutterBracket = getClutterBracketPattern(strict);
|
||||||
Pattern releaseGroup = getReleaseGroupPattern(strict);
|
Pattern releaseGroup = getReleaseGroupPattern(strict);
|
||||||
Pattern languageSuffix = getLanguageSuffixPattern(languages);
|
Pattern languageSuffix = getLanguageSuffixPattern(languages);
|
||||||
Pattern languageTag = getLanguageTagPattern(languages);
|
Pattern languageTag = getLanguageTagPattern(languages);
|
||||||
@ -101,8 +104,8 @@ public class ReleaseInfo {
|
|||||||
Pattern resolution = getResolutionPattern();
|
Pattern resolution = getResolutionPattern();
|
||||||
Pattern queryBlacklist = getBlacklistPattern();
|
Pattern queryBlacklist = getBlacklistPattern();
|
||||||
|
|
||||||
Pattern[] blacklist = new Pattern[] { releaseGroup, languageSuffix, languageTag, videoSource, videoFormat, resolution, queryBlacklist };
|
Pattern[] stopwords = new Pattern[] { getReleaseGroupPattern(true), languageTag, videoSource, videoFormat, resolution, languageSuffix };
|
||||||
Pattern[] stopwords = new Pattern[] { getReleaseGroupPattern(true), languageSuffix, languageTag, videoSource, videoFormat, resolution };
|
Pattern[] blacklist = new Pattern[] { clutterBracket, releaseGroup, languageTag, videoSource, videoFormat, resolution, languageSuffix, queryBlacklist };
|
||||||
|
|
||||||
List<String> output = new ArrayList<String>(items.size());
|
List<String> output = new ArrayList<String>(items.size());
|
||||||
for (String it : items) {
|
for (String it : items) {
|
||||||
@ -132,11 +135,9 @@ public class ReleaseInfo {
|
|||||||
for (Pattern it : stopwords) {
|
for (Pattern it : stopwords) {
|
||||||
Matcher matcher = it.matcher(item);
|
Matcher matcher = it.matcher(item);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
return item.substring(0, matcher.start()); // use substring before the matched stopword
|
item = item.substring(0, matcher.start()); // use substring before the matched stopword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no stopword found, keep original string
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +150,7 @@ public class ReleaseInfo {
|
|||||||
|
|
||||||
public Pattern getLanguageSuffixPattern(Collection<String> languages) {
|
public Pattern getLanguageSuffixPattern(Collection<String> languages) {
|
||||||
// .en.srt
|
// .en.srt
|
||||||
return compile("(?<=\\p{Punct}|\\s)(" + join(quoteAll(languages), "|") + ")(?=$)", CASE_INSENSITIVE | UNICODE_CASE | CANON_EQ);
|
return compile("(?<=[\\p{Punct}\\p{Space}])(" + join(quoteAll(languages), "|") + ")(?=[._ ]*$)", CASE_INSENSITIVE | UNICODE_CASE | CANON_EQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -173,6 +174,13 @@ public class ReleaseInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Pattern getClutterBracketPattern(boolean strict) {
|
||||||
|
// match patterns like [Action, Drama] or {ENG-XViD-MP3-DVDRiP} etc
|
||||||
|
String contentFilter = strict ? "[\\p{Space}\\p{Punct}&&[^\\[\\]]]" : "\\p{Alpha}";
|
||||||
|
return compile("(?:\\[([^\\[\\]]+?" + contentFilter + "[^\\[\\]]+?)\\])|(?:\\{([^\\{\\}]+?" + contentFilter + "[^\\{\\}]+?)\\})|(?:\\(([^\\(\\)]+?" + contentFilter + "[^\\(\\)]+?)\\))");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized Pattern getReleaseGroupPattern(boolean strict) throws IOException {
|
public synchronized Pattern getReleaseGroupPattern(boolean strict) throws IOException {
|
||||||
// pattern matching any release group name enclosed in separators
|
// pattern matching any release group name enclosed in separators
|
||||||
return compile("(?<!\\p{Alnum})(" + join(releaseGroupResource.get(), "|") + ")(?!\\p{Alnum})", strict ? 0 : CASE_INSENSITIVE | UNICODE_CASE | CANON_EQ);
|
return compile("(?<!\\p{Alnum})(" + join(releaseGroupResource.get(), "|") + ")(?!\\p{Alnum})", strict ? 0 : CASE_INSENSITIVE | UNICODE_CASE | CANON_EQ);
|
||||||
@ -314,7 +322,17 @@ public class ReleaseInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final Map<Set<Locale>, Map<String, Locale>> languageMapCache = synchronizedMap(new WeakHashMap<Set<Locale>, Map<String, Locale>>(2));
|
||||||
|
|
||||||
|
|
||||||
private Map<String, Locale> getLanguageMap(Locale... supportedDisplayLocale) {
|
private Map<String, Locale> getLanguageMap(Locale... supportedDisplayLocale) {
|
||||||
|
// try cache
|
||||||
|
Set<Locale> displayLocales = new HashSet<Locale>(asList(supportedDisplayLocale));
|
||||||
|
Map<String, Locale> languageMap = languageMapCache.get(displayLocales);
|
||||||
|
if (languageMap != null) {
|
||||||
|
return languageMap;
|
||||||
|
}
|
||||||
|
|
||||||
// use maximum strength collator by default
|
// use maximum strength collator by default
|
||||||
Collator collator = Collator.getInstance(Locale.ROOT);
|
Collator collator = Collator.getInstance(Locale.ROOT);
|
||||||
collator.setDecomposition(Collator.FULL_DECOMPOSITION);
|
collator.setDecomposition(Collator.FULL_DECOMPOSITION);
|
||||||
@ -322,9 +340,7 @@ public class ReleaseInfo {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Comparator<String> order = (Comparator) collator;
|
Comparator<String> order = (Comparator) collator;
|
||||||
|
languageMap = new TreeMap<String, Locale>(order);
|
||||||
Map<String, Locale> languageMap = new TreeMap<String, Locale>(order);
|
|
||||||
Set<Locale> displayLocales = new HashSet<Locale>(asList(supportedDisplayLocale));
|
|
||||||
|
|
||||||
for (String code : Locale.getISOLanguages()) {
|
for (String code : Locale.getISOLanguages()) {
|
||||||
Locale locale = new Locale(code);
|
Locale locale = new Locale(code);
|
||||||
@ -341,7 +357,11 @@ public class ReleaseInfo {
|
|||||||
|
|
||||||
// remove illegal tokens
|
// remove illegal tokens
|
||||||
languageMap.remove("");
|
languageMap.remove("");
|
||||||
return languageMap;
|
languageMap.remove("II");
|
||||||
|
languageMap.remove("III");
|
||||||
|
|
||||||
|
Map<String, Locale> result = unmodifiableMap(languageMap);
|
||||||
|
languageMapCache.put(displayLocales, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# source names mostly copied from [http://en.wikipedia.org/wiki/Pirated_movie_release_types]
|
# source names mostly copied from [http://en.wikipedia.org/wiki/Pirated_movie_release_types]
|
||||||
pattern.video.source: CAMRip|CAM|PDVD|TS|TELESYNC|PDVD|PPV|PPVRip|Screener|SCR|SCREENER|DVDSCR|DVDSCREENER|BDSCR|R5|R5LINE|DVD|DVDRip|DVDR|TVRip|DSR|PDTV|HDTV|DVB|DVBRip|DTHRip|VODRip|VODR|BDRip|BRRip|BluRay|BDR|BR-Scr|BR-Screener|HDDVD|HDRip|WorkPrint|VHS|VCD|TELECINE|WEB-DL|Webrip
|
pattern.video.source: CAMRip|CAM|PDVD|TS|TELESYNC|PDVD|PPV|PPVRip|Screener|SCR|SCREENER|DVDSCR|DVDSCREENER|BDSCR|R4|R5|R5LINE|R5.LINE|DVD|DVDRip|DVDR|TVRip|DSR|PDTV|HDTV|DVB|DVBRip|DTHRip|VODRip|VODR|BDRip|BRRip|BluRay|BDR|BR-Scr|BR-Screener|HDDVD|HDRip|WorkPrint|VHS|VCD|TELECINE|WEB-DL|WEBRip
|
||||||
|
|
||||||
# additional release info patterns
|
# additional release info patterns
|
||||||
pattern.video.format: DivX|Xvid|AVC|x264|h264|3ivx|mpeg|mpeg4|mp3|aac|ac3|2ch|6ch|WS|HR|720p|1080p|NTSC
|
pattern.video.format: DivX|Xvid|AVC|x264|h264|3ivx|mpeg|mpeg4|mp3|aac|ac3|2ch|6ch|WS|HR|720p|1080p|NTSC
|
||||||
|
@ -236,10 +236,12 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
|||||||
|
|
||||||
String input = null;
|
String input = null;
|
||||||
synchronized (inputMemory) {
|
synchronized (inputMemory) {
|
||||||
input = inputMemory.get(suggestion);
|
synchronized (this) {
|
||||||
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
input = inputMemory.get(suggestion);
|
||||||
input = showInputDialog("Enter movie name:", suggestion, String.format("%s/%s", movieFile.getParentFile().getName(), movieFile.getName()), parent);
|
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
||||||
inputMemory.put(suggestion, input);
|
input = showInputDialog("Enter movie name:", suggestion, String.format("%s/%s", movieFile.getParentFile().getName(), movieFile.getName()), parent);
|
||||||
|
inputMemory.put(suggestion, input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,8 +322,8 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// allow only one select dialog at a time
|
// allow only one select dialog at a time
|
||||||
synchronized (this) {
|
synchronized (selectionMemory) {
|
||||||
synchronized (selectionMemory) {
|
synchronized (this) {
|
||||||
if (selectionMemory.containsKey(fileQuery)) {
|
if (selectionMemory.containsKey(fileQuery)) {
|
||||||
return selectionMemory.get(fileQuery);
|
return selectionMemory.get(fileQuery);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ public class OpenSubtitlesXmlRpc {
|
|||||||
|
|
||||||
movies.add(new Movie(name, year, Integer.parseInt(imdbid)));
|
movies.add(new Movie(name, year, Integer.parseInt(imdbid)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(OpenSubtitlesXmlRpc.class.getName()).log(Level.INFO, String.format("Ignore movie %s: %s", movie, e.getMessage()));
|
Logger.getLogger(OpenSubtitlesXmlRpc.class.getName()).log(Level.INFO, String.format("Ignore movie [%s]: %s", movie, e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ public class TMDbClient implements MovieIdentificationService {
|
|||||||
private static final String host = "api.themoviedb.org";
|
private static final String host = "api.themoviedb.org";
|
||||||
private static final String version = "2.1";
|
private static final String version = "2.1";
|
||||||
|
|
||||||
private static final FloodLimit SEARCH_LIMIT = new FloodLimit(10, 10, TimeUnit.SECONDS);
|
private static final FloodLimit SEARCH_LIMIT = new FloodLimit(10, 12, TimeUnit.SECONDS);
|
||||||
private static final FloodLimit REQUEST_LIMIT = new FloodLimit(20, 10, TimeUnit.SECONDS);
|
private static final FloodLimit REQUEST_LIMIT = new FloodLimit(30, 12, TimeUnit.SECONDS);
|
||||||
|
|
||||||
private final String apikey;
|
private final String apikey;
|
||||||
|
|
||||||
@ -114,18 +114,27 @@ public class TMDbClient implements MovieIdentificationService {
|
|||||||
List<Movie> result = new ArrayList<Movie>();
|
List<Movie> result = new ArrayList<Movie>();
|
||||||
|
|
||||||
for (Node node : selectNodes("//movie", dom)) {
|
for (Node node : selectNodes("//movie", dom)) {
|
||||||
|
String name = getTextContent("name", node);
|
||||||
try {
|
try {
|
||||||
String name = getTextContent("name", node);
|
|
||||||
|
|
||||||
// release date format will be YYYY-MM-DD, but we only care about the year
|
// release date format will be YYYY-MM-DD, but we only care about the year
|
||||||
int year = new Scanner(getTextContent("released", node)).useDelimiter("\\D+").nextInt();
|
int year = -1;
|
||||||
|
try {
|
||||||
|
year = new Scanner(getTextContent("released", node)).useDelimiter("\\D+").nextInt();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new IllegalArgumentException("Missing data: year");
|
||||||
|
}
|
||||||
|
|
||||||
// imdb id will be tt1234567, but we only care about the number
|
// imdb id will be tt1234567, but we only care about the number
|
||||||
int imdbid = new Scanner(getTextContent("imdb_id", node)).useDelimiter("\\D+").nextInt();
|
int imdbid = -1;
|
||||||
|
try {
|
||||||
|
imdbid = new Scanner(getTextContent("imdb_id", node)).useDelimiter("\\D+").nextInt();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new IllegalArgumentException("Missing data: imdbid");
|
||||||
|
}
|
||||||
|
|
||||||
result.add(new Movie(name, year, imdbid));
|
result.add(new Movie(name, year, imdbid));
|
||||||
} catch (RuntimeException e) {
|
} catch (Exception e) {
|
||||||
// release date or imdb id are undefined
|
Logger.getLogger(TMDbClient.class.getName()).log(Level.INFO, String.format("Ignore movie [%s]: %s", name, e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,18 @@
|
|||||||
|
(?-i:CLASSiC)
|
||||||
|
(?-i:DOCU)
|
||||||
|
(?-i:ENGLISH)
|
||||||
|
(?-i:FIXED)
|
||||||
|
(?-i:FRENCH)
|
||||||
|
(?-i:GERMAN)
|
||||||
|
(?-i:iNT)
|
||||||
|
(?-i:LIMITED|LiMiTED)
|
||||||
|
(?-i:SPANISH)
|
||||||
|
(?-i:SWEDISH|SWEDiSH)
|
||||||
.+sample$
|
.+sample$
|
||||||
1-3-3-8.com
|
1-3-3-8.com
|
||||||
5[.,]1
|
5[.,]1
|
||||||
@KIDZ
|
@KIDZ
|
||||||
|
[1-3]CD
|
||||||
[1-3]CDRip
|
[1-3]CDRip
|
||||||
[1-9].?of.?[1-9]
|
[1-9].?of.?[1-9]
|
||||||
^(TV.)?(Show|Serie)[s]?
|
^(TV.)?(Show|Serie)[s]?
|
||||||
@ -13,6 +24,7 @@
|
|||||||
^Film[s]?
|
^Film[s]?
|
||||||
^HVDVD_TS$
|
^HVDVD_TS$
|
||||||
^Info
|
^Info
|
||||||
|
^l[^\p{Alnum}]
|
||||||
^Movie[s]?
|
^Movie[s]?
|
||||||
^New$
|
^New$
|
||||||
^SAMPLE
|
^SAMPLE
|
||||||
@ -28,24 +40,28 @@ By.Cool.Release
|
|||||||
CD[0]?[1-3]
|
CD[0]?[1-3]
|
||||||
CN
|
CN
|
||||||
CVCD
|
CVCD
|
||||||
|
DC
|
||||||
Demonoid
|
Demonoid
|
||||||
|
Director's.Cut
|
||||||
Directors.Cut
|
Directors.Cut
|
||||||
|
Dual.Audio
|
||||||
|
dubbed
|
||||||
|
DVDXvID
|
||||||
DVSKY
|
DVSKY
|
||||||
ENG
|
ENG
|
||||||
ENGLISH
|
|
||||||
EXTENDED
|
EXTENDED
|
||||||
Extended.Version
|
Extended.Version
|
||||||
ExtraScene
|
ExtraScene
|
||||||
ExtraTorrent
|
ExtraTorrent
|
||||||
|
Final.Cut
|
||||||
Fra
|
Fra
|
||||||
FRE
|
FRE
|
||||||
FRENCH
|
|
||||||
GER
|
GER
|
||||||
GERMAN
|
|
||||||
Hard.Subbed
|
Hard.Subbed
|
||||||
HDRip
|
HDRip
|
||||||
Hindi
|
Hindi
|
||||||
HQ
|
HQ
|
||||||
|
iNTERNAL
|
||||||
iPod
|
iPod
|
||||||
ISO
|
ISO
|
||||||
iTA
|
iTA
|
||||||
@ -53,9 +69,11 @@ iTALIA
|
|||||||
jigaxx
|
jigaxx
|
||||||
KIDZCORNER
|
KIDZCORNER
|
||||||
KOR
|
KOR
|
||||||
|
KORSUB
|
||||||
|
LMAO
|
||||||
Los.Sustitutos
|
Los.Sustitutos
|
||||||
mkvonly
|
mkvonly
|
||||||
Movie[s]?
|
MultiSub
|
||||||
MVGroup.org
|
MVGroup.org
|
||||||
NL
|
NL
|
||||||
NL.Subs
|
NL.Subs
|
||||||
@ -65,9 +83,12 @@ PROPER
|
|||||||
PSP
|
PSP
|
||||||
READNFO
|
READNFO
|
||||||
REAL.PROPER
|
REAL.PROPER
|
||||||
|
REMASTERED
|
||||||
REPACK
|
REPACK
|
||||||
|
ReRip
|
||||||
RESYNC
|
RESYNC
|
||||||
RETAIL
|
RETAIL
|
||||||
|
RiffTrax
|
||||||
Sample
|
Sample
|
||||||
sample[s]?$
|
sample[s]?$
|
||||||
Screenshot
|
Screenshot
|
||||||
@ -77,7 +98,7 @@ ShareZONE
|
|||||||
ShortKut
|
ShortKut
|
||||||
Snapshots
|
Snapshots
|
||||||
SPA
|
SPA
|
||||||
SPANISH
|
Special.Edition
|
||||||
Sub
|
Sub
|
||||||
SUBBED
|
SUBBED
|
||||||
Subs
|
Subs
|
||||||
@ -87,10 +108,12 @@ swe.?sub
|
|||||||
SYNC
|
SYNC
|
||||||
SYNCFIX
|
SYNCFIX
|
||||||
TC
|
TC
|
||||||
|
theatrical.cut
|
||||||
TPB
|
TPB
|
||||||
TRUEFRENCH
|
TRUEFRENCH
|
||||||
TS
|
TS
|
||||||
TSXVID
|
TSXVID
|
||||||
|
ultimate.edition
|
||||||
UNCUT
|
UNCUT
|
||||||
unrated
|
unrated
|
||||||
unrated.edition
|
unrated.edition
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
2WIRE
|
2WIRE
|
||||||
310yuma
|
310yuma
|
||||||
3Li
|
3Li
|
||||||
|
3LT0N
|
||||||
420RipZ
|
420RipZ
|
||||||
4HM
|
4HM
|
||||||
7SiNS
|
7SiNS
|
||||||
@ -18,6 +19,7 @@ aacrime
|
|||||||
aAF
|
aAF
|
||||||
AaS
|
AaS
|
||||||
aBD
|
aBD
|
||||||
|
AbSurdity
|
||||||
aceford
|
aceford
|
||||||
ADHD
|
ADHD
|
||||||
AE
|
AE
|
||||||
@ -32,14 +34,19 @@ AKUPX
|
|||||||
ALANiS
|
ALANiS
|
||||||
ALeSiO
|
ALeSiO
|
||||||
ALLiANCE
|
ALLiANCE
|
||||||
|
ALLZINE
|
||||||
AMiABLE
|
AMiABLE
|
||||||
|
AN0NYM0US
|
||||||
|
aNBc
|
||||||
ANBU
|
ANBU
|
||||||
Ani-Kraze
|
Ani-Kraze
|
||||||
ANiHLS
|
ANiHLS
|
||||||
AonE
|
AonE
|
||||||
ARiGOLD
|
ARiGOLD
|
||||||
ARROW
|
ARROW
|
||||||
|
ArtSubs
|
||||||
ASAP
|
ASAP
|
||||||
|
ATTENTATET
|
||||||
AVCHD
|
AVCHD
|
||||||
AVS720
|
AVS720
|
||||||
AW
|
AW
|
||||||
@ -56,6 +63,7 @@ bc10
|
|||||||
BDClub
|
BDClub
|
||||||
BDiSC
|
BDiSC
|
||||||
beAst
|
beAst
|
||||||
|
BeStDivX
|
||||||
BestHD
|
BestHD
|
||||||
BiA
|
BiA
|
||||||
BiDA
|
BiDA
|
||||||
@ -69,6 +77,7 @@ BLUEYES
|
|||||||
blueZilla
|
blueZilla
|
||||||
BluWave
|
BluWave
|
||||||
BMB
|
BMB
|
||||||
|
BORGATA
|
||||||
bReAK
|
bReAK
|
||||||
BrG
|
BrG
|
||||||
BRiGHT
|
BRiGHT
|
||||||
@ -109,13 +118,13 @@ COALiTiON
|
|||||||
Cocksure
|
Cocksure
|
||||||
COMPULSION
|
COMPULSION
|
||||||
cottage
|
cottage
|
||||||
|
COWiSO
|
||||||
CPtScene
|
CPtScene
|
||||||
CPY
|
CPY
|
||||||
CRF
|
CRF
|
||||||
CRIMSON
|
CRIMSON
|
||||||
CRiSC
|
CRiSC
|
||||||
CROSSBOW
|
CROSSBOW
|
||||||
Crow
|
|
||||||
CRYS
|
CRYS
|
||||||
CSHD
|
CSHD
|
||||||
CtrlHD
|
CtrlHD
|
||||||
@ -131,15 +140,18 @@ DARM
|
|||||||
DASH
|
DASH
|
||||||
DATA
|
DATA
|
||||||
DAW
|
DAW
|
||||||
|
DCA
|
||||||
DDC
|
DDC
|
||||||
dddc
|
dddc
|
||||||
DEAL
|
DEAL
|
||||||
decibeL
|
decibeL
|
||||||
|
DEFACED
|
||||||
DEFiNiTE
|
DEFiNiTE
|
||||||
DEFiNiTiON
|
DEFiNiTiON
|
||||||
DEFUSED
|
DEFUSED
|
||||||
DEiTY
|
DEiTY
|
||||||
DEPRAViTY
|
DEPRAViTY
|
||||||
|
DEPRiVED
|
||||||
DETAiLS
|
DETAiLS
|
||||||
DEViSE
|
DEViSE
|
||||||
DEWSTRR
|
DEWSTRR
|
||||||
@ -163,6 +175,7 @@ DnB
|
|||||||
DNL
|
DNL
|
||||||
DNR
|
DNR
|
||||||
DON
|
DON
|
||||||
|
DoNE
|
||||||
DOT
|
DOT
|
||||||
doubt
|
doubt
|
||||||
DOWN
|
DOWN
|
||||||
@ -171,6 +184,7 @@ DUPLI
|
|||||||
DUQA
|
DUQA
|
||||||
DutchReleaseTeam
|
DutchReleaseTeam
|
||||||
DvF
|
DvF
|
||||||
|
DVL
|
||||||
EBi
|
EBi
|
||||||
EbP
|
EbP
|
||||||
ECHiZEN
|
ECHiZEN
|
||||||
@ -183,6 +197,7 @@ Electri4ka
|
|||||||
ELECTRiC
|
ELECTRiC
|
||||||
Electrichka
|
Electrichka
|
||||||
elizabethtga
|
elizabethtga
|
||||||
|
EM0C0RE
|
||||||
EmC
|
EmC
|
||||||
EMPiREHD
|
EMPiREHD
|
||||||
ENCOUNTERS
|
ENCOUNTERS
|
||||||
@ -190,6 +205,7 @@ EnDoR
|
|||||||
eots
|
eots
|
||||||
EPiK
|
EPiK
|
||||||
ESiR
|
ESiR
|
||||||
|
ESPiSE
|
||||||
ETHOS
|
ETHOS
|
||||||
ETM
|
ETM
|
||||||
ETRG
|
ETRG
|
||||||
@ -198,8 +214,11 @@ EuchHD
|
|||||||
EUHD
|
EUHD
|
||||||
EuReKA
|
EuReKA
|
||||||
EUSTASS
|
EUSTASS
|
||||||
|
EwDp
|
||||||
|
EXiLE
|
||||||
EXQUiSiTE
|
EXQUiSiTE
|
||||||
ExtraTorrentRG
|
ExtraTorrentRG
|
||||||
|
EXViD
|
||||||
eztv
|
eztv
|
||||||
FaNSuB
|
FaNSuB
|
||||||
FASM
|
FASM
|
||||||
@ -210,10 +229,14 @@ FHM
|
|||||||
FiCO
|
FiCO
|
||||||
FiHTV
|
FiHTV
|
||||||
FilmHD
|
FilmHD
|
||||||
|
FiNaLe
|
||||||
|
fjall
|
||||||
FLAiTE
|
FLAiTE
|
||||||
|
Flaket
|
||||||
fLAMEhd
|
fLAMEhd
|
||||||
FLAWL3SS
|
FLAWL3SS
|
||||||
Flomp-Rumbel
|
Flomp-Rumbel
|
||||||
|
FLS
|
||||||
FLX
|
FLX
|
||||||
FmE
|
FmE
|
||||||
ForceBleue
|
ForceBleue
|
||||||
@ -232,6 +255,7 @@ FTVDT
|
|||||||
FTW-FM
|
FTW-FM
|
||||||
FTW-HD
|
FTW-HD
|
||||||
fty
|
fty
|
||||||
|
FUCT
|
||||||
Funner
|
Funner
|
||||||
FXG
|
FXG
|
||||||
FxM
|
FxM
|
||||||
@ -239,8 +263,10 @@ G3N3
|
|||||||
GAGE
|
GAGE
|
||||||
Gazdi
|
Gazdi
|
||||||
GB
|
GB
|
||||||
|
GECKOS
|
||||||
GEHENNA
|
GEHENNA
|
||||||
george.c
|
george.c
|
||||||
|
GFW
|
||||||
GFY
|
GFY
|
||||||
GiNJi
|
GiNJi
|
||||||
GMoRK
|
GMoRK
|
||||||
@ -250,6 +276,7 @@ GoLDSToNE
|
|||||||
GOTHiC
|
GOTHiC
|
||||||
GriOTS
|
GriOTS
|
||||||
Grond
|
Grond
|
||||||
|
gudhak
|
||||||
H2
|
H2
|
||||||
h264iRMU
|
h264iRMU
|
||||||
H@M
|
H@M
|
||||||
@ -293,6 +320,7 @@ HiFi
|
|||||||
HiGHTIMES
|
HiGHTIMES
|
||||||
HiNT
|
HiNT
|
||||||
HoodBag
|
HoodBag
|
||||||
|
HORiZON
|
||||||
HOWL
|
HOWL
|
||||||
HqDTS
|
HqDTS
|
||||||
HUBRiS
|
HUBRiS
|
||||||
@ -305,10 +333,13 @@ iaK
|
|||||||
iBEX
|
iBEX
|
||||||
iCANDY
|
iCANDY
|
||||||
iGNHD
|
iGNHD
|
||||||
|
iGNiTiON
|
||||||
IGUANA
|
IGUANA
|
||||||
iKA
|
iKA
|
||||||
|
iLG
|
||||||
iLL
|
iLL
|
||||||
iMAGiNE
|
iMAGiNE
|
||||||
|
iMBT
|
||||||
IMF
|
IMF
|
||||||
IMMERSE
|
IMMERSE
|
||||||
imNaKeD
|
imNaKeD
|
||||||
@ -330,6 +361,7 @@ JAVLiU
|
|||||||
JCH
|
JCH
|
||||||
JENC
|
JENC
|
||||||
JJH
|
JJH
|
||||||
|
JoLLyRoGeR
|
||||||
K-F
|
K-F
|
||||||
k2
|
k2
|
||||||
KaKa
|
KaKa
|
||||||
@ -337,7 +369,9 @@ kamera
|
|||||||
keltz
|
keltz
|
||||||
KiNGS
|
KiNGS
|
||||||
KLAXXON
|
KLAXXON
|
||||||
|
KlockreN
|
||||||
KOENiG
|
KOENiG
|
||||||
|
KonzillaRG
|
||||||
KRaLiMaRKo
|
KRaLiMaRKo
|
||||||
KYR
|
KYR
|
||||||
Kyuubi
|
Kyuubi
|
||||||
@ -355,6 +389,7 @@ LOLCATS
|
|||||||
LoneWolf
|
LoneWolf
|
||||||
LOST
|
LOST
|
||||||
LP
|
LP
|
||||||
|
LTRG
|
||||||
LTT
|
LTT
|
||||||
LUSO
|
LUSO
|
||||||
M794
|
M794
|
||||||
@ -367,6 +402,7 @@ MARiNES
|
|||||||
MAXSPEED
|
MAXSPEED
|
||||||
MC
|
MC
|
||||||
MCR
|
MCR
|
||||||
|
MEDiAMANiACS
|
||||||
MEDiEVAL
|
MEDiEVAL
|
||||||
MELiTE
|
MELiTE
|
||||||
MeTH
|
MeTH
|
||||||
@ -376,16 +412,20 @@ MiND
|
|||||||
MiNT
|
MiNT
|
||||||
MiRAGETV
|
MiRAGETV
|
||||||
MMI
|
MMI
|
||||||
|
MoF
|
||||||
MOMENTUM
|
MOMENTUM
|
||||||
MONK
|
MONK
|
||||||
MOREHD
|
MOREHD
|
||||||
MOTU
|
MOTU
|
||||||
|
MOViERUSH
|
||||||
MOViESTARS
|
MOViESTARS
|
||||||
|
MrLore
|
||||||
mSD
|
mSD
|
||||||
MsR
|
MsR
|
||||||
MuSt
|
MuSt
|
||||||
mV4U
|
mV4U
|
||||||
mVmHD
|
mVmHD
|
||||||
|
MXMG
|
||||||
MySiLU
|
MySiLU
|
||||||
N-F
|
N-F
|
||||||
NaRB
|
NaRB
|
||||||
@ -405,8 +445,9 @@ Nile
|
|||||||
NiX
|
NiX
|
||||||
NL.Subs
|
NL.Subs
|
||||||
NODLABS
|
NODLABS
|
||||||
|
NoGrp
|
||||||
NOHD
|
NOHD
|
||||||
Noir
|
NOiR
|
||||||
NORARS
|
NORARS
|
||||||
NoSCR
|
NoSCR
|
||||||
NOsegmenT
|
NOsegmenT
|
||||||
@ -427,12 +468,15 @@ ONYX
|
|||||||
ORC
|
ORC
|
||||||
ORENJi
|
ORENJi
|
||||||
ORPHEUS
|
ORPHEUS
|
||||||
|
OSiRiS
|
||||||
OSiTV
|
OSiTV
|
||||||
OUTDATED
|
OUTDATED
|
||||||
OZC
|
OZC
|
||||||
P0W4
|
P0W4
|
||||||
Pa@Ph
|
Pa@Ph
|
||||||
|
PADDO
|
||||||
papi
|
papi
|
||||||
|
PARTiCLE
|
||||||
PaYxXx
|
PaYxXx
|
||||||
PeeWee
|
PeeWee
|
||||||
PELLUCiD
|
PELLUCiD
|
||||||
@ -445,12 +489,15 @@ PiLAF
|
|||||||
PiNER
|
PiNER
|
||||||
PiX
|
PiX
|
||||||
PixelHD
|
PixelHD
|
||||||
|
playXD
|
||||||
POD
|
POD
|
||||||
PoRNDoCtOR
|
PoRNDoCtOR
|
||||||
PORNOHOLiCS
|
PORNOHOLiCS
|
||||||
|
PosTX
|
||||||
PoTuS
|
PoTuS
|
||||||
PP
|
PP
|
||||||
PPQ
|
PPQ
|
||||||
|
PRECiOUS
|
||||||
Prime
|
Prime
|
||||||
PriMeHD
|
PriMeHD
|
||||||
PRiNCE
|
PRiNCE
|
||||||
@ -460,10 +507,11 @@ PROPHETS
|
|||||||
ProPL
|
ProPL
|
||||||
PRXHD
|
PRXHD
|
||||||
PS3-TEAM
|
PS3-TEAM
|
||||||
psig
|
PSiG
|
||||||
PSV
|
PSV
|
||||||
PSYCHD
|
PSYCHD
|
||||||
Pti
|
Pti
|
||||||
|
PtP
|
||||||
PtS
|
PtS
|
||||||
Pudding
|
Pudding
|
||||||
Pukka
|
Pukka
|
||||||
@ -474,6 +522,7 @@ PxHD
|
|||||||
Q0S
|
Q0S
|
||||||
QCF
|
QCF
|
||||||
QDP
|
QDP
|
||||||
|
QiX
|
||||||
QSP
|
QSP
|
||||||
QXE
|
QXE
|
||||||
R&C
|
R&C
|
||||||
@ -493,14 +542,17 @@ REWARD
|
|||||||
RightSiZE
|
RightSiZE
|
||||||
RiplleyHD
|
RiplleyHD
|
||||||
RiPTATORz
|
RiPTATORz
|
||||||
|
RiTALiX
|
||||||
RiVER
|
RiVER
|
||||||
RMT
|
RMT
|
||||||
RoCKRioT
|
RoCKRioT
|
||||||
ROVERS
|
ROVERS
|
||||||
RSG
|
RSG
|
||||||
RTA
|
RTA
|
||||||
|
RUBY
|
||||||
RuDE
|
RuDE
|
||||||
RUDOS
|
RUDOS
|
||||||
|
RUSTLE
|
||||||
Ryugan
|
Ryugan
|
||||||
S26
|
S26
|
||||||
SAiMORNY
|
SAiMORNY
|
||||||
@ -508,10 +560,12 @@ SAiNTS
|
|||||||
SAiVERT
|
SAiVERT
|
||||||
SAMFD
|
SAMFD
|
||||||
SANTI
|
SANTI
|
||||||
saphire
|
SAPHiRE
|
||||||
Sapphire
|
Sapphire
|
||||||
|
SChiZO
|
||||||
Scratch404
|
Scratch404
|
||||||
Scratched
|
Scratched
|
||||||
|
ScWb
|
||||||
SecretMyth
|
SecretMyth
|
||||||
SECTOR7
|
SECTOR7
|
||||||
SEMTEX
|
SEMTEX
|
||||||
@ -526,6 +580,7 @@ SHDXXX
|
|||||||
shortbrehd
|
shortbrehd
|
||||||
SHS
|
SHS
|
||||||
SHUNPO
|
SHUNPO
|
||||||
|
SiC
|
||||||
SiGHTHD
|
SiGHTHD
|
||||||
SiHD
|
SiHD
|
||||||
SiLU
|
SiLU
|
||||||
@ -536,6 +591,7 @@ SLM
|
|||||||
SLO
|
SLO
|
||||||
SMoKeR
|
SMoKeR
|
||||||
Sneak
|
Sneak
|
||||||
|
SNUGGLER
|
||||||
SoCkS
|
SoCkS
|
||||||
Softfeng
|
Softfeng
|
||||||
SoW
|
SoW
|
||||||
@ -543,6 +599,7 @@ SpaceHD
|
|||||||
SPARKS
|
SPARKS
|
||||||
SPOOKY
|
SPOOKY
|
||||||
SSF
|
SSF
|
||||||
|
Stealthmaster
|
||||||
stieg
|
stieg
|
||||||
Stranded
|
Stranded
|
||||||
streetwars
|
streetwars
|
||||||
@ -556,18 +613,24 @@ Swesub
|
|||||||
SYS
|
SYS
|
||||||
t00ng0d
|
t00ng0d
|
||||||
Taka
|
Taka
|
||||||
|
TARGET
|
||||||
|
TASTE
|
||||||
TASTETV
|
TASTETV
|
||||||
TB
|
TB
|
||||||
|
TDF
|
||||||
TELEFLiX
|
TELEFLiX
|
||||||
TENEIGHTY
|
TENEIGHTY
|
||||||
TERRA
|
TERRA
|
||||||
terribleHD
|
terribleHD
|
||||||
terribleSD
|
terribleSD
|
||||||
THENiGHTMAREiNHD
|
THENiGHTMAREiNHD
|
||||||
|
TheWretched
|
||||||
THOR
|
THOR
|
||||||
THORA
|
THORA
|
||||||
THUGLiNE
|
THUGLiNE
|
||||||
|
TiDE
|
||||||
TiMELORDS
|
TiMELORDS
|
||||||
|
TiMPE
|
||||||
TiMTY
|
TiMTY
|
||||||
TiTANS
|
TiTANS
|
||||||
TjHD
|
TjHD
|
||||||
@ -599,16 +662,21 @@ UNVEiL
|
|||||||
USELESS
|
USELESS
|
||||||
UVall
|
UVall
|
||||||
VaAr3
|
VaAr3
|
||||||
|
VALiOMEDiA
|
||||||
|
VAMPS
|
||||||
Vanillapunk
|
Vanillapunk
|
||||||
VanRay
|
VanRay
|
||||||
VCDVaULT
|
VCDVaULT
|
||||||
|
VeGaN
|
||||||
Vegapunk
|
Vegapunk
|
||||||
ViCiOsO
|
ViCiOsO
|
||||||
ViKAT
|
ViKAT
|
||||||
ViNYL
|
ViNYL
|
||||||
|
ViP3R
|
||||||
ViSiON
|
ViSiON
|
||||||
ViSTA
|
ViSTA
|
||||||
ViSTA™
|
ViSTA™
|
||||||
|
ViTE
|
||||||
VLiS
|
VLiS
|
||||||
VOA
|
VOA
|
||||||
VoMiT
|
VoMiT
|
||||||
@ -618,6 +686,7 @@ VoXHD
|
|||||||
vrs
|
vrs
|
||||||
w0rm
|
w0rm
|
||||||
w4f
|
w4f
|
||||||
|
WAF
|
||||||
WANKAZ
|
WANKAZ
|
||||||
WASTE
|
WASTE
|
||||||
WAVEY
|
WAVEY
|
||||||
@ -643,6 +712,7 @@ XSHD
|
|||||||
XSTREEM
|
XSTREEM
|
||||||
XTM
|
XTM
|
||||||
XTSF
|
XTSF
|
||||||
|
XviK
|
||||||
XXX4U
|
XXX4U
|
||||||
YanY
|
YanY
|
||||||
YellowBeast
|
YellowBeast
|
||||||
|
Loading…
Reference in New Issue
Block a user