Unit3Dup 0.9.17__tar.gz → 0.9.20__tar.gz
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.
- {unit3dup-0.9.17 → unit3dup-0.9.20}/PKG-INFO +1 -1
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/PKG-INFO +1 -1
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/SOURCES.txt +4 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/top_level.txt +2 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/settings.py +48 -273
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/tags.py +93 -22
- unit3dup-0.9.20/common/trackers/ban_list.py +5 -0
- unit3dup-0.9.20/common/trackers/signs_list.py +252 -0
- unit3dup-0.9.20/common/trackers/tags_list.py +106 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/utility.py +37 -19
- unit3dup-0.9.20/docs_old/conf.py +10 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/pyproject.toml +1 -1
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/__main__.py +30 -20
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/bot.py +3 -2
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/TorrentManager.py +6 -6
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/VideoManager.py +6 -2
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/pvtVideo.py +2 -4
- {unit3dup-0.9.17 → unit3dup-0.9.20}/LICENSE +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/README.rst +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/dependency_links.txt +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/entry_points.txt +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/Unit3Dup.egg-info/requires.txt +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/bdinfo_string.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/bittorrent.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/command.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/constants.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/database.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/client.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/ftpx_service.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/ftpx_session.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/menu.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/models/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/ftpx/core/models/list.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/client.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/api.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/models/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/models/search.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/platformid.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/igdb/core/tags.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/imageHost.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/mediaresult.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/sessions/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/sessions/agents.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/sessions/exceptions.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/sessions/session.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/api.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/keywords.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/theMovieDB/core/videos.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/trailers/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/trailers/api.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/trailers/response.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/external_services/tvdb.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/extractor.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/frames.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/mediainfo.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/mediainfo_string.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/title.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/torrent_clients.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/trackers/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/trackers/data.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/trackers/itt.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/trackers/sis.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/common/trackers/trackers.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/requirements.txt +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/setup.cfg +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/automode.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/duplicate.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/exceptions.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/ContentManager.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/DocuManager.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/GameManager.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/MediaInfoManager.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/SeedManager.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/media_manager/common.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/pvtDocu.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/pvtTorrent.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/pvtTracker.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/torrent.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/unit3dup/upload.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/view/__init__.py +0 -0
- {unit3dup-0.9.17 → unit3dup-0.9.20}/view/custom_console.py +0 -0
|
@@ -69,10 +69,14 @@ common/external_services/trailers/__init__.py
|
|
|
69
69
|
common/external_services/trailers/api.py
|
|
70
70
|
common/external_services/trailers/response.py
|
|
71
71
|
common/trackers/__init__.py
|
|
72
|
+
common/trackers/ban_list.py
|
|
72
73
|
common/trackers/data.py
|
|
73
74
|
common/trackers/itt.py
|
|
75
|
+
common/trackers/signs_list.py
|
|
74
76
|
common/trackers/sis.py
|
|
77
|
+
common/trackers/tags_list.py
|
|
75
78
|
common/trackers/trackers.py
|
|
79
|
+
docs_old/conf.py
|
|
76
80
|
unit3dup/__init__.py
|
|
77
81
|
unit3dup/__main__.py
|
|
78
82
|
unit3dup/automode.py
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
2
|
import ipaddress
|
|
4
3
|
import json
|
|
5
4
|
import os
|
|
@@ -8,17 +7,23 @@ import re
|
|
|
8
7
|
import unicodedata
|
|
9
8
|
|
|
10
9
|
from pydantic import BaseModel, model_validator
|
|
10
|
+
from pathvalidate import sanitize_filepath
|
|
11
11
|
from urllib.parse import urlparse
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
from common.trackers.signs_list import SIGNS_LIST
|
|
15
|
+
from common.trackers.tags_list import TAGS_LIST
|
|
16
|
+
from common.trackers.ban_list import BAN_LIST
|
|
17
|
+
|
|
14
18
|
from common.utility import ManageTitles
|
|
15
19
|
from common import trackers
|
|
16
20
|
|
|
17
21
|
config_file = "Unit3Dbot.json"
|
|
18
22
|
user_tags_file = "tags_list.json"
|
|
19
23
|
user_sign_file = "sign_list.json"
|
|
24
|
+
bane_file = "ban_list.json"
|
|
20
25
|
|
|
21
|
-
version = "0.9.
|
|
26
|
+
version = "0.9.20"
|
|
22
27
|
|
|
23
28
|
if os.name == "nt":
|
|
24
29
|
WATCHER_DESTINATION_PATH: Path = Path(
|
|
@@ -29,7 +34,7 @@ if os.name == "nt":
|
|
|
29
34
|
DEFAULT_JSON_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{config_file}"
|
|
30
35
|
USER_TAGS_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{user_tags_file}"
|
|
31
36
|
USER_SIGN_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{user_sign_file}"
|
|
32
|
-
|
|
37
|
+
BAN_TAGS_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{bane_file}"
|
|
33
38
|
|
|
34
39
|
else:
|
|
35
40
|
WATCHER_DESTINATION_PATH: Path = Path.home() / "Unit3Dup_config" / "watcher_destination_path"
|
|
@@ -39,6 +44,7 @@ else:
|
|
|
39
44
|
DEFAULT_JSON_PATH: Path = Path.home() / "Unit3Dup_config" / f"{config_file}"
|
|
40
45
|
USER_TAGS_PATH: Path = Path.home() / "Unit3Dup_config" / f"{user_tags_file}"
|
|
41
46
|
USER_SIGN_PATH: Path = Path.home() / "Unit3Dup_config" / f"{user_sign_file}"
|
|
47
|
+
BAN_TAGS_PATH: Path = Path.home() / "Unit3Dup_config" / f"{bane_file}"
|
|
42
48
|
|
|
43
49
|
|
|
44
50
|
def get_default_path(field: str) -> str:
|
|
@@ -109,7 +115,8 @@ class UserPreferences(BaseModel):
|
|
|
109
115
|
IMGFI_PRIORITY: int = 4
|
|
110
116
|
PASSIMA_PRIORITY: int = 5
|
|
111
117
|
IMARIDE_PRIORITY: int = 6
|
|
112
|
-
|
|
118
|
+
TAGS_POSITION_MOVIE: list[str] | None = None
|
|
119
|
+
TAGS_POSITION_SERIE: list[str] | None = None
|
|
113
120
|
|
|
114
121
|
NUMBER_OF_SCREENSHOTS: int = 4
|
|
115
122
|
YOUTUBE_FAV_CHANNEL_ID: str | None = None
|
|
@@ -253,18 +260,19 @@ class Validate:
|
|
|
253
260
|
def validate_tags_position(position_list: list) -> list | None:
|
|
254
261
|
|
|
255
262
|
if not position_list:
|
|
256
|
-
print(f"-> Invalid TAG
|
|
263
|
+
print(f"-> Invalid TAG POSITION list. The list is empty !")
|
|
257
264
|
exit(1)
|
|
258
265
|
|
|
259
266
|
if len(position_list) > 17 or len(position_list) < 5:
|
|
260
|
-
print(f"-> Invalid
|
|
267
|
+
print(f"-> Invalid Tag list: number of elements exceeds the maximum allowed tags!")
|
|
261
268
|
exit(1)
|
|
262
269
|
|
|
263
270
|
for tag in position_list:
|
|
264
|
-
if tag.lower() not in ["title", "year", "season", "version", "resolution", "uhd", "platform",
|
|
271
|
+
if tag.lower() not in ["title", "part", "year", "season", "version", "resolution", "uhd", "platform",
|
|
272
|
+
"source",
|
|
265
273
|
"remux",
|
|
266
274
|
"multi", "acodec", "channels", "flag", "subtitle", "vcodec", "hdr", "video_encoder"]:
|
|
267
|
-
print(f"-> Invalid TAG
|
|
275
|
+
print(f"-> Invalid TAG '{tag}'. Please fix your configuration file")
|
|
268
276
|
exit(1)
|
|
269
277
|
|
|
270
278
|
return position_list
|
|
@@ -485,7 +493,10 @@ class Config(BaseModel):
|
|
|
485
493
|
if field == 'RELEASER_SIGN':
|
|
486
494
|
section[field] = Validate.sign(sign=section[field])
|
|
487
495
|
|
|
488
|
-
if field in ['
|
|
496
|
+
if field in ['TAGS_POSITION_MOVIE']:
|
|
497
|
+
section[field] = Validate.validate_tags_position(position_list=section[field])
|
|
498
|
+
|
|
499
|
+
if field in ['TAGS_POSITION_SERIE']:
|
|
489
500
|
section[field] = Validate.validate_tags_position(position_list=section[field])
|
|
490
501
|
|
|
491
502
|
return v
|
|
@@ -526,274 +537,27 @@ class Load:
|
|
|
526
537
|
"""
|
|
527
538
|
Creates a tags list file
|
|
528
539
|
"""
|
|
529
|
-
TAG_TYPES = {
|
|
530
|
-
"REMUX": "remux",
|
|
531
|
-
"WEB-DL": "source",
|
|
532
|
-
"WEBDL": "source",
|
|
533
|
-
"WEB-DLRIP": "source",
|
|
534
|
-
"WEBDLRIP": "source",
|
|
535
|
-
"WEB-DLMUX": "source",
|
|
536
|
-
"WEBDLMUX": "source",
|
|
537
|
-
"WEBMUX": "source",
|
|
538
|
-
"WEBRIP": "source",
|
|
539
|
-
"BD-UNTOUCHED": "source",
|
|
540
|
-
"UNTOUCHED": "source",
|
|
541
|
-
|
|
542
|
-
"TS": "source",
|
|
543
|
-
"CAM": "source",
|
|
544
|
-
"HDTS": "source",
|
|
545
|
-
"MD": "source",
|
|
546
|
-
"UHDRIP": "source",
|
|
547
|
-
"BLURAY": "source",
|
|
548
|
-
"BRRIP": "source",
|
|
549
|
-
"BDRIP": "source",
|
|
550
|
-
"FHDRIP": "source",
|
|
551
|
-
"PDTV": "source",
|
|
552
|
-
"SATRIP": "source",
|
|
553
|
-
"DVBRIP": "source",
|
|
554
|
-
"DVB-S": "source",
|
|
555
|
-
"DTTRIP": "source",
|
|
556
|
-
"WP": "source",
|
|
557
|
-
"DVDSCR": "source",
|
|
558
|
-
"TVRIP": "source",
|
|
559
|
-
"VHSRIP": "source",
|
|
560
|
-
"DVDRIP": "source",
|
|
561
|
-
"HDTV": "source",
|
|
562
|
-
"DVD5": "source",
|
|
563
|
-
"DVD9": "source",
|
|
564
|
-
"VU": "source",
|
|
565
|
-
|
|
566
|
-
"ATVP": "platform",
|
|
567
|
-
"AMZN": "platform",
|
|
568
|
-
"AMC": "platform",
|
|
569
|
-
"CN": "platform",
|
|
570
|
-
"CR": "platform",
|
|
571
|
-
"DCU": "platform",
|
|
572
|
-
"DISC": "platform",
|
|
573
|
-
"DSCP": "platform",
|
|
574
|
-
"DSNY": "platform",
|
|
575
|
-
"DSNP": "platform",
|
|
576
|
-
"DPLY": "platform",
|
|
577
|
-
"ESPN": "platform",
|
|
578
|
-
"FOOD": "platform",
|
|
579
|
-
"FOX": "platform",
|
|
580
|
-
"PLAY": "platform",
|
|
581
|
-
"HBO": "platform",
|
|
582
|
-
"HMAX": "platform",
|
|
583
|
-
"HGTV": "platform",
|
|
584
|
-
"HIST": "platform",
|
|
585
|
-
"HULU": "platform",
|
|
586
|
-
"MTOD": "platform",
|
|
587
|
-
"NATG": "platform",
|
|
588
|
-
"NF": "platform",
|
|
589
|
-
"NICK": "platform",
|
|
590
|
-
"NOW": "platform",
|
|
591
|
-
"PMNT": "platform",
|
|
592
|
-
"PMTP": "platform",
|
|
593
|
-
"PCOK": "platform",
|
|
594
|
-
"RKTN": "platform",
|
|
595
|
-
"SHO": "platform",
|
|
596
|
-
"SKST": "platform",
|
|
597
|
-
"STAN": "platform",
|
|
598
|
-
"STRP": "platform",
|
|
599
|
-
"STZ": "platform",
|
|
600
|
-
"TIMV": "platform",
|
|
601
|
-
|
|
602
|
-
"SPECIAL": "version",
|
|
603
|
-
"REPACK": "version",
|
|
604
|
-
"EXTENDED": "version",
|
|
605
|
-
"EDITION": "version",
|
|
606
|
-
"DIRECTOR'S": "version",
|
|
607
|
-
"CUT": "version",
|
|
608
|
-
|
|
609
|
-
"SUBBED": "version",
|
|
610
|
-
"MUX": "version",
|
|
611
|
-
"REMASTERED": "version",
|
|
612
|
-
"READNFO": "version",
|
|
613
|
-
"UNRATED": "version",
|
|
614
|
-
"UNCUT": "version",
|
|
615
|
-
"LIMITED": "version",
|
|
616
|
-
"ANNIVERSARY": "version",
|
|
617
|
-
"4k RESTORATION": "version",
|
|
618
|
-
"IMAX": "version",
|
|
619
|
-
"OPEN MATTE": "version",
|
|
620
|
-
"2IN1": "version",
|
|
621
|
-
|
|
622
|
-
"STV": "version",
|
|
623
|
-
"RECODE": "version",
|
|
624
|
-
"INTERNAL": "version",
|
|
625
|
-
"PROPER": "version",
|
|
626
|
-
"DUAL": "version",
|
|
627
|
-
"COMPLETE": "version",
|
|
628
|
-
"COMPLETA": "version",
|
|
629
|
-
|
|
630
|
-
"X264": "video_encoder",
|
|
631
|
-
"X265": "video_encoder",
|
|
632
|
-
}
|
|
633
|
-
|
|
634
540
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
635
541
|
with open(path, "w", encoding="utf-8") as tags_list_file:
|
|
636
|
-
json.dump(
|
|
542
|
+
json.dump(TAGS_LIST, tags_list_file, ensure_ascii=False, indent=4)
|
|
637
543
|
|
|
638
544
|
@staticmethod
|
|
639
545
|
def create_sign_list_file(path: Path):
|
|
640
546
|
"""
|
|
641
|
-
Creates a
|
|
547
|
+
Creates a sign list file
|
|
642
548
|
"""
|
|
643
|
-
TAG_TYPES = {
|
|
644
|
-
"21APRILE": "releaser",
|
|
645
|
-
"ALE88SERMETE": "releaser",
|
|
646
|
-
"ARRANCAR": "releaser",
|
|
647
|
-
"ASTOR": "releaser",
|
|
648
|
-
"AV1MERR": "releaser",
|
|
649
|
-
"BADGUY": "releaser",
|
|
650
|
-
"BITSHIFT": "releaser",
|
|
651
|
-
"BLACKBIT": "releaser",
|
|
652
|
-
"BUMBLEBEE1982": "releaser",
|
|
653
|
-
"CAPPYO": "releaser",
|
|
654
|
-
"CAVALLONZI": "releaser",
|
|
655
|
-
"CB01HD": "releaser",
|
|
656
|
-
"CHD": "releaser",
|
|
657
|
-
"CHDWEB": "releaser",
|
|
658
|
-
"CIAME": "releaser",
|
|
659
|
-
"CLOCLONE": "releaser",
|
|
660
|
-
"COMIX21": "releaser",
|
|
661
|
-
"CREW": "releaser",
|
|
662
|
-
"CSS": "releaser",
|
|
663
|
-
"CSS2": "releaser",
|
|
664
|
-
"CSS7896": "releaser",
|
|
665
|
-
"CYBER": "releaser",
|
|
666
|
-
"D3VELOPER": "releaser",
|
|
667
|
-
"DAICHISO": "releaser",
|
|
668
|
-
"DANGUARD": "releaser",
|
|
669
|
-
"DARKCOMPANY": "releaser",
|
|
670
|
-
"DARKPARANOR": "releaser",
|
|
671
|
-
"DAYMON64": "releaser",
|
|
672
|
-
"DDN": "releaser",
|
|
673
|
-
"DEDO1911": "releaser",
|
|
674
|
-
"DEMN": "releaser",
|
|
675
|
-
"DMAN": "releaser",
|
|
676
|
-
"DOCH74": "releaser",
|
|
677
|
-
"DRIIP": "releaser",
|
|
678
|
-
"DYNUX": "releaser",
|
|
679
|
-
"ELGHOTO": "releaser",
|
|
680
|
-
"ENCRYPTED": "releaser",
|
|
681
|
-
"EVN": "releaser",
|
|
682
|
-
"EZTV": "releaser",
|
|
683
|
-
"FAINO1310": "releaser",
|
|
684
|
-
"FEDECAS89": "releaser",
|
|
685
|
-
"FGT": "releaser",
|
|
686
|
-
"FHC": "releaser",
|
|
687
|
-
"FLORIN993": "releaser",
|
|
688
|
-
"FLUX": "releaser",
|
|
689
|
-
"FREZEEN": "releaser",
|
|
690
|
-
"FUSION": "releaser",
|
|
691
|
-
"G66": "releaser",
|
|
692
|
-
"GABIACAS": "releaser",
|
|
693
|
-
"GIUSEPPETNT": "releaser",
|
|
694
|
-
"GOLDENTORRENT": "releaser",
|
|
695
|
-
"GRYM": "releaser",
|
|
696
|
-
"HAPPITEAM-YNK": "releaser",
|
|
697
|
-
"HASHDEV": "releaser",
|
|
698
|
-
"HDCHINA": "releaser",
|
|
699
|
-
"HENRYDIRTY": "releaser",
|
|
700
|
-
"HONE": "releaser",
|
|
701
|
-
"HHNN": "releaser",
|
|
702
|
-
"HYRULE": "releaser",
|
|
703
|
-
"I3AM": "releaser",
|
|
704
|
-
"IBANEZ89": "releaser",
|
|
705
|
-
"IDIB": "releaser",
|
|
706
|
-
"IDN": "releaser",
|
|
707
|
-
"ILGANZO": "releaser",
|
|
708
|
-
"ILPADRINO": "releaser",
|
|
709
|
-
"ILSAGGIO": "releaser",
|
|
710
|
-
"ILSOMMO": "releaser",
|
|
711
|
-
"IPDR01": "releaser",
|
|
712
|
-
"ITT": "releaser",
|
|
713
|
-
"JOHNSEED": "releaser",
|
|
714
|
-
"KINGOFROME": "releaser",
|
|
715
|
-
"KRIKK": "releaser",
|
|
716
|
-
"LAZY-SUBS": "releaser",
|
|
717
|
-
"LEPORE": "releaser",
|
|
718
|
-
"LFI": "releaser",
|
|
719
|
-
"LULLOZZO": "releaser",
|
|
720
|
-
"MATT3O": "releaser",
|
|
721
|
-
"MATT_BROWN4": "releaser",
|
|
722
|
-
"MAX2014": "releaser",
|
|
723
|
-
"MIRCREW": "releaser",
|
|
724
|
-
"MISTERNED": "releaser",
|
|
725
|
-
"MRBLONDE": "releaser",
|
|
726
|
-
"MRROBOT": "releaser",
|
|
727
|
-
"MUETTO": "releaser",
|
|
728
|
-
"MUWATTALI": "releaser",
|
|
729
|
-
"NAHOM": "releaser",
|
|
730
|
-
"NARSETE": "releaser",
|
|
731
|
-
"NEOSTARK": "releaser",
|
|
732
|
-
"NEUROSIS": "releaser",
|
|
733
|
-
"NIMOUEH": "releaser",
|
|
734
|
-
"NOGROUP": "releaser",
|
|
735
|
-
"NOVARIP": "releaser",
|
|
736
|
-
"NTROPIC": "releaser",
|
|
737
|
-
"ODS": "releaser",
|
|
738
|
-
"ONGOIA": "releaser",
|
|
739
|
-
"PEPPE": "releaser",
|
|
740
|
-
"PENNYWISE": "releaser",
|
|
741
|
-
"PETE321": "releaser",
|
|
742
|
-
"PICOPOCO": "releaser",
|
|
743
|
-
"PING": "releaser",
|
|
744
|
-
"PINKER": "releaser",
|
|
745
|
-
"PIR8": "releaser",
|
|
746
|
-
"PLAYWEB": "releaser",
|
|
747
|
-
"PRIME": "releaser",
|
|
748
|
-
"PROMETHEUS": "releaser",
|
|
749
|
-
"PROSCIUTTO": "releaser",
|
|
750
|
-
"RADESE": "releaser",
|
|
751
|
-
"RAWR": "releaser",
|
|
752
|
-
"RARBG": "releaser",
|
|
753
|
-
"RIDDICKK": "releaser",
|
|
754
|
-
"ROGELIOBYNIGHT": "releaser",
|
|
755
|
-
"ROMEO": "releaser",
|
|
756
|
-
"RYUKXX": "releaser",
|
|
757
|
-
"S-K": "releaser",
|
|
758
|
-
"SANDWORM": "releaser",
|
|
759
|
-
"SEEDBOX": "releaser",
|
|
760
|
-
"SEEDBOX2": "releaser",
|
|
761
|
-
"SERCIUS": "releaser",
|
|
762
|
-
"SIMO01": "releaser",
|
|
763
|
-
"SIXTEEN8664": "releaser",
|
|
764
|
-
"SK4TTO": "releaser",
|
|
765
|
-
"SMURFADMIN": "releaser",
|
|
766
|
-
"SPYRO1989": "releaser",
|
|
767
|
-
"STEVEJOHNNEE": "releaser",
|
|
768
|
-
"STINGUAJT": "releaser",
|
|
769
|
-
"TAHTAKALECI": "releaser",
|
|
770
|
-
"TELESTO": "releaser",
|
|
771
|
-
"TERMINAL": "releaser",
|
|
772
|
-
"THEBLACKKING": "releaser",
|
|
773
|
-
"THEEMOJICREW": "releaser",
|
|
774
|
-
"THUDARA": "releaser",
|
|
775
|
-
"TIGRE67": "releaser",
|
|
776
|
-
"TORRENT10": "releaser",
|
|
777
|
-
"TOTAL_SHARE88": "releaser",
|
|
778
|
-
"TREE7458": "releaser",
|
|
779
|
-
"TRIVIAL99": "releaser",
|
|
780
|
-
"UBI": "releaser",
|
|
781
|
-
"V3SP4EV3R": "releaser",
|
|
782
|
-
"VIOLENT96": "releaser",
|
|
783
|
-
"VOLVIC": "releaser",
|
|
784
|
-
"WHEELIE": "releaser",
|
|
785
|
-
"WHITERHINO": "releaser",
|
|
786
|
-
"WIZARDS2K": "releaser",
|
|
787
|
-
"WRS": "releaser",
|
|
788
|
-
"XVID": "releaser",
|
|
789
|
-
"YIFY": "releaser",
|
|
790
|
-
"YTS": "releaser",
|
|
791
|
-
"ZIORIP": "releaser"
|
|
792
|
-
}
|
|
793
|
-
|
|
794
549
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
795
550
|
with open(path, "w", encoding="utf-8") as tags_sign_file:
|
|
796
|
-
json.dump(
|
|
551
|
+
json.dump(SIGNS_LIST, tags_sign_file, ensure_ascii=False, indent=4)
|
|
552
|
+
|
|
553
|
+
@staticmethod
|
|
554
|
+
def create_ban_list_file(path: Path):
|
|
555
|
+
"""
|
|
556
|
+
Creates a ban list file
|
|
557
|
+
"""
|
|
558
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
559
|
+
with open(path, "w", encoding="utf-8") as ban_list_file:
|
|
560
|
+
json.dump(BAN_LIST, ban_list_file, ensure_ascii=False, indent=4)
|
|
797
561
|
|
|
798
562
|
@staticmethod
|
|
799
563
|
def create_default_json_file(path: Path):
|
|
@@ -851,9 +615,16 @@ class Load:
|
|
|
851
615
|
"PASSIMA_PRIORITY": 5,
|
|
852
616
|
"IMARIDE_PRIORITY": 6,
|
|
853
617
|
"NUMBER_OF_SCREENSHOTS": 4,
|
|
854
|
-
"
|
|
855
|
-
|
|
856
|
-
|
|
618
|
+
"TAGS_POSITION_MOVIE": ["title", "year", "part", "version", "resolution", "uhd", "platform", "source",
|
|
619
|
+
"remux",
|
|
620
|
+
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec",
|
|
621
|
+
"video_encoder"],
|
|
622
|
+
|
|
623
|
+
"TAGS_POSITION_SERIE": ["title", "year", "season", "version", "resolution", "uhd", "platform", "source",
|
|
624
|
+
"remux",
|
|
625
|
+
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec",
|
|
626
|
+
"video_encoder"],
|
|
627
|
+
|
|
857
628
|
"YOUTUBE_FAV_CHANNEL_ID": "UCGCbxpnt25hWPFLSbvwfg_w",
|
|
858
629
|
"YOUTUBE_CHANNEL_ENABLE": "False",
|
|
859
630
|
"DUPLICATE_ON": "true",
|
|
@@ -935,6 +706,10 @@ class Load:
|
|
|
935
706
|
print(f"Create default Sign_list file: {USER_SIGN_PATH}")
|
|
936
707
|
Load.create_sign_list_file(USER_SIGN_PATH)
|
|
937
708
|
|
|
709
|
+
if not BAN_TAGS_PATH.exists():
|
|
710
|
+
print(f"Create default Ban_list file: {BAN_TAGS_PATH}")
|
|
711
|
+
Load.create_ban_list_file(BAN_TAGS_PATH)
|
|
712
|
+
|
|
938
713
|
# Since the last bot version there might are new attributes
|
|
939
714
|
# Load the json file, find the difference between json file and the code. Update the user's json file
|
|
940
715
|
update_config = JsonConfig(default_json_path=DEFAULT_JSON_PATH)
|
|
@@ -1090,7 +865,7 @@ class JsonConfig:
|
|
|
1090
865
|
|
|
1091
866
|
def json_message_new_attributes(self):
|
|
1092
867
|
|
|
1093
|
-
print("-- **
|
|
868
|
+
print("-- ** New attributes have been added since the last bot version ** --")
|
|
1094
869
|
message = ''
|
|
1095
870
|
if self.tracker_diff_keys:
|
|
1096
871
|
message += f"New Tracker Configuration attribute: {self.tracker_diff_keys}\n"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
import os
|
|
3
2
|
import re
|
|
4
3
|
from common.mediainfo import MediaFile
|
|
5
4
|
from common.utility import ManageTitles
|
|
@@ -10,12 +9,14 @@ hdr_map = {
|
|
|
10
9
|
"DOLBY VISION": "DV",
|
|
11
10
|
"DOLBY VISION HDR": "DV HDR",
|
|
12
11
|
"DOLBY VISION HDR10": "DV HDR10",
|
|
13
|
-
"DOLBY VISION HDR10+": "DV
|
|
12
|
+
"DOLBY VISION HDR10+": "DV HDR10+",
|
|
14
13
|
"HDR10PLUS": "HDR10+",
|
|
15
14
|
"HDRPLUS+": "HDR10+",
|
|
16
15
|
"HDR10+": "HDR10+",
|
|
17
16
|
"HDR10": "HDR10",
|
|
17
|
+
"BLU-RAY / HDR10": "HDR10",
|
|
18
18
|
"HDR10 / HDR10": "HDR10",
|
|
19
|
+
"HDR10 / HDR10+": "HDR10+",
|
|
19
20
|
"HDR10 / HDR10 / HDR10+": "HDR10+",
|
|
20
21
|
"SMPTE ST 2086": "HDR10",
|
|
21
22
|
"SMPTE ST 2094": "HDR10+",
|
|
@@ -56,7 +57,8 @@ video_encoder_translate = {
|
|
|
56
57
|
|
|
57
58
|
class SearchTags(object):
|
|
58
59
|
def __init__(self, filename, title: str, year: str, season: int, episode: int,
|
|
59
|
-
mediafile: MediaFile, tags_position: list, tags_list: dict, sign_list: dict,
|
|
60
|
+
mediafile: MediaFile, tags_position: list, tags_list: dict, sign_list: dict, ban_list: dict,
|
|
61
|
+
releaser_sign: str):
|
|
60
62
|
|
|
61
63
|
self.tags_position = tags_position
|
|
62
64
|
self.releaser_sign = releaser_sign
|
|
@@ -68,14 +70,29 @@ class SearchTags(object):
|
|
|
68
70
|
self.year = year
|
|
69
71
|
self.tags_dict = {}
|
|
70
72
|
self.tags_position = tags_position
|
|
71
|
-
self.TAG_TYPES = tags_list
|
|
72
|
-
self.SIGNS_LIST = sign_list
|
|
73
|
+
self.TAG_TYPES: dict = tags_list
|
|
74
|
+
self.SIGNS_LIST: dict = sign_list
|
|
75
|
+
self.BAN_LIST: dict = ban_list
|
|
73
76
|
|
|
74
77
|
@staticmethod
|
|
75
78
|
def normalize_version_tag(tag: str) -> str:
|
|
76
79
|
tag_esc = re.escape(tag)
|
|
77
80
|
return tag_esc
|
|
78
81
|
|
|
82
|
+
@staticmethod
|
|
83
|
+
def normalize_part_tag(title: str) -> str | None:
|
|
84
|
+
"""
|
|
85
|
+
Extract substring PartX
|
|
86
|
+
Try to remove noisy chars and return a normalized tag
|
|
87
|
+
Part1, Part 1, Part.1, [Part 1], Parte1, Pt1, Prt 2,
|
|
88
|
+
"""
|
|
89
|
+
pattern = r'[\[\(]?\b(?:Part|Parte|Pt|Prt)[\s\.-]*?(\d+)\b[\]\)]?'
|
|
90
|
+
match = re.search(pattern, title, re.IGNORECASE)
|
|
91
|
+
if match:
|
|
92
|
+
part_number = match.group(1)
|
|
93
|
+
return f"Part {part_number}"
|
|
94
|
+
return None
|
|
95
|
+
|
|
79
96
|
@staticmethod
|
|
80
97
|
def normalize_platform_tag(tag: str) -> str:
|
|
81
98
|
tag_esc = re.escape(tag)
|
|
@@ -86,7 +103,6 @@ class SearchTags(object):
|
|
|
86
103
|
tag_esc = re.escape(tag)
|
|
87
104
|
return tag_esc
|
|
88
105
|
|
|
89
|
-
|
|
90
106
|
@staticmethod
|
|
91
107
|
def normalize_video_encoder(tag: str) -> str:
|
|
92
108
|
tag_esc = re.escape(tag)
|
|
@@ -101,12 +117,16 @@ class SearchTags(object):
|
|
|
101
117
|
build.append(' '.join(v))
|
|
102
118
|
else:
|
|
103
119
|
build.append(str(v))
|
|
120
|
+
|
|
104
121
|
refactored = ' '.join(build) + self.releaser_sign
|
|
105
122
|
return refactored
|
|
106
123
|
|
|
107
124
|
def process(self) -> str:
|
|
108
125
|
patterns = []
|
|
109
126
|
|
|
127
|
+
# Remove banned items from categories
|
|
128
|
+
self.tags_position = [x for x in self.tags_position if x not in self.BAN_LIST]
|
|
129
|
+
|
|
110
130
|
# loop sorted TAG_TYPES dictionary
|
|
111
131
|
for i, (tag, category) in enumerate(
|
|
112
132
|
sorted(self.TAG_TYPES.items(), key=lambda x: len(x[0]), reverse=True)
|
|
@@ -131,6 +151,14 @@ class SearchTags(object):
|
|
|
131
151
|
if matches:
|
|
132
152
|
self.tags_dict.setdefault(category, []).append(matches[0])
|
|
133
153
|
|
|
154
|
+
# /// Tags with no categories
|
|
155
|
+
# Identify PartX
|
|
156
|
+
norm = self.normalize_part_tag(self.filename)
|
|
157
|
+
if norm:
|
|
158
|
+
# Skip if it is part of title es: "Wicked.Parte.2.2025.iTA" Title = Wicked Parte 2
|
|
159
|
+
if not any(t in self.title.lower() for t in ['part', 'parte']):
|
|
160
|
+
self.tags_dict.update({'part': norm})
|
|
161
|
+
|
|
134
162
|
# /// Read from mediainfo
|
|
135
163
|
updated_category = {}
|
|
136
164
|
for category in self.tags_position:
|
|
@@ -146,10 +174,13 @@ class SearchTags(object):
|
|
|
146
174
|
|
|
147
175
|
elif category == "hdr":
|
|
148
176
|
updated_category = self.mediainfo_hdr(category=category)
|
|
177
|
+
if not updated_category:
|
|
178
|
+
updated_category = {category: 'SDR'}
|
|
149
179
|
|
|
150
180
|
elif category == "uhd":
|
|
151
181
|
updated_category = self.mediainfo_uhd(category=category)
|
|
152
182
|
|
|
183
|
+
|
|
153
184
|
elif category == "subtitle":
|
|
154
185
|
if self.mediafile.subtitle_track:
|
|
155
186
|
updated_category = {'subtitle': "SUBS" if len(self.mediafile.subtitle_track) > 1 else "SUB"}
|
|
@@ -175,22 +206,7 @@ class SearchTags(object):
|
|
|
175
206
|
if not self.releaser_sign:
|
|
176
207
|
# If releaser_sign is not defined in the configuration file,
|
|
177
208
|
# try to detect a known sign from SIGN_LIST
|
|
178
|
-
|
|
179
|
-
sorted((re.escape(k) for k in self.SIGNS_LIST.keys()), key=len, reverse=True)
|
|
180
|
-
)
|
|
181
|
-
self.filename = os.path.splitext(self.filename)[0]
|
|
182
|
-
regex = re.compile(
|
|
183
|
-
r'(?:^|[\s._-])(' + pattern + r')(?=$|[\s._-]*$)',
|
|
184
|
-
re.IGNORECASE
|
|
185
|
-
)
|
|
186
|
-
matches = regex.findall(self.filename)
|
|
187
|
-
if matches:
|
|
188
|
-
self.releaser_sign = f"-{matches[0]}" if matches[0].upper() in self.SIGNS_LIST else ""
|
|
189
|
-
else:
|
|
190
|
-
self.releaser_sign = ""
|
|
191
|
-
else:
|
|
192
|
-
# Add releaser_sign from the configuration file
|
|
193
|
-
self.releaser_sign = f"-{self.releaser_sign}"
|
|
209
|
+
self.releaser_sign = self.detect_releaser(self.filename, self.SIGNS_LIST)
|
|
194
210
|
|
|
195
211
|
# /// Order according to tag position
|
|
196
212
|
tags_dict = {
|
|
@@ -255,6 +271,11 @@ class SearchTags(object):
|
|
|
255
271
|
for video in self.mediafile.video_track:
|
|
256
272
|
hdr_format_commercial = video.get('hdr_format_commercial', "")
|
|
257
273
|
hdr_format = video.get('hdr_format', "")
|
|
274
|
+
colour_primaries = video.get('color_primaries', "")
|
|
275
|
+
matrix_coefficients = video.get('matrix_coefficients', "")
|
|
276
|
+
bit_depth = video.get('bit_depth', "")
|
|
277
|
+
transfer_characteristics = video.get('transfer_characteristics', "")
|
|
278
|
+
|
|
258
279
|
# Check hdr
|
|
259
280
|
if hdr_format_commercial:
|
|
260
281
|
# print(f"hdr_format_commercial: {hdr_format_commercial}")
|
|
@@ -271,6 +292,17 @@ class SearchTags(object):
|
|
|
271
292
|
if 'DOLBY VISION' in hdr_format_commercial.upper() or 'DOLBY VISION' in hdr_format.upper():
|
|
272
293
|
hdr = f"DOLBY VISION {hdr}"
|
|
273
294
|
return {category: hdr_map.get(hdr, '*HDR')}
|
|
295
|
+
else:
|
|
296
|
+
if "2020" in colour_primaries and "2020" in matrix_coefficients:
|
|
297
|
+
if bit_depth == 10 and transfer_characteristics.strip() == 'PQ':
|
|
298
|
+
return {category: 'PQ10'}
|
|
299
|
+
else:
|
|
300
|
+
custom_console.bot_warning_log(f"<> PQ10 Warning:")
|
|
301
|
+
custom_console.bot_log(f"colour_primaries: {colour_primaries}")
|
|
302
|
+
custom_console.bot_log(f"matrix_coefficients: {matrix_coefficients}")
|
|
303
|
+
custom_console.bot_log(f"bit_depth: |{bit_depth}|")
|
|
304
|
+
custom_console.bot_log(f"transfer_characteristics: |{transfer_characteristics}|")
|
|
305
|
+
|
|
274
306
|
return {}
|
|
275
307
|
|
|
276
308
|
def mediainfo_uhd(self, category: str) -> dict:
|
|
@@ -314,3 +346,42 @@ class SearchTags(object):
|
|
|
314
346
|
result['resolution'] = f'{video_width}x{video_height}'
|
|
315
347
|
|
|
316
348
|
return result
|
|
349
|
+
|
|
350
|
+
@staticmethod
|
|
351
|
+
def detect_releaser(name: str, signs_list: dict) -> str:
|
|
352
|
+
"""
|
|
353
|
+
normalize both signs_list and base_name
|
|
354
|
+
find the start/end position of the matched sign
|
|
355
|
+
extract the substring from the original base_name
|
|
356
|
+
"""
|
|
357
|
+
# Strip the title
|
|
358
|
+
base_name = str(name).strip()
|
|
359
|
+
|
|
360
|
+
# sort dictionary from the longest to shortest to avoid partial result (es. 'crew' instead di 'mircrew')
|
|
361
|
+
tokens_signs_list_sorted = sorted(signs_list.keys(), key=len, reverse=True)
|
|
362
|
+
|
|
363
|
+
video_exts = [
|
|
364
|
+
"mp4", "mkv", "avi", "mov", "wmv", "flv", "webm", "mpeg", "mpg", "m4v", "ts", "3gp"
|
|
365
|
+
]
|
|
366
|
+
|
|
367
|
+
# Regex per catturare l'estensione alla fine (case insensitive)
|
|
368
|
+
pattern = rf"\.({'|'.join(video_exts)})$"
|
|
369
|
+
|
|
370
|
+
# # Search for signs in the base_name only at the end of the string
|
|
371
|
+
base_name = re.sub(pattern, "", base_name, flags=re.IGNORECASE)
|
|
372
|
+
|
|
373
|
+
# Search for signs in the base_name_normalized
|
|
374
|
+
for token in tokens_signs_list_sorted:
|
|
375
|
+
token = str(token)
|
|
376
|
+
pattern = re.escape(token)
|
|
377
|
+
match = re.search(pattern, base_name, re.IGNORECASE)
|
|
378
|
+
|
|
379
|
+
if match:
|
|
380
|
+
# Sign must be the last words
|
|
381
|
+
base_name_len = len(base_name)
|
|
382
|
+
match_len = match.end() - base_name_len
|
|
383
|
+
if match_len == 0:
|
|
384
|
+
# Capture any characters from the start to the end of base_name
|
|
385
|
+
sign = base_name[match.start(): match.end()]
|
|
386
|
+
return f"-{sign}"
|
|
387
|
+
return ""
|