Unit3Dup 0.8.8__tar.gz → 0.8.9__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.
Files changed (112) hide show
  1. {unit3dup-0.8.8 → unit3dup-0.8.9}/PKG-INFO +6 -17
  2. {unit3dup-0.8.8 → unit3dup-0.8.9}/README.rst +5 -16
  3. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/PKG-INFO +6 -17
  4. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/SOURCES.txt +1 -0
  5. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/command.py +1 -0
  6. unit3dup-0.8.9/common/database.py +94 -0
  7. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/pw_api.py +6 -9
  8. unit3dup-0.8.9/common/external_services/Pw/pw_manager.py +63 -0
  9. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/pw_service.py +7 -2
  10. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/imageHost.py +3 -2
  11. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/settings.py +24 -6
  12. {unit3dup-0.8.8 → unit3dup-0.8.9}/pyproject.toml +1 -1
  13. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/__main__.py +10 -2
  14. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/torrent.py +24 -15
  15. {unit3dup-0.8.8 → unit3dup-0.8.9}/view/custom_console.py +25 -0
  16. unit3dup-0.8.8/common/external_services/Pw/pw_manager.py +0 -46
  17. {unit3dup-0.8.8 → unit3dup-0.8.9}/LICENSE +0 -0
  18. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/dependency_links.txt +0 -0
  19. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/entry_points.txt +0 -0
  20. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/requires.txt +0 -0
  21. {unit3dup-0.8.8 → unit3dup-0.8.9}/Unit3Dup.egg-info/top_level.txt +0 -0
  22. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/__init__.py +0 -0
  23. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/bdinfo_string.py +0 -0
  24. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/bittorrent.py +0 -0
  25. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/constants.py +0 -0
  26. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/__init__.py +0 -0
  27. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/__init__.py +0 -0
  28. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/models/__init__.py +0 -0
  29. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/models/indexers.py +0 -0
  30. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/models/search.py +0 -0
  31. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/Pw/core/models/torrent_client_config.py +0 -0
  32. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/__init__.py +0 -0
  33. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/__init__.py +0 -0
  34. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/client.py +0 -0
  35. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/__init__.py +0 -0
  36. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/ftpx_service.py +0 -0
  37. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/ftpx_session.py +0 -0
  38. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/menu.py +0 -0
  39. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/models/__init__.py +0 -0
  40. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/ftpx/core/models/list.py +0 -0
  41. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/__init__.py +0 -0
  42. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/client.py +0 -0
  43. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/__init__.py +0 -0
  44. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/api.py +0 -0
  45. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/models/__init__.py +0 -0
  46. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/models/search.py +0 -0
  47. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/platformid.py +0 -0
  48. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/igdb/core/tags.py +0 -0
  49. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/imdb.py +0 -0
  50. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/mediaresult.py +0 -0
  51. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/sessions/__init__.py +0 -0
  52. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/sessions/agents.py +0 -0
  53. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/sessions/exceptions.py +0 -0
  54. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/sessions/session.py +0 -0
  55. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/__init__.py +0 -0
  56. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/__init__.py +0 -0
  57. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/api.py +0 -0
  58. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/keywords.py +0 -0
  59. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
  60. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
  61. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
  62. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
  63. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
  64. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
  65. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
  66. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
  67. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
  68. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
  69. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
  70. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
  71. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
  72. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/videos.py +0 -0
  73. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/trailers/__init__.py +0 -0
  74. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/trailers/api.py +0 -0
  75. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/external_services/trailers/response.py +0 -0
  76. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/extractor.py +0 -0
  77. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/frames.py +0 -0
  78. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/mediainfo.py +0 -0
  79. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/mediainfo_string.py +0 -0
  80. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/title.py +0 -0
  81. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/torrent_clients.py +0 -0
  82. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/trackers/__init__.py +0 -0
  83. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/trackers/data.py +0 -0
  84. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/trackers/itt.py +0 -0
  85. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/trackers/sis.py +0 -0
  86. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/trackers/trackers.py +0 -0
  87. {unit3dup-0.8.8 → unit3dup-0.8.9}/common/utility.py +0 -0
  88. {unit3dup-0.8.8 → unit3dup-0.8.9}/requirements.txt +0 -0
  89. {unit3dup-0.8.8 → unit3dup-0.8.9}/setup.cfg +0 -0
  90. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/__init__.py +0 -0
  91. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/automode.py +0 -0
  92. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/bot.py +0 -0
  93. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/duplicate.py +0 -0
  94. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/exceptions.py +0 -0
  95. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media.py +0 -0
  96. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/ContentManager.py +0 -0
  97. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/DocuManager.py +0 -0
  98. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/GameManager.py +0 -0
  99. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/MediaInfoManager.py +0 -0
  100. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/SeedManager.py +0 -0
  101. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/TorrentManager.py +0 -0
  102. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/VideoManager.py +0 -0
  103. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/__init__.py +0 -0
  104. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/media_manager/common.py +0 -0
  105. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/pvtDocu.py +0 -0
  106. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/pvtTorrent.py +0 -0
  107. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/pvtTracker.py +0 -0
  108. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/pvtVideo.py +0 -0
  109. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/upload.py +0 -0
  110. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/web/__init__.py +0 -0
  111. {unit3dup-0.8.8 → unit3dup-0.8.9}/unit3dup/web/main.py +0 -0
  112. {unit3dup-0.8.8 → unit3dup-0.8.9}/view/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Unit3Dup
