Unit3Dup 0.9.9__tar.gz → 0.9.11__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.9 → unit3dup-0.9.11}/PKG-INFO +1 -1
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/PKG-INFO +1 -1
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/p2p_tags.py +113 -158
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/settings.py +1 -1
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/utility.py +45 -29
- {unit3dup-0.9.9 → unit3dup-0.9.11}/pyproject.toml +1 -1
- {unit3dup-0.9.9 → unit3dup-0.9.11}/LICENSE +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/README.rst +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/SOURCES.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/dependency_links.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/entry_points.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/requires.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/Unit3Dup.egg-info/top_level.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/bdinfo_string.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/bittorrent.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/command.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/constants.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/database.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/client.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/ftpx_service.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/ftpx_session.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/menu.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/models/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/ftpx/core/models/list.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/client.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/api.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/models/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/models/search.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/platformid.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/igdb/core/tags.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/imageHost.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/mediaresult.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/sessions/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/sessions/agents.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/sessions/exceptions.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/sessions/session.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/api.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/keywords.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/videos.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/trailers/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/trailers/api.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/trailers/response.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/tvdb.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/extractor.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/frames.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/mediainfo.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/mediainfo_string.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/title.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/torrent_clients.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/trackers/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/trackers/data.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/trackers/itt.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/trackers/sis.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/common/trackers/trackers.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/requirements.txt +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/setup.cfg +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/__main__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/automode.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/bot.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/duplicate.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/exceptions.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/ContentManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/DocuManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/GameManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/MediaInfoManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/SeedManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/TorrentManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/VideoManager.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/media_manager/common.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/pvtDocu.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/pvtTorrent.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/pvtTracker.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/pvtVideo.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/torrent.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/unit3dup/upload.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/view/__init__.py +0 -0
- {unit3dup-0.9.9 → unit3dup-0.9.11}/view/custom_console.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import os
|
|
3
3
|
import re
|
|
4
|
+
from collections import deque
|
|
4
5
|
from common.utility import ManageTitles
|
|
5
6
|
from common.mediainfo import MediaFile
|
|
6
|
-
from collections import deque
|
|
7
7
|
|
|
8
8
|
TAG_TYPES = {
|
|
9
9
|
"WEB-DL": "source",
|
|
@@ -16,8 +16,10 @@ TAG_TYPES = {
|
|
|
16
16
|
"REMUX": "source",
|
|
17
17
|
"VU": "source",
|
|
18
18
|
"UHD": "source",
|
|
19
|
+
"UHDRIP": "source",
|
|
19
20
|
"BLURAY": "source",
|
|
20
21
|
|
|
22
|
+
"ATVP": "platform",
|
|
21
23
|
"AMZN": "platform",
|
|
22
24
|
"AMC": "platform",
|
|
23
25
|
"CN": "platform",
|
|
@@ -53,8 +55,6 @@ TAG_TYPES = {
|
|
|
53
55
|
"STZ": "platform",
|
|
54
56
|
"TIMV": "platform",
|
|
55
57
|
|
|
56
|
-
"SUB": "subtitle",
|
|
57
|
-
"SUBS": "subtitle",
|
|
58
58
|
"ITA": "flag",
|
|
59
59
|
"ENG": "flag",
|
|
60
60
|
"FRA": "flag",
|
|
@@ -65,6 +65,9 @@ TAG_TYPES = {
|
|
|
65
65
|
"POR": "flag",
|
|
66
66
|
"PRT": "flag",
|
|
67
67
|
|
|
68
|
+
"SUB": "subtitle",
|
|
69
|
+
"SUBS": "subtitle",
|
|
70
|
+
|
|
68
71
|
"ATMOS": "audio",
|
|
69
72
|
"TRUEHD": "audio",
|
|
70
73
|
"DTSHD": "audio",
|
|
@@ -74,19 +77,19 @@ TAG_TYPES = {
|
|
|
74
77
|
"DDP5.1": "audio",
|
|
75
78
|
"DDP2.0": "audio",
|
|
76
79
|
"DTS": "audio",
|
|
77
|
-
|
|
80
|
+
"XLL": "audio",
|
|
78
81
|
"DD7.1": "audio",
|
|
79
82
|
"DD5.1": "audio",
|
|
80
83
|
"DD2.0": "audio",
|
|
81
|
-
|
|
82
84
|
"DD+ 7.1": "audio",
|
|
83
85
|
"DD+ 5.1": "audio",
|
|
84
86
|
"DD+ 2.0": "audio",
|
|
85
|
-
|
|
87
|
+
"DTS-HD MA 7.1": "audio",
|
|
88
|
+
"DTS-HD MA 5.1": "audio",
|
|
89
|
+
"DTS-HD MA 2.0": "audio",
|
|
86
90
|
"DD 7.1": "audio",
|
|
87
91
|
"DD 5.1": "audio",
|
|
88
92
|
"DD 2.0": "audio",
|
|
89
|
-
|
|
90
93
|
"AAC2.0": "audio",
|
|
91
94
|
"AAC5.1": "audio",
|
|
92
95
|
"AC3": "audio",
|
|
@@ -94,22 +97,25 @@ TAG_TYPES = {
|
|
|
94
97
|
"DD+": "audio",
|
|
95
98
|
"DDP": "audio",
|
|
96
99
|
"E-AC3": "audio",
|
|
100
|
+
"E-AC-3": "audio",
|
|
97
101
|
"EAC3": "audio",
|
|
98
102
|
"AC-3": "audio",
|
|
99
103
|
"AAC": "audio",
|
|
104
|
+
"AAC LC": "audio",
|
|
100
105
|
"AVC": "audio",
|
|
101
106
|
|
|
102
107
|
"7.1": "channels",
|
|
103
108
|
"5.1": "channels",
|
|
104
109
|
"2.0": "channels",
|
|
105
110
|
|
|
111
|
+
"X.264": "video_encoder",
|
|
112
|
+
"X264": "video_encoder",
|
|
113
|
+
"X.265": "video_encoder",
|
|
114
|
+
"X265": "video_encoder",
|
|
115
|
+
|
|
106
116
|
"H.264": "video",
|
|
107
|
-
"X.264": "video",
|
|
108
|
-
"X264": "video",
|
|
109
|
-
"H264": "video",
|
|
110
117
|
"H.265": "video",
|
|
111
|
-
"
|
|
112
|
-
"X265": "video",
|
|
118
|
+
"H264": "video",
|
|
113
119
|
"H265": "video",
|
|
114
120
|
"HEVC": "video",
|
|
115
121
|
"DV": "video",
|
|
@@ -121,7 +127,6 @@ TAG_TYPES = {
|
|
|
121
127
|
"HDR": "video",
|
|
122
128
|
"HDR10+": "video",
|
|
123
129
|
"FHDRIP": "video",
|
|
124
|
-
"UHDRIP": "video",
|
|
125
130
|
"FULL HD": "video",
|
|
126
131
|
"FULLHD": "video",
|
|
127
132
|
"HD": "video",
|
|
@@ -136,14 +141,15 @@ TAG_TYPES = {
|
|
|
136
141
|
"720P": "resolution",
|
|
137
142
|
"576P": "resolution",
|
|
138
143
|
"480P": "resolution",
|
|
139
|
-
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
|
|
143
147
|
class P2pTags:
|
|
144
|
-
def __init__(
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
def __init__(
|
|
149
|
+
self, filename: str, title: str, year: str, mediafile_resolution: str,
|
|
150
|
+
season: int, episode: int, episode_title: str, releaser_sign: str,
|
|
151
|
+
tags_position: list, mediafile: MediaFile
|
|
152
|
+
):
|
|
147
153
|
self.filename = filename
|
|
148
154
|
self.title = title
|
|
149
155
|
self.year = year
|
|
@@ -156,55 +162,65 @@ class P2pTags:
|
|
|
156
162
|
self.tags_position = tags_position
|
|
157
163
|
self.sign_in_title: str | None = None
|
|
158
164
|
|
|
165
|
+
self.tags_sorted = self._extract_tags()
|
|
166
|
+
|
|
167
|
+
def _extract_tags(self) -> list:
|
|
159
168
|
search_tags = sorted(TAG_TYPES.keys(), key=len, reverse=True)
|
|
160
|
-
pattern = re.compile(
|
|
161
|
-
r'\b(?:' + '|'.join(map(re.escape, search_tags)) + r')\b',
|
|
162
|
-
re.IGNORECASE
|
|
163
|
-
)
|
|
169
|
+
pattern = re.compile(r'\b(?:' + '|'.join(map(re.escape, search_tags)) + r')\b', re.IGNORECASE)
|
|
164
170
|
|
|
165
171
|
# Search for tags in the title
|
|
166
|
-
tags_match = pattern.findall(filename
|
|
167
|
-
# remove dope
|
|
168
|
-
tags_match = list(dict.fromkeys(tags_match))
|
|
169
|
-
|
|
172
|
+
tags_match = list(dict.fromkeys(pattern.findall(self.filename)))
|
|
170
173
|
# Search for channels
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
ch = "5.1"
|
|
176
|
-
elif channel_s == 8:
|
|
177
|
-
ch = "7.1"
|
|
178
|
-
elif channel_s == 2:
|
|
179
|
-
ch = "2.0"
|
|
180
|
-
|
|
181
|
-
# extract categories results
|
|
182
|
-
categories = [TAG_TYPES.get(tag) for tag in tags_match]
|
|
174
|
+
ch = ''
|
|
175
|
+
if self.mediafile.audio_track:
|
|
176
|
+
channel_s = self.mediafile.audio_track[0].get('channel_s', 0)
|
|
177
|
+
ch = {2: "2.0", 6: "5.1", 8: "7.1"}.get(channel_s, "")
|
|
183
178
|
|
|
179
|
+
# Categories of found tags
|
|
180
|
+
categories = [TAG_TYPES.get(tag.upper()) for tag in tags_match]
|
|
184
181
|
# Add video codec only if there is no video categories
|
|
185
|
-
if 'video' not in categories:
|
|
186
|
-
video_codec = self.mediafile.video_track[0].get('format', "")
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
182
|
+
if 'video' not in categories and self.mediafile.video_track:
|
|
183
|
+
video_codec = self.mediafile.video_track[0].get('format', "")
|
|
184
|
+
if video_codec:
|
|
185
|
+
tags_match.append(video_codec)
|
|
186
|
+
|
|
187
|
+
# Add audio codec only if there is no video categories
|
|
188
|
+
if 'audio' not in categories and self.mediafile.audio_track:
|
|
189
|
+
for audio in self.mediafile.audio_track:
|
|
190
|
+
# Other_format https://github.com/sbraz/pymediainfo/discussions/119#discussioncomment-2330673
|
|
191
|
+
# con format mi restituisce solo DTS
|
|
192
|
+
# Use other_format per format che hanno uno o piu tag
|
|
193
|
+
other_format = audio.get('other_format', [])
|
|
194
|
+
if other_format:
|
|
195
|
+
tags_match.append(other_format[0])
|
|
193
196
|
|
|
194
197
|
# Add tag language if there is no tag
|
|
195
198
|
flags = self._audio_lang()
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
missing_flags = [tag for tag in flags if tag not in tags_match]
|
|
199
|
-
tags_match.extend(missing_flags)
|
|
199
|
+
missing_flags = [tag for tag in flags if tag not in tags_match]
|
|
200
|
+
tags_match.extend(missing_flags)
|
|
200
201
|
|
|
201
202
|
# Add subtitle tag if subtitle_track exist and there is no 'sub' in the title
|
|
202
|
-
if 'subtitle' not in categories:
|
|
203
|
-
|
|
204
|
-
if self.mediafile.subtitle_track:
|
|
205
|
-
tags_match.append(sub_tag)
|
|
203
|
+
if 'subtitle' not in categories and self.mediafile.subtitle_track:
|
|
204
|
+
tags_match.append("SUBS" if len(self.mediafile.subtitle_track) > 1 else "SUB")
|
|
206
205
|
|
|
207
|
-
|
|
206
|
+
return self._normalize_tags(tags_match, ch)
|
|
207
|
+
|
|
208
|
+
def _audio_lang(self) -> set:
|
|
209
|
+
if not self.mediafile:
|
|
210
|
+
return set()
|
|
211
|
+
langs = set()
|
|
212
|
+
for track in self.mediafile.audio_track:
|
|
213
|
+
for l in track.get('other_language', []):
|
|
214
|
+
c = ManageTitles.convert_iso(l)
|
|
215
|
+
if c:
|
|
216
|
+
if isinstance(c, list):
|
|
217
|
+
langs.update(c)
|
|
218
|
+
else:
|
|
219
|
+
langs.update(c)
|
|
220
|
+
break
|
|
221
|
+
return langs
|
|
222
|
+
|
|
223
|
+
def _normalize_tags(self, tags_match: list, channel_tag: str) -> list:
|
|
208
224
|
audio_translate = {
|
|
209
225
|
"AC3": "DD",
|
|
210
226
|
"AC-3": "DD",
|
|
@@ -214,139 +230,85 @@ class P2pTags:
|
|
|
214
230
|
"DDP5.1": "DD+",
|
|
215
231
|
"DDP7.1": "DD+",
|
|
216
232
|
"DDP": "DD+",
|
|
233
|
+
"DTS XLL": "DTS-HD MA",
|
|
217
234
|
}
|
|
218
235
|
|
|
219
|
-
# Translate video codec
|
|
220
236
|
video_translate = {
|
|
221
|
-
"
|
|
222
|
-
"
|
|
223
|
-
"X264": "
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
227
|
-
"X.265": "x265",
|
|
228
|
-
"X265": "x265",
|
|
229
|
-
"HEVC": "x265",
|
|
237
|
+
"AVC": "H.264",
|
|
238
|
+
"X265": "x.265",
|
|
239
|
+
"X264": "x.264",
|
|
240
|
+
"HEVC": "H.265",
|
|
241
|
+
"H265": "H.265",
|
|
242
|
+
"H264": "H.264",
|
|
230
243
|
}
|
|
231
244
|
|
|
232
|
-
# lower the res..
|
|
233
245
|
resolution_lower = {"4320P", "2160P", "1080P", "720P", "576P", "480P"}
|
|
234
|
-
codec_lower = {
|
|
235
|
-
|
|
236
|
-
has_channel_tag = ch in tags_match
|
|
237
|
-
new_tags = []
|
|
246
|
+
codec_lower = {"X.264", "X265", "X.265", "X264"}
|
|
238
247
|
|
|
239
248
|
# verify the tags found in the title
|
|
249
|
+
normalized = []
|
|
240
250
|
for tag in tags_match:
|
|
241
251
|
t = tag.upper()
|
|
242
252
|
if t in audio_translate:
|
|
243
253
|
codec = audio_translate[t]
|
|
244
|
-
|
|
245
|
-
if ch and not has_channel_tag:
|
|
246
|
-
tag = f"{codec} {ch}"
|
|
247
|
-
else:
|
|
248
|
-
tag = codec
|
|
249
|
-
|
|
254
|
+
tag = f"{codec} {channel_tag}" if channel_tag else codec
|
|
250
255
|
elif t in video_translate:
|
|
251
256
|
tag = video_translate[t]
|
|
252
|
-
|
|
253
|
-
# Lower the res
|
|
254
|
-
elif t in resolution_lower:
|
|
257
|
+
elif t in resolution_lower or t in codec_lower:
|
|
255
258
|
tag = t.lower()
|
|
256
|
-
|
|
257
|
-
# Fix the 'sub' word
|
|
258
259
|
elif t == "SUB":
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
elif t in codec_lower:
|
|
263
|
-
tag = t.lower()
|
|
264
|
-
|
|
265
|
-
new_tags.append(tag)
|
|
266
|
-
|
|
267
|
-
tags_match = new_tags
|
|
260
|
+
tag = "SUBS" if len(self.mediafile.subtitle_track) > 1 else "SUB"
|
|
261
|
+
normalized.append(tag)
|
|
268
262
|
|
|
269
263
|
# Check if a 'resolution' tag exists and add mediafile resolution if it doesn't
|
|
270
|
-
if not any(TAG_TYPES.get(tag.upper()) == "resolution" for tag in
|
|
271
|
-
|
|
264
|
+
if not any(TAG_TYPES.get(tag.upper()) == "resolution" for tag in normalized):
|
|
265
|
+
normalized.append(self.mediafile_resolution)
|
|
272
266
|
|
|
267
|
+
# Sort and alternate audio/flag tags
|
|
268
|
+
return self._sort_tags(normalized, channel_tag)
|
|
269
|
+
|
|
270
|
+
def _sort_tags(self, tags: list, channel_tag: str) -> list:
|
|
273
271
|
# /// Sort tags based on 2 rules:
|
|
274
272
|
# 1) Order by tag_positions
|
|
275
273
|
# 2) For audio and flag categories alternate them (audio/flag/audio/flag)
|
|
276
274
|
# We can't sort each tags so we create dedicated list
|
|
277
|
-
audio_q = deque()
|
|
278
|
-
flag_q = deque()
|
|
279
|
-
channel_q = deque()
|
|
280
|
-
|
|
281
|
-
# This dict is for other categories
|
|
275
|
+
audio_q, flag_q, channel_q = deque(), deque(), deque()
|
|
282
276
|
other_groups = {}
|
|
283
277
|
|
|
284
|
-
|
|
285
|
-
# All other tags will follow the normal precedence order
|
|
286
|
-
for tag in tags_match:
|
|
278
|
+
for tag in tags:
|
|
287
279
|
cat = TAG_TYPES.get(tag.upper(), "unknown")
|
|
288
280
|
if cat == "audio":
|
|
289
|
-
|
|
290
|
-
audio_q.append(tag)
|
|
281
|
+
audio_q.append(tag.upper())
|
|
291
282
|
elif cat == "channels":
|
|
292
283
|
channel_q.append(tag)
|
|
293
284
|
elif cat == "flag":
|
|
294
|
-
|
|
295
|
-
|
|
285
|
+
flag_q.append(tag.upper())
|
|
286
|
+
elif cat == "video":
|
|
287
|
+
other_groups.setdefault(cat, []).append(tag.upper())
|
|
288
|
+
elif cat == "video_encoder":
|
|
289
|
+
# Skip video encoder
|
|
290
|
+
continue
|
|
296
291
|
else:
|
|
297
|
-
# Add the other tags to other_groups
|
|
298
292
|
other_groups.setdefault(cat, []).append(tag)
|
|
299
293
|
|
|
300
294
|
# Alternate only if we have at least 2 audio and 2 flag tags
|
|
295
|
+
mixed = []
|
|
301
296
|
if len(audio_q) >= 2 and len(flag_q) >= 2:
|
|
302
|
-
mixed_audio_ch_flag = []
|
|
303
|
-
# Alternate
|
|
304
297
|
while audio_q or flag_q:
|
|
305
|
-
if audio_q:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if channel_q:
|
|
309
|
-
mixed_audio_ch_flag.append(channel_q.popleft())
|
|
310
|
-
if flag_q:
|
|
311
|
-
# get the first right flag and append to new list
|
|
312
|
-
mixed_audio_ch_flag.append(flag_q.popleft())
|
|
298
|
+
if audio_q: mixed.append(audio_q.popleft())
|
|
299
|
+
if channel_q: mixed.append(channel_q.popleft())
|
|
300
|
+
if flag_q: mixed.append(flag_q.popleft())
|
|
313
301
|
else:
|
|
314
|
-
|
|
315
|
-
mixed_audio_ch_flag = list(audio_q) + list(channel_q) + list(flag_q)
|
|
302
|
+
mixed = list(audio_q) + list(channel_q) + list(flag_q)
|
|
316
303
|
|
|
317
|
-
# Rebuild the title ordering each tag+ audio/flag by tag_position
|
|
318
304
|
result = []
|
|
319
|
-
|
|
320
305
|
for cat in self.tags_position:
|
|
321
|
-
if cat in ("audio", "channels", "flag"):
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
result.extend(mixed_audio_ch_flag)
|
|
325
|
-
# clear
|
|
326
|
-
mixed_audio_ch_flag = []
|
|
306
|
+
if cat in ("audio", "channels", "flag") and mixed:
|
|
307
|
+
result.extend(mixed)
|
|
308
|
+
mixed = []
|
|
327
309
|
elif cat in other_groups:
|
|
328
310
|
result.extend(other_groups[cat])
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
def _audio_lang(self) -> list:
|
|
332
|
-
|
|
333
|
-
if not self.mediafile:
|
|
334
|
-
return []
|
|
335
|
-
|
|
336
|
-
lang: list = []
|
|
337
|
-
for track in self.mediafile.audio_track:
|
|
338
|
-
l = track.get('other_language', None)
|
|
339
|
-
if l:
|
|
340
|
-
for t in l:
|
|
341
|
-
c = ManageTitles.convert_iso(t)
|
|
342
|
-
if c:
|
|
343
|
-
if isinstance(c, list):
|
|
344
|
-
lang.extend(c)
|
|
345
|
-
break
|
|
346
|
-
else:
|
|
347
|
-
lang.append(c)
|
|
348
|
-
break
|
|
349
|
-
return lang
|
|
311
|
+
return result
|
|
350
312
|
|
|
351
313
|
def process(self) -> str:
|
|
352
314
|
se_str = ''
|
|
@@ -357,21 +319,14 @@ class P2pTags:
|
|
|
357
319
|
elif self.episode is not None:
|
|
358
320
|
se_str = f"E{self.episode:02d}"
|
|
359
321
|
|
|
322
|
+
# Detect releaser sign in filename if not provided
|
|
360
323
|
if not self.releaser_sign:
|
|
361
|
-
|
|
362
|
-
base_name = os.path.basename(self.filename)
|
|
363
|
-
filename, file_ext = os.path.splitext(base_name)
|
|
324
|
+
filename, _ = os.path.splitext(os.path.basename(self.filename))
|
|
364
325
|
m = re.search(r'-([A-Za-z0-9]+)$', filename)
|
|
365
|
-
|
|
366
|
-
if m and m.group(1) not in TAG_TYPES:
|
|
367
|
-
self.sign_in_title = f"-{m.group(1)}"
|
|
368
|
-
else:
|
|
369
|
-
self.sign_in_title = ""
|
|
326
|
+
self.sign_in_title = f"-{m.group(1)}" if m and m.group(1) not in TAG_TYPES else ""
|
|
370
327
|
else:
|
|
371
328
|
self.sign_in_title = f"-{self.releaser_sign}"
|
|
372
329
|
|
|
373
|
-
parts = [self.title, str(self.year), se_str
|
|
374
|
-
filtered_parts = [
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return f"{title} {' '.join(self.tags_sorted)}{self.sign_in_title}"
|
|
330
|
+
parts = [self.title, str(self.year), se_str]
|
|
331
|
+
filtered_parts = [p for p in parts if p]
|
|
332
|
+
return f"{' '.join(filtered_parts)} {' '.join(self.tags_sorted)}{self.sign_in_title}"
|
|
@@ -15,7 +15,7 @@ from common.utility import ManageTitles
|
|
|
15
15
|
from common import trackers
|
|
16
16
|
|
|
17
17
|
config_file = "Unit3Dbot.json"
|
|
18
|
-
version = "0.9.
|
|
18
|
+
version = "0.9.11"
|
|
19
19
|
|
|
20
20
|
if os.name == "nt":
|
|
21
21
|
WATCHER_DESTINATION_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / "watcher_destination_path"
|
|
@@ -43,17 +43,33 @@ class ManageTitles:
|
|
|
43
43
|
"ES-MX": "ESP"
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
# From mediainfo
|
|
47
|
+
long_name = {
|
|
48
|
+
"ENGLISH": "ENG",
|
|
49
|
+
"ITALIAN": "ITA",
|
|
50
|
+
"GERMAN": "DEU",
|
|
51
|
+
"FRENCH": "FRA",
|
|
52
|
+
"SPANISH": "ESP",
|
|
53
|
+
"JAPANESE": "JPN",
|
|
54
|
+
"BRAZILIAN": "BRA",
|
|
55
|
+
"RUSSIAN": "RUS",
|
|
56
|
+
"CHINESE": "CHN",
|
|
57
|
+
"AMERICAN": "USA",
|
|
58
|
+
"BRITISH": "GBR"
|
|
59
|
+
}
|
|
46
60
|
@staticmethod
|
|
47
61
|
def convert_iso(code) -> list | str | None:
|
|
48
62
|
""" Convert iso 2 to 3 """
|
|
49
63
|
code = code.upper()
|
|
50
|
-
|
|
51
64
|
# if it's 'multilang'
|
|
52
65
|
if '-' in code:
|
|
53
66
|
codes = code.split('-')
|
|
54
67
|
else:
|
|
55
68
|
codes = [code]
|
|
56
69
|
|
|
70
|
+
if code in ManageTitles.long_name:
|
|
71
|
+
codes = [ManageTitles.long_name[code]]
|
|
72
|
+
|
|
57
73
|
result = []
|
|
58
74
|
for part in codes:
|
|
59
75
|
# Capture the 2 or 3 letter code followed by '-' or end string
|
|
@@ -167,45 +183,45 @@ class ManageTitles:
|
|
|
167
183
|
filename_sanitized = re.sub(r"v\d+(?:[ .]\d+)*", "", filename_sanitized).strip()
|
|
168
184
|
|
|
169
185
|
# Remove dots, extra spaces
|
|
170
|
-
filename_sanitized = re.sub(r"[._]", " ", filename_sanitized)
|
|
186
|
+
# filename_sanitized = re.sub(r"[._]", " ", filename_sanitized)
|
|
171
187
|
|
|
172
188
|
# remove spaces, tab, newline
|
|
173
189
|
filename_sanitized = re.sub(r"\s+", " ", filename_sanitized)
|
|
174
190
|
|
|
175
191
|
# Recover tag
|
|
176
|
-
filename_sanitized = ManageTitles.recover_tag(filename_sanitized)
|
|
192
|
+
# filename_sanitized = ManageTitles.recover_tag(filename_sanitized)
|
|
177
193
|
|
|
178
194
|
# remove double space
|
|
179
195
|
filename_sanitized = re.sub(r"\s+", " ", filename_sanitized).strip()
|
|
180
196
|
|
|
181
197
|
return filename_sanitized
|
|
182
198
|
|
|
183
|
-
@staticmethod
|
|
184
|
-
def recover_tag(filename_sanitized: str) -> str:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
# @staticmethod
|
|
200
|
+
# def recover_tag(filename_sanitized: str) -> str:
|
|
201
|
+
#
|
|
202
|
+
# # Add the tag
|
|
203
|
+
# replacements = [
|
|
204
|
+
# (r'\b7 \b1\b', '7.1'),
|
|
205
|
+
# (r'\b5 \b1\b', '5.1'),
|
|
206
|
+
# (r'\bDDP5 \b1\b', 'DDP5.1'),
|
|
207
|
+
# (r'\bDDP2 \b0\b', 'DDP2.0'),
|
|
208
|
+
# (r'\bDD5 \b1\b', 'DD5.1'),
|
|
209
|
+
# (r'\bDD2 \b0\b', 'DD2.0'),
|
|
210
|
+
# (r'\b2 \b0\b', '2.0'),
|
|
211
|
+
# (r'\bWEB \bDL\b', 'WEB-DL'),
|
|
212
|
+
# (r'\bWEB \bDLMUX\b', 'WEB-DLMUX'),
|
|
213
|
+
# (r'\bBD \bUNTOUCHED\b', 'BD-UNTOUCHED'),
|
|
214
|
+
# (r'\bCINEMA \bMD\b', 'CINEMA-MD'),
|
|
215
|
+
# (r'\bHEVC \bFHC\b', 'HEVC-FHC'),
|
|
216
|
+
# (r'\bCBR \bCBZ\b', 'CBR-CBZ'),
|
|
217
|
+
# (r'\bH \b264\b', 'H.264'),
|
|
218
|
+
# (r'\bH \b265\b', 'H.265'),
|
|
219
|
+
# (r'\bAAC2 \b0\b', 'AAC2.0'),
|
|
220
|
+
# ]
|
|
221
|
+
#
|
|
222
|
+
# for tag, replacement in replacements:
|
|
223
|
+
# filename_sanitized = re.sub(tag, replacement, filename_sanitized, flags=re.IGNORECASE)
|
|
224
|
+
# return filename_sanitized
|
|
209
225
|
|
|
210
226
|
|
|
211
227
|
class MyString:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/__init__.py
RENAMED
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/details.py
RENAMED
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/movie/movie.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/details.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unit3dup-0.9.9 → unit3dup-0.9.11}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|