ittup 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. ittup/__init__.py +1 -0
  2. ittup/__main__.py +5 -0
  3. ittup/common/__init__.py +4 -0
  4. ittup/common/about.py +15 -0
  5. ittup/common/bdinfo_string.py +98 -0
  6. ittup/common/bittorrent.py +14 -0
  7. ittup/common/command.py +162 -0
  8. ittup/common/constants.py +18 -0
  9. ittup/common/database.py +78 -0
  10. ittup/common/external_services/__init__.py +9 -0
  11. ittup/common/external_services/ftpx/__init__.py +0 -0
  12. ittup/common/external_services/ftpx/client.py +305 -0
  13. ittup/common/external_services/ftpx/core/__init__.py +0 -0
  14. ittup/common/external_services/ftpx/core/ftpx_service.py +76 -0
  15. ittup/common/external_services/ftpx/core/ftpx_session.py +159 -0
  16. ittup/common/external_services/ftpx/core/menu.py +17 -0
  17. ittup/common/external_services/ftpx/core/models/__init__.py +0 -0
  18. ittup/common/external_services/ftpx/core/models/list.py +17 -0
  19. ittup/common/external_services/igdb/__init__.py +0 -0
  20. ittup/common/external_services/igdb/client.py +262 -0
  21. ittup/common/external_services/igdb/core/__init__.py +0 -0
  22. ittup/common/external_services/igdb/core/api.py +70 -0
  23. ittup/common/external_services/igdb/core/models/__init__.py +0 -0
  24. ittup/common/external_services/igdb/core/models/search.py +13 -0
  25. ittup/common/external_services/igdb/core/platformid.py +24 -0
  26. ittup/common/external_services/igdb/core/tags.py +13 -0
  27. ittup/common/external_services/imageHost.py +324 -0
  28. ittup/common/external_services/mediaresult.py +25 -0
  29. ittup/common/external_services/sessions/__init__.py +0 -0
  30. ittup/common/external_services/sessions/agents.py +212 -0
  31. ittup/common/external_services/sessions/exceptions.py +100 -0
  32. ittup/common/external_services/sessions/session.py +149 -0
  33. ittup/common/external_services/theMovieDB/__init__.py +4 -0
  34. ittup/common/external_services/theMovieDB/core/__init__.py +8 -0
  35. ittup/common/external_services/theMovieDB/core/api.py +574 -0
  36. ittup/common/external_services/theMovieDB/core/keywords.py +7 -0
  37. ittup/common/external_services/theMovieDB/core/models/__init__.py +0 -0
  38. ittup/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
  39. ittup/common/external_services/theMovieDB/core/models/movie/alternative.py +2 -0
  40. ittup/common/external_services/theMovieDB/core/models/movie/details.py +82 -0
  41. ittup/common/external_services/theMovieDB/core/models/movie/movie.py +48 -0
  42. ittup/common/external_services/theMovieDB/core/models/movie/nowplaying.py +69 -0
  43. ittup/common/external_services/theMovieDB/core/models/movie/release_info.py +49 -0
  44. ittup/common/external_services/theMovieDB/core/models/movie/translations.py +33 -0
  45. ittup/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
  46. ittup/common/external_services/theMovieDB/core/models/tvshow/alternative.py +14 -0
  47. ittup/common/external_services/theMovieDB/core/models/tvshow/details.py +139 -0
  48. ittup/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +27 -0
  49. ittup/common/external_services/theMovieDB/core/models/tvshow/translations.py +45 -0
  50. ittup/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +50 -0
  51. ittup/common/external_services/theMovieDB/core/videos.py +21 -0
  52. ittup/common/external_services/trailers/__init__.py +3 -0
  53. ittup/common/external_services/trailers/api.py +120 -0
  54. ittup/common/external_services/trailers/response.py +51 -0
  55. ittup/common/external_services/tvdb.py +45 -0
  56. ittup/common/extractor.py +124 -0
  57. ittup/common/frames.py +221 -0
  58. ittup/common/mediainfo.py +206 -0
  59. ittup/common/mediainfo_string.py +103 -0
  60. ittup/common/settings.py +952 -0
  61. ittup/common/tags.py +415 -0
  62. ittup/common/title.py +127 -0
  63. ittup/common/torrent_clients.py +280 -0
  64. ittup/common/trackers/__init__.py +8 -0
  65. ittup/common/trackers/ban_list.py +5 -0
  66. ittup/common/trackers/data.py +22 -0
  67. ittup/common/trackers/itt.py +153 -0
  68. ittup/common/trackers/signs_list.py +293 -0
  69. ittup/common/trackers/tags_list.py +118 -0
  70. ittup/common/trackers/trackers.py +46 -0
  71. ittup/common/utility.py +394 -0
  72. ittup/core/__init__.py +5 -0
  73. ittup/core/__main__.py +289 -0
  74. ittup/core/automode.py +122 -0
  75. ittup/core/bot.py +294 -0
  76. ittup/core/duplicate.py +270 -0
  77. ittup/core/exceptions.py +122 -0
  78. ittup/core/media.py +378 -0
  79. ittup/core/media_manager/ContentManager.py +199 -0
  80. ittup/core/media_manager/DocuManager.py +76 -0
  81. ittup/core/media_manager/GameManager.py +107 -0
  82. ittup/core/media_manager/MediaInfoManager.py +26 -0
  83. ittup/core/media_manager/SeedManager.py +49 -0
  84. ittup/core/media_manager/TorrentManager.py +153 -0
  85. ittup/core/media_manager/VideoManager.py +145 -0
  86. ittup/core/media_manager/__init__.py +0 -0
  87. ittup/core/media_manager/common.py +265 -0
  88. ittup/core/pvtDocu.py +123 -0
  89. ittup/core/pvtTorrent.py +78 -0
  90. ittup/core/pvtTracker.py +481 -0
  91. ittup/core/pvtVideo.py +104 -0
  92. ittup/core/torrent.py +467 -0
  93. ittup/core/upload.py +168 -0
  94. ittup/view/__init__.py +3 -0
  95. ittup/view/custom_console.py +148 -0
  96. ittup-1.1.0.dist-info/METADATA +182 -0
  97. ittup-1.1.0.dist-info/RECORD +101 -0
  98. ittup-1.1.0.dist-info/WHEEL +5 -0
  99. ittup-1.1.0.dist-info/entry_points.txt +2 -0
  100. ittup-1.1.0.dist-info/licenses/LICENSE +22 -0
  101. ittup-1.1.0.dist-info/top_level.txt +1 -0
