Add config.ini, backup path (#99)

This commit is contained in:
Helper 2024-04-11 10:44:40 +02:00 committed by GitHub
parent d942613dd8
commit eb6110e14f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 258 additions and 66 deletions

View File

@ -69,50 +69,6 @@ python3 update.py
You can change some behaviors by tweaking the configuration file.
```json
{
"DEFAULT": {
"debug": false,
"get_info": false,
"show_message": true,
"clean_console": true,
"get_moment_title": false,
"root_path": "videos",
"movies_folder_name": "Movies",
"series_folder_name": "Series",
"anime_folder_name": "Anime",
"not_close": false,
"swith_anime": false
},
"SITE": {
"streaming_site_name": "streamingcommunity",
"streaming_domain": "forum",
"anime_site_name": "animeunity",
"anime_domain": "to"
},
"M3U8": {
"tdqm_workers": 20,
"tqdm_progress_timeout": 10,
"minimum_ts_files_in_folder": 15,
"download_percentage": 1,
"requests_timeout": 5,
"enable_time_quit": false,
"tqdm_show_progress": false,
"cleanup_tmp_folder": true
},
"M3U8_OPTIONS": {
"download_audio": true,
"download_subtitles": true,
"specific_list_audio": [
"ita"
],
"specific_list_subtitles": [
"eng"
],
"map_episode_name": "%(tv_name)_S%(season)E%(episode)_%(episode_name)",
}
}
```
#### Options
@ -140,6 +96,8 @@ You can change some behaviors by tweaking the configuration file.
| minimum_ts_files_in_folder | 15 | The minimum number of .ts files expected in a folder. | 10 |
| download_percentage | 1 | The percentage of download completion required to consider the download complete. | 0.95 |
| requests_timeout | 5 | The timeout duration for HTTP requests in seconds. | 10 |
| use_openssl | false | Indicates whether OpenSSL should be utilized for encryption during the conversion of TS files with key and IV. | true |
| use_codecs | false | Specifies whether specific codecs (e.g., h264 for video, AAC for audio) should be used for converting TS files to MP4. | true |
| enable_time_quit | false | Whether to enable quitting the download after a certain time period. | true |
| tqdm_show_progress | false | Whether to show progress during downloads or not.**May slow down your PC** | true |
| cleanup_tmp_folder | true | Whether to clean up temporary folders after processing or not. | false |
@ -159,13 +117,13 @@ You can change some behaviors by tweaking the configuration file.
* Windows: `C:\\MyLibrary\\Folder` or `\\\\MyServer\\MyLibrary` (if you want to use a network folder).
* Linux/MacOS: `Desktop/MyLibrary/Folder`
## Tutorial
For a detailed walkthrough, refer to the [video tutorial](https://www.youtube.com/watch?v=Ok7hQCgxqLg&ab_channel=Nothing)
#### Episode name usage:
You can choose different vars:
* `%(tv_name)` : Is the name of TV Show
* `%(season)` : Is the number of the season
* `%(episode)` : Is the number of the episode
* `%(episode_name)` : Is the name of the episode
>NOTE: You don't need to add .mp4 at the end
>NOTE: You don't need to add .mp4 at the end
## Tutorial
For a detailed walkthrough, refer to the [video tutorial](https://www.youtube.com/watch?v=Ok7hQCgxqLg&ab_channel=Nothing)

View File

@ -19,7 +19,7 @@ from Src.Util.config import config_manager
# Variable
DEBUG_MODE = config_manager.get_bool("DEFAULT", "debug")
DEBUG_FFMPEG = "debug" if DEBUG_MODE else "error"
USE_CODECS = False
USE_CODECS = config_manager.get_bool("M3U8", "use_codecs")

View File

@ -146,17 +146,20 @@ def move_ffmpeg_exe_to_top_level(install_dir: str) -> None:
raise
def add_install_dir_to_environment_path(install_dir: str) -> None:
'''
"""
Add the install directory to the environment PATH variable.
Args:
install_dir (str): The directory to be added to the environment PATH variable.
'''
"""
install_dir = os.path.abspath(os.path.join(install_dir, 'bin'))
set_env_path(install_dir)
def download_ffmpeg():
"""
Main function to donwload ffmpeg and add to win path
"""
# Get FFMPEG download URL
ffmpeg_url = get_ffmpeg_download_url()
@ -189,13 +192,16 @@ def download_ffmpeg():
logging.info(f'Adding {install_dir} to environment PATH variable')
add_install_dir_to_environment_path(install_dir)
def check_ffmpeg():
def check_ffmpeg() -> bool:
"""
Check if FFmpeg is installed and available on the system PATH.
This function checks if FFmpeg is installed and available on the system PATH.
If FFmpeg is found, it prints its version. If not found, it attempts to download
FFmpeg and add it to the system PATH.
Returns:
bool: If ffmpeg is present or not
"""
console.print("[green]Checking FFmpeg...")
@ -209,6 +215,8 @@ def check_ffmpeg():
if show_version:
get_version()
return True
except:
try:
@ -225,3 +233,5 @@ def check_ffmpeg():
console.print("[red]Unable to download or add FFmpeg to the PATH.[/red]")
console.print(f"Error: {e}")
raise
return False

188
Src/Util/_tmpConfig.py Normal file
View File

@ -0,0 +1,188 @@
# 11.04.24
import os
import tempfile
import configparser
import logging
import json
from typing import Union, List
# Costant
repo_name = "StreamingCommunity_api"
config_file_name = f"{repo_name}_config.ini"
class ConfigError(Exception):
"""
Exception raised for errors related to configuration management.
"""
def __init__(self, message: str):
"""
Initialize ConfigError with the given error message.
Args:
message (str): The error message.
"""
self.message = message
super().__init__(self.message)
logging.error(self.message)
class ConfigManager:
"""
Class to manage configuration settings using a config file.
"""
def __init__(self, config_file_name: str = config_file_name, defaults: dict = None):
"""
Initialize ConfigManager.
Args:
config_file_name (str, optional): The name of the configuration file. Default is 'config.ini'.
defaults (dict, optional): A dictionary containing default values for variables. Default is None.
"""
self.config_file_path = os.path.join(tempfile.gettempdir(), config_file_name)
self.config = configparser.ConfigParser()
self.logger = logging.getLogger(__name__)
# Create config file if it doesn't exist
if not os.path.exists(self.config_file_path):
with open(self.config_file_path, 'w') as config_file:
if defaults:
for section, options in defaults.items():
if not self.config.has_section(section):
self.config.add_section(section)
for key, value in options.items():
self.config.set(section, key, str(value))
self.config.write(config_file)
# Read existing config
self.config.read(self.config_file_path)
def _check_section_and_key(self, section: str, key: str) -> None:
"""
Check if the given section and key exist in the configuration file.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
Raises:
ConfigError: If the section or key does not exist.
"""
if not self.config.has_section(section):
raise ConfigError(f"Section '{section}' does not exist in the configuration file.")
if not self.config.has_option(section, key):
raise ConfigError(f"Key '{key}' does not exist in section '{section}'.")
def get_int(self, section: str, key: str, default: Union[int, None] = None) -> Union[int, None]:
"""
Get the value of a variable from the config file as an integer.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
default (int, optional): Default value if the variable doesn't exist. Default is None.
Returns:
int or None: Value of the variable as an integer or default value.
"""
try:
self._check_section_and_key(section, key)
return int(self.config.get(section, key))
except (ConfigError, ValueError):
return default
def get_string(self, section: str, key: str, default: Union[str, None] = None) -> Union[str, None]:
"""
Get the value of a variable from the config file as a string.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
default (str, optional): Default value if the variable doesn't exist. Default is None.
Returns:
str or None: Value of the variable as a string or default value.
"""
try:
self._check_section_and_key(section, key)
return self.config.get(section, key)
except ConfigError:
return default
def get_bool(self, section: str, key: str, default: Union[bool, None] = None) -> Union[bool, None]:
"""
Get the value of a variable from the config file as a boolean.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
default (bool, optional): Default value if the variable doesn't exist. Default is None.
Returns:
bool or None: Value of the variable as a boolean or default value.
"""
try:
self._check_section_and_key(section, key)
return self.config.getboolean(section, key)
except ConfigError:
return default
def get_list(self, section: str, key: str, default: Union[List, None] = None) -> Union[List, None]:
"""
Get the value of a variable from the config file as a list.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
default (List, optional): Default value if the variable doesn't exist. Default is None.
Returns:
List or None: Value of the variable as a list or default value.
"""
try:
self._check_section_and_key(section, key)
value = self.config.get(section, key)
return json.loads(value)
except (ConfigError, json.JSONDecodeError):
return default
def add_variable(self, section: str, key: str, value: Union[int, str, bool, List]) -> None:
"""
Add or update a variable in the config file.
Args:
section (str): The section in the config file.
key (str): The key of the variable.
value (int, str, bool, List): The value of the variable.
"""
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, key, str(value))
with open(self.config_file_path, 'w') as config_file:
self.config.write(config_file)
self.logger.info(f"Added or updated variable '{key}' in section '{section}'")
def reload_config(self) -> None:
"""
Reload the configuration from the file.
"""
self.config.clear()
self.config.read(self.config_file_path)
self.logger.info("Configuration file reloaded")
# Output
defaults = {
'Requirements': {
'ffmpeg': False
},
'Backup' : {
'path': False
}
}
temp_config_manager = ConfigManager(defaults=defaults)

View File

@ -1,9 +1,5 @@
# 07.04.24
# to do
# run somehwere backup
# add config to trace if ffmpeg is install, using config in local or temp
import platform
import os
import logging
@ -98,16 +94,23 @@ def backup_path():
original_path = get_env("Path")
try:
script_dir = os.path.dirname(__file__)
# Create backup dir
script_dir = os.path.join(os.path.expanduser("~"), "Backup")
os.makedirs(script_dir, exist_ok=True)
backup_file = os.path.join(script_dir, "path_backup.txt")
with open(backup_file, "w") as f:
for path in original_path.split("\n"):
if len(path) > 3:
f.write(f"{path}; \n")
# Check if backup file exist
if not os.path.exists(backup_file):
logging.info("Backup of PATH variable created.")
print("Backup of PATH variable created.")
with open(backup_file, "w") as f:
for path in original_path.split("\n"):
if len(path) > 3:
f.write(f"{path}; \n")
logging.info("Backup of PATH variable created.")
print("Backup of PATH variable created.")
except Exception as e:
logging.error(f"Failed to create backup of PATH variable: {e}")

View File

@ -1,9 +1,17 @@
# 10.04.24
# Internal utilities
from Src.Lib.Unidecode import transliterate
from Src.Util.config import config_manager
from Src.Api.Class.EpisodeType import Episode
# Config
map_episode = config_manager.get('M3U8_OPTIONS', 'map_episode_name')
def map_episode_title(tv_name: str, episode, number_season: int):
def map_episode_title(tv_name: str, episode: Episode, number_season: int):
"""
Maps the episode title to a specific format.
@ -15,9 +23,11 @@ def map_episode_title(tv_name: str, episode, number_season: int):
Returns:
str: The mapped episode title.
"""
map_episode_temp = map_episode
map_episode_temp = map_episode_temp.replace("%(tv_name)", tv_name)
map_episode_temp = map_episode_temp.replace("%(season)", str(number_season).zfill(2))
map_episode_temp = map_episode_temp.replace("%(episode)", str(episode.number).zfill(2))
map_episode_temp = map_episode_temp.replace("%(episode_name)", episode.name)
return transliterate(map_episode_temp)

View File

@ -27,6 +27,7 @@
"download_percentage": 1,
"requests_timeout": 5,
"use_openssl": false,
"use_codecs": false,
"enable_time_quit": false,
"tqdm_show_progress": false,
"cleanup_tmp_folder": true

26
run.py
View File

@ -19,13 +19,15 @@ from Src.Api import (
from Src.Util.message import start_message
from Src.Util.console import console, msg
from Src.Util.config import config_manager
from Src.Util._tmpConfig import temp_config_manager
from Src.Util._win32 import backup_path
from Src.Util.os import remove_folder, remove_file
from Src.Upload.update import update as git_update
from Src.Lib.FFmpeg import check_ffmpeg
from Src.Util.logger import Logger
# Variable
# Config
DEBUG_MODE = config_manager.get_bool("DEFAULT", "debug")
DEBUG_GET_ALL_INFO = config_manager.get_bool('DEFAULT', 'get_info')
SWITCH_TO = config_manager.get_bool('DEFAULT', 'swith_anime')
@ -40,6 +42,7 @@ def initialize():
# Get system where script is run
run_system = platform.system()
# Enable debug with info
if DEBUG_MODE:
@ -54,20 +57,38 @@ def initialize():
console.log("Install python version > 3.11")
sys.exit(0)
# Removing temporary folder
remove_folder("tmp")
remove_file("debug.log")
start_message()
# Attempting GitHub update
try:
git_update()
except Exception as e:
console.print(f"[blue]Req github [white]=> [red]Failed: {e}")
# Checking ffmpeg availability ( only win )
if run_system == 'Windows':
check_ffmpeg()
# Check if backup of path exist
if not temp_config_manager.get_bool('Backup', 'path'):
# Make backup of init path
backup_path()
temp_config_manager.add_variable('Backup', 'path', True)
# Check if tmp config ffmpeg is present
if not temp_config_manager.get_bool('Requirements', 'ffmpeg'):
output_ffmpeg = check_ffmpeg()
# If ffmpeg is present is win systems change config
if output_ffmpeg:
temp_config_manager.add_variable('Requirements', 'ffmpeg', True)
def main():
"""
@ -111,6 +132,7 @@ def main():
# End
console.print("\n[red]Done")
def main_switch():
"""
Main function for anime unity