warp-beacon 2.3.39__py3-none-any.whl → 2.3.41__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- warp_beacon/__version__.py +1 -1
- warp_beacon/scraper/exceptions.py +2 -0
- warp_beacon/scraper/youtube/abstract.py +75 -17
- warp_beacon/scraper/youtube/youtube.py +29 -8
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/METADATA +2 -1
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/RECORD +10 -10
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/WHEEL +1 -1
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/entry_points.txt +0 -0
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/licenses/LICENSE +0 -0
- {warp_beacon-2.3.39.dist-info → warp_beacon-2.3.41.dist-info}/top_level.txt +0 -0
warp_beacon/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "2.3.
|
1
|
+
__version__ = "2.3.41"
|
2
2
|
|
@@ -7,26 +7,29 @@ import socket
|
|
7
7
|
import ssl
|
8
8
|
#from abc import abstractmethod
|
9
9
|
from typing import Callable, Union, Optional
|
10
|
+
import logging
|
10
11
|
import json
|
11
12
|
import urllib
|
12
13
|
import http.client
|
14
|
+
import pytubefix.exceptions
|
13
15
|
import requests
|
14
16
|
from PIL import Image
|
15
17
|
import numpy as np
|
18
|
+
from urllib.parse import urlparse, parse_qs
|
16
19
|
|
17
|
-
|
18
|
-
from warp_beacon.scraper.abstract import ScraperAbstract
|
19
|
-
#from warp_beacon.mediainfo.abstract import MediaInfoAbstract
|
20
|
-
from warp_beacon.scraper.exceptions import TimeOut, Unavailable, extract_exception_message
|
21
|
-
|
20
|
+
import pytubefix
|
22
21
|
from pytubefix import YouTube
|
23
22
|
from pytubefix.innertube import _default_clients
|
24
23
|
from pytubefix.streams import Stream
|
25
24
|
from pytubefix.innertube import InnerTube, _client_id, _client_secret
|
26
|
-
from pytubefix.exceptions import VideoUnavailable, VideoPrivate, MaxRetriesExceeded
|
25
|
+
#from pytubefix.exceptions import VideoUnavailable, VideoPrivate, MaxRetriesExceeded
|
27
26
|
from pytubefix import request
|
27
|
+
import yt_dlp
|
28
28
|
|
29
|
-
import
|
29
|
+
from warp_beacon.jobs.download_job import DownloadJob
|
30
|
+
from warp_beacon.scraper.abstract import ScraperAbstract
|
31
|
+
#from warp_beacon.mediainfo.abstract import MediaInfoAbstract
|
32
|
+
from warp_beacon.scraper.exceptions import TimeOut, Unavailable, extract_exception_message
|
30
33
|
|
31
34
|
def patched_fetch_bearer_token(self) -> None:
|
32
35
|
"""Fetch an OAuth token."""
|
@@ -101,13 +104,24 @@ class YoutubeAbstract(ScraperAbstract):
|
|
101
104
|
os.rename(filename, new_filepath)
|
102
105
|
|
103
106
|
return new_filepath
|
107
|
+
|
108
|
+
def get_video_id(self, url: str) -> Optional[str]:
|
109
|
+
parsed_url = urlparse(url)
|
110
|
+
query = parse_qs(parsed_url.query)
|
111
|
+
return query.get('v', [None])[0]
|
104
112
|
|
105
113
|
def remove_tmp_files(self) -> None:
|
106
114
|
for i in os.listdir(self.DOWNLOAD_DIR):
|
107
115
|
if "yt_download_" in i:
|
108
116
|
os.unlink("%s/%s" % (self.DOWNLOAD_DIR, i))
|
109
117
|
|
110
|
-
def calculate_size_with_padding(self,
|
118
|
+
def calculate_size_with_padding(self,
|
119
|
+
image: Image,
|
120
|
+
aspect_ratio_width: int,
|
121
|
+
aspect_ratio_height: int,
|
122
|
+
target_size: tuple=(320, 320),
|
123
|
+
background_color: tuple=(0, 0, 0)
|
124
|
+
) -> Image:
|
111
125
|
aspect_ratio = aspect_ratio_width / aspect_ratio_height
|
112
126
|
target_width, target_height = target_size
|
113
127
|
|
@@ -194,7 +208,7 @@ class YoutubeAbstract(ScraperAbstract):
|
|
194
208
|
kwargs["timeout"] = timeout
|
195
209
|
ret_val = func(*args, **kwargs)
|
196
210
|
break
|
197
|
-
except MaxRetriesExceeded:
|
211
|
+
except pytubefix.exceptions.MaxRetriesExceeded:
|
198
212
|
# do noting, not interested
|
199
213
|
pass
|
200
214
|
#except http.client.IncompleteRead as e:
|
@@ -216,7 +230,21 @@ class YoutubeAbstract(ScraperAbstract):
|
|
216
230
|
retries += 1
|
217
231
|
timeout += timeout_increment
|
218
232
|
time.sleep(pause_secs)
|
219
|
-
except (VideoUnavailable, VideoPrivate) as e:
|
233
|
+
except (pytubefix.exceptions.VideoUnavailable, pytubefix.exceptions.VideoPrivate) as e:
|
234
|
+
raise Unavailable(extract_exception_message(e))
|
235
|
+
except yt_dlp.utils.DownloadError as e:
|
236
|
+
raise Unavailable(extract_exception_message(e))
|
237
|
+
except yt_dlp.utils.GeoRestrictedError:
|
238
|
+
raise Unavailable(extract_exception_message(e))
|
239
|
+
except yt_dlp.utils.PostProcessingError as e:
|
240
|
+
raise Unavailable(extract_exception_message(e))
|
241
|
+
except yt_dlp.utils.ExtractorError as e:
|
242
|
+
raise Unavailable(extract_exception_message(e))
|
243
|
+
except yt_dlp.utils.MaxDownloadsReached as e:
|
244
|
+
raise Unavailable(extract_exception_message(e))
|
245
|
+
except yt_dlp.utils.UnavailableVideoError as e:
|
246
|
+
raise Unavailable(extract_exception_message(e))
|
247
|
+
except yt_dlp.utils.ThrottledDownload as e:
|
220
248
|
raise Unavailable(extract_exception_message(e))
|
221
249
|
|
222
250
|
return ret_val
|
@@ -241,8 +269,8 @@ class YoutubeAbstract(ScraperAbstract):
|
|
241
269
|
yt_opts["token_file"] = self.YT_SESSION_FILE % self.account_index
|
242
270
|
if self.proxy:
|
243
271
|
proxy_dsn = self.proxy.get("dsn", "")
|
272
|
+
logging.info("Using proxy DSN '%s'", proxy_dsn)
|
244
273
|
if proxy_dsn:
|
245
|
-
logging.info("Using proxy DSN '%s'", proxy_dsn)
|
246
274
|
if "https://" in proxy_dsn:
|
247
275
|
yt_opts["proxies"] = {"https": proxy_dsn}
|
248
276
|
elif "http://" in proxy_dsn:
|
@@ -251,14 +279,44 @@ class YoutubeAbstract(ScraperAbstract):
|
|
251
279
|
logging.warning("Proxy DSN malformed!")
|
252
280
|
return YouTube(**yt_opts)
|
253
281
|
|
254
|
-
def
|
282
|
+
def build_yt_dlp(self, timeout: int = 0) -> yt_dlp.YoutubeDL:
|
283
|
+
auth_data = {}
|
284
|
+
with open(self.YT_SESSION_FILE % self.account_index, 'r', encoding="utf-8") as f:
|
285
|
+
auth_data = json.loads(f.read())
|
286
|
+
time_name = str(time.time()).replace('.', '_')
|
287
|
+
ydl_opts = {
|
288
|
+
'outtmpl': f'{self.DOWNLOAD_DIR}/{time_name}.%(ext)s',
|
289
|
+
'format': 'bestvideo+bestaudio/best',
|
290
|
+
'merge_output_format': 'mp4',
|
291
|
+
'noplaylist': True,
|
292
|
+
'tv_auth': auth_data
|
293
|
+
}
|
294
|
+
|
295
|
+
if self.proxy:
|
296
|
+
proxy_dsn = self.proxy.get("dsn", "")
|
297
|
+
logging.info("Using proxy DSN '%s'", proxy_dsn)
|
298
|
+
if proxy_dsn:
|
299
|
+
ydl_opts["proxy"] = proxy_dsn
|
300
|
+
|
301
|
+
return yt_dlp.YoutubeDL(ydl_opts)
|
302
|
+
|
303
|
+
def _download(self, _: str, __: int = 60) -> list:
|
255
304
|
raise NotImplementedError("You should to implement _download method")
|
305
|
+
|
306
|
+
def _download_yt_dlp(self, _: str, __: int = 60) -> list:
|
307
|
+
raise NotImplementedError("You should to implement _download_yt_dlp method")
|
256
308
|
|
257
309
|
def download(self, job: DownloadJob) -> list:
|
310
|
+
ret = []
|
258
311
|
try:
|
259
|
-
|
260
|
-
except Unavailable:
|
261
|
-
logging.warning("
|
262
|
-
time.sleep(2)
|
312
|
+
ret = self.download_hndlr(self._download, job.url, session=True)
|
313
|
+
except (Unavailable, TimeOut):
|
314
|
+
logging.warning("Download failed, trying to download with yt_dlp")
|
263
315
|
|
264
|
-
|
316
|
+
try:
|
317
|
+
ret = self.download_hndlr(self._download_yt_dlp, job.url)
|
318
|
+
except NotImplementedError:
|
319
|
+
logging.info("yt_dlp is not supported for this submodule yet")
|
320
|
+
raise Unavailable("Video unvailable")
|
321
|
+
|
322
|
+
return ret
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
|
-
from warp_beacon.scraper.youtube.abstract import YoutubeAbstract
|
3
|
-
from warp_beacon.scraper.exceptions import YoutubeLiveError, NotFound, YotubeAgeRestrictedError
|
1
|
+
import logging
|
4
2
|
|
5
3
|
from pytubefix.exceptions import AgeRestrictedError
|
6
4
|
|
7
|
-
import
|
5
|
+
from warp_beacon.jobs.types import JobType
|
6
|
+
from warp_beacon.scraper.youtube.abstract import YoutubeAbstract
|
7
|
+
from warp_beacon.scraper.exceptions import YoutubeLiveError, NotFound, YotubeAgeRestrictedError
|
8
8
|
|
9
9
|
class YoutubeScraper(YoutubeAbstract):
|
10
10
|
YT_MAX_RETRIES_DEFAULT = 8
|
@@ -28,18 +28,18 @@ class YoutubeScraper(YoutubeAbstract):
|
|
28
28
|
|
29
29
|
return False
|
30
30
|
|
31
|
-
def _download(self, url: str, session: bool = True, timeout: int =
|
31
|
+
def _download(self, url: str, session: bool = True, timeout: int = 60) -> list:
|
32
32
|
res = []
|
33
33
|
try:
|
34
34
|
thumbnail = None
|
35
|
+
video_id = self.get_video_id(url)
|
36
|
+
if video_id:
|
37
|
+
thumbnail = self.download_hndlr(self.download_thumbnail, video_id)
|
35
38
|
yt = self.build_yt(url, session=session)
|
36
39
|
|
37
40
|
if self.is_live(yt.initial_data):
|
38
41
|
raise YoutubeLiveError("Youtube Live is not supported")
|
39
42
|
|
40
|
-
if yt:
|
41
|
-
thumbnail = self.download_hndlr(self.download_thumbnail, yt.video_id)
|
42
|
-
|
43
43
|
stream = yt.streams.get_highest_resolution()
|
44
44
|
|
45
45
|
if not stream:
|
@@ -65,4 +65,25 @@ class YoutubeScraper(YoutubeAbstract):
|
|
65
65
|
except AgeRestrictedError as e:
|
66
66
|
raise YotubeAgeRestrictedError("Youtube Age Restricted error")
|
67
67
|
|
68
|
+
return res
|
69
|
+
|
70
|
+
def _download_yt_dlp(self, url: str, timeout: int = 60) -> list:
|
71
|
+
res = []
|
72
|
+
thumbnail = None
|
73
|
+
video_id = self.get_video_id(url)
|
74
|
+
if video_id:
|
75
|
+
thumbnail = self.download_hndlr(self.download_thumbnail, video_id)
|
76
|
+
with self.build_yt_dlp() as ydl:
|
77
|
+
info = ydl.extract_info(url, download=True)
|
78
|
+
local_file = ydl.prepare_filename(info)
|
79
|
+
logging.debug("Temp filename: '%s'", local_file)
|
80
|
+
res.append({
|
81
|
+
"socket_timeout": timeout,
|
82
|
+
"local_media_path": local_file,
|
83
|
+
"performer": info.get("uploader", "Unknown"),
|
84
|
+
"thumb": thumbnail,
|
85
|
+
"canonical_name": info.get("title", ''),
|
86
|
+
"media_type": JobType.VIDEO
|
87
|
+
})
|
88
|
+
|
68
89
|
return res
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: warp_beacon
|
3
|
-
Version: 2.3.
|
3
|
+
Version: 2.3.41
|
4
4
|
Summary: Telegram bot for expanding external media links
|
5
5
|
Home-page: https://github.com/sb0y/warp_beacon
|
6
6
|
Author: Andrey Bagrintsev
|
@@ -237,6 +237,7 @@ Requires-Dist: pillow
|
|
237
237
|
Requires-Dist: pymongo
|
238
238
|
Requires-Dist: instagrapi==2.0.0
|
239
239
|
Requires-Dist: bs4
|
240
|
+
Requires-Dist: yt_dlp
|
240
241
|
Dynamic: author
|
241
242
|
Dynamic: home-page
|
242
243
|
Dynamic: license-file
|
@@ -4,7 +4,7 @@ var/warp_beacon/accounts.json,sha256=OsXdncs6h88xrF_AP6_WDCK1waGBn9SR-uYdIeK37GM
|
|
4
4
|
var/warp_beacon/placeholder.gif,sha256=cE5CGJVaop4Sx21zx6j4AyoHU0ncmvQuS2o6hJfEH88,6064
|
5
5
|
var/warp_beacon/proxies.json,sha256=VnjlQDXumOEq72ZFjbh6IqHS1TEHqn8HPYAZqWCeSIA,95
|
6
6
|
warp_beacon/__init__.py,sha256=_rThNODmz0nDp_n4mWo_HKaNFE5jk1_7cRhHyYaencI,163
|
7
|
-
warp_beacon/__version__.py,sha256=
|
7
|
+
warp_beacon/__version__.py,sha256=eJo4w0wy-rkbDxnK_FYM-eSEodG5CN8jr8NCff2SMpU,24
|
8
8
|
warp_beacon/warp_beacon.py,sha256=7KEtZDj-pdhtl6m-zFLsSojs1ZR4o7L0xbqtdmYPvfE,342
|
9
9
|
warp_beacon/compress/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
warp_beacon/compress/video.py,sha256=_PDMVYCyzLYxHv1uZmmzGcG_8rjaZr7BTXsXTTy_oS4,2846
|
@@ -24,16 +24,16 @@ warp_beacon/scheduler/scheduler.py,sha256=ddPhExSgj_RGR1eSDlIm0hVgTVM_76UEMEl9i-
|
|
24
24
|
warp_beacon/scraper/__init__.py,sha256=V_C5SmAmRtjFfVBtTotOHCW3ILMQ8m_ulrBF6ry59_A,16944
|
25
25
|
warp_beacon/scraper/abstract.py,sha256=28a0aBKZpi8IKptLWdB6RuVbOkrUbrhT7LSZX7QRQtg,2725
|
26
26
|
warp_beacon/scraper/account_selector.py,sha256=oqwtyT2_xBYkx_7ysoz0VLa-x8EpiBifmF12MUNLCW8,5316
|
27
|
-
warp_beacon/scraper/exceptions.py,sha256=
|
27
|
+
warp_beacon/scraper/exceptions.py,sha256=QBHLA8hK1sL8uJu5JhidbXoBXPZtMMtV26nYfHvO4NU,1339
|
28
28
|
warp_beacon/scraper/fail_handler.py,sha256=_blvckfTZ4xWVancQKVRXH5ClKGwfrBxMwvXIFZh1qA,975
|
29
29
|
warp_beacon/scraper/link_resolver.py,sha256=Rc9ZuMyOo3iPywDHwjngy-WRQ2SXhJwxcg-5ripx7tM,2447
|
30
30
|
warp_beacon/scraper/instagram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
31
|
warp_beacon/scraper/instagram/instagram.py,sha256=TpIBS9S3zcLbeGax4CENVo6WP75EE6oIttc-MjWYVjs,13815
|
32
32
|
warp_beacon/scraper/youtube/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
-
warp_beacon/scraper/youtube/abstract.py,sha256=
|
33
|
+
warp_beacon/scraper/youtube/abstract.py,sha256=rJrcJ9g-BETkDGqbfE7gq5TxpoF2HPxOC_XdpeTJEpA,11675
|
34
34
|
warp_beacon/scraper/youtube/music.py,sha256=6FIU1tqKvW7Osh3jg8fqli2W30Lgp_GM33S9lfOnk0s,1418
|
35
35
|
warp_beacon/scraper/youtube/shorts.py,sha256=k3yGF9b8HTzNE6h4VE0zsMGB6kWP-V2xiLhIY3QZXvs,1269
|
36
|
-
warp_beacon/scraper/youtube/youtube.py,sha256=
|
36
|
+
warp_beacon/scraper/youtube/youtube.py,sha256=JX3hHHuWiGK81A8POcc0F1GYr1FLjQyIzrp0Mzy9_dU,2863
|
37
37
|
warp_beacon/storage/__init__.py,sha256=0Vajd0oITKJfu2vmNx5uQSt3-L6vwIvUYWJo8HZCjco,3398
|
38
38
|
warp_beacon/storage/mongo.py,sha256=qC4ZiO8XXvPnP0rJwz4CJx42pqFsyAjCiW10W5QdT6E,527
|
39
39
|
warp_beacon/telegram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -43,9 +43,9 @@ warp_beacon/telegram/handlers.py,sha256=XXIfdV_RCj7tyZMPXchuKmGoDdweOaR08ADDaBPW
|
|
43
43
|
warp_beacon/telegram/placeholder_message.py,sha256=wN9-BRiyrtHG-EvXtZkGJHt2CX71munQ57ITttjt0mw,6400
|
44
44
|
warp_beacon/telegram/utils.py,sha256=9uebX53G16mV7ER7WgfdWBLFHHw14S8HBt9URrIskg0,4440
|
45
45
|
warp_beacon/uploader/__init__.py,sha256=E9rlZIf7xlQz6MutMOwJ8S5Vm2uheR5nv23Kv8duRQg,5427
|
46
|
-
warp_beacon-2.3.
|
47
|
-
warp_beacon-2.3.
|
48
|
-
warp_beacon-2.3.
|
49
|
-
warp_beacon-2.3.
|
50
|
-
warp_beacon-2.3.
|
51
|
-
warp_beacon-2.3.
|
46
|
+
warp_beacon-2.3.41.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
47
|
+
warp_beacon-2.3.41.dist-info/METADATA,sha256=S18xumQDMp35RZ49TerDM62XACK9XjEQ-d4N3mS1A_I,22626
|
48
|
+
warp_beacon-2.3.41.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
49
|
+
warp_beacon-2.3.41.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
|
50
|
+
warp_beacon-2.3.41.dist-info/top_level.txt,sha256=qGjHVVfyf6lTmbdSA-fQq0rHS1YVS4HoJT3rag5xgPE,1141
|
51
|
+
warp_beacon-2.3.41.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|