3
- Version: 0.8.8
3
+ Version: 0.8.9
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -66,24 +66,19 @@ It performs the following tasks:
66
66
  unit3dup can grab the first page, convert it to an image (using xpdf),
67
67
  and then the bot can upload it to an image host, then add the link to the torrent page description.
68
68
 
69
- .. image:: https://img.shields.io/badge/INSTALL-gr
70
- :alt: install
71
69
 
72
- Ubuntu/Debian
73
- -------------
74
- pip install unit3dup
70
+ Install and Upgrade
71
+ ===================
75
72
 
76
- Upgrade
77
- -------
78
- pip install unit3dup --upgrade
73
+ - pip install unit3dup --upgrade
79
74
 
80
75
  Ubuntu/Debian Dependencies
81
76
  --------------------------
82
- sudo apt install ffmpeg
77
+ - sudo apt install ffmpeg
83
78
 
84
79
  Only for pdf
85
80
  ------------
86
- sudo apt install poppler-utils
81
+ - sudo apt install poppler-utils
87
82
 
88
83
 
89
84
  Windows Dependencies
@@ -110,12 +105,6 @@ Alternative method
110
105
  4. unit3dup
111
106
 
112
107
 
113
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
114
- :alt: Bot Update
115
-
116
- 1. pip install unit3dup --upgrade
117
-
118
-
119
108
 
120
109
  RUN
121
110
  ======
@@ -35,24 +35,19 @@ It performs the following tasks:
35
35
  unit3dup can grab the first page, convert it to an image (using xpdf),
36
36
  and then the bot can upload it to an image host, then add the link to the torrent page description.
37
37
 
38
- .. image:: https://img.shields.io/badge/INSTALL-gr
39
- :alt: install
40
38
 
41
- Ubuntu/Debian
42
- -------------
43
- pip install unit3dup
39
+ Install and Upgrade
40
+ ===================
44
41
 
45
- Upgrade
46
- -------
47
- pip install unit3dup --upgrade
42
+ - pip install unit3dup --upgrade
48
43
 
49
44
  Ubuntu/Debian Dependencies
50
45
  --------------------------
51
- sudo apt install ffmpeg
46
+ - sudo apt install ffmpeg
52
47
 
53
48
  Only for pdf
54
49
  ------------
55
- sudo apt install poppler-utils
50
+ - sudo apt install poppler-utils
56
51
 
57
52
 
58
53
  Windows Dependencies
@@ -79,12 +74,6 @@ Alternative method
79
74
  4. unit3dup
80
75
 
81
76
 
82
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
83
- :alt: Bot Update
84
-
85
- 1. pip install unit3dup --upgrade
86
-
87
-
88
77
 
