* 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') })
|
||||
println "Movie Count: " + movies.size()
|
||||
|
|
|
@ -313,8 +313,9 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||
derivatesByMovieFile.put(movieFile, new ArrayList<File>());
|
||||
}
|
||||
for (File file : orphanedFiles) {
|
||||
List<File> orphanParent = listPath(file);
|
||||
for (File movieFile : movieFiles) {
|
||||
if (isDerived(file, movieFile)) {
|
||||
if (orphanParent.contains(movieFile.getParentFile()) && isDerived(file, movieFile)) {
|
||||
derivatesByMovieFile.get(movieFile).add(file);
|
||||
break;
|
||||
}
|
||||
|
@ -382,7 +383,11 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||
if (movie == null) {
|
||||
CLILogger.fine(format("Auto-detect movie from context: [%s]", file));
|
||||
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) {
|
||||
Analytics.trackEvent(service.getName(), "SearchMovie", movie.toString(), 1);
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.text.CollationKey;
|
||||
import java.text.Collator;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
@ -301,19 +302,13 @@ public class MediaDetection {
|
|||
|
||||
// search by file name or folder name
|
||||
List<String> terms = new ArrayList<String>();
|
||||
|
||||
// 1. term: try to match movie pattern 'name (year)' or use filename as is
|
||||
Matcher nameMatcher = compile("^(.+?)[(]((?:19|20)\\d{2})[)]").matcher(movieFile.getName());
|
||||
if (nameMatcher.find()) {
|
||||
terms.add(String.format("%s (%s)", nameMatcher.group(1).trim(), nameMatcher.group(2)));
|
||||
} else {
|
||||
terms.add(getName(movieFile));
|
||||
}
|
||||
terms.add(reduceMovieName(getName(movieFile)));
|
||||
|
||||
// 2. term: first meaningful parent folder
|
||||
File movieFolder = guessMovieFolder(movieFile);
|
||||
if (movieFolder != null) {
|
||||
terms.add(getName(movieFolder));
|
||||
terms.add(reduceMovieName(getName(movieFolder)));
|
||||
}
|
||||
|
||||
List<Movie> movieNameMatches = matchMovieName(terms, locale, strict);
|
||||
|
@ -329,6 +324,11 @@ public class MediaDetection {
|
|||
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
|
||||
if (queryLookupService != null) {
|
||||
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 {
|
||||
// first meaningful parent folder (max 2 levels deep)
|
||||
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
|
||||
final HighPerformanceMatcher nameMatcher = new HighPerformanceMatcher(3);
|
||||
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) {
|
||||
String movieIdentifier = movie.getName();
|
||||
String movieIdentifier = movie.getKey();
|
||||
String commonName = nameMatcher.matchFirstCommonSequence(name, movieIdentifier);
|
||||
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);
|
||||
if (strictCommonName != null && strictCommonName.length() >= strictMovieIdentifier.length()) {
|
||||
// prefer strict match
|
||||
matchMap.put(movie, strictCommonName);
|
||||
matchMap.put(movie.getValue(), strictCommonName);
|
||||
} else if (!strict) {
|
||||
// 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 {
|
||||
// remove blacklisted terms
|
||||
Set<String> querySet = new LinkedHashSet<String>();
|
||||
|
|
|
@ -3,6 +3,7 @@ package net.sourceforge.filebot.media;
|
|||
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
import static java.util.Collections.*;
|
||||
import static java.util.ResourceBundle.*;
|
||||
import static java.util.regex.Pattern.*;
|
||||
import static net.sourceforge.filebot.similarity.Normalization.*;
|
||||
|
@ -28,6 +29,7 @@ import java.util.Map;
|
|||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
@ -93,6 +95,7 @@ public class ReleaseInfo {
|
|||
public List<String> cleanRelease(Collection<String> items, boolean strict) throws IOException {
|
||||
Set<String> languages = getLanguageMap(Locale.ENGLISH, Locale.getDefault()).keySet();
|
||||
|
||||
Pattern clutterBracket = getClutterBracketPattern(strict);
|
||||
Pattern releaseGroup = getReleaseGroupPattern(strict);
|
||||
Pattern languageSuffix = getLanguageSuffixPattern(languages);
|
||||
Pattern languageTag = getLanguageTagPattern(languages);
|
||||
|
@ -101,8 +104,8 @@ public class ReleaseInfo {
|
|||
Pattern resolution = getResolutionPattern();
|
||||
Pattern queryBlacklist = getBlacklistPattern();
|
||||
|
||||
Pattern[] blacklist = new Pattern[] { releaseGroup, languageSuffix, languageTag, videoSource, videoFormat, resolution, queryBlacklist };
|
||||
Pattern[] stopwords = new Pattern[] { getReleaseGroupPattern(true), languageSuffix, languageTag, videoSource, videoFormat, resolution };
|
||||
Pattern[] stopwords = new Pattern[] { getReleaseGroupPattern(true), languageTag, videoSource, videoFormat, resolution, languageSuffix };
|
||||
Pattern[] blacklist = new Pattern[] { clutterBracket, releaseGroup, languageTag, videoSource, videoFormat, resolution, languageSuffix, queryBlacklist };
|
||||
|
||||
List<String> output = new ArrayList<String>(items.size());
|
||||
for (String it : items) {
|
||||
|
@ -132,11 +135,9 @@ public class ReleaseInfo {
|
|||
for (Pattern it : stopwords) {
|
||||
Matcher matcher = it.matcher(item);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -149,7 +150,7 @@ public class ReleaseInfo {
|
|||
|
||||
public Pattern getLanguageSuffixPattern(Collection<String> languages) {
|
||||
// .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 {
|
||||
// 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);
|
||||
|
@ -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) {
|
||||
// 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
|
||||
Collator collator = Collator.getInstance(Locale.ROOT);
|
||||
collator.setDecomposition(Collator.FULL_DECOMPOSITION);
|
||||
|
@ -322,9 +340,7 @@ public class ReleaseInfo {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
Comparator<String> order = (Comparator) collator;
|
||||
|
||||
Map<String, Locale> languageMap = new TreeMap<String, Locale>(order);
|
||||
Set<Locale> displayLocales = new HashSet<Locale>(asList(supportedDisplayLocale));
|
||||
languageMap = new TreeMap<String, Locale>(order);
|
||||
|
||||
for (String code : Locale.getISOLanguages()) {
|
||||
Locale locale = new Locale(code);
|
||||
|
@ -341,7 +357,11 @@ public class ReleaseInfo {
|
|||
|
||||
// remove illegal tokens
|
||||
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]
|
||||
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
|
||||
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;
|
||||
synchronized (inputMemory) {
|
||||
input = inputMemory.get(suggestion);
|
||||
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
||||
input = showInputDialog("Enter movie name:", suggestion, String.format("%s/%s", movieFile.getParentFile().getName(), movieFile.getName()), parent);
|
||||
inputMemory.put(suggestion, input);
|
||||
synchronized (this) {
|
||||
input = inputMemory.get(suggestion);
|
||||
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
||||
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
|
||||
synchronized (this) {
|
||||
synchronized (selectionMemory) {
|
||||
synchronized (selectionMemory) {
|
||||
synchronized (this) {
|
||||
if (selectionMemory.containsKey(fileQuery)) {
|
||||
return selectionMemory.get(fileQuery);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ public class OpenSubtitlesXmlRpc {
|
|||
|
||||
movies.add(new Movie(name, year, Integer.parseInt(imdbid)));
|
||||
} 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 version = "2.1";
|
||||
|
||||
private static final FloodLimit SEARCH_LIMIT = new FloodLimit(10, 10, TimeUnit.SECONDS);
|
||||
private static final FloodLimit REQUEST_LIMIT = new FloodLimit(20, 10, TimeUnit.SECONDS);
|
||||
private static final FloodLimit SEARCH_LIMIT = new FloodLimit(10, 12, TimeUnit.SECONDS);
|
||||
private static final FloodLimit REQUEST_LIMIT = new FloodLimit(30, 12, TimeUnit.SECONDS);
|
||||
|
||||
private final String apikey;
|
||||
|
||||
|
@ -114,18 +114,27 @@ public class TMDbClient implements MovieIdentificationService {
|
|||
List<Movie> result = new ArrayList<Movie>();
|
||||
|
||||
for (Node node : selectNodes("//movie", dom)) {
|
||||
String name = getTextContent("name", node);
|
||||
try {
|
||||
String name = getTextContent("name", node);
|
||||
|
||||
// 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
|
||||
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));
|
||||
} catch (RuntimeException e) {
|
||||
// release date or imdb id are undefined
|
||||
} catch (Exception e) {
|
||||
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$
|
||||
1-3-3-8.com
|
||||
5[.,]1
|
||||
@KIDZ
|
||||
[1-3]CD
|
||||
[1-3]CDRip
|
||||
[1-9].?of.?[1-9]
|
||||
^(TV.)?(Show|Serie)[s]?
|
||||
|
@ -13,6 +24,7 @@
|
|||
^Film[s]?
|
||||
^HVDVD_TS$
|
||||
^Info
|
||||
^l[^\p{Alnum}]
|
||||
^Movie[s]?
|
||||
^New$
|
||||
^SAMPLE
|
||||
|
@ -28,24 +40,28 @@ By.Cool.Release
|
|||
CD[0]?[1-3]
|
||||
CN
|
||||
CVCD
|
||||
DC
|
||||
Demonoid
|
||||
Director's.Cut
|
||||
Directors.Cut
|
||||
Dual.Audio
|
||||
dubbed
|
||||
DVDXvID
|
||||
DVSKY
|
||||
ENG
|
||||
ENGLISH
|
||||
EXTENDED
|
||||
Extended.Version
|
||||
ExtraScene
|
||||
ExtraTorrent
|
||||
Final.Cut
|
||||
Fra
|
||||
FRE
|
||||
FRENCH
|
||||
GER
|
||||
GERMAN
|
||||
Hard.Subbed
|
||||
HDRip
|
||||
Hindi
|
||||
HQ
|
||||
iNTERNAL
|
||||
iPod
|
||||
ISO
|
||||
iTA
|
||||
|
@ -53,9 +69,11 @@ iTALIA
|
|||
jigaxx
|
||||
KIDZCORNER
|
||||
KOR
|
||||
KORSUB
|
||||
LMAO
|
||||
Los.Sustitutos
|
||||
mkvonly
|
||||
Movie[s]?
|
||||
MultiSub
|
||||
MVGroup.org
|
||||
NL
|
||||
NL.Subs
|
||||
|
@ -65,9 +83,12 @@ PROPER
|
|||
PSP
|
||||
READNFO
|
||||
REAL.PROPER
|
||||
REMASTERED
|
||||
REPACK
|
||||
ReRip
|
||||
RESYNC
|
||||
RETAIL
|
||||
RiffTrax
|
||||
Sample
|
||||
sample[s]?$
|
||||
Screenshot
|
||||
|
@ -77,7 +98,7 @@ ShareZONE
|
|||
ShortKut
|
||||
Snapshots
|
||||
SPA
|
||||
SPANISH
|
||||
Special.Edition
|
||||
Sub
|
||||
SUBBED
|
||||
Subs
|
||||
|
@ -87,10 +108,12 @@ swe.?sub
|
|||
SYNC
|
||||
SYNCFIX
|
||||
TC
|
||||
theatrical.cut
|
||||
TPB
|
||||
TRUEFRENCH
|
||||
TS
|
||||
TSXVID
|
||||
ultimate.edition
|
||||
UNCUT
|
||||
unrated
|
||||
unrated.edition
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
2WIRE
|
||||
310yuma
|
||||
3Li
|
||||
3LT0N
|
||||
420RipZ
|
||||
4HM
|
||||
7SiNS
|
||||
|
@ -18,6 +19,7 @@ aacrime
|
|||
aAF
|
||||
AaS
|
||||
aBD
|
||||
AbSurdity
|
||||
aceford
|
||||
ADHD
|
||||
AE
|
||||
|
@ -32,14 +34,19 @@ AKUPX
|
|||
ALANiS
|
||||
ALeSiO
|
||||
ALLiANCE
|
||||
ALLZINE
|
||||
AMiABLE
|
||||
AN0NYM0US
|
||||
aNBc
|
||||
ANBU
|
||||
Ani-Kraze
|
||||
ANiHLS
|
||||
AonE
|
||||
ARiGOLD
|
||||
ARROW
|
||||
ArtSubs
|
||||
ASAP
|
||||
ATTENTATET
|
||||
AVCHD
|
||||
AVS720
|
||||
AW
|
||||
|
@ -56,6 +63,7 @@ bc10
|
|||
BDClub
|
||||
BDiSC
|
||||
beAst
|
||||
BeStDivX
|
||||
BestHD
|
||||
BiA
|
||||
BiDA
|
||||
|
@ -69,6 +77,7 @@ BLUEYES
|
|||
blueZilla
|
||||
BluWave
|
||||
BMB
|
||||
BORGATA
|
||||
bReAK
|
||||
BrG
|
||||
BRiGHT
|
||||
|
@ -109,13 +118,13 @@ COALiTiON
|
|||
Cocksure
|
||||
COMPULSION
|
||||
cottage
|
||||
COWiSO
|
||||
CPtScene
|
||||
CPY
|
||||
CRF
|
||||
CRIMSON
|
||||
CRiSC
|
||||
CROSSBOW
|
||||
Crow
|
||||
CRYS
|
||||
CSHD
|
||||
CtrlHD
|
||||
|
@ -131,15 +140,18 @@ DARM
|
|||
DASH
|
||||
DATA
|
||||
DAW
|
||||
DCA
|
||||
DDC
|
||||
dddc
|
||||
DEAL
|
||||
decibeL
|
||||
DEFACED
|
||||
DEFiNiTE
|
||||
DEFiNiTiON
|
||||
DEFUSED
|
||||
DEiTY
|
||||
DEPRAViTY
|
||||
DEPRiVED
|
||||
DETAiLS
|
||||
DEViSE
|
||||
DEWSTRR
|
||||
|
@ -163,6 +175,7 @@ DnB
|
|||
DNL
|
||||
DNR
|
||||
DON
|
||||
DoNE
|
||||
DOT
|
||||
doubt
|
||||
DOWN
|
||||
|
@ -171,6 +184,7 @@ DUPLI
|
|||
DUQA
|
||||
DutchReleaseTeam
|
||||
DvF
|
||||
DVL
|
||||
EBi
|
||||
EbP
|
||||
ECHiZEN
|
||||
|
@ -183,6 +197,7 @@ Electri4ka
|
|||
ELECTRiC
|
||||
Electrichka
|
||||
elizabethtga
|
||||
EM0C0RE
|
||||
EmC
|
||||
EMPiREHD
|
||||
ENCOUNTERS
|
||||
|
@ -190,6 +205,7 @@ EnDoR
|
|||
eots
|
||||
EPiK
|
||||
ESiR
|
||||
ESPiSE
|
||||
ETHOS
|
||||
ETM
|
||||
ETRG
|
||||
|
@ -198,8 +214,11 @@ EuchHD
|
|||
EUHD
|
||||
EuReKA
|
||||
EUSTASS
|
||||
EwDp
|
||||
EXiLE
|
||||
EXQUiSiTE
|
||||
ExtraTorrentRG
|
||||
EXViD
|
||||
eztv
|
||||
FaNSuB
|
||||
FASM
|
||||
|
@ -210,10 +229,14 @@ FHM
|
|||
FiCO
|
||||
FiHTV
|
||||
FilmHD
|
||||
FiNaLe
|
||||
fjall
|
||||
FLAiTE
|
||||
Flaket
|
||||
fLAMEhd
|
||||
FLAWL3SS
|
||||
Flomp-Rumbel
|
||||
FLS
|
||||
FLX
|
||||
FmE
|
||||
ForceBleue
|
||||
|
@ -232,6 +255,7 @@ FTVDT
|
|||
FTW-FM
|
||||
FTW-HD
|
||||
fty
|
||||
FUCT
|
||||
Funner
|
||||
FXG
|
||||
FxM
|
||||
|
@ -239,8 +263,10 @@ G3N3
|
|||
GAGE
|
||||
Gazdi
|
||||
GB
|
||||
GECKOS
|
||||
GEHENNA
|
||||
george.c
|
||||
GFW
|
||||
GFY
|
||||
GiNJi
|
||||
GMoRK
|
||||
|
@ -250,6 +276,7 @@ GoLDSToNE
|
|||
GOTHiC
|
||||
GriOTS
|
||||
Grond
|
||||
gudhak
|
||||
H2
|
||||
h264iRMU
|
||||
H@M
|
||||
|
@ -293,6 +320,7 @@ HiFi
|
|||
HiGHTIMES
|
||||
HiNT
|
||||
HoodBag
|
||||
HORiZON
|
||||
HOWL
|
||||
HqDTS
|
||||
HUBRiS
|
||||
|
@ -305,10 +333,13 @@ iaK
|
|||
iBEX
|
||||
iCANDY
|
||||
iGNHD
|
||||
iGNiTiON
|
||||
IGUANA
|
||||
iKA
|
||||
iLG
|
||||
iLL
|
||||
iMAGiNE
|
||||
iMBT
|
||||
IMF
|
||||
IMMERSE
|
||||
imNaKeD
|
||||
|
@ -330,6 +361,7 @@ JAVLiU
|
|||
JCH
|
||||
JENC
|
||||
JJH
|
||||
JoLLyRoGeR
|
||||
K-F
|
||||
k2
|
||||
KaKa
|
||||
|
@ -337,7 +369,9 @@ kamera
|
|||
keltz
|
||||
KiNGS
|
||||
KLAXXON
|
||||
KlockreN
|
||||
KOENiG
|
||||
KonzillaRG
|
||||
KRaLiMaRKo
|
||||
KYR
|
||||
Kyuubi
|
||||
|
@ -355,6 +389,7 @@ LOLCATS
|
|||
LoneWolf
|
||||
LOST
|
||||
LP
|
||||
LTRG
|
||||
LTT
|
||||
LUSO
|
||||
M794
|
||||
|
@ -367,6 +402,7 @@ MARiNES
|
|||
MAXSPEED
|
||||
MC
|
||||
MCR
|
||||
MEDiAMANiACS
|
||||
MEDiEVAL
|
||||
MELiTE
|
||||
MeTH
|
||||
|
@ -376,16 +412,20 @@ MiND
|
|||
MiNT
|
||||
MiRAGETV
|
||||
MMI
|
||||
MoF
|
||||
MOMENTUM
|
||||
MONK
|
||||
MOREHD
|
||||
MOTU
|
||||
MOViERUSH
|
||||
MOViESTARS
|
||||
MrLore
|
||||
mSD
|
||||
MsR
|
||||
MuSt
|
||||
mV4U
|
||||
mVmHD
|
||||
MXMG
|
||||
MySiLU
|
||||
N-F
|
||||
NaRB
|
||||
|
@ -405,8 +445,9 @@ Nile
|
|||
NiX
|
||||
NL.Subs
|
||||
NODLABS
|
||||
NoGrp
|
||||
NOHD
|
||||
Noir
|
||||
NOiR
|
||||
NORARS
|
||||
NoSCR
|
||||
NOsegmenT
|
||||
|
@ -427,12 +468,15 @@ ONYX
|
|||
ORC
|
||||
ORENJi
|
||||
ORPHEUS
|
||||
OSiRiS
|
||||
OSiTV
|
||||
OUTDATED
|
||||
OZC
|
||||
P0W4
|
||||
Pa@Ph
|
||||
PADDO
|
||||
papi
|
||||
PARTiCLE
|
||||
PaYxXx
|
||||
PeeWee
|
||||
PELLUCiD
|
||||
|
@ -445,12 +489,15 @@ PiLAF
|
|||
PiNER
|
||||
PiX
|
||||
PixelHD
|
||||
playXD
|
||||
POD
|
||||
PoRNDoCtOR
|
||||
PORNOHOLiCS
|
||||
PosTX
|
||||
PoTuS
|
||||
PP
|
||||
PPQ
|
||||
PRECiOUS
|
||||
Prime
|
||||
PriMeHD
|
||||
PRiNCE
|
||||
|
@ -460,10 +507,11 @@ PROPHETS
|
|||
ProPL
|
||||
PRXHD
|
||||
PS3-TEAM
|
||||
psig
|
||||
PSiG
|
||||
PSV
|
||||
PSYCHD
|
||||
Pti
|
||||
PtP
|
||||
PtS
|
||||
Pudding
|
||||
Pukka
|
||||
|
@ -474,6 +522,7 @@ PxHD
|
|||
Q0S
|
||||
QCF
|
||||
QDP
|
||||
QiX
|
||||
QSP
|
||||
QXE
|
||||
R&C
|
||||
|
@ -493,14 +542,17 @@ REWARD
|
|||
RightSiZE
|
||||
RiplleyHD
|
||||
RiPTATORz
|
||||
RiTALiX
|
||||
RiVER
|
||||
RMT
|
||||
RoCKRioT
|
||||
ROVERS
|
||||
RSG
|
||||
RTA
|
||||
RUBY
|
||||
RuDE
|
||||
RUDOS
|
||||
RUSTLE
|
||||
Ryugan
|
||||
S26
|
||||
SAiMORNY
|
||||
|
@ -508,10 +560,12 @@ SAiNTS
|
|||
SAiVERT
|
||||
SAMFD
|
||||
SANTI
|
||||
saphire
|
||||
SAPHiRE
|
||||
Sapphire
|
||||
SChiZO
|
||||
Scratch404
|
||||
Scratched
|
||||
ScWb
|
||||
SecretMyth
|
||||
SECTOR7
|
||||
SEMTEX
|
||||
|
@ -526,6 +580,7 @@ SHDXXX
|
|||
shortbrehd
|
||||
SHS
|
||||
SHUNPO
|
||||
SiC
|
||||
SiGHTHD
|
||||
SiHD
|
||||
SiLU
|
||||
|
@ -536,6 +591,7 @@ SLM
|
|||
SLO
|
||||
SMoKeR
|
||||
Sneak
|
||||
SNUGGLER
|
||||
SoCkS
|
||||
Softfeng
|
||||
SoW
|
||||
|
@ -543,6 +599,7 @@ SpaceHD
|
|||
SPARKS
|
||||
SPOOKY
|
||||
SSF
|
||||
Stealthmaster
|
||||
stieg
|
||||
Stranded
|
||||
streetwars
|
||||
|
@ -556,18 +613,24 @@ Swesub
|
|||
SYS
|
||||
t00ng0d
|
||||
Taka
|
||||
TARGET
|
||||
TASTE
|
||||
TASTETV
|
||||
TB
|
||||
TDF
|
||||
TELEFLiX
|
||||
TENEIGHTY
|
||||
TERRA
|
||||
terribleHD
|
||||
terribleSD
|
||||
THENiGHTMAREiNHD
|
||||
TheWretched
|
||||
THOR
|
||||
THORA
|
||||
THUGLiNE
|
||||
TiDE
|
||||
TiMELORDS
|
||||
TiMPE
|
||||
TiMTY
|
||||
TiTANS
|
||||
TjHD
|
||||
|
@ -599,16 +662,21 @@ UNVEiL
|
|||
USELESS
|
||||
UVall
|
||||
VaAr3
|
||||
VALiOMEDiA
|
||||
VAMPS
|
||||
Vanillapunk
|
||||
VanRay
|
||||
VCDVaULT
|
||||
VeGaN
|
||||
Vegapunk
|
||||
ViCiOsO
|
||||
ViKAT
|
||||
ViNYL
|
||||
ViP3R
|
||||
ViSiON
|
||||
ViSTA
|
||||
ViSTA™
|
||||
ViTE
|
||||
VLiS
|
||||
VOA
|
||||
VoMiT
|
||||
|
@ -618,6 +686,7 @@ VoXHD
|
|||
vrs
|
||||
w0rm
|
||||
w4f
|
||||
WAF
|
||||
WANKAZ
|
||||
WASTE
|
||||
WAVEY
|
||||
|
@ -643,6 +712,7 @@ XSHD
|
|||
XSTREEM
|
||||
XTM
|
||||
XTSF
|
||||
XviK
|
||||
XXX4U
|
||||
YanY
|
||||
YellowBeast
|
||||
|
|
Loading…
Reference in New Issue