From 24812487366b902eee74fa1c0f8cbc69e7b36d64 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Wed, 15 Nov 2023 09:00:32 +0100 Subject: [PATCH 01/10] Add ability to have a different name for folder --- README.md | 2 ++ app/src/config.py | 1 + app/src/connect.py | 2 +- app/src/series.py | 9 ++++++++- app/src/static_types.py | 1 + config.sample.json | 3 ++- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 70d808b..8107822 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ An example configuration is provided in the docker-compose.yml file. Configure t - `TA_TOKEN`: Tube Archivist API token, accessible from the settings page - `JF_URL`: Full URL where Jellyfin is reachable - `JF_TOKEN`: Jellyfin API token + - `JF_FOLDER`: Folder override if your folder is not named "YouTube" on your Filesystem. - `LISTEN_PORT`: Optionally change the port where the integration is listening for messages. Defaults to `8001`. If you change this, make sure to also change the json link for auto trigger as described below. Mount the `/youtube` folder from Tube Archivist also in this container at `/youtube` to give this integration access to the media archive. @@ -83,6 +84,7 @@ pip install requests - `ta_token`: Tube Archivist API token, accessible from the settings page - `jf_url`: Full URL where Jellyfin is reachable - `jf_token`: Jellyfin API token + - `jf_folder`: Name of the folder where TubeArchivist puts the files into Then run the script from the main folder with python, e.g. ```python diff --git a/app/src/config.py b/app/src/config.py index 7a27663..58b428a 100644 --- a/app/src/config.py +++ b/app/src/config.py @@ -38,6 +38,7 @@ def get_config_env() -> ConfigType | Literal[False]: "ta_token": os.environ["TA_TOKEN"], "jf_url": os.environ["JF_URL"], "jf_token": os.environ["JF_TOKEN"], + "jf_folder": os.environ['JF_FOLDER'] } return config_content diff --git a/app/src/connect.py b/app/src/connect.py index 7c41c1f..4478f5e 100644 --- a/app/src/connect.py +++ b/app/src/connect.py @@ -9,7 +9,7 @@ from src.static_types import ConfigType, TAChannel, TAVideo CONFIG: ConfigType = get_config() TIMEOUT = 60 -EXPECTED_ENV = {"ta_url", "ta_token", "jf_url", "jf_token", "ta_video_path"} +EXPECTED_ENV = {"ta_url", "ta_token", "jf_url", "jf_token", "ta_video_path"} # js_folder is optional class Jellyfin: diff --git a/app/src/series.py b/app/src/series.py index 0e9a7f2..82f55e8 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -22,8 +22,15 @@ class Library: """get collection id for youtube folder""" path: str = "Items?Recursive=true&includeItemTypes=Folder" folders: dict = Jellyfin().get(path) + folder_name: str | None = get_config()["jf_folder"] + + if not folder_name or len(folder_name) < 1: + folder_name = "youtube" + else: + folder_name = folder_name.lower() + for folder in folders["Items"]: - if folder.get("Name").lower() == "youtube": + if folder.get("Name").lower() == folder_name: return folder.get("Id") raise ValueError("youtube folder not found") diff --git a/app/src/static_types.py b/app/src/static_types.py index bf011b1..1c2d62a 100644 --- a/app/src/static_types.py +++ b/app/src/static_types.py @@ -11,6 +11,7 @@ class ConfigType(TypedDict): ta_token: str jf_url: str jf_token: str + jf_folder: str | None class TAChannel(TypedDict): diff --git a/config.sample.json b/config.sample.json index 444b661..fab8ff2 100644 --- a/config.sample.json +++ b/config.sample.json @@ -3,5 +3,6 @@ "ta_url": "http://tubearchivist.local", "ta_token": "xxxxxxxxxxxxxxxx", "jf_url": "http://jellyfin.local:8096", - "jf_token": "yyyyyyyyyyyyyyyy" + "jf_token": "yyyyyyyyyyyyyyyy", + "jf_folder": "YouTube" } From a4b5081c7a3c1ceb3e227a93341c9ccc31ca7a67 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Thu, 21 Dec 2023 06:29:37 +0100 Subject: [PATCH 02/10] Ignore venv folder from jetbrains --- deploy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy.sh b/deploy.sh index 8ab1d49..f8181e7 100755 --- a/deploy.sh +++ b/deploy.sh @@ -17,12 +17,12 @@ function validate { echo "running black" black --force-exclude "migrations/*" --diff --color --check -l 79 "$check_path" echo "running codespell" - codespell --skip="./.git,./.venv,./.mypy_cache" "$check_path" + codespell --skip="./.git,./.venv,venv,./.mypy_cache" "$check_path" echo "running flake8" - flake8 "$check_path" --exclude "migrations,.venv" --count --max-complexity=10 \ + flake8 "$check_path" --exclude "migrations,.venv,venv" --count --max-complexity=10 \ --max-line-length=79 --show-source --statistics echo "running isort" - isort --skip "migrations" --skip ".venv" --check-only --diff --profile black -l 79 "$check_path" + isort --skip "migrations" --skip ".venv" --skip "venv" --check-only --diff --profile black -l 79 "$check_path" printf " \n> all validations passed\n" } From fccf9c865a51d247381859d0ac17ac13046b91db Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Thu, 21 Dec 2023 06:29:43 +0100 Subject: [PATCH 03/10] Fixes --- app/src/config.py | 10 +++++++++- app/src/connect.py | 8 +++++++- app/src/series.py | 9 ++------- app/src/static_types.py | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/config.py b/app/src/config.py index 58b428a..1fbaffd 100644 --- a/app/src/config.py +++ b/app/src/config.py @@ -29,6 +29,12 @@ def get_config_file() -> ConfigType | Literal[False]: return False +def get_variable_or_default(variable: str, default: str) -> str: + if not variable or len(variable) < 1: + return default + return variable + + def get_config_env() -> ConfigType | Literal[False]: """read config from environment""" if "TA_URL" in os.environ: @@ -38,7 +44,9 @@ def get_config_env() -> ConfigType | Literal[False]: "ta_token": os.environ["TA_TOKEN"], "jf_url": os.environ["JF_URL"], "jf_token": os.environ["JF_TOKEN"], - "jf_folder": os.environ['JF_FOLDER'] + "jf_folder": get_variable_or_default( + os.environ["JF_FOLDER"], "youtube" + ), } return config_content diff --git a/app/src/connect.py b/app/src/connect.py index 4478f5e..8d18541 100644 --- a/app/src/connect.py +++ b/app/src/connect.py @@ -9,7 +9,13 @@ from src.static_types import ConfigType, TAChannel, TAVideo CONFIG: ConfigType = get_config() TIMEOUT = 60 -EXPECTED_ENV = {"ta_url", "ta_token", "jf_url", "jf_token", "ta_video_path"} # js_folder is optional +EXPECTED_ENV = { + "ta_url", + "ta_token", + "jf_url", + "jf_token", + "ta_video_path", +} # jf_folder is optional class Jellyfin: diff --git a/app/src/series.py b/app/src/series.py index 82f55e8..ad884dd 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -22,15 +22,10 @@ class Library: """get collection id for youtube folder""" path: str = "Items?Recursive=true&includeItemTypes=Folder" folders: dict = Jellyfin().get(path) - folder_name: str | None = get_config()["jf_folder"] - - if not folder_name or len(folder_name) < 1: - folder_name = "youtube" - else: - folder_name = folder_name.lower() + folder_name: str = get_config()["jf_folder"] for folder in folders["Items"]: - if folder.get("Name").lower() == folder_name: + if folder.get("Name").lower() == folder_name.lower(): return folder.get("Id") raise ValueError("youtube folder not found") diff --git a/app/src/static_types.py b/app/src/static_types.py index 1c2d62a..ecf7fee 100644 --- a/app/src/static_types.py +++ b/app/src/static_types.py @@ -11,7 +11,7 @@ class ConfigType(TypedDict): ta_token: str jf_url: str jf_token: str - jf_folder: str | None + jf_folder: str class TAChannel(TypedDict): From 8b70df5f93f28c0f3e48f87360e22ec6251789c9 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Thu, 21 Dec 2023 11:31:40 +0100 Subject: [PATCH 04/10] Relace function with builtin --- app/src/config.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/config.py b/app/src/config.py index 1fbaffd..d30e51f 100644 --- a/app/src/config.py +++ b/app/src/config.py @@ -29,12 +29,6 @@ def get_config_file() -> ConfigType | Literal[False]: return False -def get_variable_or_default(variable: str, default: str) -> str: - if not variable or len(variable) < 1: - return default - return variable - - def get_config_env() -> ConfigType | Literal[False]: """read config from environment""" if "TA_URL" in os.environ: @@ -44,9 +38,7 @@ def get_config_env() -> ConfigType | Literal[False]: "ta_token": os.environ["TA_TOKEN"], "jf_url": os.environ["JF_URL"], "jf_token": os.environ["JF_TOKEN"], - "jf_folder": get_variable_or_default( - os.environ["JF_FOLDER"], "youtube" - ), + "jf_folder": os.environ.get("JF_FOLDER", "youtube"), } return config_content From 1ea8832cac1b260a410e37875fb70a94f7bce861 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 16:04:15 +0100 Subject: [PATCH 05/10] Improvements --- app/src/connect.py | 3 ++- app/src/series.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/connect.py b/app/src/connect.py index 8d18541..d12d982 100644 --- a/app/src/connect.py +++ b/app/src/connect.py @@ -15,7 +15,8 @@ EXPECTED_ENV = { "jf_url", "jf_token", "ta_video_path", -} # jf_folder is optional + "jf_folder", +} class Jellyfin: diff --git a/app/src/series.py b/app/src/series.py index ad884dd..2ba5d9b 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -84,7 +84,7 @@ class Library: return print("waiting for library refresh") - sleep(5) + sleep(10) class Show: From a17d8de8d4372dcc67986b28554ae4fcff668029 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 16:09:03 +0100 Subject: [PATCH 06/10] Improvements --- app/src/series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/series.py b/app/src/series.py index 2ba5d9b..4995431 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -74,7 +74,7 @@ class Library: path: str = f"Items/{collection_id}/Refresh?Recursive=true&ImageRefreshMode=Default&MetadataRefreshMode=Default" # noqa: E501 Jellyfin().post(path, False) - for _ in range(12): + for _ in range(24): response = Jellyfin().get("Library/VirtualFolders") for folder in response: if not folder["ItemId"] == collection_id: From 58335947699c1f3215b65557fc91344a789c1879 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 16:15:05 +0100 Subject: [PATCH 07/10] Improvements --- app/src/series.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/series.py b/app/src/series.py index 4995431..bfeda69 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -210,9 +210,11 @@ class Show: jf_id: str = self.show["Id"] path: str = f"Items/{jf_id}/Refresh?Recursive=true&ImageRefreshMode=Default&MetadataRefreshMode=Default" # noqa: E501 Jellyfin().post(path, False) - for _ in range(12): + for _ in range(100): all_existing: set[str] = set(self._get_existing_seasons()) + print(f"[setup] seasons: {all_existing}") + if expected_season in all_existing: return From 61b584f5470b22e343b17f6aaad089bceb2bd912 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 16:22:09 +0100 Subject: [PATCH 08/10] Improvements --- app/src/series.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/series.py b/app/src/series.py index bfeda69..764a6b7 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -209,11 +209,12 @@ class Show: """wait for season to be created in JF""" jf_id: str = self.show["Id"] path: str = f"Items/{jf_id}/Refresh?Recursive=true&ImageRefreshMode=Default&MetadataRefreshMode=Default" # noqa: E501 + print(f"[setup] {path=}") Jellyfin().post(path, False) for _ in range(100): all_existing: set[str] = set(self._get_existing_seasons()) - print(f"[setup] seasons: {all_existing}") + print(f"[setup] seasons: {all_existing} {expected_season=}") if expected_season in all_existing: return From 429010f664f7729209271ea89d7e39113861b9ca Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 16:33:22 +0100 Subject: [PATCH 09/10] Improvements --- app/src/series.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/series.py b/app/src/series.py index 764a6b7..1cd702b 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -230,6 +230,8 @@ class Show: path: str = f"Shows/{series_id}/Seasons" all_seasons: dict = Jellyfin().get(path) + print(f"[setup] {path=} all_seasons_items={all_seasons['Items']}") + return [str(i.get("IndexNumber")) for i in all_seasons["Items"]] def delete_folders(self, folders: list[str]) -> None: From 7d1941ed7595896103dfcfa8e8c8f0d5b4aa7514 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Tue, 19 Mar 2024 17:35:30 +0100 Subject: [PATCH 10/10] Improvements --- app/src/series.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/series.py b/app/src/series.py index 1cd702b..382806d 100644 --- a/app/src/series.py +++ b/app/src/series.py @@ -232,7 +232,9 @@ class Show: print(f"[setup] {path=} all_seasons_items={all_seasons['Items']}") - return [str(i.get("IndexNumber")) for i in all_seasons["Items"]] + res = [str(i.get("Name")) for i in all_seasons["Items"]] + + return [name.split(' ')[1] if ' ' in name else name for name in res] def delete_folders(self, folders: list[str]) -> None: """delete temporary folders created"""