Unit3Dup 0.8.8__tar.gz → 0.8.10__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.10}/PKG-INFO +12 -34
  2. {unit3dup-0.8.8 → unit3dup-0.8.10}/README.rst +11 -33
  3. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/PKG-INFO +12 -34
  4. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/SOURCES.txt +1 -0
  5. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/command.py +1 -0
  6. unit3dup-0.8.10/common/database.py +94 -0
  7. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/pw_api.py +6 -9
  8. unit3dup-0.8.10/common/external_services/Pw/pw_manager.py +63 -0
  9. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/pw_service.py +7 -2
  10. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/imageHost.py +3 -2
  11. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/settings.py +24 -6
  12. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/utility.py +3 -2
  13. {unit3dup-0.8.8 → unit3dup-0.8.10}/pyproject.toml +1 -1
  14. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/__main__.py +10 -2
  15. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/ContentManager.py +1 -1
  16. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/torrent.py +24 -15
  17. {unit3dup-0.8.8 → unit3dup-0.8.10}/view/custom_console.py +25 -0
  18. unit3dup-0.8.8/common/external_services/Pw/pw_manager.py +0 -46
  19. {unit3dup-0.8.8 → unit3dup-0.8.10}/LICENSE +0 -0
  20. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/dependency_links.txt +0 -0
  21. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/entry_points.txt +0 -0
  22. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/requires.txt +0 -0
  23. {unit3dup-0.8.8 → unit3dup-0.8.10}/Unit3Dup.egg-info/top_level.txt +0 -0
  24. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/__init__.py +0 -0
  25. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/bdinfo_string.py +0 -0
  26. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/bittorrent.py +0 -0
  27. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/constants.py +0 -0
  28. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/__init__.py +0 -0
  29. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/__init__.py +0 -0
  30. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/models/__init__.py +0 -0
  31. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/models/indexers.py +0 -0
  32. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/models/search.py +0 -0
  33. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/Pw/core/models/torrent_client_config.py +0 -0
  34. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/__init__.py +0 -0
  35. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/__init__.py +0 -0
  36. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/client.py +0 -0
  37. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/__init__.py +0 -0
  38. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/ftpx_service.py +0 -0
  39. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/ftpx_session.py +0 -0
  40. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/menu.py +0 -0
  41. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/models/__init__.py +0 -0
  42. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/ftpx/core/models/list.py +0 -0
  43. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/__init__.py +0 -0
  44. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/client.py +0 -0
  45. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/__init__.py +0 -0
  46. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/api.py +0 -0
  47. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/models/__init__.py +0 -0
  48. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/models/search.py +0 -0
  49. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/platformid.py +0 -0
  50. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/igdb/core/tags.py +0 -0
  51. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/imdb.py +0 -0
  52. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/mediaresult.py +0 -0
  53. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/sessions/__init__.py +0 -0
  54. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/sessions/agents.py +0 -0
  55. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/sessions/exceptions.py +0 -0
  56. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/sessions/session.py +0 -0
  57. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/__init__.py +0 -0
  58. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/__init__.py +0 -0
  59. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/api.py +0 -0
  60. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/keywords.py +0 -0
  61. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
  62. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
  63. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
  64. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
  65. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
  66. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
  67. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
  68. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
  69. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
  70. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
  71. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
  72. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
  73. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
  74. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/theMovieDB/core/videos.py +0 -0
  75. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/trailers/__init__.py +0 -0
  76. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/trailers/api.py +0 -0
  77. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/external_services/trailers/response.py +0 -0
  78. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/extractor.py +0 -0
  79. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/frames.py +0 -0
  80. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/mediainfo.py +0 -0
  81. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/mediainfo_string.py +0 -0
  82. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/title.py +0 -0
  83. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/torrent_clients.py +0 -0
  84. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/trackers/__init__.py +0 -0
  85. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/trackers/data.py +0 -0
  86. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/trackers/itt.py +0 -0
  87. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/trackers/sis.py +0 -0
  88. {unit3dup-0.8.8 → unit3dup-0.8.10}/common/trackers/trackers.py +0 -0
  89. {unit3dup-0.8.8 → unit3dup-0.8.10}/requirements.txt +0 -0
  90. {unit3dup-0.8.8 → unit3dup-0.8.10}/setup.cfg +0 -0
  91. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/__init__.py +0 -0
  92. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/automode.py +0 -0
  93. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/bot.py +0 -0
  94. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/duplicate.py +0 -0
  95. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/exceptions.py +0 -0
  96. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media.py +0 -0
  97. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/DocuManager.py +0 -0
  98. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/GameManager.py +0 -0
  99. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/MediaInfoManager.py +0 -0
  100. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/SeedManager.py +0 -0
  101. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/TorrentManager.py +0 -0
  102. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/VideoManager.py +0 -0
  103. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/__init__.py +0 -0
  104. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/media_manager/common.py +0 -0
  105. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/pvtDocu.py +0 -0
  106. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/pvtTorrent.py +0 -0
  107. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/pvtTracker.py +0 -0
  108. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/pvtVideo.py +0 -0
  109. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/upload.py +0 -0
  110. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/web/__init__.py +0 -0
  111. {unit3dup-0.8.8 → unit3dup-0.8.10}/unit3dup/web/main.py +0 -0
  112. {unit3dup-0.8.8 → unit3dup-0.8.10}/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.10
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -66,25 +66,11 @@ 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
75
-
76
- Upgrade
77
- -------
78
- pip install unit3dup --upgrade
79
-
80
- Ubuntu/Debian Dependencies
81
- --------------------------
82
- sudo apt install ffmpeg
83
-
84
- Only for pdf
85
- ------------
86
- sudo apt install poppler-utils
70
+ Install and Upgrade
71
+ ===================
87
72
 
