feat: initial flake for manual operation

This commit is contained in:
D. Moonfire 2022-12-06 14:08:00 +00:00
parent 0f3afc9510
commit 2dff9a702b
12 changed files with 1530 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
result

290
TASKS.md Normal file
View file

@ -0,0 +1,290 @@
# Tasks
## Set up Configuration
autoProcessConfig =
pkgs.writeText "autoProcess.ini"
(
pkgs.lib.generators.toINI {} {
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 = "";
};
}
);

View file

@ -0,0 +1,127 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"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": 1654084003,
"narHash": "sha256-j/XrVVistvM+Ua+0tNFvO5z83isL+LBgmBi9XppxuKA=",
"owner": "DavHau",
"repo": "mach-nix",
"rev": "7e14360bde07dcae32e5e24f366c83272f52923f",
"type": "github"
},
"original": {
"id": "mach-nix",
"ref": "3.5.0",
"type": "indirect"
}
},
"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": {
"lastModified": 1670064435,
"narHash": "sha256-+ELoY30UN+Pl3Yn7RWRPabykwebsVK/kYE9JsIsUMxQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "61a8a98e6d557e6dd7ed0cdb54c3a3e3bbc5e25c",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pypi-deps-db": {
"flake": false,
"locked": {
"lastModified": 1643877077,
"narHash": "sha256-jv8pIvRFTP919GybOxXE5TfOkrjTbdo9QiCO1TD3ZaY=",
"owner": "DavHau",
"repo": "pypi-deps-db",
"rev": "da53397f0b782b0b18deb72ef8e0fb5aa7c98aa3",
"type": "github"
},
"original": {
"owner": "DavHau",
"repo": "pypi-deps-db",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"mach-nix": "mach-nix",
"nixpkgs": "nixpkgs_2",
"sma": "sma"
}
},
"sma": {
"flake": false,
"locked": {
"lastModified": 1670070685,
"narHash": "sha256-7m+GAlc5Lz00mWi2kNhHJ4Ov7Nrlrm7YOqPXzaEzEBI=",
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"rev": "819abd4043411fa45b6b2f0154f8a21de2557b63",
"type": "github"
},
"original": {
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,33 @@
{
description = "Internal Build Environment";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
mach-nix.url = "mach-nix/3.5.0";
sma.url = "github:mdhiggins/sickbeard_mp4_automator";
sma.flake = false;
};
outputs = {
self,
nixpkgs,
flake-utils,
mach-nix,
sma,
}:
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
defaultPackage = mach-nix.lib."${system}".mkPython {
requirements = ''
${builtins.readFile "${sma}/setup/requirements.txt"}
setuptools
'';
};
formatter = pkgs.alejandra;
}
);
}

192
flake.lock Normal file
View file

