Unit3Dup 0.8.7__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.
Potentially problematic release.
This version of Unit3Dup might be problematic. Click here for more details.
- {unit3dup-0.8.7 → unit3dup-0.8.9}/PKG-INFO +6 -17
- {unit3dup-0.8.7 → unit3dup-0.8.9}/README.rst +5 -16
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/PKG-INFO +6 -17
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/SOURCES.txt +3 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/top_level.txt +1 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/command.py +1 -0
- unit3dup-0.8.9/common/database.py +94 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/pw_api.py +6 -9
- unit3dup-0.8.9/common/external_services/Pw/pw_manager.py +63 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/pw_service.py +7 -2
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/imageHost.py +23 -3
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/settings.py +73 -11
- {unit3dup-0.8.7 → unit3dup-0.8.9}/pyproject.toml +1 -1
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/__main__.py +10 -2
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/torrent.py +24 -15
- unit3dup-0.8.9/unit3dup/web/__init__.py +0 -0
- unit3dup-0.8.9/unit3dup/web/main.py +46 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/view/custom_console.py +25 -0
- unit3dup-0.8.7/common/external_services/Pw/pw_manager.py +0 -46
- {unit3dup-0.8.7 → unit3dup-0.8.9}/LICENSE +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/dependency_links.txt +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/entry_points.txt +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/Unit3Dup.egg-info/requires.txt +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/bdinfo_string.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/bittorrent.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/constants.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/models/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/models/indexers.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/models/search.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/Pw/core/models/torrent_client_config.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/client.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/ftpx_service.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/ftpx_session.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/menu.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/models/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/ftpx/core/models/list.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/client.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/api.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/models/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/models/search.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/platformid.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/igdb/core/tags.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/imdb.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/mediaresult.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/sessions/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/sessions/agents.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/sessions/exceptions.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/sessions/session.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/api.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/keywords.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/theMovieDB/core/videos.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/trailers/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/trailers/api.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/external_services/trailers/response.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/extractor.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/frames.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/mediainfo.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/mediainfo_string.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/title.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/torrent_clients.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/trackers/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/trackers/data.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/trackers/itt.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/trackers/sis.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/trackers/trackers.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/common/utility.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/requirements.txt +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/setup.cfg +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/automode.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/bot.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/duplicate.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/exceptions.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/ContentManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/DocuManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/GameManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/MediaInfoManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/SeedManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/TorrentManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/VideoManager.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/__init__.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/media_manager/common.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/pvtDocu.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/pvtTorrent.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/pvtTracker.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/pvtVideo.py +0 -0
- {unit3dup-0.8.7 → unit3dup-0.8.9}/unit3dup/upload.py +0 -0
- {unit3dup-0.8.7 → 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.
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
pip install unit3dup
|
|
70
|
+
Install and Upgrade
|
|
71
|
+
===================
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
-------
|
|
78
|
-
pip install --upgrade unit3dup
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
pip install unit3dup
|
|
39
|
+
Install and Upgrade
|
|
40
|
+
===================
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
-------
|
|
47
|
-
pip install --upgrade unit3dup
|
|
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.
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
pip install unit3dup
|
|
70
|
+
Install and Upgrade
|
|
71
|
+
===================
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
-------
|
|
78
|
-
pip install --upgrade unit3dup
|
|
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
|
|
@@ -102,5 +103,7 @@ unit3dup/media_manager/TorrentManager.py
|
|
|
102
103
|
unit3dup/media_manager/VideoManager.py
|
|
103
104
|
unit3dup/media_manager/__init__.py
|
|
104
105
|
unit3dup/media_manager/common.py
|
|
106
|
+
unit3dup/web/__init__.py
|
|
107
|
+
unit3dup/web/main.py
|
|
105
108
|
view/__init__.py
|
|
106
109
|
view/custom_console.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) -> [
|
|
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
|
-
|
|
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
|
|
|
@@ -5,7 +5,6 @@ import json
|
|
|
5
5
|
import time
|
|
6
6
|
import requests
|
|
7
7
|
|
|
8
|
-
from PIL import Image
|
|
9
8
|
from abc import ABC, abstractmethod
|
|
10
9
|
from common import config_settings
|
|
11
10
|
from view import custom_console
|
|
@@ -16,6 +15,7 @@ class ImageUploader(ABC):
|
|
|
16
15
|
self.image = base64.b64encode(image)
|
|
17
16
|
self.key = key
|
|
18
17
|
self.image_name = image_name
|
|
18
|
+
self.timeout = 30
|
|
19
19
|
|
|
20
20
|
@abstractmethod
|
|
21
21
|
def get_endpoint(self):
|
|
@@ -40,7 +40,7 @@ class ImageUploader(ABC):
|
|
|
40
40
|
try:
|
|
41
41
|
upload_n += 1
|
|
42
42
|
response = requests.post(
|
|
43
|
-
self.get_endpoint(), data = data, files = files, timeout =
|
|
43
|
+
self.get_endpoint(), data = data, files = files, timeout = self.timeout
|
|
44
44
|
)
|
|
45
45
|
response.raise_for_status()
|
|
46
46
|
return response.json()
|
|
@@ -61,7 +61,7 @@ class ImageUploader(ABC):
|
|
|
61
61
|
except requests.exceptions.Timeout:
|
|
62
62
|
custom_console.bot_log(
|
|
63
63
|
f"[{self.__class__.__name__}] We did not receive a response from the server"
|
|
64
|
-
f" within the
|
|
64
|
+
f" within the {self.timeout} second limit"
|
|
65
65
|
)
|
|
66
66
|
break
|
|
67
67
|
|
|
@@ -163,6 +163,20 @@ class ImgFi(ImageUploader):
|
|
|
163
163
|
def get_field_name(self) -> str:
|
|
164
164
|
return 'source'
|
|
165
165
|
|
|
166
|
+
class PassIMA(ImageUploader):
|
|
167
|
+
|
|
168
|
+
priority= config_settings.user_preferences.PASSIMA_PRIORITY
|
|
169
|
+
def get_endpoint(self) -> str:
|
|
170
|
+
return "https://passtheima.ge/api/1/upload"
|
|
171
|
+
|
|
172
|
+
def get_data(self) -> dict:
|
|
173
|
+
return {
|
|
174
|
+
"key": self.key,
|
|
175
|
+
"title": self.image_name,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
def get_field_name(self) -> str:
|
|
179
|
+
return 'source'
|
|
166
180
|
|
|
167
181
|
|
|
168
182
|
class ImageUploaderFallback:
|
|
@@ -213,6 +227,10 @@ class ImageUploaderFallback:
|
|
|
213
227
|
|
|
214
228
|
if uploader_host == "ImgFi":
|
|
215
229
|
return response['image']['url']
|
|
230
|
+
|
|
231
|
+
if uploader_host == "PassIMA":
|
|
232
|
+
return response['image']['url']
|
|
233
|
+
|
|
216
234
|
return None
|
|
217
235
|
|
|
218
236
|
class Build:
|
|
@@ -232,6 +250,7 @@ class Build:
|
|
|
232
250
|
self.LENSDUMP_KEY= config_settings.tracker_config.LENSDUMP_KEY
|
|
233
251
|
self.PTSCREENS_KEY= config_settings.tracker_config.PTSCREENS_KEY
|
|
234
252
|
self.IMGFI_KEY = config_settings.tracker_config.IMGFI_KEY
|
|
253
|
+
self.PASSIMA_KEY = config_settings.tracker_config.PASSIMA_KEY
|
|
235
254
|
self.extracted_frames = extracted_frames
|
|
236
255
|
|
|
237
256
|
|
|
@@ -251,6 +270,7 @@ class Build:
|
|
|
251
270
|
PtScreens(img_bytes, self.PTSCREENS_KEY,image_name=image_name),
|
|
252
271
|
LensDump(img_bytes, self.LENSDUMP_KEY,image_name=image_name),
|
|
253
272
|
ImgFi(img_bytes, self.IMGFI_KEY,image_name=image_name),
|
|
273
|
+
PassIMA(img_bytes, self.PASSIMA_KEY, image_name=image_name),
|
|
254
274
|
]
|
|
255
275
|
|
|
256
276
|
# Sorting list based on priority
|
|
@@ -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.
|
|
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,12 +40,20 @@ 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
|
-
"
|
|
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])
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
|
|
50
|
+
class Ccolors:
|
|
51
|
+
OKCYAN = '\033[96m'
|
|
52
|
+
OKGREEN = '\033[92m'
|
|
53
|
+
WARNING = '\033[93m'
|
|
54
|
+
FAIL = '\033[91m'
|
|
55
|
+
ENDC = '\033[0m'
|
|
56
|
+
|
|
49
57
|
class TrackerConfig(BaseModel):
|
|
50
58
|
ITT_URL: str
|
|
51
59
|
ITT_APIKEY: str | None = None
|
|
@@ -60,6 +68,7 @@ class TrackerConfig(BaseModel):
|
|
|
60
68
|
LENSDUMP_KEY: str | None = None
|
|
61
69
|
PTSCREENS_KEY: str | None = None
|
|
62
70
|
IMGFI_KEY: str | None = None
|
|
71
|
+
PASSIMA_KEY: str | None = None
|
|
63
72
|
YOUTUBE_KEY: str | None = None
|
|
64
73
|
IGDB_CLIENT_ID: str | None = None
|
|
65
74
|
IGDB_ID_SECRET: str | None = None
|
|
@@ -92,6 +101,7 @@ class UserPreferences(BaseModel):
|
|
|
92
101
|
FREE_IMAGE_PRIORITY: int = 2
|
|
93
102
|
IMGBB_PRIORITY: int = 3
|
|
94
103
|
IMGFI_PRIORITY: int = 4
|
|
104
|
+
PASSIMA_PRIORITY: int = 5
|
|
95
105
|
NUMBER_OF_SCREENSHOTS: int = 4
|
|
96
106
|
YOUTUBE_FAV_CHANNEL_ID: str | None = None
|
|
97
107
|
YOUTUBE_CHANNEL_ENABLE: bool = False
|
|
@@ -120,7 +130,7 @@ class Options(BaseModel):
|
|
|
120
130
|
PW_API_KEY: str | None = None
|
|
121
131
|
PW_URL: str = "http://localhost:9696/api/v1"
|
|
122
132
|
PW_TORRENT_ARCHIVE_PATH: str | None = None
|
|
123
|
-
|
|
133
|
+
PW_DOWNLOAD_PATH: str | None = None
|
|
124
134
|
FTPX_USER: str = "user"
|
|
125
135
|
FTPX_PASS: str = "pass"
|
|
126
136
|
FTPX_IP: str = "127.0.0.1"
|
|
@@ -415,11 +425,11 @@ class Config(BaseModel):
|
|
|
415
425
|
'CACHE_SCR','CACHE_DBONLINE', 'PERSONAL_RELEASE']:
|
|
416
426
|
section[field] = Validate.boolean(value=section[field], field_name=field)
|
|
417
427
|
|
|
418
|
-
if field in ['TORRENT_COMMENT','
|
|
428
|
+
if field in ['TORRENT_COMMENT','WATCHER_PATH','DEFAULT_TRACKER']:
|
|
419
429
|
section[field] = Validate.string(value=section[field], field_name=field)
|
|
420
430
|
|
|
421
431
|
if field in ['NUMBER_OF_SCREENSHOTS','COMPRESS_SCSHOT','IMGBB_PRIORITY','FREE_IMAGE_PRIORITY',
|
|
422
|
-
'LENSDUMP_PRIORITY','WATCHER_INTERVAL','SIZE_TH', 'FAST_LOAD']:
|
|
432
|
+
'LENSDUMP_PRIORITY','PASSIMA_PRIORITY','WATCHER_INTERVAL','SIZE_TH', 'FAST_LOAD']:
|
|
423
433
|
section[field] = Validate.integer(value=section[field], field_name=field)
|
|
424
434
|
|
|
425
435
|
if field == 'PREFERRED_LANG':
|
|
@@ -441,11 +451,29 @@ class Config(BaseModel):
|
|
|
441
451
|
section[field] =Validate.unit3dup_path(path=section[field],field_name=field,
|
|
442
452
|
default_path=get_default_path(field=field))
|
|
443
453
|
|
|
454
|
+
|
|
444
455
|
return v
|
|
445
456
|
|
|
446
457
|
@model_validator(mode='before')
|
|
447
458
|
def set_default_options(cls, v):
|
|
448
|
-
|
|
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
|
|
449
477
|
|
|
450
478
|
@model_validator(mode='before')
|
|
451
479
|
def set_default_console_options(cls, v):
|
|
@@ -502,6 +530,7 @@ class Load:
|
|
|
502
530
|
"LENSDUMP_KEY": "no_key",
|
|
503
531
|
"PTSCREENS_KEY": "no_key",
|
|
504
532
|
"IMGFI_KEY": "no_key",
|
|
533
|
+
"PASSIMA_KEY": "no_key",
|
|
505
534
|
"YOUTUBE_KEY": "no_key",
|
|
506
535
|
"IGDB_CLIENT_ID": "no_key",
|
|
507
536
|
"IGDB_ID_SECRET": "no_key",
|
|
@@ -532,6 +561,7 @@ class Load:
|
|
|
532
561
|
"FREE_IMAGE_PRIORITY": 2,
|
|
533
562
|
"IMGBB_PRIORITY": 3,
|
|
534
563
|
"IMGFI_PRIORITY": 4,
|
|
564
|
+
"PASSIMA_PRIORITY": 5,
|
|
535
565
|
"NUMBER_OF_SCREENSHOTS": 4,
|
|
536
566
|
"YOUTUBE_FAV_CHANNEL_ID": "UCGCbxpnt25hWPFLSbvwfg_w",
|
|
537
567
|
"YOUTUBE_CHANNEL_ENABLE": "False",
|
|
@@ -558,7 +588,7 @@ class Load:
|
|
|
558
588
|
"PW_API_KEY": "no_key",
|
|
559
589
|
"PW_URL": "http://localhost:9696/api/v1",
|
|
560
590
|
"PW_TORRENT_ARCHIVE_PATH": ".",
|
|
561
|
-
"
|
|
591
|
+
"PW_DOWNLOAD_PATH": ".",
|
|
562
592
|
"FTPX_USER": "user",
|
|
563
593
|
"FTPX_PASS": "pass",
|
|
564
594
|
"FTPX_IP": "127.0.0.1",
|
|
@@ -741,10 +771,11 @@ class JsonConfig:
|
|
|
741
771
|
return json.loads(json_data)
|
|
742
772
|
|
|
743
773
|
except json.JSONDecodeError as e:
|
|
744
|
-
print(f"
|
|
745
|
-
|
|
746
|
-
print(
|
|
747
|
-
|
|
774
|
+
print(f"* Please fix the error{Ccolors.WARNING} near Line {e.lineno}{Ccolors.ENDC}"
|
|
775
|
+
f" and {Ccolors.WARNING}Column {e.colno}{Ccolors.ENDC} in the config file: *\n")
|
|
776
|
+
print(f"{e.msg}\n")
|
|
777
|
+
# Seek And...
|
|
778
|
+
self.aim(line=e.lineno,col=e.colno)
|
|
748
779
|
exit(1)
|
|
749
780
|
except FileNotFoundError:
|
|
750
781
|
print(f"Configuration '{self.default_json_path}' not found")
|
|
@@ -797,3 +828,34 @@ class JsonConfig:
|
|
|
797
828
|
|
|
798
829
|
print(message)
|
|
799
830
|
|
|
831
|
+
def aim(self, line: int, col: int):
|
|
832
|
+
"""
|
|
833
|
+
Try to identify the exact location of json error
|
|
834
|
+
Args:
|
|
835
|
+
line: Error line from the try block
|
|
836
|
+
col: Error line from the try block
|
|
837
|
+
Returns:
|
|
838
|
+
None
|
|
839
|
+
"""
|
|
840
|
+
|
|
841
|
+
# Open the configuration file
|
|
842
|
+
with open(self.default_json_path, 'r') as file:
|
|
843
|
+
lines = file.readlines()
|
|
844
|
+
|
|
845
|
+
# Test the line value
|
|
846
|
+
if line <= len(lines):
|
|
847
|
+
# Create a "context" around the error....
|
|
848
|
+
line_context1 = lines[line -2].rstrip('\n')
|
|
849
|
+
line_context2 = lines[line + 1].rstrip('\n')
|
|
850
|
+
|
|
851
|
+
# Try to identify the position
|
|
852
|
+
line_text = lines[line - 1].rstrip('\n')
|
|
853
|
+
print(f"{line_context1}")
|
|
854
|
+
print(f"{Ccolors.WARNING}>>> {line_text}{Ccolors.ENDC}")
|
|
855
|
+
|
|
856
|
+
# Put the cursor under the error
|
|
857
|
+
cursor = ' ' * (col-1) + '^'
|
|
858
|
+
print(f"{Ccolors.WARNING} {cursor}{Ccolors.ENDC}")
|
|
859
|
+
print(f"{line_context2}")
|
|
860
|
+
else:
|
|
861
|
+
print("Line number is out of range !")
|
|
@@ -127,8 +127,10 @@ def main():
|
|
|
127
127
|
|
|
128
128
|
# Pw
|
|
129
129
|
if cli.args.pw:
|
|
130
|
-
|
|
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
|