* allow drop of file names via verification files (e.g. sfv) in "New Names" list
* added before() and after() substring operations to ExpressionFormat.global.js * refactoring
This commit is contained in:
parent
9c456b275a
commit
b4578e9cdf
|
@ -60,11 +60,8 @@ public final class FileBotUtilities {
|
|||
}
|
||||
|
||||
|
||||
public static final ExtensionFileFilter TORRENT_FILES = MediaTypes.getDefault().filter("application/torrent");
|
||||
public static final ExtensionFileFilter LIST_FILES = MediaTypes.getDefault().filter("application/list");
|
||||
public static final ExtensionFileFilter VIDEO_FILES = MediaTypes.getDefault().filter("video");
|
||||
public static final ExtensionFileFilter SUBTITLE_FILES = MediaTypes.getDefault().filter("subtitle");
|
||||
public static final ExtensionFileFilter SFV_FILES = MediaTypes.getDefault().filter("verification/sfv");
|
||||
public static final ExtensionFileFilter VIDEO_FILES = MediaTypes.getFilter("video");
|
||||
public static final ExtensionFileFilter SUBTITLE_FILES = MediaTypes.getFilter("subtitle");
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,34 +34,29 @@ public class MediaTypes {
|
|||
}
|
||||
|
||||
|
||||
private static MediaTypes instance;
|
||||
private static final MediaTypes data = unmarshal();
|
||||
|
||||
|
||||
public static synchronized MediaTypes getDefault() {
|
||||
if (instance == null) {
|
||||
try {
|
||||
Unmarshaller unmarshaller = JAXBContext.newInstance(MediaTypes.class).createUnmarshaller();
|
||||
|
||||
// initialize singleton instance
|
||||
instance = (MediaTypes) unmarshaller.unmarshal(MediaTypes.class.getResource("media.types"));
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
private static MediaTypes unmarshal() {
|
||||
try {
|
||||
Unmarshaller unmarshaller = JAXBContext.newInstance(MediaTypes.class).createUnmarshaller();
|
||||
|
||||
return (MediaTypes) unmarshaller.unmarshal(MediaTypes.class.getResource("media.types"));
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public ExtensionFileFilter filter(String name) {
|
||||
return new ExtensionFileFilter(extensions(name));
|
||||
public static ExtensionFileFilter getFilter(String name) {
|
||||
return new ExtensionFileFilter(getExtensionList(name));
|
||||
}
|
||||
|
||||
|
||||
public List<String> extensions(String name) {
|
||||
public static List<String> getExtensionList(String name) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
|
||||
for (Type type : types) {
|
||||
for (Type type : data.types) {
|
||||
if (type.name.startsWith(name)) {
|
||||
addAll(list, type.extensions);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import net.sf.ehcache.Cache;
|
|||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sourceforge.filebot.FileBotUtilities;
|
||||
import net.sourceforge.filebot.MediaTypes;
|
||||
import net.sourceforge.filebot.hash.SfvFormat;
|
||||
import net.sourceforge.filebot.hash.VerificationFileScanner;
|
||||
import net.sourceforge.filebot.mediainfo.MediaInfo;
|
||||
|
@ -259,7 +260,7 @@ public class EpisodeFormatBindingBean {
|
|||
private String getChecksumFromSfvFile(File file) throws IOException {
|
||||
File folder = file.getParentFile();
|
||||
|
||||
for (File sfvFile : folder.listFiles(SFV_FILES)) {
|
||||
for (File sfvFile : folder.listFiles(MediaTypes.getFilter("verification/sfv"))) {
|
||||
VerificationFileScanner scanner = new VerificationFileScanner(sfvFile, new SfvFormat());
|
||||
|
||||
try {
|
||||
|
|
|
@ -34,6 +34,28 @@ String.prototype.space = function(replacement) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return substring before the given delimiter.
|
||||
*/
|
||||
String.prototype.before = function(delimiter) {
|
||||
var endIndex = this.indexOf(delimiter);
|
||||
|
||||
// delimiter was found, return leading substring, else return original value
|
||||
return endIndex >= 0 ? this.substring(0, endIndex) : this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return substring after the given delimiter.
|
||||
*/
|
||||
String.prototype.after = function(delimiter) {
|
||||
var startIndex = this.indexOf(delimiter);
|
||||
|
||||
// delimiter was found, return trailing substring, else return original value
|
||||
return startIndex >= 0 ? this.substring(startIndex + delimiter.length, this.length) : this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace trailing parenthesis including any leading whitespace.
|
||||
*
|
||||
|
|
|
@ -71,4 +71,16 @@ public enum HashType {
|
|||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
public static HashType forName(String name) {
|
||||
for (HashType value : HashType.values()) {
|
||||
if (value.name().equalsIgnoreCase(name)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// value not found
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ public enum SubtitleFormat {
|
|||
public abstract SubtitleReader newReader(Readable readable);
|
||||
|
||||
|
||||
public ExtensionFileFilter filter() {
|
||||
return MediaTypes.getDefault().filter("subtitle/" + this);
|
||||
public ExtensionFileFilter getFilter() {
|
||||
return MediaTypes.getFilter("subtitle/" + this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ public class EpisodeFormatDialog extends JDialog {
|
|||
Settings.userRoot().put("dialog.sample.episode", episodeString);
|
||||
firePreviewSampleChanged();
|
||||
} catch (ParseException e) {
|
||||
Logger.getLogger("ui").warning(String.format("Cannot parse %s", episodeString));
|
||||
Logger.getLogger("ui").warning(String.format("Cannot parse '%s'", episodeString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ public class EpisodeFormatDialog extends JDialog {
|
|||
try {
|
||||
return EpisodeFormat.getInstance().parseObject(sample);
|
||||
} catch (Exception e) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e);
|
||||
Logger.getLogger(getClass().getName()).warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,11 +332,7 @@ public class EpisodeFormatDialog extends JDialog {
|
|||
String sample = Settings.userRoot().get("dialog.sample.file");
|
||||
|
||||
if (sample != null) {
|
||||
try {
|
||||
return new File(sample);
|
||||
} catch (Exception e) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
return new File(sample);
|
||||
}
|
||||
|
||||
// default sample
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
package net.sourceforge.filebot.ui.panel.list;
|
||||
|
||||
|
||||
import static net.sourceforge.filebot.FileBotUtilities.*;
|
||||
import static net.sourceforge.tuned.FileUtilities.*;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -11,6 +10,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.filebot.MediaTypes;
|
||||
import net.sourceforge.filebot.torrent.Torrent;
|
||||
import net.sourceforge.filebot.ui.FileBotList;
|
||||
import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy;
|
||||
|
@ -21,7 +21,7 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
|
|||
|
||||
private FileBotList<? super String> list;
|
||||
|
||||
|
||||
|
||||
public FileListTransferablePolicy(FileBotList<? super String> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
|
|||
|
||||
if (containsOnly(files, FOLDERS)) {
|
||||
loadFolders(files);
|
||||
} else if (containsOnly(files, TORRENT_FILES)) {
|
||||
} else if (containsOnly(files, MediaTypes.getFilter("application/torrent"))) {
|
||||
loadTorrents(files);
|
||||
} else {
|
||||
loadFiles(files);
|
||||
|
|
|
@ -3,7 +3,6 @@ package net.sourceforge.filebot.ui.panel.rename;
|
|||
|
||||
|
||||
import static java.awt.datatransfer.DataFlavor.*;
|
||||
import static net.sourceforge.filebot.FileBotUtilities.*;
|
||||
import static net.sourceforge.filebot.ui.transfer.FileTransferable.*;
|
||||
import static net.sourceforge.tuned.FileUtilities.*;
|
||||
|
||||
|
@ -17,9 +16,10 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sourceforge.filebot.MediaTypes;
|
||||
import net.sourceforge.filebot.hash.HashType;
|
||||
import net.sourceforge.filebot.hash.VerificationFileScanner;
|
||||
import net.sourceforge.filebot.torrent.Torrent;
|
||||
import net.sourceforge.filebot.ui.transfer.ArrayTransferable;
|
||||
import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy;
|
||||
|
@ -94,12 +94,17 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
|
|||
|
||||
|
||||
@Override
|
||||
protected void load(List<File> files) throws FileNotFoundException {
|
||||
protected void load(List<File> files) throws IOException {
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
|
||||
if (containsOnly(files, LIST_FILES)) {
|
||||
if (containsOnly(files, MediaTypes.getFilter("application/list"))) {
|
||||
// list files
|
||||
loadListFiles(files, values);
|
||||
} else if (containsOnly(files, TORRENT_FILES)) {
|
||||
} else if (containsOnly(files, MediaTypes.getFilter("verification"))) {
|
||||
// verification files
|
||||
loadVerificationFiles(files, values);
|
||||
} else if (containsOnly(files, MediaTypes.getFilter("application/torrent"))) {
|
||||
// torrent files
|
||||
loadTorrentFiles(files, values);
|
||||
} else if (containsOnly(files, FOLDERS)) {
|
||||
// load files from each folder
|
||||
|
@ -107,6 +112,7 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
|
|||
values.addAll(FastFile.foreach(folder.listFiles()));
|
||||
}
|
||||
} else {
|
||||
// just add all given files
|
||||
values.addAll(FastFile.foreach(files));
|
||||
}
|
||||
|
||||
|
@ -132,24 +138,42 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
|
|||
}
|
||||
|
||||
|
||||
protected void loadTorrentFiles(List<File> files, List<Object> values) {
|
||||
try {
|
||||
for (File file : files) {
|
||||
Torrent torrent = new Torrent(file);
|
||||
|
||||
for (Torrent.Entry entry : torrent.getFiles()) {
|
||||
values.add(new AbstractFile(entry.getName(), entry.getLength()));
|
||||
protected void loadVerificationFiles(List<File> files, List<Object> values) throws IOException {
|
||||
for (File file : files) {
|
||||
HashType format = HashType.forName(getExtension(file));
|
||||
|
||||
// check if format is valid
|
||||
if (format == null)
|
||||
continue;
|
||||
|
||||
// add all file names from verification file
|
||||
VerificationFileScanner scanner = new VerificationFileScanner(file, format.getFormat());
|
||||
|
||||
try {
|
||||
while (scanner.hasNext()) {
|
||||
values.add(scanner.next().getKey().getName());
|
||||
}
|
||||
} finally {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void loadTorrentFiles(List<File> files, List<Object> values) throws IOException {
|
||||
for (File file : files) {
|
||||
Torrent torrent = new Torrent(file);
|
||||
|
||||
for (Torrent.Entry entry : torrent.getFiles()) {
|
||||
values.add(new AbstractFile(entry.getName(), entry.getLength()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getFileFilterDescription() {
|
||||
return "text files and torrent files";
|
||||
return "text files, verification files, torrent files";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,8 +8,11 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
|
@ -28,7 +31,7 @@ final class SubtitleUtilities {
|
|||
|
||||
// gather all formats, put likely formats first
|
||||
for (SubtitleFormat format : SubtitleFormat.values()) {
|
||||
if (format.filter().accept(file.getName())) {
|
||||
if (format.getFilter().accept(file.getName())) {
|
||||
priorityList.addFirst(format);
|
||||
} else {
|
||||
priorityList.addLast(format);
|
||||
|
@ -62,6 +65,20 @@ final class SubtitleUtilities {
|
|||
}
|
||||
|
||||
|
||||
public static String md5(ByteBuffer data) {
|
||||
try {
|
||||
MessageDigest hash = MessageDigest.getInstance("md-5");
|
||||
hash.update(data);
|
||||
|
||||
// return hex string
|
||||
return String.format("%032x", new BigInteger(1, hash.digest()));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// will not happen
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static byte[] read(File source) throws IOException {
|
||||
InputStream in = new FileInputStream(source);
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ import java.text.FieldPosition;
|
|||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class EpisodeFormat extends Format {
|
||||
|
@ -48,23 +46,39 @@ public class EpisodeFormat extends Format {
|
|||
|
||||
@Override
|
||||
public Episode parseObject(String source, ParsePosition pos) {
|
||||
Pattern pattern = Pattern.compile("(.*) - (?:(\\w+?)x)?(\\w+)? - (.*)");
|
||||
String[] section = source.substring(pos.getIndex()).split(" - ", 3);
|
||||
|
||||
Matcher matcher = pattern.matcher(source).region(pos.getIndex(), source.length());
|
||||
|
||||
if (!matcher.matches()) {
|
||||
pos.setErrorIndex(matcher.regionStart());
|
||||
// series name and episode identifier are required
|
||||
if (section.length < 2) {
|
||||
pos.setErrorIndex(0);
|
||||
return null;
|
||||
}
|
||||
|
||||
// episode number must not be null
|
||||
if (matcher.group(3) == null) {
|
||||
pos.setErrorIndex(matcher.start(3));
|
||||
return null;
|
||||
// normalize and check
|
||||
for (int i = 0; i < section.length; i++) {
|
||||
section[i] = section[i].trim();
|
||||
|
||||
if (section[i].isEmpty()) {
|
||||
pos.setErrorIndex(0);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pos.setIndex(matcher.end());
|
||||
return new Episode(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4));
|
||||
String[] sxe = section[1].split("x", 2);
|
||||
|
||||
// series name
|
||||
String name = section[0];
|
||||
|
||||
// season number and episode number
|
||||
String season = (sxe.length == 2) ? sxe[0] : null;
|
||||
String episode = (sxe.length == 2) ? sxe[1] : section[1];
|
||||
|
||||
// episode title
|
||||
String title = (section.length == 3) ? section[2] : null;
|
||||
|
||||
// did parse input
|
||||
pos.setIndex(source.length());
|
||||
return new Episode(name, season, episode, title);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue