summaryrefslogtreecommitdiffhomepage
path: root/libs/libfilebot
diff options
context:
space:
mode:
authorpanni <[email protected]>2018-10-31 17:08:29 +0100
committerpanni <[email protected]>2018-10-31 17:08:29 +0100
commit8f584143f8afc46a75a83dab5243739772e3562b (patch)
treec7dae21e993880af8bee71ad7b5a63f2977db577 /libs/libfilebot
parent4beaeaa99e84bbe1ed87d0466a55a22ba25c8437 (diff)
downloadbazarr-8f584143f8afc46a75a83dab5243739772e3562b.tar.gz
bazarr-8f584143f8afc46a75a83dab5243739772e3562b.zip
update deps
Diffstat (limited to 'libs/libfilebot')
-rw-r--r--libs/libfilebot/LICENSE21
-rw-r--r--libs/libfilebot/README.md17
-rw-r--r--libs/libfilebot/__init__.py5
-rw-r--r--libs/libfilebot/lib.py38
-rw-r--r--libs/libfilebot/main.py135
5 files changed, 216 insertions, 0 deletions
diff --git a/libs/libfilebot/LICENSE b/libs/libfilebot/LICENSE
new file mode 100644
index 000000000..8864d4a39
--- /dev/null
+++ b/libs/libfilebot/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/libs/libfilebot/README.md b/libs/libfilebot/README.md
new file mode 100644
index 000000000..3356c5a17
--- /dev/null
+++ b/libs/libfilebot/README.md
@@ -0,0 +1,17 @@
+# libfilebot
+
+Returns the `net.filebot.filename` property of a file without binary python package dependencies.
+It instead uses system-provided binaries while *trying* to avoid calling the filebot-jvm-monstrosity.
+
+*This is a quick-hack-excerpt from [Sub-Zero.bundle](https://github.com/pannal/Sub-Zero.bundle), so don't expect constant maintenance or code-quality.*
+
+#### Currently supports:
+
+* `xattr` command on darwin/osx
+* NTFS advanced data streams via python pyADS
+* `getfattr`, `attr` and `filebot` commands for every other OS
+
+
+#### Dependencies
+
+* [pyADS](https://github.com/RobinDavid/pyADS) for Windows \ No newline at end of file
diff --git a/libs/libfilebot/__init__.py b/libs/libfilebot/__init__.py
new file mode 100644
index 000000000..c734afaef
--- /dev/null
+++ b/libs/libfilebot/__init__.py
@@ -0,0 +1,5 @@
+# coding=utf-8
+
+from main import get_filebot_attrs
+
+__all__ = ["get_filebot_attrs"]
diff --git a/libs/libfilebot/lib.py b/libs/libfilebot/lib.py
new file mode 100644
index 000000000..ac7e469b0
--- /dev/null
+++ b/libs/libfilebot/lib.py
@@ -0,0 +1,38 @@
+# coding=utf-8
+
+import os
+import sys
+
+
+def find_executable(executable, path=None):
+ """Find if 'executable' can be run. Looks for it in 'path'
+ (string that lists directories separated by 'os.pathsep';
+ defaults to os.environ['PATH']). Checks for all executable
+ extensions. Returns full path or None if no command is found.
+ """
+ if path is None:
+ path = os.environ['PATH']
+ paths = path.split(os.pathsep)
+ extlist = ['']
+ if os.name == 'os2':
+ (base, ext) = os.path.splitext(executable)
+ # executable files on OS/2 can have an arbitrary extension, but
+ # .exe is automatically appended if no dot is present in the name
+ if not ext:
+ executable = executable + ".exe"
+ elif sys.platform == 'win32':
+ pathext = os.environ['PATHEXT'].lower().split(os.pathsep)
+ (base, ext) = os.path.splitext(executable)
+ if ext.lower() not in pathext:
+ extlist = pathext
+ for ext in extlist:
+ execname = executable + ext
+ if os.path.isfile(execname):
+ return execname
+ else:
+ for p in paths:
+ f = os.path.join(p, execname)
+ if os.path.isfile(f):
+ return f
+ else:
+ return None \ No newline at end of file
diff --git a/libs/libfilebot/main.py b/libs/libfilebot/main.py
new file mode 100644
index 000000000..9a4e685eb
--- /dev/null
+++ b/libs/libfilebot/main.py
@@ -0,0 +1,135 @@
+# coding=utf-8
+
+import subprocess
+import sys
+import traceback
+import logging
+import re
+import binascii
+import types
+import os
+
+from pipes import quote
+from lib import find_executable
+
+mswindows = False
+if sys.platform == "win32":
+ mswindows = True
+ from pyads import ADS
+
+logger = logging.getLogger(__name__)
+
+
+def quote_args(seq):
+ return ' '.join(quote(arg) for arg in seq)
+
+
+def win32_xattr(fn):
+ handler = ADS(fn)
+ try:
+ return handler.get_stream_content("net.filebot.filename")
+ except IOError:
+ pass
+
+
+def default_xattr(fn):
+ if not default_xattr_bin:
+ raise Exception("Neither getfattr, attr nor filebot were found")
+
+ if "getfattr" in default_xattr_bin:
+ return ["getfattr", "-n", "user.net.filebot.filename", fn]
+
+ elif "attr" in default_xattr_bin:
+ return ["attr", "-g", "net.filebot.filename", fn]
+
+ return ["filebot", "-script", "fn:xattr", fn]
+
+
+XATTR_MAP = {
+ "default": (
+ default_xattr,
+ lambda result: re.search('(?um)(net\.filebot\.filename(?=="|: )[=:" ]+|Attribute.+:\s)([^"\n\r\0]+)',
+ result).group(2)
+ ),
+ # "darwin": (
+ # lambda fn: ["xattr", "-p", "net.filebot.filename", fn],
+ # lambda result: binascii.unhexlify(result.strip().replace(' ', '').replace('\r\n', '').replace('\r', '')
+ # .replace('\n', '')).strip("\x00")
+ # ),
+ "darwin": (
+ lambda fn: ["filebot", "-script", "fn:xattr", fn],
+ lambda result: re.search('(?um)(net\.filebot\.filename(?=="|: )[=:" ]+|Attribute.+:\s)([^"\n\r\0]+)',
+ result).group(2)
+ ),
+ "win32": (
+ lambda fn: fn,
+ win32_xattr,
+ )
+}
+
+if sys.platform not in XATTR_MAP:
+ default_xattr_bin = find_executable("getfattr") or find_executable("attr") or find_executable("filebot") \
+ or "filebot"
+
+
+def get_filebot_attrs(fn):
+ """
+ Currently only supports the filebot filename attrs
+ :param fn: filename
+ :return:
+ """
+
+ if sys.platform in XATTR_MAP:
+ logger.debug("Using native xattr calls for %s", sys.platform)
+ else:
+ logger.debug("Using %s for %s", default_xattr_bin, sys.platform)
+
+ args_func, match_func = XATTR_MAP.get(sys.platform, XATTR_MAP["default"])
+
+ args = args_func(fn)
+ if isinstance(args, types.ListType):
+ try:
+ env = dict(os.environ)
+ if not mswindows:
+ env_path = {"PATH": os.pathsep.join(
+ [
+ "/usr/local/bin",
+ "/usr/bin",
+ "/usr/local/sbin",
+ "/usr/sbin",
+ os.environ.get("PATH", "")
+ ]
+ )
+ }
+ env = dict(os.environ, **env_path)
+
+ env.pop("LD_LIBRARY_PATH", None)
+
+ proc = subprocess.Popen(quote_args(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
+ env=env)
+ output, errors = proc.communicate()
+
+ if proc.returncode == 1:
+ logger.info(u"%s: Couldn't get filebot original filename, args: %r, output: %r, error: %r", fn, args,
+ output, errors)
+ return
+
+ output = output.decode()
+
+ except:
+ logger.error(u"%s: Unexpected error while getting filebot original filename: %s", fn,
+ traceback.format_exc())
+ return
+ else:
+ output = args
+
+ try:
+ orig_fn = match_func(output)
+ return orig_fn.strip()
+ except:
+ logger.info(u"%s: Couldn't get filebot original filename" % fn)
+ logger.debug(u"%s: Result: %r" % (fn, output))
+
+
+if __name__ == "__main__":
+ print get_filebot_attrs(sys.argv[1])