@ -0,0 +1,192 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"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_3",
"nixpkgs": "nixpkgs_2",
"pypi-deps-db": "pypi-deps-db"
},
"locked": {
"lastModified": 1654084003,
"narHash": "sha256-j/XrVVistvM+Ua+0tNFvO5z83isL+LBgmBi9XppxuKA=",
"owner": "DavHau",
"repo": "mach-nix",
"rev": "7e14360bde07dcae32e5e24f366c83272f52923f",
"type": "github"
},
"original": {
"id": "mach-nix",
"ref": "3.5.0",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1670064435,
"narHash": "sha256-+ELoY30UN+Pl3Yn7RWRPabykwebsVK/kYE9JsIsUMxQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "61a8a98e6d557e6dd7ed0cdb54c3a3e3bbc5e25c",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"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_3": {
"locked": {
"lastModified": 1670064435,
"narHash": "sha256-+ELoY30UN+Pl3Yn7RWRPabykwebsVK/kYE9JsIsUMxQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "61a8a98e6d557e6dd7ed0cdb54c3a3e3bbc5e25c",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pypi-deps-db": {
"flake": false,
"locked": {
"lastModified": 1643877077,
"narHash": "sha256-jv8pIvRFTP919GybOxXE5TfOkrjTbdo9QiCO1TD3ZaY=",
"owner": "DavHau",
"repo": "pypi-deps-db",
"rev": "da53397f0b782b0b18deb72ef8e0fb5aa7c98aa3",
"type": "github"
},
"original": {
"owner": "DavHau",
"repo": "pypi-deps-db",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"sma": "sma",
"sma-env": "sma-env"
}
},
"sma": {
"flake": false,
"locked": {
"lastModified": 1670070685,
"narHash": "sha256-7m+GAlc5Lz00mWi2kNhHJ4Ov7Nrlrm7YOqPXzaEzEBI=",
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"rev": "819abd4043411fa45b6b2f0154f8a21de2557b63",
"type": "github"
},
"original": {
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"type": "github"
}
},
"sma-env": {
"inputs": {
"flake-utils": "flake-utils_2",
"mach-nix": "mach-nix",
"nixpkgs": "nixpkgs_3",
"sma": "sma_2"
},
"locked": {
"lastModified": 1,
"narHash": "sha256-Ziazr1bcU8OKJPTMuFTSUYYHiMPJyXBDrh0cOxP/S3s=",
"path": "/nix/store/b247nwz5rifn91kpgxydschi6lhjj4iw-source/build-environment",
"type": "path"
},
"original": {
"path": "/nix/store/b247nwz5rifn91kpgxydschi6lhjj4iw-source/build-environment",
"type": "path"
}
},
"sma_2": {
"flake": false,
"locked": {
"lastModified": 1670070685,
"narHash": "sha256-7m+GAlc5Lz00mWi2kNhHJ4Ov7Nrlrm7YOqPXzaEzEBI=",
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"rev": "819abd4043411fa45b6b2f0154f8a21de2557b63",
"type": "github"
},
"original": {
"owner": "mdhiggins",
"repo": "sickbeard_mp4_automator",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

61
flake.nix Normal file
View file

@ -0,0 +1,61 @@
{
description = "SMA Conversion/Tagging Automation Script";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
sma.url = "github:mdhiggins/sickbeard_mp4_automator";
sma.flake = false;
sma-env.url = "./build-environment";
};
outputs = {
self,
nixpkgs,
flake-utils,
sma,
sma-env,
}:
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
imports = [./module.nix];
nixosModules.sickbeard-mp4-automator = import ./module.nix;
defaultPackage = pkgs.stdenv.mkDerivation {
name = "sickbeard-mp4-automator";
src = self;
buildInputs = [
pkgs.rsync
pkgs.ffmpeg
sma-env.defaultPackage."${system}"
];
buildPhase = ''
# Create the directories we need.
mkdir -p build/sma/config
# Copy in the static files which mess up the permissions.
rsync -a ${sma}/ build/sma/
rsync -a ${./.}/sma/ build/sma/
rsync -a ${./.}/scripts/ build/scripts/
'';
installPhase = ''
# Create our basic deployment folder and copy our setup into it.
mkdir -p $out/sma/config $out/bin
rsync -a build/ $out/
# Install our scripts to set up the environment.
install build/scripts/sma-manual.sh $out/bin/sma-manual
'';
};
# We like our code pretty.
formatter = pkgs.alejandra;
}
);
}

336
module.nix Normal file
View file

@ -0,0 +1,336 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
cfg = config.sickbeard-mp4-automator;
in {
options = {
sickbeard-mp4-automator = {
customConfig = mkOption {
type = types.bool;
default = true;
description = ''
If true, then write out a custom configuration to /etc/sickbeard-mp4-automator/autoProcess.ini.
'';
};
plex = {
host = mkOption {
type = types.str;
default = "localhost";
description = ''
The host name for the Plex server.
'';
};
port = mkOption {
type = types.port;
default = 32400;
description = ''
The port for the Plex server.
'';
};
refresh = mkOption {
type = types.bool;
default = false;
description = ''
Should SMA notify the Plex server of an update.
'';
};
token = mkOption {
type = types.string;
default = '';
description = ''
The API token for the Plex server.
'';
};
};
};
};
config = lib.mkIf config.sickbeard-mp4-automator.customConfig {
environment.etc."/etc/sickbeard-mp4-automator/autoProcess.ini" = {
mode = "0644";
text = pkgs.lib.generators.toINI {} {
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 = cfg.plex.host;
port = cfg.plex.port;
refresh = cfg.plex.refresh;
token = cfg.plex.token;
};
};
};
};
}

14
scripts/sma-manual.sh Normal file
View file

@ -0,0 +1,14 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p ffmpeg
bindir=$(dirname $0)
rootdir=$(dirname $bindir)
smadir="$rootdir/sma";
# If there is a custom configuration, then we use that over the one inside
# the package.
if [ -f /etc/sickbeard-mp4-automator/autoProcess.ini ]
then
SMA_CONFIG=/etc/sickbeard-mp4-automator/autoProcess.ini
fi
$smadir/manual.py "$@"

