commit dcfad411fe22dbe1561cbb84aecc95e4e42d9af0 Author: D. Moonfire Date: Sun Aug 27 17:35:12 2023 -0500 chore: initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2be92b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +result diff --git a/autoProcess.ini b/autoProcess.ini new file mode 100644 index 0000000..23d0f55 --- /dev/null +++ b/autoProcess.ini @@ -0,0 +1,257 @@ +[Converter] +ffmpeg = ffmpeg +ffprobe = ffprobe +threads = 0 +hwaccels = +hwaccel-decoders = +hwdevices = +hwaccel-output-format = +output-directory = +output-directory-space-ratio = 0.0 +output-format = mp4 +output-extension = mp4 +temp-extension = +minimum-size = 0 +ignored-extensions = nfo, ds_store +copy-to = +move-to = +delete-original = True +process-same-extensions = False +bypass-if-copying-all = False +force-convert = False +post-process = False +wait-post-process = False +detailed-progress = False +opts-separator = , +preopts = +postopts = +regex-directory-replace = [^\w\-_\. ] + +[Permissions] +chmod = 0644 +uid = -1 +gid = -1 + +[Metadata] +relocate-moov = True +full-path-guess = True +tag = True +tag-language = eng +download-artwork = poster +sanitize-disposition = +strip-metadata = False +keep-titles = False + +[Video] +codec = h264, x264 +max-bitrate = 0 +bitrate-ratio = +crf = -1 +crf-profiles = +preset = +codec-parameters = +dynamic-parameters = False +max-width = 0 +profile = +max-level = 0.0 +pix-fmt = +prioritize-source-pix-fmt = True +filter = +force-filter = False + +[HDR] +codec = +pix-fmt = +space = bt2020nc +transfer = smpte2084 +primaries = bt2020 +preset = +codec-parameters = +filter = +force-filter = False +profile = + +[Audio] +codec = ac3 +languages = +default-language = +include-original-language = True +first-stream-of-language = False +channel-bitrate = 128 +variable-bitrate = 0 +max-bitrate = 0 +max-channels = 0 +filter = +profile = +force-filter = False +sample-rates = +sample-format = +copy-original = False +aac-adtstoasc = False +ignored-dispositions = +force-default = False +unique-dispositions = False +stream-codec-combinations = + +[Audio.Sorting] +sorting = language, channels.d, map, d.comment +default-sorting = channels.d, map, d.comment +codecs = + +[Universal Audio] +codec = aac +channel-bitrate = 128 +variable-bitrate = 0 +first-stream-only = False +filter = +profile = +force-filter = False + +[Audio.ChannelFilters] + +[Subtitle] +codec = mov_text +codec-image-based = +languages = +default-language = +include-original-language = False +first-stream-of-language = False +encoding = +burn-subtitles = False +burn-dispositions = +embed-subs = False +embed-image-subs = False +embed-only-internal-subs = False +filename-dispositions = forced +ignore-embedded-subs = False +ignored-dispositions = +force-default = False +unique-dispositions = False +attachment-codec = +remove-bitstream-subs = False + +[Subtitle.Sorting] +sorting = language, d.comment, d.default.d, d.forced.d +codecs = +burn-sorting = language, d.comment, d.default.d, d.forced.d + +[Subtitle.CleanIt] +enabled = False +config-path = +tags = + +[Subtitle.FFSubsync] +enabled = False + +[Subtitle.Subliminal] +download-subs = False +download-forced-subs = False +include-hearing-impaired-subs = False +providers = + +[Subtitle.Subliminal.Auth] + +[Sonarr] +host = localhost +port = 8989 +apikey = +ssl = False +webroot = +force-rename = False +rescan = True +block-reprocess = False + +[Radarr] +host = localhost +port = 7878 +apikey = +ssl = False +webroot = +force-rename = False +rescan = True +block-reprocess = False + +[Sickbeard] +host = localhost +port = 8081 +ssl = False +apikey = +webroot = +username = +password = + +[Sickrage] +host = localhost +port = 8081 +ssl = False +apikey = +webroot = +username = +password = + +[SABNZBD] +convert = True +sickbeard-category = sickbeard +sickrage-category = sickrage +sonarr-category = sonarr +radarr-category = radarr +bypass-category = bypass +output-directory = +path-mapping = + +[Deluge] +sickbeard-label = sickbeard +sickrage-label = sickrage +sonarr-label = sonarr +radarr-label = radarr +bypass-label = bypass +convert = True +host = localhost +port = 58846 +username = +password = +output-directory = +remove = False +path-mapping = + +[qBittorrent] +sickbeard-label = sickbeard +sickrage-label = sickrage +sonarr-label = sonarr +radarr-label = radarr +bypass-label = bypass +convert = True +action-before = +action-after = +host = localhost +port = 8080 +ssl = False +username = +password = +output-directory = +path-mapping = + +[uTorrent] +sickbeard-label = sickbeard +sickrage-label = sickrage +sonarr-label = sonarr +radarr-label = radarr +bypass-label = bypass +convert = True +webui = False +action-before = +action-after = +host = localhost +ssl = False +port = 8080 +username = +password = +output-directory = +path-mapping = + +[Plex] +host = localhost +port = 32400 +refresh = False +token = + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..0076ebd --- /dev/null +++ b/flake.lock @@ -0,0 +1,123 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "revCount": 85, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/numtide/flake-utils/0.1.85%2Brev-f9e7cf818399d17d347f847525c5a5a8032e4e44/018a2375-3956-7f5c-9bbc-bd668014303a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/numtide/flake-utils/0.1.85.tar.gz" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "mach-nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs", + "pypi-deps-db": "pypi-deps-db" + }, + "locked": { + "lastModified": 1689108475, + "narHash": "sha256-Tg8mLKfgIigFSA6IodqSaxjfYVZ0xELqUDtGJhsdN6g=", + "owner": "DavHau", + "repo": "mach-nix", + "rev": "725aab8d52eb2f5b8ff67bea61049011ef31597c", + "type": "github" + }, + "original": { + "owner": "DavHau", + "repo": "mach-nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1643805626, + "narHash": "sha256-AXLDVMG+UaAGsGSpOtQHPIKB+IZ0KSd9WS77aanGzgc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "554d2d8aa25b6e583575459c297ec23750adb6cb", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "narHash": "sha256-5nm4yrEHKupjn62MibENtfqlP6pWcRTuSKrMiH9bLkc=", + "rev": "5690c4271f2998c304a45c91a0aeb8fb69feaea7", + "revCount": 518598, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.518598%2Brev-5690c4271f2998c304a45c91a0aeb8fb69feaea7/018a32e8-6e96-7b90-bccc-a5cf4c5ac2dd/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.0.tar.gz" + } + }, + "pypi-deps-db": { + "flake": false, + "locked": { + "lastModified": 1685526402, + "narHash": "sha256-V0SXx0dWlUBL3E/wHWTszrkK2dOnuYYnBc7n6e0+NQU=", + "owner": "DavHau", + "repo": "pypi-deps-db", + "rev": "ba35683c35218acb5258b69a9916994979dc73a9", + "type": "github" + }, + "original": { + "owner": "DavHau", + "repo": "pypi-deps-db", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "mach-nix": "mach-nix", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..8eaabed --- /dev/null +++ b/flake.nix @@ -0,0 +1,84 @@ +{ + description = "Sickbeard's MP4 Automator"; + + inputs = { + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.0.tar.gz"; + flake-utils.url = + "https://flakehub.com/f/numtide/flake-utils/0.1.85.tar.gz"; + mach-nix.url = "github:DavHau/mach-nix"; + }; + + outputs = { self, nixpkgs, flake-utils, mach-nix, ... }: + let + ver = "0.0.20230814"; + in flake-utils.lib.eachDefaultSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; + in rec { + defaultPackage = mach-nix.lib.${system}.buildPythonApplication rec { + pname = "sbmp4a"; + version = ver; + format = "setuptools"; + + src = pkgs.fetchFromGitHub { + owner = "mdhiggins"; + repo = "sickbeard_mp4_automator"; + rev = "5cbc33749bf771678702c7196302f7c1515758ae"; + hash = "sha256-ExUlagZ9rt+bAFcORdB69YtpGNY/Dj6Gdgdo85GMa1k="; + }; + + requirements = builtins.readFile ./requirements.txt; + + #propagatedBuildInputs = [ pkgs.python311Packages.setuptools ]; + + preBuild = '' + # Use our setup.py because sbmp4a doesn't provide one. + cp ${./setup.py} setup.py + substituteInPlace setup.py --replace VERSION ${ver} + ''; + + postInstall = '' + manual=$out/bin/sbmp4a + mkdir -p $out/bin + cp ${src}/manual.py $manual + + # This program creates the two ini file if they are missing, so we + # provide one that fits our environment so it doesn't try to write + # into a read-only file system. + config=$out/lib/python3.9/site-packages/sbmp4a/config + cp ${./autoProcess.ini} $config/autoProcess.ini + cp ${./logging.ini} $config/logging.ini + + # Logging is also done inside the source tree, which we don't want + # and Nix can't handle (ro filesystem), so we redirect that to the + # /tmp/ partition. + logpy=$out/lib/python3.9/site-packages/sbmp4a/resources/log.py + substituteInPlace $logpy --replace "logpath = configpath" "logpath = '/tmp/sbmp4a'" + + # Replace various import statements because sbmp4a wasn't written + # as an application, it was written as a standalone application we're + # forcing into a Nix package. + # + # This has the elegance of a monkey beating on a black obelisk with a bone. + for i in $(find $out -name "*.py") $manual + do + echo "fixing imports: $i" + + for j in autoprocess converter resources + do + substituteInPlace $i --replace "from $j" "from sbmp4a.$j" + done + done + ''; + + meta = with pkgs.lib; { + description = + "Automatically convert video files to a standardized format with metadata tagging to create a beautiful and uniform media library"; + homepage = "https://github.com/mdhiggins/sbmp4a"; + license = licenses.mit; + maintainers = with maintainers; [ ]; + }; + }; + + formatter = pkgs.alejandra; + }); +} diff --git a/logging.ini b/logging.ini new file mode 100644 index 0000000..133b943 --- /dev/null +++ b/logging.ini @@ -0,0 +1,61 @@ +[loggers] +keys = root, manual, nzbget + +[handlers] +keys = consoleHandler, nzbgetHandler, fileHandler, manualHandler + +[formatters] +keys = simpleFormatter, minimalFormatter, nzbgetFormatter + +[logger_root] +level = DEBUG +handlers = consoleHandler, fileHandler + +[logger_nzbget] +level = DEBUG +handlers = nzbgetHandler, fileHandler +propagate = 0 +qualname = NZBGetPostProcess + +[logger_manual] +level = DEBUG +handlers = manualHandler, fileHandler +propagate = 0 +qualname = MANUAL + +[handler_consoleHandler] +class = StreamHandler +level = INFO +formatter = simpleFormatter +args = (sys.stdout,) + +[handler_nzbgetHandler] +class = StreamHandler +level = INFO +formatter = nzbgetFormatter +args = (sys.stdout,) + +[handler_manualHandler] +class = StreamHandler +level = INFO +formatter = minimalFormatter +args = (sys.stdout,) + +[handler_fileHandler] +class = handlers.RotatingFileHandler +level = INFO +formatter = simpleFormatter +args = ('%(logfilename)s', 'a', 100000, 3, 'utf-8') + +[formatter_simpleFormatter] +format = %(asctime)s - %(name)s - %(levelname)s - %(message)s +datefmt = %Y-%m-%d %H:%M:%S + +[formatter_minimalFormatter] +format = %(message)s +datefmt = + +[formatter_nzbgetFormatter] +format = [%(levelname)s] %(message)s +datefmt = + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..14f6667 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +requests +idna +requests-cache +babelfish +tmdbsimple +mutagen +guessit +subliminal +python-dateutil +stevedore +qtfaststart +cleanit +plexapi +setuptools \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..895f7b1 --- /dev/null +++ b/setup.py @@ -0,0 +1,21 @@ +from setuptools import setup, find_packages + +setup( + name='sbmp4a', + version='VERSION', + packages=[ + 'sbmp4a', + 'sbmp4a.autoprocess', + 'sbmp4a.config', + 'sbmp4a.converter', + 'sbmp4a.resources', + ], + package_dir={ + 'sbmp4a': '.', + }, + entry_points={ + 'console_scripts': [ + 'sbmp4a=sbmp4a.manual:main', + ], + }, +) \ No newline at end of file