89
78
  RUN
90
79
  ======
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Unit3Dup
3
- Version: 0.8.8
3
+ Version: 0.8.9
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -66,24 +66,19 @@ It performs the following tasks:
66
66
  unit3dup can grab the first page, convert it to an image (using xpdf),
67
67
  and then the bot can upload it to an image host, then add the link to the torrent page description.
68
68
 
69
- .. image:: https://img.shields.io/badge/INSTALL-gr
70
- :alt: install
71
69
 
72
- Ubuntu/Debian
73
- -------------
74
- pip install unit3dup
70
+ Install and Upgrade
71
+ ===================
75
72
 
76
- Upgrade
77
- -------
78
- pip install unit3dup --upgrade
73
+ - pip install unit3dup --upgrade
79
74
 
80
75
  Ubuntu/Debian Dependencies
81
76
  --------------------------
82
- sudo apt install ffmpeg
77
+ - sudo apt install ffmpeg
83
78
 
84
79
  Only for pdf
85
80
  ------------
86
- sudo apt install poppler-utils
81
+ - sudo apt install poppler-utils
87
82
 
88
83
 
89
84
  Windows Dependencies
@@ -110,12 +105,6 @@ Alternative method
110
105
  4. unit3dup
111
106
 
112
107
 
113
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
114
- :alt: Bot Update
115
-
116
- 1. pip install unit3dup --upgrade
117
-
118
-
119
108
 
120
109
  RUN
121
110
  ======
@@ -13,6 +13,7 @@ common/bdinfo_string.py
13
13
  common/bittorrent.py
14
14
  common/command.py
15
15
  common/constants.py
16
+ common/database.py
16
17
  common/extractor.py
17
18
  common/frames.py
18
19
  common/mediainfo.py
@@ -47,6 +47,7 @@ class CommandLine:
47
47
  parser.add_argument("-ftp", "--ftp", action="store_true", help="Connect to FTP")
48
48
 
49
49
  # optional
50
+ parser.add_argument("-dump", "--dump", type=str, help="Download all torrent files")
50
51
  parser.add_argument("-s", "--search", type=str, help="Search for torrent")
51
52
  parser.add_argument("-i", "--info", type=str, help="Get info on torrent")
52
53
  parser.add_argument("-up", "--uploader", type=str, help="Search by uploader")