7
setup.py Normal file
View file

@ -0,0 +1,7 @@
from distutils.core import setup
setup(
name='sma',
version='0.0.1',
scripts=["manual.py"],
)

256
sma/config/autoProcess.ini Normal file
View file

@ -0,0 +1,256 @@
[Audio]
aac-adtstoasc=False
channel-bitrate=128
codec=ac3
copy-original=False
default-language=
filter=
first-stream-of-language=False
force-default=False
force-filter=False
ignored-dispositions=
include-original-language=True
languages=
max-bitrate=0
max-channels=0
profile=
sample-format=
sample-rates=
stream-codec-combinations=
unique-dispositions=False
variable-bitrate=0
[Audio.ChannelFilters]
[Audio.Sorting]
codecs=
default-sorting=channels.d, map, d.comment
sorting=language, channels.d, map, d.comment
[Converter]
bypass-if-copying-all=False
copy-to=
delete-original=True
detailed-progress=False
ffmpeg=ffmpeg
ffprobe=ffprobe
force-convert=False
hwaccel-decoders=
hwaccel-output-format=
hwaccels=
hwdevices=
ignored-extensions=nfo, ds_store
minimum-size=0
move-to=
opts-separator=,
output-directory=
output-directory-space-ratio=0.0
output-extension=mp4
output-format=mp4
post-process=False
postopts=
preopts=
process-same-extensions=False
regex-directory-replace=[^w-_. ]
temp-extension=
threads=0
wait-post-process=False
[Deluge]
bypass-label=bypass
convert=True
host=localhost
output-directory=
password=
path-mapping=
port=58846
radarr-label=radarr
remove=False
sickbeard-label=sickbeard
sickrage-label=sickrage
sonarr-label=sonarr
username=
[HDR]
codec=
codec-parameters=
filter=
force-filter=False
pix-fmt=
preset=
primaries=bt2020
profile=
space=bt2020nc
transfer=smpte2084
[Metadata]
download-artwork=poster
full-path-guess=True
keep-titles=False
relocate-moov=True
sanitize-disposition=
strip-metadata=False
tag=True
tag-language=eng
[Permissions]
chmod=0644
gid=-1
uid=-1
[Plex]
host=localhost
port=32400
refresh=False
token=
[Radarr]
apikey=
block-reprocess=False
force-rename=False
host=localhost
port=7878
rescan=True
ssl=False
webroot=
[SABNZBD]
bypass-category=bypass
convert=True
output-directory=
path-mapping=
radarr-category=radarr
sickbeard-category=sickbeard
sickrage-category=sickrage
sonarr-category=sonarr
[Sickbeard]
apikey=
host=localhost
password=
port=8081
ssl=False
username=
webroot=
[Sickrage]
apikey=
host=localhost
password=
port=8081
ssl=False
username=
webroot=
[Sonarr]
apikey=
block-reprocess=False
force-rename=False
host=localhost
port=8989
rescan=True
ssl=False
webroot=
[Subtitle]
attachment-codec=
burn-dispositions=
burn-subtitles=False
codec=mov_text
codec-image-based=
default-language=
embed-image-subs=False
embed-only-internal-subs=False
embed-subs=False
encoding=
filename-dispositions=forced
first-stream-of-language=False
force-default=False
ignore-embedded-subs=False
ignored-dispositions=
include-original-language=False
languages=
remove-bitstream-subs=False
unique-dispositions=False
[Subtitle.CleanIt]
config-path=
enabled=False
tags=
[Subtitle.FFSubsync]
enabled=False
[Subtitle.Sorting]
burn-sorting=language, d.comment, d.default.d, d.forced.d
codecs=
sorting=language, d.comment, d.default.d, d.forced.d
[Subtitle.Subliminal]
download-forced-subs=False
download-subs=False
include-hearing-impaired-subs=False
providers=
[Subtitle.Subliminal.Auth]
[Universal Audio]
channel-bitrate=128
codec=aac
filter=
first-stream-only=False
force-filter=False
profile=
variable-bitrate=0
[Video]
bitrate-ratio=
codec=h264, x264
codec-parameters=
crf=-1
crf-profiles=
dynamic-parameters=False
filter=
force-filter=False
max-bitrate=0
max-level=0.0
max-width=0
pix-fmt=
preset=
prioritize-source-pix-fmt=True
profile=
[qBittorrent]
action-after=
action-before=
bypass-label=bypass
convert=True
host=localhost
output-directory=
password=
path-mapping=
port=8080
radarr-label=radarr
sickbeard-label=sickbeard
sickrage-label=sickrage
sonarr-label=sonarr
ssl=False
username=
[uTorrent]
action-after=
action-before=
bypass-label=bypass
convert=True
host=localhost
output-directory=
password=
path-mapping=
port=8080
radarr-label=radarr
sickbeard-label=sickbeard
sickrage-label=sickrage
sonarr-label=sonarr
ssl=False
username=
webui=False