73
+ - pip install unit3dup --upgrade
88
74
 
89
75
  Windows Dependencies
90
76
  --------------------
@@ -92,29 +78,21 @@ Windows Dependencies
92
78
  PATH environment user variable
93
79
 
94
80
 
81
+ Only for pdf
82
+ ~~~~~~~~~~~~
95
83
  1. Download and unzip poppler for Windows from https://github.com/oschwartz10612/poppler-windows/releases
96
84
  2. Put the folder 'bin' in the system path (e.g. ``C:\poppler-24.08.0\Library\bin``)
97
85
  3. *Close and reopen a new console window*
98
86
  4. Test it: Run ``pdftocairo`` in the terminal
99
87
 
100
88
 
101
- Alternative method
102
- ------------------
103
-
104
- 1. Download the last release (https://github.com/31December99/Unit3Dup/releases)
105
-
106
- 2. unzip it
107
-
108
- 3. pip install .
109
-
110
- 4. unit3dup
111
-
112
-
113
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
114
- :alt: Bot Update
115
-
116
- 1. pip install unit3dup --upgrade
89
+ Ubuntu/Debian Dependencies
90
+ --------------------------
91
+ - sudo apt install ffmpeg
117
92
 
93
+ Only for pdf
94
+ ~~~~~~~~~~~~
95
+ - sudo apt install poppler-utils
118
96
 
119
97
 
120
98
  RUN
@@ -35,25 +35,11 @@ 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
44
-
45
- Upgrade
46
- -------
47
- pip install unit3dup --upgrade
48
-
49
- Ubuntu/Debian Dependencies
50
- --------------------------
51
- sudo apt install ffmpeg
52
-
53
- Only for pdf
54
- ------------
55
- sudo apt install poppler-utils
39
+ Install and Upgrade
40
+ ===================
56
41
 
42
+ - pip install unit3dup --upgrade
57
43
 
58
44
  Windows Dependencies
59
45
  --------------------
@@ -61,29 +47,21 @@ Windows Dependencies
61
47
  PATH environment user variable
62
48
 
63
49
 
50
+ Only for pdf
51
+ ~~~~~~~~~~~~
64
52
  1. Download and unzip poppler for Windows from https://github.com/oschwartz10612/poppler-windows/releases
65
53
  2. Put the folder 'bin' in the system path (e.g. ``C:\poppler-24.08.0\Library\bin``)
66
54
  3. *Close and reopen a new console window*
67
55
  4. Test it: Run ``pdftocairo`` in the terminal
68
56
 
69
57
 
70
- Alternative method
71
- ------------------
72
-
73
- 1. Download the last release (https://github.com/31December99/Unit3Dup/releases)
74
-
75
- 2. unzip it
76
-
77
- 3. pip install .
78
-
79
- 4. unit3dup
80
-
81
-
82
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
83
- :alt: Bot Update
84
-
85
- 1. pip install unit3dup --upgrade
58
+ Ubuntu/Debian Dependencies
59
+ --------------------------
60
+ - sudo apt install ffmpeg
86
61
 
62
+ Only for pdf
63
+ ~~~~~~~~~~~~
64
+ - sudo apt install poppler-utils
87
65
 
88
66
 
89
67
  RUN
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Unit3Dup
3
- Version: 0.8.8
3
+ Version: 0.8.10
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -66,25 +66,11 @@ 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
75
-
76
- Upgrade
77
- -------
78
- pip install unit3dup --upgrade
79
-
80
- Ubuntu/Debian Dependencies
81
- --------------------------
82
- sudo apt install ffmpeg
83
-
84
- Only for pdf
85
- ------------
86
- sudo apt install poppler-utils
70
+ Install and Upgrade
71
+ ===================
87
72
 
73
+ - pip install unit3dup --upgrade
88
74
 
89
75
  Windows Dependencies
90
76
  --------------------
@@ -92,29 +78,21 @@ Windows Dependencies
92
78
  PATH environment user variable
93
79
 
94
80
 
81
+ Only for pdf
82
+ ~~~~~~~~~~~~
95
83
  1. Download and unzip poppler for Windows from https://github.com/oschwartz10612/poppler-windows/releases
96
84
  2. Put the folder 'bin' in the system path (e.g. ``C:\poppler-24.08.0\Library\bin``)
97
85
  3. *Close and reopen a new console window*
98
86
  4. Test it: Run ``pdftocairo`` in the terminal
99
87
 
100
88
 
101
- Alternative method
102
- ------------------
103
-
104
- 1. Download the last release (https://github.com/31December99/Unit3Dup/releases)
105
-
106
- 2. unzip it
107
-
108
- 3. pip install .
109
-
110
- 4. unit3dup
111
-
112
-
113
- .. image:: https://img.shields.io/badge/Bot_UPDATE-gr
114
- :alt: Bot Update
115
-
116
- 1. pip install unit3dup --upgrade
89
+ Ubuntu/Debian Dependencies
90
+ --------------------------
91
+ - sudo apt install ffmpeg
117
92
 
93
+ Only for pdf
94
+ ~~~~~~~~~~~~
95
+ - sudo apt install poppler-utils
118
96
 
119
97
 
120
98
  RUN
@@ -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.10"
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",
@@ -162,8 +162,8 @@ class ManageTitles:
162
162
  # Remove v version
163
163
  filename_sanitized = re.sub(r"v\d+(?:[ .]\d+)*", "", filename_sanitized).strip()
164
164
 
165
- # Remove dots, hyphens and extra spaces
166
- filename_sanitized = re.sub(r"[.\-_]", " ", filename_sanitized)
165
+ # Remove dots, extra spaces
166
+ filename_sanitized = re.sub(r"[._]", " ", filename_sanitized)
167
167
 
168
168
  # remove spaces, tab, newline
169
169
  filename_sanitized = re.sub(r"\s+", " ", filename_sanitized)
@@ -183,6 +183,7 @@ class ManageTitles:
183
183
  replacements = [
184
184
  (r'\b7 \b1\b', '7.1'),
185
185
  (r'\b5 \b1\b', '5.1'),
186
+ (r'\bDDP5 \b1\b', 'DDP5.1'),
186
187
  (r'\b2 \b0\b', '2.0'),
187
188
  (r'\bWEB \bDL\b', 'WEB-DL'),
188
189
  (r'\bWEB \bDLMUX\b', 'WEB-DLMUX'),
@@ -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.10"
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
@@ -70,7 +70,7 @@ class ContentManager:
70
70
  # and not part of the title
71
71
  if media.category=='tv':
72
72
  # Search for the first result (Sx) in self.path
73
- torrent_pack = bool(re.search(r"S\d+(?!.*E\d+)", self.path))
73
+ torrent_pack = bool(re.search(r"(S\d+(?!.*E\d+))|(S\d+E\d+-E?\d+)", self.path))
74
74
  else:
75
75
  torrent_pack = False
76
76
 
@@ -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