@@ -0,0 +1,94 @@
1
+ import json
2
+ import sqlite3
3
+
4
+ # Torrent attributes
5
+ create_table_sql = ('\n'
6
+ 'CREATE TABLE IF NOT EXISTS torrents (\n'
7
+ ' id INTEGER PRIMARY KEY AUTOINCREMENT,\n'
8
+ ' name TEXT,\n'
9
+ ' category TEXT,\n'
10
+ ' category_id INTEGER,\n'
11
+ ' created_at TEXT,\n'
12
+ ' description TEXT,\n'
13
+ ' details_link TEXT,\n'
14
+ ' download_link TEXT,\n'
15
+ ' double_upload BOOLEAN,\n'
16
+ ' featured BOOLEAN,\n'
17
+ ' freeleech TEXT,\n'
18
+ ' igdb_id INTEGER,\n'
19
+ ' imdb_id TEXT,\n'
20
+ ' info_hash TEXT,\n'
21
+ ' internal BOOLEAN,\n'
22
+ ' leechers INTEGER,\n'
23
+ ' magnet_link TEXT,\n'
24
+ ' mal_id INTEGER,\n'
25
+ ' media_info TEXT,\n'
26
+ ' release_year INTEGER,\n'
27
+ ' resolution TEXT,\n'
28
+ ' resolution_id INTEGER,\n'
29
+ ' seeders INTEGER,\n'
30
+ ' size INTEGER,\n'
31
+ ' times_completed INTEGER,\n'
32
+ ' tmdb_id INTEGER,\n'
33
+ ' tvdb_id INTEGER,\n'
34
+ ' type TEXT,\n'
35
+ ' type_id INTEGER,\n'
36
+ ' uploader TEXT,\n'
37
+ ' personal_release BOOLEAN,\n'
38
+ ' refundable BOOLEAN,\n'
39
+ ' num_file INTEGER,\n'
40
+ ' bd_info TEXT,\n'
41
+ ' genres TEXT,\n'
42
+ ' poster TEXT,\n'
43
+ ' meta TEXT,\n'
44
+ ' files TEXT\n'
45
+ ')\n')
46
+
47
+
48
+ class Database:
49
+ """
50
+ Create a new database and populate it with torrents attributes
51
+ Search torrents based on attributes
52
+ """
53
+
54
+ def __init__(self, db_file):
55
+ self.filename = db_file
56
+ self.database = sqlite3.connect(f"{db_file}.db")
57
+ self.cursor = self.database.cursor()
58
+ self.build()
59
+
60
+ def build(self):
61
+ self.cursor.execute(create_table_sql)
62
+ self.database.commit()
63
+
64
+ def write(self, data: dict):
65
+ for key, value in data.items():
66
+ if isinstance(value, (dict,list)):
67
+ data[key] = json.dumps(value)
68
+
69
+ keys = ', '.join(data.keys())
70
+ placeholders = ', '.join(['?'] * len(data))
71
+ values = tuple(data.values())
72
+
73
+ sql = f'''INSERT INTO torrents ({keys}) VALUES ({placeholders})'''
74
+ self.cursor.execute(sql, values)
75
+ self.database.commit()
76
+
77
+ def search(self, query: str):
78
+ # Search a substring in 'name'
79
+ self.cursor.execute("SELECT name FROM torrents WHERE name LIKE ?", ('%' + query + '%',))
80
+ results = self.cursor.fetchall()
81
+ # print the results
82
+ for r in results:
83
+ print(f"[database]{r}")
84
+ input("[DATABASE] Press Enter to continue...")
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import os.path
3
3
 
4
+ import httpx
5
+
4
6
  from common.external_services.Pw.core.models.torrent_client_config import (
5
7
  TorrentClientConfig,
6
8
  )
@@ -37,7 +39,7 @@ class PwAPI(MyHttp):
37
39
  custom_console.bot_question_log("No PW_API_KEY provided\n")
38
40
  exit(1)
39
41
 
40
- def get_indexers(self) -> ["Indexer"]:
42
+ def get_indexers(self) -> list[type[[Indexer]]]:
41
43
  """Get all indexers."""
42
44
 
43
45
  response = self.get_url(url=f"{self.base_url}/indexer", params={})
@@ -46,15 +48,10 @@ class PwAPI(MyHttp):
46
48
  indexers_list = response.json()
47
49
  return [Indexer(**indexer) for indexer in indexers_list]
48
50
  else:
49
- return []
51
+ return [Indexer]
50
52
 
51
- def get_torrent_url(self, url: str, filename: str):
52
-
53
- response = self.get_url(url=url)
54
- if response.status_code == 200:
55
- # Write the torrent to file
56
- with open(os.path.join(config_settings.options.PW_TORRENT_ARCHIVE_PATH,f"{filename}.torrent"), 'wb') as f:
57
- f.write(response.content)
53
+ def get_torrent_url(self, url: str, filename: str)-> httpx.Response :
54
+ return self.get_url(url=url)
58
55
 
59
56
  def search(self, query: str) -> list[Search] | None:
