Unit3DwebUp 0.0.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- config/__init__.py +4 -0
- config/api_data.py +28 -0
- config/constants.py +34 -0
- config/host_data.py +47 -0
- config/itt.py +154 -0
- config/logger.py +37 -0
- config/settings.py +212 -0
- config/sis.py +137 -0
- config/tags.py +395 -0
- config/trackers.py +47 -0
- external/__init__.py +0 -0
- external/async_http_client_service.py +48 -0
- external/websocket.py +41 -0
- models/__init__.py +0 -0
- models/interfaces.py +39 -0
- models/keywords.py +13 -0
- models/media.py +597 -0
- models/media_info.py +142 -0
- models/movie.py +287 -0
- models/tv.py +266 -0
- models/tvdb_search.py +102 -0
- models/videos.py +26 -0
- repositories/__init__.py +0 -0
- repositories/db_online.py +82 -0
- repositories/interfaces.py +59 -0
- repositories/job_repos.py +166 -0
- repositories/media_info_factory.py +28 -0
- services/__init__.py +0 -0
- services/auto_async_service.py +237 -0
- services/create_torrent_service.py +94 -0
- services/interfaces.py +72 -0
- services/itt_tracker_helper.py +463 -0
- services/itt_tracker_service.py +85 -0
- services/lifespan_service.py +58 -0
- services/media_service.py +114 -0
- services/tags_service.py +389 -0
- services/tmdb.py +246 -0
- services/torrent_client_service.py +92 -0
- services/torrent_service.py +107 -0
- services/tvdb.py +65 -0
- services/utility.py +433 -0
- services/video_service.py +356 -0
- unit3dwebup-0.0.14.dist-info/METADATA +191 -0
- unit3dwebup-0.0.14.dist-info/RECORD +53 -0
- unit3dwebup-0.0.14.dist-info/WHEEL +5 -0
- unit3dwebup-0.0.14.dist-info/entry_points.txt +2 -0
- unit3dwebup-0.0.14.dist-info/top_level.txt +6 -0
- use_case/__init__.py +0 -0
- use_case/make_torrent_usecase.py +67 -0
- use_case/process_all_usecase.py +43 -0
- use_case/scan_media_usecase.py +133 -0
- use_case/seed_usecase.py +117 -0
- use_case/upload_usecase.py +77 -0
config/__init__.py
ADDED
config/api_data.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# Same as the old code 08.21
|
|
4
|
+
from config.settings import get_settings
|
|
5
|
+
|
|
6
|
+
settings = get_settings()
|
|
7
|
+
|
|
8
|
+
# Get data based on tracker name. For example itt e sis
|
|
9
|
+
trackers_api_data = {
|
|
10
|
+
'ITT':
|
|
11
|
+
{
|
|
12
|
+
"url": settings.tracker.ITT_URL,
|
|
13
|
+
"api_key": settings.tracker.ITT_APIKEY,
|
|
14
|
+
"pass_key": settings.tracker.ITT_PID,
|
|
15
|
+
"announce": f"{settings.tracker.ITT_URL}/announce/{settings.tracker.ITT_PID}",
|
|
16
|
+
"source": "ItaTorrents",
|
|
17
|
+
}
|
|
18
|
+
,
|
|
19
|
+
'SIS':
|
|
20
|
+
{
|
|
21
|
+
"url": settings.tracker.SIS_URL,
|
|
22
|
+
"api_key": settings.tracker.SIS_APIKEY,
|
|
23
|
+
"pass_key": settings.tracker.SIS_PID,
|
|
24
|
+
"announce": f"{settings.tracker.SIS_URL}/announce/{settings.tracker.SIS_PID}",
|
|
25
|
+
"source": "ShareIsland",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
config/constants.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MediaStatus(IntEnum):
|
|
6
|
+
"""
|
|
7
|
+
It tracks the status during the creation of a media file
|
|
8
|
+
"""
|
|
9
|
+
INDEXED = 0
|
|
10
|
+
|
|
11
|
+
# Searching tmdb,tvdb,imdb
|
|
12
|
+
DB_IDENTIFIED = 1
|
|
13
|
+
DB_NOT_IDENTIFIED = 10
|
|
14
|
+
DB_ERROR = 11
|
|
15
|
+
|
|
16
|
+
# When extracting the screenshots from the video file
|
|
17
|
+
VIDEO_READY = 2
|
|
18
|
+
VIDEO_ERROR = 20
|
|
19
|
+
|
|
20
|
+
# When uploading raw data to the image host
|
|
21
|
+
DESCRIPTION_READY = 3
|
|
22
|
+
DESCRIPTION_ERROR = 30
|
|
23
|
+
|
|
24
|
+
# When generating the torrent file *.torrent
|
|
25
|
+
TORRENT_GENERATED = 4
|
|
26
|
+
TORRENT_ERROR = 40
|
|
27
|
+
|
|
28
|
+
# When uploading torrent files to the tracker
|
|
29
|
+
TRACKER_UPLOADED = 5
|
|
30
|
+
TRACKER_NOT_UPLOADED = 50
|
|
31
|
+
|
|
32
|
+
# When seeding one or more torrent files
|
|
33
|
+
TORRENT_SEED = 7
|
|
34
|
+
TORRENT_SEED_ERROR = 70
|
config/host_data.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from config.settings import get_settings
|
|
4
|
+
|
|
5
|
+
settings = get_settings()
|
|
6
|
+
|
|
7
|
+
# Same as the old 0.8.21. Set the priority based on the config file
|
|
8
|
+
# TODO : host rotation on failure is not implemented yet
|
|
9
|
+
master_uploaders = ['ImgBB', 'PtScreens', 'LensDump', 'ImgFi', 'PassIMA', 'ImaRide', 'Freeimage']
|
|
10
|
+
|
|
11
|
+
upload_hosts = {
|
|
12
|
+
"ImgBB": {
|
|
13
|
+
"url": "https://api.imgbb.com/1/upload",
|
|
14
|
+
"data": {"key": settings.tracker.IMGBB_KEY, "fieldname": "name"},
|
|
15
|
+
"fieldname": "image"
|
|
16
|
+
},
|
|
17
|
+
"Freeimage": {
|
|
18
|
+
"url": "https://freeimage.host/api/1/upload",
|
|
19
|
+
"data": {"key": settings.tracker.FREE_IMAGE_KEY, "fieldname": "name"},
|
|
20
|
+
"fieldname": "image"
|
|
21
|
+
},
|
|
22
|
+
"PtScreens": {
|
|
23
|
+
"url": "https://ptscreens.com/api/1/upload",
|
|
24
|
+
"data": {"key": settings.tracker.PTSCREENS_KEY, "fieldname": "title"},
|
|
25
|
+
"fieldname": "source"
|
|
26
|
+
},
|
|
27
|
+
"LensDump": {
|
|
28
|
+
"url": "https://lensdump.com/api/1/upload",
|
|
29
|
+
"data": {"key": settings.tracker.LENSDUMP_KEY, "fieldname": "title"},
|
|
30
|
+
"fieldname": "source"
|
|
31
|
+
},
|
|
32
|
+
"ImgFi": {
|
|
33
|
+
"url": "https://imgfi.com/api/1/upload",
|
|
34
|
+
"data": {"key": settings.tracker.IMGFI_KEY, "fieldname": "title"},
|
|
35
|
+
"fieldname": "source"
|
|
36
|
+
},
|
|
37
|
+
"PassIMA": {
|
|
38
|
+
"url": "https://passtheima.ge/api/1/upload",
|
|
39
|
+
"data": {"key": settings.tracker.PASSIMA_KEY, "title": "name"},
|
|
40
|
+
"fieldname": "source"
|
|
41
|
+
},
|
|
42
|
+
"ImaRide": {
|
|
43
|
+
"url": "https://www.imageride.net/api/1/upload",
|
|
44
|
+
"data": {"key": settings.tracker.IMARIDE_KEY, "fieldname": "title"},
|
|
45
|
+
"fieldname": "source"
|
|
46
|
+
}
|
|
47
|
+
}
|
config/itt.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# List of constants pointing to the itt tracker
|
|
4
|
+
# TODO: Add automode to extract these constants?
|
|
5
|
+
itt_data = {
|
|
6
|
+
"CATEGORY": {"movie": 1,
|
|
7
|
+
"series": 2,
|
|
8
|
+
"edicola": 6,
|
|
9
|
+
"game": 4},
|
|
10
|
+
|
|
11
|
+
"FREELECH": {"size20": 100,
|
|
12
|
+
"size15": 75,
|
|
13
|
+
"size10": 50,
|
|
14
|
+
"size5": 25},
|
|
15
|
+
|
|
16
|
+
"TYPE_ID": {"full-disc": 1,
|
|
17
|
+
"remux": 2,
|
|
18
|
+
"bdremux": 2,
|
|
19
|
+
"vh": 2,
|
|
20
|
+
"untouched": 2,
|
|
21
|
+
"bd-untouched": 2,
|
|
22
|
+
"encode": 3,
|
|
23
|
+
"bluray": 3,
|
|
24
|
+
"fullhd": 3,
|
|
25
|
+
"hevc": 3,
|
|
26
|
+
"hdrip": 3,
|
|
27
|
+
"vu": 2,
|
|
28
|
+
"web-dl": 4,
|
|
29
|
+
"webdl": 4,
|
|
30
|
+
"web": 4,
|
|
31
|
+
"web-dlmux": 4,
|
|
32
|
+
"webrip": 5,
|
|
33
|
+
"hdtv": 6,
|
|
34
|
+
"mac": 12,
|
|
35
|
+
"macos": 12,
|
|
36
|
+
"windows": 13,
|
|
37
|
+
"pc": 13,
|
|
38
|
+
"cinema-md": 14,
|
|
39
|
+
"hdts": 14,
|
|
40
|
+
"wrs": 14,
|
|
41
|
+
"md": 14,
|
|
42
|
+
"altro": 15,
|
|
43
|
+
"pdf": 16,
|
|
44
|
+
"nintendo": 17,
|
|
45
|
+
"nsw": 17,
|
|
46
|
+
"ps4": 18,
|
|
47
|
+
"psn": 18,
|
|
48
|
+
"epub": 19,
|
|
49
|
+
"mp4": 20,
|
|
50
|
+
"pack": 22,
|
|
51
|
+
"avi": 23,
|
|
52
|
+
"dvdrip": 24,
|
|
53
|
+
"bdrip": 25,
|
|
54
|
+
"webmux": 26,
|
|
55
|
+
"dlmux": 27,
|
|
56
|
+
"bdmux": 29,
|
|
57
|
+
"3d": 32,
|
|
58
|
+
"cbr-cbz": 33,
|
|
59
|
+
"ps5": 35,
|
|
60
|
+
"psvr": 35,
|
|
61
|
+
},
|
|
62
|
+
"TYPE_ID_AUDIO": {"flac": 7,
|
|
63
|
+
"alac": 8,
|
|
64
|
+
"ac3": 9,
|
|
65
|
+
"aac": 10,
|
|
66
|
+
"mp3": 11,
|
|
67
|
+
},
|
|
68
|
+
"TAGS": {
|
|
69
|
+
"SD": 1,
|
|
70
|
+
"HD": 0,
|
|
71
|
+
},
|
|
72
|
+
"RESOLUTION": {
|
|
73
|
+
"4320p": 1,
|
|
74
|
+
"2160p": 2,
|
|
75
|
+
"1080p": 3,
|
|
76
|
+
"1080i": 4,
|
|
77
|
+
"720p": 5,
|
|
78
|
+
"576p": 6,
|
|
79
|
+
"576i": 7,
|
|
80
|
+
"480p": 8,
|
|
81
|
+
"480i": 9,
|
|
82
|
+
"altro": 10,
|
|
83
|
+
},
|
|
84
|
+
"CODEC": [
|
|
85
|
+
"h261",
|
|
86
|
+
"h262",
|
|
87
|
+
"h263",
|
|
88
|
+
"h264",
|
|
89
|
+
"x264",
|
|
90
|
+
"x265",
|
|
91
|
+
"avc",
|
|
92
|
+
"h265",
|
|
93
|
+
"hevc",
|
|
94
|
+
"vp8",
|
|
95
|
+
"vp9",
|
|
96
|
+
"av1",
|
|
97
|
+
"mpeg-1",
|
|
98
|
+
"mpeg-4",
|
|
99
|
+
"wmv",
|
|
100
|
+
"theora",
|
|
101
|
+
"divx",
|
|
102
|
+
"xvid",
|
|
103
|
+
"prores",
|
|
104
|
+
"dnxhd",
|
|
105
|
+
"cinepak",
|
|
106
|
+
"indeo",
|
|
107
|
+
"dv",
|
|
108
|
+
"ffv1",
|
|
109
|
+
"sorenson",
|
|
110
|
+
"rv40",
|
|
111
|
+
"cineform",
|
|
112
|
+
"huffyuv",
|
|
113
|
+
"mjpeg",
|
|
114
|
+
"lagarith",
|
|
115
|
+
"msu",
|
|
116
|
+
"rle",
|
|
117
|
+
"dirac",
|
|
118
|
+
"wmv3",
|
|
119
|
+
"vorbis",
|
|
120
|
+
"smpte",
|
|
121
|
+
"mjpeg",
|
|
122
|
+
"ffvhuff",
|
|
123
|
+
"v210",
|
|
124
|
+
"yuv4:2:2",
|
|
125
|
+
"yuv4:4:4",
|
|
126
|
+
"hap",
|
|
127
|
+
"sheervideo",
|
|
128
|
+
"ut",
|
|
129
|
+
"quicktime",
|
|
130
|
+
"rududu",
|
|
131
|
+
"h.266",
|
|
132
|
+
"vvc",
|
|
133
|
+
"mjpeg 4:2:0",
|
|
134
|
+
"h.263+",
|
|
135
|
+
"h.263++",
|
|
136
|
+
"vp4",
|
|
137
|
+
"vp5",
|
|
138
|
+
"vp6",
|
|
139
|
+
"vp7",
|
|
140
|
+
"vp8",
|
|
141
|
+
"vp9",
|
|
142
|
+
"vp10",
|
|
143
|
+
"vp11",
|
|
144
|
+
"vp12",
|
|
145
|
+
"vp3",
|
|
146
|
+
"vp2",
|
|
147
|
+
"vp1",
|
|
148
|
+
"amv",
|
|
149
|
+
"daala",
|
|
150
|
+
"gecko",
|
|
151
|
+
"nvenc",
|
|
152
|
+
"bluray",
|
|
153
|
+
],
|
|
154
|
+
}
|
config/logger.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
COLORS = {
|
|
7
|
+
logging.DEBUG: "\033[36m", # -> cyano
|
|
8
|
+
logging.INFO: "\033[32m", # -> green
|
|
9
|
+
logging.WARNING: "\033[33m", # -> yellow
|
|
10
|
+
logging.ERROR: "\033[31m", # -> red
|
|
11
|
+
logging.CRITICAL: "\033[41m", # -> red background
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
RESET = "\033[0m"
|
|
15
|
+
|
|
16
|
+
class ColorFormatter(logging.Formatter):
|
|
17
|
+
|
|
18
|
+
# Called by the handler
|
|
19
|
+
def format(self, record):
|
|
20
|
+
color = COLORS.get(record.levelno, "")
|
|
21
|
+
message = super().format(record)
|
|
22
|
+
return f"{color}{message}{RESET}"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# /// Attempt to create a dedicated logger for Docker....
|
|
26
|
+
def get_logger(name: str = "app_logger") -> logging.Logger:
|
|
27
|
+
logger = logging.getLogger(name)
|
|
28
|
+
|
|
29
|
+
if not logger.hasHandlers():
|
|
30
|
+
logger.setLevel(logging.INFO)
|
|
31
|
+
handler = logging.StreamHandler(sys.stdout)
|
|
32
|
+
formatter = ColorFormatter("[%(levelname)s] %(name)s: %(message)s")
|
|
33
|
+
handler.setFormatter(formatter) # Custom formatter
|
|
34
|
+
logger.addHandler(handler)
|
|
35
|
+
return logger
|
|
36
|
+
|
|
37
|
+
|
config/settings.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import os
|
|
3
|
+
from functools import lru_cache
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, field_validator, model_validator, HttpUrl, Field, ValidationError
|
|
8
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
9
|
+
from config.logger import get_logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# /// Class to help avoid typos...
|
|
13
|
+
class TorrentClient(str, Enum):
|
|
14
|
+
qbittorrent = "qbittorrent"
|
|
15
|
+
transmission = "transmission"
|
|
16
|
+
rtorrent = "rtorrent"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# /// Check for missing value
|
|
20
|
+
class BaseConfigModel(BaseModel):
|
|
21
|
+
|
|
22
|
+
@field_validator("*", mode="before")
|
|
23
|
+
@classmethod
|
|
24
|
+
def empty_to_none(cls, v):
|
|
25
|
+
if v == "":
|
|
26
|
+
return None
|
|
27
|
+
return v
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# /// version
|
|
31
|
+
class Unit3DwebUp(BaseConfigModel):
|
|
32
|
+
VERSION: str = "build"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# /// TRACKER CONFIG
|
|
36
|
+
class TrackerConfig(BaseConfigModel):
|
|
37
|
+
ITT_URL: HttpUrl
|
|
38
|
+
ITT_APIKEY: str = None
|
|
39
|
+
ITT_PID: str | None = None
|
|
40
|
+
SIS_URL: HttpUrl
|
|
41
|
+
SIS_APIKEY: str | None = None
|
|
42
|
+
SIS_PID: str | None = None
|
|
43
|
+
MULTI_TRACKER: list[str]
|
|
44
|
+
TMDB_APIKEY: str = None
|
|
45
|
+
TVDB_APIKEY: str = None
|
|
46
|
+
IMGBB_KEY: str = None
|
|
47
|
+
FREE_IMAGE_KEY: str | None = None
|
|
48
|
+
LENSDUMP_KEY: str | None = None
|
|
49
|
+
PTSCREENS_KEY: str | None = None
|
|
50
|
+
IMGFI_KEY: str | None = None
|
|
51
|
+
PASSIMA_KEY: str | None = None
|
|
52
|
+
IMARIDE_KEY: str | None = None
|
|
53
|
+
YOUTUBE_KEY: str | None = None
|
|
54
|
+
IGDB_CLIENT_ID: str | None = None
|
|
55
|
+
IGDB_ID_SECRET: str | None = None
|
|
56
|
+
|
|
57
|
+
@field_validator("MULTI_TRACKER", mode="before")
|
|
58
|
+
@classmethod
|
|
59
|
+
def parse_multi_tracker(cls, v):
|
|
60
|
+
if isinstance(v, str):
|
|
61
|
+
return [x.strip() for x in v.split(",") if x.strip()]
|
|
62
|
+
return v
|
|
63
|
+
|
|
64
|
+
@field_validator("*")
|
|
65
|
+
@classmethod
|
|
66
|
+
def validate_api_keys(cls, v, info):
|
|
67
|
+
if info.field_name.endswith("_KEY") or "APIKEY" in info.field_name:
|
|
68
|
+
if v is not None and len(v) < 5:
|
|
69
|
+
raise ValueError(f"{info.field_name} too short")
|
|
70
|
+
return v
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# /// TORRENT CLIENT CONFIG
|
|
74
|
+
class TorrentClientConfig(BaseConfigModel):
|
|
75
|
+
# Default value when the variable is commented out
|
|
76
|
+
QBIT_USER: str = "admin"
|
|
77
|
+
QBIT_PASS: str = "admin"
|
|
78
|
+
QBIT_HOST: str = "http://127.0.0.1"
|
|
79
|
+
QBIT_PORT: int = 8080
|
|
80
|
+
SHARED_QBIT_PATH: str = "/tmp"
|
|
81
|
+
|
|
82
|
+
TRASM_USER: str = "admin"
|
|
83
|
+
TRASM_PASS: str = "admin"
|
|
84
|
+
TRASM_HOST: str = "http://127.0.0.1"
|
|
85
|
+
TRASM_PORT: int = 9091
|
|
86
|
+
SHARED_TRASM_PATH: str = "/tmp"
|
|
87
|
+
|
|
88
|
+
RTORR_USER: str = "admin"
|
|
89
|
+
RTORR_PASS: str = "admin"
|
|
90
|
+
RTORR_HOST: str = "http://127.0.0.1"
|
|
91
|
+
RTORR_PORT: int = 5000
|
|
92
|
+
SHARED_RTORR_PATH: str = "/tmp"
|
|
93
|
+
|
|
94
|
+
TORRENT_CLIENT: TorrentClient = "qbittorrent"
|
|
95
|
+
TAG: str = "TAG1"
|
|
96
|
+
|
|
97
|
+
@field_validator("QBIT_PORT", "TRASM_PORT", "RTORR_PORT")
|
|
98
|
+
@classmethod
|
|
99
|
+
def validate_ports(cls, v):
|
|
100
|
+
if not 1 <= v <= 65535:
|
|
101
|
+
raise ValueError("invalid port range")
|
|
102
|
+
return v
|
|
103
|
+
|
|
104
|
+
@model_validator(mode="after")
|
|
105
|
+
def validate_selected_client(self):
|
|
106
|
+
if self.TORRENT_CLIENT == TorrentClient.qbittorrent:
|
|
107
|
+
if not self.QBIT_HOST:
|
|
108
|
+
raise ValueError("qbittorrent selected but no host has been configured")
|
|
109
|
+
if self.TORRENT_CLIENT == TorrentClient.transmission:
|
|
110
|
+
if not self.TRASM_HOST:
|
|
111
|
+
raise ValueError("transmission selected but no host has been configured")
|
|
112
|
+
if self.TORRENT_CLIENT == TorrentClient.rtorrent:
|
|
113
|
+
if not self.RTORR_HOST:
|
|
114
|
+
raise ValueError("rtorrent selected but no host has been configured")
|
|
115
|
+
return self
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# /// USER PREFERENCES
|
|
119
|
+
class UserPreferences(BaseConfigModel):
|
|
120
|
+
RELEASER_SIGN: str = ""
|
|
121
|
+
TAG_POSITION_MOVIE: list[str]
|
|
122
|
+
TAG_POSITION_SERIE: list[str]
|
|
123
|
+
PTSCREENS_PRIORITY: int = 0
|
|
124
|
+
LENSDUMP_PRIORITY: int = 1
|
|
125
|
+
FREE_IMAGE_PRIORITY: int = 2
|
|
126
|
+
IMGBB_PRIORITY: int = 3
|
|
127
|
+
IMGFI_PRIORITY: int = 4
|
|
128
|
+
PASSIMA_PRIORITY: int = 5
|
|
129
|
+
IMARIDE_PRIORITY: int = 6
|
|
130
|
+
|
|
131
|
+
NUMBER_OF_SCREENSHOTS: int = 4
|
|
132
|
+
YOUTUBE_CHANNEL_ENABLE: bool = False
|
|
133
|
+
DUPLICATE_ON: bool = False # Todo Not yet implemented
|
|
134
|
+
SKIP_DUPLICATE: bool = False #
|
|
135
|
+
SKIP_YOUTUBE: bool = False
|
|
136
|
+
SIZE_TH: int = 50
|
|
137
|
+
WATCHER_INTERVAL: int = 60
|
|
138
|
+
WATCHER_PATH: str | None = None
|
|
139
|
+
WATCHER_DESTINATION_PATH: str | None = None
|
|
140
|
+
TORRENT_ARCHIVE_PATH: str = None
|
|
141
|
+
SCAN_PATH: str = None
|
|
142
|
+
COMPRESS_SCSHOT: int = 4
|
|
143
|
+
TORRENT_COMMENT: str | None = "no_comment"
|
|
144
|
+
PREFERRED_LANG: str | None = "all"
|
|
145
|
+
ANON: bool = False
|
|
146
|
+
WEBP_ENABLED: bool = False
|
|
147
|
+
PERSONAL_RELEASE: bool = False
|
|
148
|
+
FAST_LOAD: int = 0
|
|
149
|
+
|
|
150
|
+
@field_validator("WATCHER_INTERVAL")
|
|
151
|
+
@classmethod
|
|
152
|
+
def validate_interval(cls, v):
|
|
153
|
+
if v < 5:
|
|
154
|
+
raise ValueError("WATCHER_INTERVAL too low")
|
|
155
|
+
return v
|
|
156
|
+
|
|
157
|
+
@field_validator("TAG_POSITION_MOVIE", "TAG_POSITION_SERIE", mode="before")
|
|
158
|
+
@classmethod
|
|
159
|
+
def parse_tag_position(cls, v):
|
|
160
|
+
if isinstance(v, str):
|
|
161
|
+
return [x.strip() for x in v.split(",") if x.strip()]
|
|
162
|
+
return v
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# /// APP SETTINGS
|
|
166
|
+
class Settings(BaseSettings):
|
|
167
|
+
"""
|
|
168
|
+
Set default settings
|
|
169
|
+
"""
|
|
170
|
+
unit3DwebUp: Unit3DwebUp = Field(default_factory=Unit3DwebUp)
|
|
171
|
+
tracker: TrackerConfig = Field(default_factory=TrackerConfig)
|
|
172
|
+
torrent: TorrentClientConfig = Field(default_factory=TorrentClientConfig)
|
|
173
|
+
prefs: UserPreferences = Field(default_factory=UserPreferences)
|
|
174
|
+
|
|
175
|
+
model_config = SettingsConfigDict(
|
|
176
|
+
env_nested_delimiter="__",
|
|
177
|
+
# /// lo utilizzo quando lo testo in locale
|
|
178
|
+
# docker utilizza 'env_file:' nel suo file yml
|
|
179
|
+
env_file=".env" if not os.getenv("DOCKER") else None,
|
|
180
|
+
extra="ignore"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@lru_cache
|
|
185
|
+
def get_settings() -> Settings:
|
|
186
|
+
"""
|
|
187
|
+
:return: settings cached
|
|
188
|
+
"""
|
|
189
|
+
logger = get_logger("settings_logger")
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
settings = Settings()
|
|
193
|
+
except ValidationError as e:
|
|
194
|
+
for err in e.errors():
|
|
195
|
+
field_path = ".".join(str(loc) for loc in err["loc"])
|
|
196
|
+
logger.warning(f"{field_path} value not set or invalid")
|
|
197
|
+
logger.warning("-" * 50)
|
|
198
|
+
|
|
199
|
+
raise SystemExit(1)
|
|
200
|
+
|
|
201
|
+
# Create a folder for each tracker name in the MULTI_TRACKER environment variable
|
|
202
|
+
torrent_archive_path = Path("/home/app/torrent_archive") if os.getenv("DOCKER") == "true" else Path(
|
|
203
|
+
settings.prefs.TORRENT_ARCHIVE_PATH)
|
|
204
|
+
if not Path.exists(torrent_archive_path):
|
|
205
|
+
logger.warning(f"The path {torrent_archive_path} does not exist")
|
|
206
|
+
raise SystemExit(1)
|
|
207
|
+
|
|
208
|
+
for tracker_name in settings.tracker.MULTI_TRACKER:
|
|
209
|
+
torrent_archive_tracker_path = Path(torrent_archive_path) / tracker_name.upper()
|
|
210
|
+
os.makedirs(torrent_archive_tracker_path, exist_ok=True)
|
|
211
|
+
|
|
212
|
+
return settings
|
config/sis.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# List of constants pointing to the sis tracker
|
|
4
|
+
# TODO: Add automode to extract these constants?
|
|
5
|
+
sis_data = {
|
|
6
|
+
"CATEGORY": {"movie": 1,
|
|
7
|
+
"series": 2,
|
|
8
|
+
"ebook": 15,
|
|
9
|
+
"edicola": 17,
|
|
10
|
+
"xxx": 19,
|
|
11
|
+
"Music": 3,
|
|
12
|
+
"game": 7,
|
|
13
|
+
"software": 23,
|
|
14
|
+
"eventi sportivi": 24,
|
|
15
|
+
"misc": 25},
|
|
16
|
+
|
|
17
|
+
"FREELECH": {"size20": 100,
|
|
18
|
+
"size15": 75,
|
|
19
|
+
"size10": 50,
|
|
20
|
+
"size5": 25},
|
|
21
|
+
|
|
22
|
+
"TYPE_ID": {
|
|
23
|
+
"encode": 15,
|
|
24
|
+
"web": 27,
|
|
25
|
+
"web-dl": 27,
|
|
26
|
+
"webrip": 27,
|
|
27
|
+
"remux": 7,
|
|
28
|
+
"disk": 26,
|
|
29
|
+
"cinemanews": 42,
|
|
30
|
+
"hdtv": 33,
|
|
31
|
+
"windows": 31,
|
|
32
|
+
"pc": 31,
|
|
33
|
+
"linux": 39,
|
|
34
|
+
"android": 38,
|
|
35
|
+
"appleos": 32,
|
|
36
|
+
"mp3": 25,
|
|
37
|
+
"flac": 24,
|
|
38
|
+
"epub": 48,
|
|
39
|
+
"pdf": 49,
|
|
40
|
+
"altro": 47,
|
|
41
|
+
|
|
42
|
+
},
|
|
43
|
+
"TYPE_ID_AUDIO": {
|
|
44
|
+
"flac": 24,
|
|
45
|
+
"alac": 8,
|
|
46
|
+
"ac3": 9,
|
|
47
|
+
"aac": 10,
|
|
48
|
+
"mp3": 25,
|
|
49
|
+
},
|
|
50
|
+
"TAGS": {
|
|
51
|
+
"SD": 1,
|
|
52
|
+
"HD": 0,
|
|
53
|
+
},
|
|
54
|
+
"RESOLUTION": {
|
|
55
|
+
"4320p": 1,
|
|
56
|
+
"2160p": 2,
|
|
57
|
+
'1440p': 3,
|
|
58
|
+
"1080p": 3,
|
|
59
|
+
"1080i": 4,
|
|
60
|
+
"720p": 5,
|
|
61
|
+
"576p": 6,
|
|
62
|
+
"576i": 7,
|
|
63
|
+
"480p": 8,
|
|
64
|
+
"480i": 9,
|
|
65
|
+
"altro": 11,
|
|
66
|
+
},
|
|
67
|
+
"CODEC": [
|
|
68
|
+
"h261",
|
|
69
|
+
"h262",
|
|
70
|
+
"h263",
|
|
71
|
+
"h264",
|
|
72
|
+
"x264",
|
|
73
|
+
"x265",
|
|
74
|
+
"avc",
|
|
75
|
+
"h265",
|
|
76
|
+
"hevc",
|
|
77
|
+
"vp8",
|
|
78
|
+
"vp9",
|
|
79
|
+
"av1",
|
|
80
|
+
"mpeg-1",
|
|
81
|
+
"mpeg-4",
|
|
82
|
+
"wmv",
|
|
83
|
+
"theora",
|
|
84
|
+
"divx",
|
|
85
|
+
"xvid",
|
|
86
|
+
"prores",
|
|
87
|
+
"dnxhd",
|
|
88
|
+
"cinepak",
|
|
89
|
+
"indeo",
|
|
90
|
+
"dv",
|
|
91
|
+
"ffv1",
|
|
92
|
+
"sorenson",
|
|
93
|
+
"rv40",
|
|
94
|
+
"cineform",
|
|
95
|
+
"huffyuv",
|
|
96
|
+
"mjpeg",
|
|
97
|
+
"lagarith",
|
|
98
|
+
"msu",
|
|
99
|
+
"rle",
|
|
100
|
+
"dirac",
|
|
101
|
+
"wmv3",
|
|
102
|
+
"vorbis",
|
|
103
|
+
"smpte",
|
|
104
|
+
"mjpeg",
|
|
105
|
+
"ffvhuff",
|
|
106
|
+
"v210",
|
|
107
|
+
"yuv4:2:2",
|
|
108
|
+
"yuv4:4:4",
|
|
109
|
+
"hap",
|
|
110
|
+
"sheervideo",
|
|
111
|
+
"ut",
|
|
112
|
+
"quicktime",
|
|
113
|
+
"rududu",
|
|
114
|
+
"h.266",
|
|
115
|
+
"vvc",
|
|
116
|
+
"mjpeg 4:2:0",
|
|
117
|
+
"h.263+",
|
|
118
|
+
"h.263++",
|
|
119
|
+
"vp4",
|
|
120
|
+
"vp5",
|
|
121
|
+
"vp6",
|
|
122
|
+
"vp7",
|
|
123
|
+
"vp8",
|
|
124
|
+
"vp9",
|
|
125
|
+
"vp10",
|
|
126
|
+
"vp11",
|
|
127
|
+
"vp12",
|
|
128
|
+
"vp3",
|
|
129
|
+
"vp2",
|
|
130
|
+
"vp1",
|
|
131
|
+
"amv",
|
|
132
|
+
"daala",
|
|
133
|
+
"gecko",
|
|
134
|
+
"nvenc",
|
|
135
|
+
"bluray",
|
|
136
|
+
],
|
|
137
|
+
}
|