60
sma/config/logging.ini Normal file
View file

@ -0,0 +1,60 @@
[loggers]
keys = root, manual, nzbget
[handlers]
keys = consoleHandler, nzbgetHandler, fileHandler, manualHandler
[formatters]
keys = simpleFormatter, minimalFormatter, nzbgetFormatter
[logger_root]
level = DEBUG
handlers = consoleHandler
[logger_nzbget]
level = DEBUG
handlers = nzbgetHandler
propagate = 0
qualname = NZBGetPostProcess
[logger_manual]
level = DEBUG
handlers = manualHandler
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 =

153
sma/resources/log.py Normal file
View file

@ -0,0 +1,153 @@
import logging
import os
import sys
import shutil
from logging.config import fileConfig
from logging.handlers import BaseRotatingHandler
try:
from configparser import RawConfigParser
except ImportError:
from ConfigParser import RawConfigParser
defaults = {
'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': ''
}
}
CONFIG_DEFAULT = "logging.ini"
CONFIG_DIRECTORY = "./config"
RESOURCE_DIRECTORY = "./resources"
RELATIVE_TO_ROOT = "../"
LOG_NAME = "sma.log"
def checkLoggingConfig(configfile):
write = True
config = RawConfigParser()
if os.path.exists(configfile):
config.read(configfile)
write = False
for s in defaults:
if not config.has_section(s):
config.add_section(s)
write = True
for k in defaults[s]:
if not config.has_option(s, k):
config.set(s, k, str(defaults[s][k]))
# Remove sysLogHandler if you're on Windows
if 'sysLogHandler' in config.get('handlers', 'keys'):
config.set('handlers', 'keys', config.get('handlers', 'keys').replace('sysLogHandler', ''))
write = True
while config.get('handlers', 'keys').endswith(",") or config.get('handlers', 'keys').endswith(" "):
config.set('handlers', 'keys', config.get('handlers', 'keys')[:-1])
write = True
if write:
fp = open(configfile, "w")
config.write(fp)
fp.close()
def getLogger(name=None, custompath=None):
if custompath:
custompath = os.path.realpath(custompath)
if not os.path.isdir(custompath):
custompath = os.path.dirname(custompath)
rootpath = os.path.abspath(custompath)
resourcepath = os.path.normpath(os.path.join(rootpath, RESOURCE_DIRECTORY))
configpath = os.path.normpath(os.path.join(rootpath, CONFIG_DIRECTORY))
else:
rootpath = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), RELATIVE_TO_ROOT))
resourcepath = os.path.normpath(os.path.join(rootpath, RESOURCE_DIRECTORY))
configpath = os.path.normpath(os.path.join(rootpath, CONFIG_DIRECTORY))
logpath = configpath
if not os.path.isdir(logpath):
os.makedirs(logpath)
if not os.path.isdir(configpath):
os.makedirs(configpath)
configfile = os.path.abspath(os.path.join(configpath, CONFIG_DEFAULT)).replace("\\", "\\\\")
checkLoggingConfig(configfile)
logfile = os.path.abspath(os.path.join(logpath, LOG_NAME)).replace("\\", "\\\\")
#fileConfig(configfile, defaults={'logfilename': logfile})
logger = logging.getLogger(name)
rotatingFileHandlers = [x for x in logger.handlers if isinstance(x, BaseRotatingHandler)]
for rh in rotatingFileHandlers:
rh.rotator = rotator
return logging.getLogger(name)
def rotator(source, dest):
if os.path.exists(source):
try:
os.rename(source, dest)
except:
try:
shutil.copyfile(source, dest)
open(source, 'w').close()
except Exception as e:
print("Error rotating logfiles: %s." % (e))