60
57
  """Get search queue."""
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import argparse
4
+ import os
5
+
6
+ from common.external_services.Pw.pw_service import PwService
7
+ from common.utility import ManageTitles
8
+ from common.database import Database
9
+ from common import config_settings
10
+ from unit3dup.media import Media
11
+
12
+
13
+ from qbittorrent import Client
14
+ from view import custom_console
15
+
16
+ class PwManager:
17
+
18
+ def __init__(self,cli: argparse.Namespace):
19
+ # Keyword
20
+ self.search = cli.pw
21
+
22
+ # filename for the new download
23
+ self.filename = ManageTitles.normalize_filename(self.search)
24
+
25
+ # Select the tracker database
26
+ self.database = Database(db_file=cli.tracker)
27
+
28
+
29
+ def process(self):
30
+
31
+ # a new qbittorrent instance
32
+ qb = Client(f"http://{config_settings.torrent_client_config.QBIT_HOST}:{config_settings.torrent_client_config.QBIT_PORT}/")
33
+ # a new pw instance
34
+ pw_service = PwService()
35
+ # Query the indexers
36
+ search = pw_service.search(query=self.search)
37
+
38
+ content = []
39
+ if search:
40
+ for index, s in enumerate(search):
41
+ if s.seeders > 0:
42
+ category = s.categories[0]['name']
43
+ if category in ['Movies','TV','TV/HD']:
44
+ content.append(s)
45
+ custom_console.bot_process_table_pw(content=content)
46
+
47
+
48
+ for c in content:
49
+ test = Media(folder=f"c:\\test\\{c.fileName}", subfolder=f"c:\\test\\{c.fileName}")
50
+ print(f"[Prowlarr] {c.fileName}")
51
+ self.database.search(test.guess_title)
52
+
53
+
54
+ """"
55
+ qb.login(username=config_settings.torrent_client_config.QBIT_USER,
56
+ password=config_settings.torrent_client_config.QBIT_PASS)
57
+
58
+ for torrent in content:
59
+ filename = str(os.path.join(config_settings.options.PW_TORRENT_ARCHIVE_PATH,torrent.fileName))
60
+ print(filename)
61
+ magnet = pw_service.get_torrent_from_pw(torrent_url=torrent.downloadUrl,download_filename=filename)
62
+ qb.download_from_link(magnet, savepath=config_settings.options.PW_DOWNLOAD_PATH)
63
+ """
@@ -23,7 +23,12 @@ class PwService:
23
23
  def send_torrent_to_client(self, payload):
24
24
  return self.pw_api.send_torrent_to_client(payload)
25
25
 
26
- def get_torrent_from_pw(self, torrent_url: str, download_filename: str):
27
- return self.pw_api.get_torrent_url(url=torrent_url, filename=download_filename)
26
+ def get_torrent_from_pw(self, torrent_url: str, download_filename: str)-> str | None:
27
+ response = self.pw_api.get_torrent_url(url=torrent_url, filename=download_filename)
28
+ # Redirect (PW)
29
+ if response.status_code == 301:
30
+ return response.headers.get('Location')
31
+ return None
32
+
28
33
 
29
34
 
@@ -15,6 +15,7 @@ class ImageUploader(ABC):
15
15
  self.image = base64.b64encode(image)
16
16
  self.key = key
17
17
  self.image_name = image_name
18
+ self.timeout = 30
18
19
 
19
20
  @abstractmethod
20
21
  def get_endpoint(self):
@@ -39,7 +40,7 @@ class ImageUploader(ABC):
39
40
  try:
40
41
  upload_n += 1
41
42
  response = requests.post(
42
- self.get_endpoint(), data = data, files = files, timeout = 20
43
+ self.get_endpoint(), data = data, files = files, timeout = self.timeout
43
44
  )
44
45
  response.raise_for_status()
45
46
  return response.json()
@@ -60,7 +61,7 @@ class ImageUploader(ABC):
60
61
  except requests.exceptions.Timeout:
61
62
  custom_console.bot_log(
62
63
  f"[{self.__class__.__name__}] We did not receive a response from the server"
63
- f" within the 20 second limit"
64
+ f" within the {self.timeout} second limit"
64
65
  )
65
66
  break
66
67
 
@@ -13,7 +13,7 @@ from common.utility import ManageTitles
13
13
  from common import trackers
14
14
 
15
15
  config_file = "Unit3Dbot.json"
16
- version = "0.8.8"
16
+ version = "0.8.9"
17
17
 
18
18
  if os.name == "nt":
19
19
  PW_TORRENT_ARCHIVE_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / "pw_torrent_archive"
@@ -40,7 +40,7 @@ def get_default_path(field: str)-> str:
40
40
  "CACHE_PATH": CACHE_PATH,