ittup/__init__.py ADDED
@@ -0,0 +1 @@
1
+ # -*- coding: utf-8 -*-
ittup/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ from ittup.core.__main__ import main
3
+
4
+ if __name__ == "__main__":
5
+ main()
@@ -0,0 +1,4 @@
1
+ from ittup.common.settings import Load
2
+
3
+ config_settings = Load.load_config()
4
+
ittup/common/about.py ADDED
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ from importlib.metadata import PackageNotFoundError, version as _package_version
3
+
4
+ APP_NAME = "ittup"
5
+ APP_DESCRIPTION = "ItaTorrents uploader"
6
+ REPO_URL = "https://github.com/TehMaat/ittup"
7
+
8
+ # The version is defined only in pyproject.toml and read from the installed package metadata
9
+ try:
10
+ __version__ = _package_version(APP_NAME)
11
+ except PackageNotFoundError:
12
+ # Running from a source checkout without installing the package
13
+ __version__ = "0.0.0+unknown"
14
+
15
+ USER_AGENT = f"{APP_NAME}/{__version__} (+{REPO_URL})"
@@ -0,0 +1,98 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class BDInfo:
4
+ """
5
+ A class to represent information about a Blu-ray disc.
6
+
7
+ Attributes:
8
+ disc_label (str): The label or name of the disc.
9
+ disc_size (str): The size of the disc.
10
+ protection (str): The type of protection applied to the disc.
11
+ playlist (str): The playlist information.
12
+ size (str): The size of the content on the disc.
13
+ length (str): The length of the content on the disc.
14
+ total_bitrate (str): The total bitrate of the disc content.
15
+ video (str): The video specifications.
16
+ audio (list[str]): A list of audio specifications.
17
+ languages (list[str]): A list of languages extracted from audio specifications.
18
+ subtitles (list[str]): A list of subtitle specifications.
19
+
20
+ Methods:
21
+ from_bdinfo_string(bd_info_string: str) -> 'BDInfo':
22
+ Creates an instance of BDInfo from a formatted string.
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ disc_label: str,
28
+ disc_size: str,
29
+ protection: str,
30
+ playlist: str,
31
+ size: str,
32
+ length: str,
33
+ total_bitrate: str,
34
+ video: str,
35
+ audio: list[str],
36
+ languages: list[str],
37
+ subtitles: list[str],
38
+ ):
39
+ self.disc_label = disc_label
40
+ self.disc_size = disc_size
41
+ self.protection = protection
42
+ self.playlist = playlist
43
+ self.size = size
44
+ self.length = length
45
+ self.total_bitrate = total_bitrate
46
+ self.video = video
47
+ self.audio = audio
48
+ self.languages = languages
49
+ self.subtitles = subtitles
50
+
51
+ @classmethod
52
+ def from_bdinfo_string(cls, bd_info_string: str) -> 'BDInfo':
53
+ """
54
+ Creates an instance of BDInfo from a formatted string.
55
+
56
+ Args:
57
+ bd_info_string (str): A string containing Blu-ray disc information formatted with labels and values.
58
+
59
+ Returns:
60
+ BDInfo: An instance of the BDInfo class with attributes populated from the input string.
61
+ """
62
+ lines = bd_info_string.strip().split("\n")
63
+ data = {"audio": [], "subtitles": []}
64
+
65
+ for line in lines:
66
+ # Parsing Audio
67
+ if ": " in line:
68
+ key, value = line.split(": ", 1)
69
+ key = key.strip().replace(" ", "_").lower()
70
+
71
+ if key == "audio":
72
+ data["audio"].append(value.strip().lower())
73
+ elif key == "subtitle":
74
+ data["subtitles"].append(value.strip().lower())
75
+ else:
76
+ data[key] = value.strip()
77
+
78
+ # Parsing Languages
79
+ languages_parsed = []
80
+ for item in data["audio"]:
81
+ item = item.replace("(", " ")
82
+ item = item.replace(")", " ")
83
+ item = item.split("/")
84
+ languages_parsed.append(item[0].strip())
85
+
86
+ return cls(
87
+ disc_label=data.get("disc_label"),
88
+ disc_size=data.get("disc_size"),
89
+ protection=data.get("protection"),
90
+ playlist=data.get("playlist"),
91
+ size=data.get("size"),
92
+ length=data.get("length"),
93
+ total_bitrate=data.get("total_bitrate"),
94
+ video=data.get("video"),
95
+ audio=data["audio"],
96
+ languages=languages_parsed,
97
+ subtitles=data["subtitles"],
98
+ )
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from dataclasses import dataclass
4
+ from ittup.core.pvtTorrent import Mytorrent
5
+ from ittup.core.media import Media
6
+
7
+
8
+ @dataclass
9
+ class BittorrentData:
10
+ tracker_response: str
11
+ torrent_response: Mytorrent | None
12
+ content: Media
13
+ tracker_message: dict
14
+ archive_path: str
@@ -0,0 +1,162 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import argparse
4
+
5
+ from ittup.common.utility import System
6
+ from ittup.common.about import APP_DESCRIPTION, APP_NAME
7
+
8
+
9
+ class RemovedFlag(argparse.Action):
10
+ def __call__(self, parser, namespace, values, option_string=None):
11
+ parser.error(f"'{option_string}' has been removed: {APP_NAME} uploads only to ItaTorrents")
12
+
13
+
14
+ class CommandLine:
15
+ """
16
+ Handle command line arguments
17
+ """
18
+
19
+ def __init__(self):
20
+
21
+ # /////////////////////////
22
+ # Main parser
23
+ # /////////////////////////
24
+ parser = argparse.ArgumentParser(
25
+ prog=APP_NAME,
26
+ description=f"{APP_DESCRIPTION}: manage torrents, uploads, searches and config checks",
27
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter
28
+ )
29
+
30
+ # /////////////////////////
31
+ # Groups
32
+ # /////////////////////////
33
+ cfg_group = parser.add_argument_group("Config Commands")
34
+ upload_group = parser.add_argument_group("Upload Commands")
35
+ search_group = parser.add_argument_group("Search Commands")
36
+ filter_group = parser.add_argument_group("Filter Options")
37
+ special_group = parser.add_argument_group("Special Flags")
38
+
39
+ # /////////////////////////
40
+ # Config Commands
41
+ # /////////////////////////
42
+ cfg_group.add_argument(
43
+ "-check", "--check",
44
+ action="store_true",
45
+ help="Check config files"
46
+ )
47
+
48
+ # /////////////////////////
49
+ # Upload Commands
50
+ # /////////////////////////
51
+ upload_group.add_argument("-u", "--upload", type=str, help="Upload path")
52
+ upload_group.add_argument("-f", "--folder", type=str, help="Upload folder")
53
+ upload_group.add_argument("-scan", "--scan", type=str, help="Scan folder")
54
+ upload_group.add_argument("-reseed", "--reseed", action="store_true", help="Reseed folder")
55
+ upload_group.add_argument("-watcher", "--watcher", action="store_true", help="Start watcher")
56
+ upload_group.add_argument("-notitle", "--notitle", type=str, help="Manual title")
57
+
58
+ upload_group.add_argument(
59
+ "-force",
60
+ nargs='?',
61
+ const="movie",
62
+ type=str,
63
+ default=None,
64
+ help="Force category"
65
+ )
66
+
67
+ upload_group.add_argument("-noseed", "--noseed", action="store_true", help="Disable seeding")
68
+ upload_group.add_argument("-noup", "--noup", action="store_true", help="Torrent only")
69
+ upload_group.add_argument("-dup", "--duplicate", action="store_true", help="Check duplicates")
70
+ upload_group.add_argument("-personal", "--personal", action="store_true", help="Personal release")
71
+ upload_group.add_argument("-ftp", "--ftp", action="store_true", help="Connect FTP")
72
+
73
+ # Removed flags: ittup uploads only to ItaTorrents. Without this '-mt' would be parsed as '-m t'
74
+ upload_group.add_argument("-mt", "--mt", "-tracker", "--tracker", nargs='?', action=RemovedFlag,
75
+ help=argparse.SUPPRESS)
76
+
77
+ # /////////////////////////
78
+ # Search Commands
79
+ # /////////////////////////
80
+ search_group.add_argument("-dmp", "--dump", action="store_true", help="Dump titles")
81
+ search_group.add_argument("-sch", "--search", type=str, help="Search torrent")
82
+ search_group.add_argument("-db", "--dbsave", action="store_true", help="Save results")
83
+ search_group.add_argument("-i", "--info", type=str, help="Torrent info")
84
+ search_group.add_argument("-up", "--uploader", type=str, help="By uploader")
85
+ search_group.add_argument("-d", "--description", type=str, help="By description")
86
+ search_group.add_argument("-bd", "--bdinfo", type=str, help="Show BDInfo")
87
+ search_group.add_argument("-m", "--mediainfo", type=str, help="Show MediaInfo")
88
+ search_group.add_argument("-int", "--internal", action="store_true", help="Internal Release")
89
+ search_group.add_argument("-mod", "--moderation", action="store_true", help="In moderation")
90
+
91
+
92
+ # /////////////////////////
93
+ # Filter Options
94
+ # /////////////////////////
95
+ filter_group.add_argument("-st", "--startyear", type=str, help="Start year")
96
+ filter_group.add_argument("-en", "--endyear", type=str, help="End year")
97
+ filter_group.add_argument("-type", "--type", type=str, help="Type")
98
+ filter_group.add_argument("-res", "--resolution", type=str, help="Resolution")
99
+ filter_group.add_argument("-file", "--filename", type=str, help="Filename")
100
+ filter_group.add_argument("-se", "--season", type=str, help="Season")
101
+ filter_group.add_argument("-ep", "--episode", type=str, help="Episode")
102
+
103
+ # IDs
104
+ filter_group.add_argument("-tmdb", "--tmdb_id", type=str, help="TMDB ID")
105
+ filter_group.add_argument("-imdb", "--imdb_id", type=str, help="IMDB ID")
106
+ filter_group.add_argument("-tvdb", "--tvdb_id", type=int, help="TVDB ID")
107
+ filter_group.add_argument("-mal", "--mal_id", type=str, help="MAL ID")
108
+ filter_group.add_argument("-playid", "--playlist_id", type=str, help="Playlist ID")
109
+ filter_group.add_argument("-coll", "--collection_id", type=str, help="Collection ID")
110
+
111
+ # Status
112
+ filter_group.add_argument("-free", "--freelech", type=str, help="Freeleech")
113
+ filter_group.add_argument("-al", "--alive", action="store_true", help="Alive")
114
+ filter_group.add_argument("-dd", "--dead", action="store_true", help="Dead")
115
+ filter_group.add_argument("-dy", "--dying", action="store_true", help="Dying")
116
+
117
+ # /////////////////////////
118
+ # Special Flags
119
+ # /////////////////////////
120
+ special_group.add_argument("-du", "--doubleup", action="store_true", help="DoubleUp")
121
+ special_group.add_argument("-fe", "--featured", action="store_true", help="Featured")
122
+ special_group.add_argument("-re", "--refundable", action="store_true", help="Refundable")
123
+ special_group.add_argument("-str", "--stream", action="store_true", help="Stream")
124
+ special_group.add_argument("-sd", "--standard", action="store_true", help="SD")
125
+ special_group.add_argument("-hs", "--highspeed", action="store_true", help="Highspeed")
126
+ special_group.add_argument("-inter", "--intern_r", action="store_true", help="Internal Release")
127
+ special_group.add_argument("-pr", "--prelease", action="store_true", help="Personal")
128
+
129
+ # /////////////////////////
130
+ # Parse args
131
+ # /////////////////////////
132
+ self.args = parser.parse_args()
133
+
134
+ # /////////////////////////
135
+ # Check scan path
136
+ # /////////////////////////
137
+ self.is_dir = os.path.isdir(self.args.scan) if self.args.scan else None
138
+
139
+ # /////////////////////////
140
+ # Expand upload path
141
+ # /////////////////////////
142
+ if self.args.upload:
143
+ self.args.upload = os.path.expanduser(self.args.upload)
144
+
145
+ # /////////////////////////
146
+ # Validate force category
147
+ # /////////////////////////
148
+ if self.args.force:
149
+
150
+ self.args.force = self.args.force[:10]
151
+
152
+ valid_categories = [
153
+ System.category_list[System.MOVIE],
154
+ System.category_list[System.GAME],
155
+ System.category_list[System.TV_SHOW],
156
+ System.category_list[System.DOCUMENTARY]
157
+ ]
158
+
159
+ if self.args.force.lower() not in valid_categories:
160
+ self.args.force = None
161
+ print("Invalid -force category")
162
+ exit()
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ language_dict = {
4
+ "IT": "Italian",
5
+ "ES": "Spanish",
6
+ "DE": "German",
7
+ "FR": "French",
8
+ "EN": "English",
9
+ "TR": "Turkish",
10
+ "PT": "Portuguese",
11
+ "JA": "Japanese",
12
+ "BG": "Bulgarian",
13
+ "PL": "Polish"
14
+ }
15
+
16
+
17
+ def my_language(iso639_1: str)-> str | None:
18
+ return language_dict.get(iso639_1.upper(), '')
@@ -0,0 +1,78 @@
1
+ import json
2
+ import os
3
+ import sqlite3
4
+ from ittup.core import config_settings
5
+
6
+ # Torrent attributes
7
+ create_table_sql = ('\n'
8
+ 'CREATE TABLE IF NOT EXISTS torrents (\n'
9
+ ' id INTEGER PRIMARY KEY AUTOINCREMENT,\n'
10
+ ' name TEXT,\n'
11
+ ' category TEXT,\n'
12
+ ' category_id INTEGER,\n'
13
+ ' created_at TEXT,\n'
14
+ ' description TEXT,\n'
15
+ ' details_link TEXT,\n'
16
+ ' download_link TEXT,\n'
17
+ ' double_upload BOOLEAN,\n'
18
+ ' featured BOOLEAN,\n'
19
+ ' freeleech TEXT,\n'
20
+ ' igdb_id INTEGER,\n'
21
+ ' imdb_id TEXT,\n'
22
+ ' info_hash TEXT,\n'
23
+ ' internal BOOLEAN,\n'
24
+ ' leechers INTEGER,\n'
25
+ ' magnet_link TEXT,\n'
26
+ ' mal_id INTEGER,\n'
27
+ ' media_info TEXT,\n'
28
+ ' release_year INTEGER,\n'
29
+ ' resolution TEXT,\n'
30
+ ' resolution_id INTEGER,\n'
31
+ ' seeders INTEGER,\n'
32
+ ' size INTEGER,\n'
33
+ ' times_completed INTEGER,\n'
34
+ ' tmdb_id INTEGER,\n'
35
+ ' tvdb_id INTEGER,\n'
36
+ ' type TEXT,\n'
37
+ ' type_id INTEGER,\n'
38
+ ' uploader TEXT,\n'
39
+ ' personal_release BOOLEAN,\n'
40
+ ' refundable BOOLEAN,\n'
41
+ ' num_file INTEGER,\n'
42
+ ' bd_info TEXT,\n'
43
+ ' genres TEXT,\n'
44
+ ' poster TEXT,\n'
45
+ ' meta TEXT,\n'
46
+ ' files TEXT\n'
47
+ ')\n')
48
+
49
+
50
+ class Database:
51
+ """
52
+ Create a new database and populate it with torrents attributes
53
+ Search torrents based on attributes
54
+ """
55
+
56
+ def __init__(self, db_file):
57
+ self.filename = db_file
58
+ self.CACHE_PATH = config_settings.user_preferences.CACHE_PATH
59
+ self.database = sqlite3.connect(os.path.join(self.CACHE_PATH, f"{db_file}.db"))
60
+ self.cursor = self.database.cursor()
61
+ self.build()
62
+
63
+ def build(self):
64
+ self.cursor.execute("DROP TABLE IF EXISTS torrents")
65
+ self.cursor.execute(create_table_sql)
66
+ self.database.commit()
67
+
68
+ def write(self, data: dict):
69
+ for key, value in data.items():
70
+ if isinstance(value, (dict, list)):
71
+ data[key] = json.dumps(value)
72
+
73
+ keys = ', '.join(data.keys())
74
+ placeholders = ', '.join(['?'] * len(data))
75
+ values = tuple(data.values())
76
+ sql = f'''INSERT INTO torrents ({keys}) VALUES ({placeholders})'''
77
+ self.cursor.execute(sql, values)
78
+ self.database.commit()
@@ -0,0 +1,9 @@
1
+ import logging
2
+
3
+ logging.basicConfig(
4
+ level=logging.INFO,
5
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
6
+ )
7
+
8
+ logger = logging.getLogger(__name__)
9
+
File without changes