ittup 1.2.1__tar.gz → 1.2.2__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.
- {ittup-1.2.1 → ittup-1.2.2}/PKG-INFO +2 -2
- {ittup-1.2.1 → ittup-1.2.2}/README.rst +1 -1
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/settings.py +3 -5
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/tags.py +123 -20
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/PKG-INFO +2 -2
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/SOURCES.txt +2 -1
- {ittup-1.2.1 → ittup-1.2.2}/pyproject.toml +1 -1
- ittup-1.2.2/tests/test_vcodec.py +129 -0
- {ittup-1.2.1 → ittup-1.2.2}/LICENSE +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/__main__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/about.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/bdinfo_string.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/bittorrent.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/command.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/constants.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/database.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/client.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/ftpx_service.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/ftpx_session.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/menu.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/models/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/ftpx/core/models/list.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/client.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/api.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/models/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/models/search.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/platformid.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/igdb/core/tags.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/imageHost.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/mediaresult.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/sessions/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/sessions/agents.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/sessions/exceptions.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/sessions/session.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/api.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/keywords.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/alternative.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/translations.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/videos.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/trailers/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/trailers/api.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/trailers/response.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/tvdb.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/extractor.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/frames.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/mediainfo.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/mediainfo_string.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/title.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/torrent_clients.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/ban_list.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/data.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/itt.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/signs_list.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/tags_list.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/trackers/trackers.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/common/utility.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/__main__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/automode.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/bot.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/duplicate.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/exceptions.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/ContentManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/DocuManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/GameManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/MediaInfoManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/SeedManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/TorrentManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/VideoManager.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/media_manager/common.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/pvtDocu.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/pvtTorrent.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/pvtTracker.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/pvtVideo.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/torrent.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/core/upload.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/view/__init__.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup/view/custom_console.py +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/dependency_links.txt +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/entry_points.txt +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/requires.txt +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/ittup.egg-info/top_level.txt +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/requirements.txt +0 -0
- {ittup-1.2.1 → ittup-1.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ittup
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: ItaTorrents uploader
|
|
5
5
|
Author: Parzival, TehMaat
|
|
6
6
|
License-Expression: MIT
|
|
@@ -68,7 +68,7 @@ It performs the following tasks:
|
|
|
68
68
|
- Seeding in qBittorrent, Transmission or rTorrent
|
|
69
69
|
- Reseeding one or more torrents at a time
|
|
70
70
|
- Seed your torrents across different OS
|
|
71
|
-
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr
|
|
71
|
+
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
ITTup can grab the first page, convert it to an image (using xpdf),
|
|
@@ -35,7 +35,7 @@ It performs the following tasks:
|
|
|
35
35
|
- Seeding in qBittorrent, Transmission or rTorrent
|
|
36
36
|
- Reseeding one or more torrents at a time
|
|
37
37
|
- Seed your torrents across different OS
|
|
38
|
-
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr
|
|
38
|
+
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
ITTup can grab the first page, convert it to an image (using xpdf),
|
|
@@ -625,13 +625,11 @@ class Load:
|
|
|
625
625
|
"NUMBER_OF_SCREENSHOTS": 4,
|
|
626
626
|
"TAGS_POSITION_MOVIE": ["title", "year", "part", "version", "resolution", "uhd", "platform", "source",
|
|
627
627
|
"remux",
|
|
628
|
-
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec",
|
|
629
|
-
"video_encoder"],
|
|
628
|
+
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec"],
|
|
630
629
|
|
|
631
630
|
"TAGS_POSITION_SERIE": ["title", "season", "version", "resolution", "uhd", "platform", "source",
|
|
632
631
|
"remux",
|
|
633
|
-
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec",
|
|
634
|
-
"video_encoder"],
|
|
632
|
+
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec"],
|
|
635
633
|
|
|
636
634
|
"YOUTUBE_PREF_LANG": "IT",
|
|
637
635
|
"DUPLICATE_ON": "true",
|
|
@@ -662,7 +660,7 @@ class Load:
|
|
|
662
660
|
"MY_TEXT_1": "",
|
|
663
661
|
"MY_TEXT_2": "",
|
|
664
662
|
"MY_TEXT_3": "",
|
|
665
|
-
"MY_TEXT_H": "
|
|
663
|
+
"MY_TEXT_H": ""
|
|
666
664
|
},
|
|
667
665
|
"options": {
|
|
668
666
|
"FTPX_USER": "user",
|
|
@@ -46,18 +46,28 @@ audio_translate = {
|
|
|
46
46
|
"MPEG Audio": "MPEG",
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"H264": "H.264",
|
|
49
|
+
# Codec family from the MediaInfo 'format' of the video track
|
|
50
|
+
video_family = {
|
|
51
|
+
"AVC": "264",
|
|
52
|
+
"HEVC": "265",
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
# Release type from the source/remux tags of the file name. Each tag is mapped on its own:
|
|
56
|
+
# DLMUX is in the "remux" category but it is a WEB-DL
|
|
57
|
+
UNTOUCHED_TAGS = {"REMUX", "BDREMUX", "BDMUX", "VU", "UNTOUCHED", "DVDMUX", "FULL DISC"}
|
|
58
|
+
WEB_TAGS = {"WEB-DL", "WEB", "WEBDL", "WEB-DLMUX", "WEBDLMUX", "WEB-MUX", "WEBMUX", "DLMUX", "HDTV"}
|
|
59
|
+
ENCODE_TAGS = {"ENCODE", "WEBRIP", "BDRIP", "BRRIP", "DVDRIP", "UHDRIP", "FHDRIP", "WEB-DLRIP", "WEBDLRIP"}
|
|
60
|
+
|
|
61
|
+
# How each release type writes the 264/265 codec
|
|
62
|
+
video_codec_labels = {
|
|
63
|
+
"untouched": {"264": "AVC", "265": "HEVC"},
|
|
64
|
+
"web": {"264": "H.264", "265": "H.265"},
|
|
65
|
+
"encode": {"264": "x264", "265": "x265"},
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
# x264, x.264, H264, H.265, AVC, HEVC... in the file name
|
|
69
|
+
NAME_CODEC_PATTERN = re.compile(r'(?<![a-z0-9])(?:[xh][._ -]?26([45])|(avc)|(hevc))(?![a-z0-9])', re.IGNORECASE)
|
|
70
|
+
|
|
61
71
|
TAG_NORMALIZE = {
|
|
62
72
|
"BLURAY": "BluRay",
|
|
63
73
|
"BLU-RAY": "BluRay",
|
|
@@ -85,6 +95,8 @@ class SearchTags(object):
|
|
|
85
95
|
self.title = title
|
|
86
96
|
self.year = year
|
|
87
97
|
self.tags_dict = {}
|
|
98
|
+
self.release_type: str | None = None
|
|
99
|
+
self.name_family: str | None = None
|
|
88
100
|
|
|
89
101
|
self.TAG_TYPES: dict = tags_list
|
|
90
102
|
self.SIGNS_LIST: dict = sign_list
|
|
@@ -187,6 +199,14 @@ class SearchTags(object):
|
|
|
187
199
|
if self.tags_dict.get("source", None):
|
|
188
200
|
self.tags_dict["source"] = list(dict.fromkeys(self.tags_dict["source"]))
|
|
189
201
|
|
|
202
|
+
# x264/x265 from the file name only tell the codec family: the codec is written by vcodec
|
|
203
|
+
name_encoders = self.tags_dict.pop('video_encoder', [])
|
|
204
|
+
self.name_family = self.codec_family_from_name(self.filename, name_encoders)
|
|
205
|
+
# Read the release type before 'remux' gets the REMUX tag appended below
|
|
206
|
+
self.release_type = self.detect_release_type(
|
|
207
|
+
self.tags_dict.get('source', []) + self.tags_dict.get('remux', [])
|
|
208
|
+
)
|
|
209
|
+
|
|
190
210
|
if norm:
|
|
191
211
|
# Skip if it is part of title es: "Wicked.Parte.2.2025.iTA" Title = Wicked Parte 2
|
|
192
212
|
if not any(t in self.title.lower() for t in ['part', 'parte']):
|
|
@@ -208,10 +228,6 @@ class SearchTags(object):
|
|
|
208
228
|
elif category == "vcodec":
|
|
209
229
|
updated_category = self.mediainfo_video(category=category)
|
|
210
230
|
|
|
211
|
-
elif category == "video_encoder":
|
|
212
|
-
if self.tags_dict.get('video_encoder', None):
|
|
213
|
-
self.tags_dict['video_encoder'][0] = self.tags_dict['video_encoder'][0].lower()
|
|
214
|
-
|
|
215
231
|
elif category == "hdr":
|
|
216
232
|
updated_category = self.mediainfo_hdr(category=category)
|
|
217
233
|
if not updated_category:
|
|
@@ -297,16 +313,103 @@ class SearchTags(object):
|
|
|
297
313
|
audio_codecs.extend(languages)
|
|
298
314
|
return {category: audio_codecs}
|
|
299
315
|
|
|
316
|
+
@staticmethod
|
|
317
|
+
def detect_release_type(tags: list) -> str | None:
|
|
318
|
+
"""
|
|
319
|
+
Release type from the source/remux tags: 'encode', 'untouched', 'web' or None when uncertain
|
|
320
|
+
(es. BLURAY alone or no tags)
|
|
321
|
+
"""
|
|
322
|
+
tags = {str(tag).upper() for tag in tags}
|
|
323
|
+
if tags & ENCODE_TAGS:
|
|
324
|
+
return "encode"
|
|
325
|
+
if tags & UNTOUCHED_TAGS:
|
|
326
|
+
return "untouched"
|
|
327
|
+
if tags & WEB_TAGS:
|
|
328
|
+
return "web"
|
|
329
|
+
return None
|
|
330
|
+
|
|
331
|
+
@staticmethod
|
|
332
|
+
def codec_family_from_name(filename: str, name_encoders: list) -> str | None:
|
|
333
|
+
"""
|
|
334
|
+
Codec family ('264' or '265') written in the file name, None if missing or ambiguous
|
|
335
|
+
"""
|
|
336
|
+
families = {str(tag)[-3:] for tag in name_encoders}
|
|
337
|
+
for match in NAME_CODEC_PATTERN.finditer(filename):
|
|
338
|
+
if match.group(1):
|
|
339
|
+
families.add(f"26{match.group(1)}")
|
|
340
|
+
elif match.group(2):
|
|
341
|
+
families.add("264")
|
|
342
|
+
else:
|
|
343
|
+
families.add("265")
|
|
344
|
+
families &= {"264", "265"}
|
|
345
|
+
return families.pop() if len(families) == 1 else None
|
|
346
|
+
|
|
347
|
+
@staticmethod
|
|
348
|
+
def encoder_signature(video: dict) -> str | None:
|
|
349
|
+
"""
|
|
350
|
+
x264/x265 signature left by the encoder in the video track ('264', '265' or None)
|
|
351
|
+
"""
|
|
352
|
+
library = str(video.get('writing_library') or '').lower()
|
|
353
|
+
for family in ("264", "265"):
|
|
354
|
+
if f"x{family}" in library:
|
|
355
|
+
return family
|
|
356
|
+
settings = str(video.get('encoding_settings') or '').lower()
|
|
357
|
+
if "cabac=" in settings:
|
|
358
|
+
return "264"
|
|
359
|
+
if "cpuid=" in settings or "ctu=" in settings:
|
|
360
|
+
return "265"
|
|
361
|
+
return None
|
|
362
|
+
|
|
363
|
+
@staticmethod
|
|
364
|
+
def normalize_other_codec(video: dict, filename: str) -> str:
|
|
365
|
+
"""
|
|
366
|
+
Codecs other than 264/265 (AV1, VP9, VC-1, MPEG-2, XviD...)
|
|
367
|
+
"""
|
|
368
|
+
video_format = str(video.get('format') or '')
|
|
369
|
+
if video_format == "MPEG Video":
|
|
370
|
+
version = re.search(r'\d', str(video.get('format_version') or ''))
|
|
371
|
+
return f"MPEG-{version.group(0)}" if version else "MPEG"
|
|
372
|
+
if video_format == "MPEG-4 Visual":
|
|
373
|
+
hint = f"{video.get('codec_id') or ''} {video.get('writing_library') or ''} {filename}".upper()
|
|
374
|
+
if "XVID" in hint:
|
|
375
|
+
return "XviD"
|
|
376
|
+
if "DIVX" in hint or "DX50" in hint:
|
|
377
|
+
return "DivX"
|
|
378
|
+
return "MPEG-4"
|
|
379
|
+
return video_format
|
|
380
|
+
|
|
300
381
|
def mediainfo_video(self, category: str) -> dict:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
382
|
+
video = self.mediafile.video_track[0] if self.mediafile.video_track else {}
|
|
383
|
+
video_format = str(video.get('format') or '')
|
|
384
|
+
mediainfo_family = video_family.get(video_format)
|
|
385
|
+
|
|
386
|
+
# The file name tells the family, MediaInfo wins when they don't agree
|
|
387
|
+
family = self.name_family
|
|
388
|
+
if video_format:
|
|
389
|
+
if self.name_family and self.name_family != mediainfo_family:
|
|
390
|
+
custom_console.bot_warning_log(
|
|
391
|
+
f"<> Video codec warning: the file name says {self.name_family} but MediaInfo says"
|
|
392
|
+
f" '{video_format}'. Using MediaInfo")
|
|
393
|
+
family = mediainfo_family
|
|
394
|
+
|
|
395
|
+
if not family:
|
|
396
|
+
if video_format:
|
|
397
|
+
return {category: self.normalize_other_codec(video, self.filename)}
|
|
398
|
+
return {}
|
|
399
|
+
|
|
400
|
+
# The encoder in MediaInfo is only a check: it is never read on a WEB-DL
|
|
401
|
+
if self.release_type == "untouched":
|
|
402
|
+
if self.encoder_signature(video):
|
|
403
|
+
custom_console.bot_warning_log(
|
|
404
|
+
f"<> Warning: possible fake REMUX, the video track was encoded with"
|
|
405
|
+
f" '{video.get('writing_library') or 'x' + family}'")
|
|
406
|
+
label = "untouched"
|
|
407
|
+
elif self.release_type in ("encode", "web"):
|
|
408
|
+
label = self.release_type
|
|
409
|
+
else:
|
|
410
|
+
label = "encode" if self.encoder_signature(video) else "web"
|
|
309
411
|
|
|
412
|
+
return {category: video_codec_labels[label][family]}
|
|
310
413
|
|
|
311
414
|
def mediainfo_hdr(self, category: str) -> dict:
|
|
312
415
|
if self.mediafile.video_track:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ittup
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: ItaTorrents uploader
|
|
5
5
|
Author: Parzival, TehMaat
|
|
6
6
|
License-Expression: MIT
|
|
@@ -68,7 +68,7 @@ It performs the following tasks:
|
|
|
68
68
|
- Seeding in qBittorrent, Transmission or rTorrent
|
|
69
69
|
- Reseeding one or more torrents at a time
|
|
70
70
|
- Seed your torrents across different OS
|
|
71
|
-
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr
|
|
71
|
+
- Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
ITTup can grab the first page, convert it to an image (using xpdf),
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from types import SimpleNamespace
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from ittup.common import tags
|
|
7
|
+
from ittup.common.settings import Validate
|
|
8
|
+
from ittup.common.tags import SearchTags
|
|
9
|
+
from ittup.common.trackers.tags_list import TAGS_LIST
|
|
10
|
+
|
|
11
|
+
TAGS_POSITION = ["title", "year", "part", "version", "resolution", "uhd", "platform", "source", "remux",
|
|
12
|
+
"multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec"]
|
|
13
|
+
|
|
14
|
+
X264_LIBRARY = "x264 core 164 r3095 baee400"
|
|
15
|
+
X265_LIBRARY = "x265 3.5+1-f0c1022b6:[Linux][GCC 9.3.0][64 bit] 10bit"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def warnings(monkeypatch):
|
|
20
|
+
logged = []
|
|
21
|
+
monkeypatch.setattr(tags.custom_console, "bot_warning_log", logged.append)
|
|
22
|
+
return logged
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def build_title(filename: str, video_format: str | None, writing_library: str = "",
|
|
26
|
+
encoding_settings: str = "", tags_position: list | None = None,
|
|
27
|
+
**video_fields) -> tuple[str, dict]:
|
|
28
|
+
video_track = []
|
|
29
|
+
if video_format:
|
|
30
|
+
video_track.append({"format": video_format, "writing_library": writing_library,
|
|
31
|
+
"encoding_settings": encoding_settings, **video_fields})
|
|
32
|
+
mediafile = SimpleNamespace(video_track=video_track, audio_track=[], subtitle_track=[])
|
|
33
|
+
media = SimpleNamespace(mediafile=mediafile, torrent_pack=False, resolution="1080p", pack=None)
|
|
34
|
+
search = SearchTags(filename=filename, title="Movie", year="2020", season=None, episode=None, media=media,
|
|
35
|
+
tags_position=list(tags_position or TAGS_POSITION), tags_list=TAGS_LIST, sign_list={},
|
|
36
|
+
ban_list={"dummy": "banned"}, releaser_sign="")
|
|
37
|
+
return search.process()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def vcodec(filename: str, video_format: str | None, **kwargs) -> str | None:
|
|
41
|
+
_, tags_dict = build_title(filename, video_format, **kwargs)
|
|
42
|
+
return tags_dict.get("vcodec")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_remux_hevc(warnings):
|
|
46
|
+
assert vcodec("Movie.2020.2160p.BluRay.REMUX.HEVC.TrueHD.7.1-GRP.mkv", "HEVC") == "HEVC"
|
|
47
|
+
assert not warnings
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_remux_with_x265_signature_warns(warnings):
|
|
51
|
+
codec = vcodec("Movie.2020.2160p.BluRay.REMUX.HEVC-GRP.mkv", "HEVC", writing_library=X265_LIBRARY)
|
|
52
|
+
assert codec == "HEVC"
|
|
53
|
+
assert any("fake REMUX" in message for message in warnings)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_web_dl_avc_with_x264_signature(warnings):
|
|
57
|
+
codec = vcodec("Movie.2020.1080p.AMZN.WEB-DL.DDP5.1.H.264-GRP.mkv", "AVC", writing_library=X264_LIBRARY)
|
|
58
|
+
assert codec == "H.264"
|
|
59
|
+
assert not warnings
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_dlmux_is_web_dl():
|
|
63
|
+
assert vcodec("Movie.2020.1080p.DLMux.ITA.ENG.AC3-GRP.mkv", "AVC", writing_library=X264_LIBRARY) == "H.264"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_webrip_x265():
|
|
67
|
+
assert vcodec("Movie.2020.1080p.WEBRip.x265-GRP.mkv", "HEVC") == "x265"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_encode_x265_is_not_doubled(warnings):
|
|
71
|
+
title, tags_dict = build_title("Movie.2020.1080p.BDRip.x265.10bit-GRP.mkv", "HEVC",
|
|
72
|
+
writing_library=X265_LIBRARY)
|
|
73
|
+
assert tags_dict["vcodec"] == "x265"
|
|
74
|
+
assert "video_encoder" not in tags_dict
|
|
75
|
+
assert "H.265" not in title
|
|
76
|
+
assert title.count("x265") == 1
|
|
77
|
+
assert not warnings
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_bluray_alone_with_x264_signature():
|
|
81
|
+
assert vcodec("Movie.2020.1080p.BluRay.DTS-GRP.mkv", "AVC", writing_library=X264_LIBRARY) == "x264"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_bluray_alone_without_signature():
|
|
85
|
+
assert vcodec("Movie.2020.1080p.BluRay.DTS-GRP.mkv", "AVC") == "H.264"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_no_release_type_no_signature():
|
|
89
|
+
assert vcodec("Movie.2020.1080p.ITA.ENG-GRP.mkv", "AVC") == "H.264"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_signature_from_encoding_settings():
|
|
93
|
+
settings = "cabac=1 / ref=4 / deblock=1:-3:-3 / analyse=0x3:0x133"
|
|
94
|
+
assert vcodec("Movie.2020.1080p.ITA-GRP.mkv", "AVC", encoding_settings=settings) == "x264"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_name_and_mediainfo_disagree(warnings):
|
|
98
|
+
codec = vcodec("Movie.2020.1080p.BDRip.x264-GRP.mkv", "HEVC", writing_library=X265_LIBRARY)
|
|
99
|
+
assert codec == "x265"
|
|
100
|
+
assert any("MediaInfo" in message for message in warnings)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_family_from_name_without_mediainfo():
|
|
104
|
+
assert vcodec("Movie.2020.1080p.WEBRip.x264-GRP.mkv", None) == "x264"
|
|
105
|
+
assert vcodec("Movie.2020.1080p.BluRay.REMUX.AVC-GRP.mkv", None) == "AVC"
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize("video_format, video_fields, expected", [
|
|
109
|
+
("AV1", {}, "AV1"),
|
|
110
|
+
("VP9", {}, "VP9"),
|
|
111
|
+
("VC-1", {}, "VC-1"),
|
|
112
|
+
("MPEG Video", {"format_version": "Version 2"}, "MPEG-2"),
|
|
113
|
+
("MPEG-4 Visual", {"codec_id": "XVID"}, "XviD"),
|
|
114
|
+
])
|
|
115
|
+
def test_other_codecs(warnings, video_format, video_fields, expected):
|
|
116
|
+
# The release type rules don't apply to codecs other than 264/265
|
|
117
|
+
assert vcodec("Movie.2020.1080p.BluRay.REMUX-GRP.mkv", video_format, **video_fields) == expected
|
|
118
|
+
assert vcodec("Movie.2020.1080p.WEBRip-GRP.mkv", video_format, writing_library=X264_LIBRARY,
|
|
119
|
+
**video_fields) == expected
|
|
120
|
+
assert not warnings
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_video_encoder_in_tags_position():
|
|
124
|
+
position = TAGS_POSITION + ["video_encoder"]
|
|
125
|
+
assert Validate.validate_tags_position(position) == position
|
|
126
|
+
|
|
127
|
+
title, tags_dict = build_title("Movie.2020.1080p.WEBRip.x265-GRP.mkv", "HEVC", tags_position=position)
|
|
128
|
+
assert "video_encoder" not in tags_dict
|
|
129
|
+
assert title.lower().count("265") == 1
|
|
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
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/__init__.py
RENAMED
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/details.py
RENAMED
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/movie/movie.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/common/external_services/theMovieDB/core/models/tvshow/details.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ittup-1.2.1 → ittup-1.2.2}/ittup/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|