41
41
  "WATCHER_DESTINATION_PATH": WATCHER_DESTINATION_PATH,
42
42
  "WATCHER_PATH": WATCHER_PATH,
43
- "PW_DOWNLOAD": PW_DOWNLOAD_PATH,
43
+ "PW_DOWNLOAD_PATH": PW_DOWNLOAD_PATH,
44
44
  "PW_TORRENT_ARCHIVE_PATH": PW_TORRENT_ARCHIVE_PATH
45
45
  }
46
46
  return str(default_paths[field])
@@ -130,7 +130,7 @@ class Options(BaseModel):
130
130
  PW_API_KEY: str | None = None
131
131
  PW_URL: str = "http://localhost:9696/api/v1"
132
132
  PW_TORRENT_ARCHIVE_PATH: str | None = None
133
- PW_DOWNLOAD: str | None = None
133
+ PW_DOWNLOAD_PATH: str | None = None
134
134
  FTPX_USER: str = "user"
135
135
  FTPX_PASS: str = "pass"
136
136
  FTPX_IP: str = "127.0.0.1"
@@ -425,7 +425,7 @@ class Config(BaseModel):
425
425
  'CACHE_SCR','CACHE_DBONLINE', 'PERSONAL_RELEASE']:
426
426
  section[field] = Validate.boolean(value=section[field], field_name=field)
427
427
 
428
- if field in ['TORRENT_COMMENT','PW_TORRENT_ARCHIVE_PATH','WATCHER_PATH','DEFAULT_TRACKER']:
428
+ if field in ['TORRENT_COMMENT','WATCHER_PATH','DEFAULT_TRACKER']:
429
429
  section[field] = Validate.string(value=section[field], field_name=field)
430
430
 
431
431
  if field in ['NUMBER_OF_SCREENSHOTS','COMPRESS_SCSHOT','IMGBB_PRIORITY','FREE_IMAGE_PRIORITY',
@@ -451,11 +451,29 @@ class Config(BaseModel):
451
451
  section[field] =Validate.unit3dup_path(path=section[field],field_name=field,
452
452
  default_path=get_default_path(field=field))
453
453
 
454
+
454
455
  return v
455
456
 
456
457
  @model_validator(mode='before')
457
458
  def set_default_options(cls, v):
458
- return v or Options()
459
+ section = v['options']
460
+
461
+ for field, value in section.items():
462
+ if value is None:
463
+ print(f"Please fix the '{field}' value")
464
+ exit(1)
465
+ else:
466
+ field = field.upper()
467
+
468
+ if field == 'PW_TORRENT_ARCHIVE_PATH':
469
+ section[field] = Validate.unit3dup_path(path=section[field], field_name=field,
470
+ default_path=get_default_path(field=field))
471
+
472
+ if field == 'PW_DOWNLOAD_PATH':
473
+ section[field] = Validate.unit3dup_path(path=section[field], field_name=field,
474
+ default_path=get_default_path(field=field))
475
+
476
+ return v
459
477
 
460
478
  @model_validator(mode='before')
461
479
  def set_default_console_options(cls, v):
@@ -570,7 +588,7 @@ class Load:
570
588
  "PW_API_KEY": "no_key",
571
589
  "PW_URL": "http://localhost:9696/api/v1",
572
590
  "PW_TORRENT_ARCHIVE_PATH": ".",
573
- "PW_DOWNLOAD": ".",
591
+ "PW_DOWNLOAD_PATH": ".",
574
592
  "FTPX_USER": "user",
575
593
  "FTPX_PASS": "pass",
576
594
  "FTPX_IP": "127.0.0.1",
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  dynamic = ["dependencies"]
7
7
  name = "Unit3Dup"
8
- version = "0.8.8"
8
+ version = "0.8.9"
9
9
  description = "An uploader for the Unit3D torrent tracker"
10
10
  readme = "README.rst"
11
11
  requires-python = ">=3.10"
@@ -127,8 +127,10 @@ def main():
127
127
 
128
128
  # Pw
129
129
  if cli.args.pw:
130
- bot = Bot(path=cli.args.pw,cli=cli.args, trackers_name_list=tracker_name_list)
131
- bot.pw()
130
+ print("Not yet implemented")
131
+ # bot = Bot(path=cli.args.pw,cli=cli.args, trackers_name_list=tracker_name_list)
132
+ # bot.pw()
133
+ return
132
134
 
133
135
 
134
136
  # ftp and upload
@@ -154,6 +156,12 @@ def main():
154
156
  torrent_info.view_search(cli.args.search)
155
157
  return
156
158
 
159
+ # Dump
160
+ if cli.args.dump:
161
+ print("Not yet implemented")
162
+ # torrent_info.view_search(cli.args.dump,inkey=False)
163
+ return
164
+
157
165
  if cli.args.info:
158
166
  torrent_info.view_search(cli.args.info, info=True)
159
167
  return
@@ -1,8 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import re
3
+ import time
3
4
  import requests
4
5
 
5
6
  from common.trackers.trackers import TRACKData
7
+ from common.database import Database
6
8
  from unit3dup import pvtTracker
7
9
  from view import custom_console
8
10
 
@@ -10,8 +12,9 @@ class Torrent:
10
12
 
11
13
  def __init__(self, tracker_name: str):
12
14
 
13
- self.perPage = 130
15
+ self.perPage = 100
14
16
  self.tracker = pvtTracker.Unit3d(tracker_name=tracker_name)
17
+ self.database = Database(db_file=tracker_name)
15
18
 
16
19
  def get_unique_id(self, media_info: str) -> str:
17
20
  # Divido per campi
@@ -142,7 +145,6 @@ class View(Torrent):
142
145
  def __init__(self, tracker_name: str):
143
146
  super().__init__(tracker_name=tracker_name)
144
147
 
145
- self.perPage = 130
146
148
  # Load the constant tracker
147
149
  self.tracker_data = TRACKData.load_from_module(tracker_name=tracker_name)
148
150
  print()
@@ -171,10 +173,8 @@ class View(Torrent):
171
173
  f" -> {item['attributes']['name']}"
172
174
  )
173
175
 
174
- @staticmethod
175
- def print_normal(tracker_data: dict):
176
+ def print_normal(self, tracker_data: dict):
176
177
  data = [item for item in tracker_data["data"]]
177
-
178
178
  for item in data:
179
179
  if item['attributes']['tmdb_id'] != 0:
180
180
  if not item['attributes']['release_year']:
@@ -184,14 +184,18 @@ class View(Torrent):
184
184
 
185
185
  media = f"[TRACKER] TMDB: {item['attributes']['tmdb_id']} - {release_year}"
186
186
 
187
+ elif item['attributes']['igdb_id'] !=0:
188
+ media = f"[TRACKER] IGDB: {item['attributes']['igdb_id']}"
187
189
  else:
188
- media = f"[TRACKER] IGDB: {item['attributes']['igdb_id']}"
190
+ media = f"[TRACKER] DOC:"
189
191
 
192
+ # Print a data to the console
190
193
  custom_console.bot_log(f"\n {media} - {item['attributes']['name']}")
194
+ # Save torrent data into database
195
+ self.database.write(item['attributes'])
191
196
 
192
197
 
193
-
194
- def page_view(self, tracker_data: dict, tracker: pvtTracker, info=False):
198
+ def page_view(self, tracker_data: dict, tracker: pvtTracker, info=False, inkey=True):
195
199
 
196
200
  self.print_normal(tracker_data) if not info else self.print_info(tracker_data)
197
201
  page = 0
@@ -199,12 +203,17 @@ class View(Torrent):
199
203
  if not tracker_data["links"]["next"]:
200
204
  break
201
205
 
206
+ # Wait for user input if inkey is True
202
207
  page += 1
203
- custom_console.bot_question_log(
204
- f"\n Prossima Pagina '{page}' - Premi un tasto per continuare, Q(quit) - "
205
- )
206
- if input().lower() == "q":
207
- break
208
+ if inkey:
209
+ custom_console.bot_question_log(
210
+ f"\n Prossima Pagina '{page}' - Premi un tasto per continuare, Q(quit) - "
211
+ )
212
+ if input().lower() == "q":
213
+ break
214
+ else:
215
+ # otherwise wait for 2 seconds ( 30 request/ 60sec max) dirty
216
+ time.sleep(2)
208
217
  print()
209
218
  custom_console.rule(f"\n[bold blue]'Page -> {page}'", style="#ea00d9")
210
219
  tracker_data = tracker.next(url=tracker_data["links"]["next"])
@@ -214,11 +223,11 @@ class View(Torrent):
214
223
  else self.print_info(tracker_data)
215
224
  )
216
225
 
217
- def view_search(self, keyword: str, info=False):
226
+ def view_search(self, keyword: str, info=False, inkey=True):
218
227
  tracker_data = self.search(keyword=keyword)
219
228
  custom_console.log(f"Searching.. '{keyword}'")
220
229
  (
221
- self.page_view(tracker_data=tracker_data, tracker=self.tracker)
230
+ self.page_view(tracker_data=tracker_data, tracker=self.tracker,inkey=inkey)
222
231
  if not info
223
232
  else self.page_view(
224
233
  tracker_data=tracker_data, tracker=self.tracker, info=True
@@ -69,6 +69,31 @@ class CustomConsole(Console):
69
69
 
70
70
  self.print(Align.center(table))
71
71
 
72
+ def bot_process_table_pw(self, content: list):
73
+
74
+ table = Table(
75
+ title="Here is your files list" if content else "There are no files here",
76
+ border_style="bold blue",
77
+ header_style="red blue",
78
+ )
79
+
80
+ table.add_column("Category", style="dim")
81
+ table.add_column("Indexer", justify="left", style="bold green")
82
+ table.add_column("Title", justify="left", style="bold green")
83
+ table.add_column("Size", justify="left", style="bold green")
84
+ table.add_column("Seeders", justify="left", style="bold green")
85
+
86
+ for item in content:
87
+ table.add_row(
88
+ item.categories[0]['name'],
89
+ item.indexer,
90
+ item.title,
91
+ str(item.size),
92
+ str(item.seeders),
93
+ )
94
+
95
+ self.print(Align.center(table))
96
+
72
97
  def bot_tmdb_table_log(self, result, title: str, media_info_language: str):
73
98
 
74
99
  self.print("\n")
@@ -1,46 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import argparse
4
- import os
5
-
6
- from common.external_services.Pw.pw_service import PwService
7
- from common.utility import ManageTitles
8
- from common import config_settings
9
-
10
- from qbittorrent import Client
11
- from view import custom_console
12
-
13
- class PwManager:
14
-
15
- def __init__(self,cli: argparse.Namespace):
16
- # Keyword
17
- self.search = cli.pw
18
-
19
- # filename for the new download
20
- self.filename = ManageTitles.normalize_filename(self.search)
21
-
22
-
23
- def process(self):
24
-
25
- # a new qbittorent instance
26
- qb = Client(f"http://{config_settings.tracker_config.QBIT_HOST}:{config_settings.tracker_config.QBIT_PORT}/")
27
- # a new pw instance
28
- pw_service = PwService()
29
- # Query the indexers
30
- search = pw_service.search(query=self.search)
31
-
32
- if search:
33
- for index, s in enumerate(search):
34
- if s.seeders > 0:
35
- torrent_file = search[index]
36
- custom_console.log(torrent_file.downloadUrl)
37
- pw_service.get_torrent_from_pw(torrent_url=torrent_file.downloadUrl,download_filename=self.filename)
38
-
39
- qb.login(username=config_settings.tracker_config.QBIT_USER,
40
- password=config_settings.tracker_config.QBIT_PASS)
41
-
42
- qb.download_from_file(
43
- file_buffer=open(os.path.join(config_settings.options.PW_TORRENT_ARCHIVE_PATH,
44
- f"{self.filename}.torrent"), "rb"),
45
- savepath=config_settings.options.PW_DOWNLOAD_PATH,
46
- )
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