warp-beacon 2.7.12__tar.gz → 2.7.13__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 (71) hide show
  1. {warp_beacon-2.7.12/warp_beacon.egg-info → warp_beacon-2.7.13}/PKG-INFO +1 -1
  2. warp_beacon-2.7.13/warp_beacon/__version__.py +2 -0
  3. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/youtube/abstract.py +28 -0
  4. warp_beacon-2.7.13/warp_beacon/scraper/youtube/shorts.py +124 -0
  5. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/youtube/youtube.py +0 -28
  6. {warp_beacon-2.7.12 → warp_beacon-2.7.13/warp_beacon.egg-info}/PKG-INFO +1 -1
  7. warp_beacon-2.7.12/warp_beacon/__version__.py +0 -2
  8. warp_beacon-2.7.12/warp_beacon/scraper/youtube/shorts.py +0 -61
  9. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/LICENSE +0 -0
  10. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/MANIFEST.in +0 -0
  11. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/README.md +0 -0
  12. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/assets/cc-group-black.png +0 -0
  13. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/assets/placeholder.gif +0 -0
  14. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/etc/.gitignore +0 -0
  15. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/etc/accounts.json +0 -0
  16. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/etc/proxies.json +0 -0
  17. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/etc/warp_beacon.conf +0 -0
  18. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/etc/warp_beacon.service +0 -0
  19. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/pyproject.toml +0 -0
  20. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/setup.cfg +0 -0
  21. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/setup.py +0 -0
  22. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/__init__.py +0 -0
  23. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/compress/__init__.py +0 -0
  24. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/compress/video.py +0 -0
  25. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/jobs/__init__.py +0 -0
  26. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/jobs/abstract.py +0 -0
  27. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/jobs/download_job.py +0 -0
  28. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/jobs/types.py +0 -0
  29. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/jobs/upload_job.py +0 -0
  30. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/mediainfo/__init__.py +0 -0
  31. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/mediainfo/abstract.py +0 -0
  32. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/mediainfo/audio.py +0 -0
  33. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/mediainfo/silencer.py +0 -0
  34. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/mediainfo/video.py +0 -0
  35. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scheduler/__init__.py +0 -0
  36. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scheduler/instagram_human.py +0 -0
  37. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scheduler/scheduler.py +0 -0
  38. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/__init__.py +0 -0
  39. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/abstract.py +0 -0
  40. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/account_selector.py +0 -0
  41. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/exceptions.py +0 -0
  42. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/fail_handler.py +0 -0
  43. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/instagram/__init__.py +0 -0
  44. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/instagram/captcha.py +0 -0
  45. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/instagram/instagram.py +0 -0
  46. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/instagram/wb_instagrapi.py +0 -0
  47. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/link_resolver.py +0 -0
  48. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/utils.py +0 -0
  49. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/youtube/__init__.py +0 -0
  50. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/scraper/youtube/music.py +0 -0
  51. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/storage/__init__.py +0 -0
  52. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/storage/mongo.py +0 -0
  53. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/__init__.py +0 -0
  54. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/bot.py +0 -0
  55. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/caption_shortener.py +0 -0
  56. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/download_status.py +0 -0
  57. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/edit_message.py +0 -0
  58. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/handlers.py +0 -0
  59. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/placeholder_message.py +0 -0
  60. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/progress_bar.py +0 -0
  61. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/progress_file_reader.py +0 -0
  62. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/types.py +0 -0
  63. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/telegram/utils.py +0 -0
  64. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/uploader/__init__.py +0 -0
  65. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/warp_beacon.py +0 -0
  66. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon/yt_auth.py +0 -0
  67. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon.egg-info/SOURCES.txt +0 -0
  68. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon.egg-info/dependency_links.txt +0 -0
  69. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon.egg-info/entry_points.txt +0 -0
  70. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon.egg-info/requires.txt +0 -0
  71. {warp_beacon-2.7.12 → warp_beacon-2.7.13}/warp_beacon.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warp_beacon
3
- Version: 2.7.12
3
+ Version: 2.7.13
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
@@ -0,0 +1,2 @@
1
+ __version__ = "2.7.13"
2
+
@@ -13,6 +13,7 @@ from typing import Callable, Optional, Union
13
13
  from urllib.parse import parse_qs, urlparse
14
14
 
15
15
  import numpy as np
16
+ import av
16
17
  import pytubefix
17
18
  import pytubefix.exceptions
18
19
  import requests
@@ -387,3 +388,30 @@ class YoutubeAbstract(ScraperAbstract):
387
388
  raise Unavailable("Сontent unvailable")
388
389
 
389
390
  return ret
391
+
392
+ def mux_raw_copy(self, video_path: str, audio_path: str, output_path: str) -> str:
393
+ try:
394
+ with av.open(video_path) as input_video, av.open(audio_path) as input_audio, av.open(output_path, mode='w') as output:
395
+ in_video_stream = input_video.streams.video[0]
396
+ in_audio_stream = input_audio.streams.audio[0]
397
+
398
+ video_stream_map = output.add_stream(template=in_video_stream)
399
+ audio_stream_map = output.add_stream(template=in_audio_stream)
400
+
401
+ for packet in input_video.demux(in_video_stream):
402
+ if packet.dts is None:
403
+ continue
404
+ packet.stream = video_stream_map
405
+ output.mux(packet)
406
+
407
+ for packet in input_audio.demux(in_audio_stream):
408
+ if packet.dts is None:
409
+ continue
410
+ packet.stream = audio_stream_map
411
+ output.mux(packet)
412
+ except Exception as e:
413
+ logging.error("Failed to mux audio and video!")
414
+ logging.exception(e)
415
+ return ''
416
+
417
+ return output_path
@@ -0,0 +1,124 @@
1
+ import os
2
+ import io
3
+ from typing import Optional
4
+ import time
5
+
6
+ import logging
7
+
8
+ from pytubefix.exceptions import AgeRestrictedError
9
+
10
+ from warp_beacon.jobs.types import JobType
11
+ from warp_beacon.scraper.youtube.abstract import YoutubeAbstract
12
+
13
+ from warp_beacon.scraper.exceptions import NotFound, YotubeAgeRestrictedError
14
+
15
+ class YoutubeShortsScraper(YoutubeAbstract):
16
+ YT_MAX_RETRIES_DEFAULT = 8
17
+ YT_PAUSE_BEFORE_RETRY_DEFAULT = 3
18
+ YT_TIMEOUT_DEFAULT = 2
19
+ YT_TIMEOUT_INCREMENT_DEFAULT = 60
20
+
21
+ def _download(self, url: str, session: bool = True, thumbnail: Optional[io.BytesIO] = None, timeout: int = 60) -> list:
22
+ res = self._download_pytubefix_max_res(url=url, session=session, thumbnail=thumbnail, timeout=timeout)
23
+ if not res:
24
+ res = self._download_pytube_dash(url=url, session=session, thumbnail=thumbnail, timeout=timeout)
25
+
26
+ return res
27
+
28
+ def _download_pytube_dash(self, url: str, session: bool = True, thumbnail: Optional[io.BytesIO] = None, timeout: int = 0) -> list:
29
+ res = []
30
+ yt = self.build_yt(url, session=session)
31
+ stream = yt.streams.get_highest_resolution()
32
+
33
+ if not stream:
34
+ raise NotFound("No suitable video stream found")
35
+
36
+ local_file = stream.download(
37
+ output_path=self.DOWNLOAD_DIR,
38
+ max_retries=0,
39
+ timeout=timeout,
40
+ skip_existing=False,
41
+ filename_prefix="yt_download_"
42
+ )
43
+
44
+ local_file = self.rename_local_file(local_file)
45
+
46
+ logging.debug("Temp filename: '%s'", local_file)
47
+ res.append({
48
+ "local_media_path": local_file,
49
+ "performer": yt.author,
50
+ "thumb": thumbnail,
51
+ "canonical_name": stream.title,
52
+ "media_type": JobType.VIDEO
53
+ })
54
+
55
+ return res
56
+
57
+ def _download_yt_dlp(self, url: str, thumbnail: Optional[io.BytesIO] = None, timeout: int = 60) -> list:
58
+ res = []
59
+ with self.build_yt_dlp(timeout) as ydl:
60
+ info = ydl.extract_info(url, download=True)
61
+ local_file = ydl.prepare_filename(info)
62
+ logging.debug("Temp filename: '%s'", local_file)
63
+ res.append({
64
+ "local_media_path": local_file,
65
+ "performer": info.get("uploader", "Unknown"),
66
+ "thumb": thumbnail,
67
+ "canonical_name": info.get("title", ''),
68
+ "media_type": JobType.VIDEO
69
+ })
70
+
71
+ return res
72
+
73
+ def _download_pytubefix_max_res(self, url: str, session: bool = True, thumbnail: Optional[io.BytesIO] = None, timeout: int = 60) -> list:
74
+ res = []
75
+ local_video_file, local_audio_file = '', ''
76
+ try:
77
+ yt = self.build_yt(url, session=session)
78
+
79
+ video_stream = yt.streams.filter(adaptive=True, file_extension='mp4', only_video=True).order_by('resolution').desc().first()
80
+ audio_stream = yt.streams.filter(adaptive=True, file_extension='mp4', only_audio=True).order_by('abr').desc().first()
81
+
82
+ local_video_file = video_stream.download(
83
+ output_path=self.DOWNLOAD_DIR,
84
+ max_retries=3,
85
+ timeout=timeout,
86
+ skip_existing=False,
87
+ filename_prefix="yt_download_video_"
88
+ )
89
+ local_video_file = self.rename_local_file(local_video_file)
90
+ logging.debug("Temp video filename: '%s'", local_video_file)
91
+ local_audio_file = audio_stream.download(
92
+ output_path=self.DOWNLOAD_DIR,
93
+ max_retries=3,
94
+ timeout=timeout,
95
+ skip_existing=False,
96
+ filename_prefix="yt_download_audio_"
97
+ )
98
+ local_audio_file = self.rename_local_file(local_audio_file)
99
+ logging.debug("Temp audio filename: '%s'", local_audio_file)
100
+
101
+ muxed_video = self.mux_raw_copy(
102
+ video_path=local_video_file,
103
+ audio_path=local_audio_file,
104
+ output_path=f"{self.DOWNLOAD_DIR}/yt_muxed_video_{int(time.time())}.mp4")
105
+ if muxed_video:
106
+ muxed_video = self.rename_local_file(muxed_video)
107
+ logging.debug("Temp muxed filename: '%s'", muxed_video)
108
+
109
+ res.append({
110
+ "local_media_path": muxed_video,
111
+ "performer": yt.author,
112
+ "thumb": thumbnail,
113
+ "canonical_name": yt.title,
114
+ "media_type": JobType.VIDEO
115
+ })
116
+ except AgeRestrictedError as e:
117
+ raise YotubeAgeRestrictedError("Youtube Age Restricted error")
118
+ finally:
119
+ if os.path.exists(local_video_file):
120
+ os.unlink(local_video_file)
121
+ if os.path.exists(local_audio_file):
122
+ os.unlink(local_audio_file)
123
+
124
+ return res
@@ -4,7 +4,6 @@ import io
4
4
  from typing import Optional
5
5
  import logging
6
6
 
7
- import av
8
7
  from pytubefix.exceptions import AgeRestrictedError
9
8
 
10
9
  from warp_beacon.jobs.types import JobType
@@ -39,33 +38,6 @@ class YoutubeScraper(YoutubeAbstract):
39
38
  res = self._download_pytube_dash(url=url, session=session, thumbnail=thumbnail, timeout=timeout)
40
39
 
41
40
  return res
42
-
43
- def mux_raw_copy(self, video_path: str, audio_path: str, output_path: str) -> str:
44
- try:
45
- with av.open(video_path) as input_video, av.open(audio_path) as input_audio, av.open(output_path, mode='w') as output:
46
- in_video_stream = input_video.streams.video[0]
47
- in_audio_stream = input_audio.streams.audio[0]
48
-
49
- video_stream_map = output.add_stream(template=in_video_stream)
50
- audio_stream_map = output.add_stream(template=in_audio_stream)
51
-
52
- for packet in input_video.demux(in_video_stream):
53
- if packet.dts is None:
54
- continue
55
- packet.stream = video_stream_map
56
- output.mux(packet)
57
-
58
- for packet in input_audio.demux(in_audio_stream):
59
- if packet.dts is None:
60
- continue
61
- packet.stream = audio_stream_map
62
- output.mux(packet)
63
- except Exception as e:
64
- logging.error("Failed to mux audio and video!")
65
- logging.exception(e)
66
- return ''
67
-
68
- return output_path
69
41
 
70
42
  def _download_pytubefix_max_res(self, url: str, session: bool = True, thumbnail: Optional[io.BytesIO] = None, timeout: int = 60) -> list:
71
43
  res = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warp_beacon
3
- Version: 2.7.12
3
+ Version: 2.7.13
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
@@ -1,2 +0,0 @@
1
- __version__ = "2.7.12"
2
-
@@ -1,61 +0,0 @@
1
- import io
2
- from typing import Optional
3
-
4
- import logging
5
-
6
- from warp_beacon.jobs.types import JobType
7
- from warp_beacon.scraper.youtube.abstract import YoutubeAbstract
8
- from warp_beacon.scraper.exceptions import NotFound
9
-
10
- from warp_beacon.mediainfo.video import VideoInfo
11
-
12
- class YoutubeShortsScraper(YoutubeAbstract):
13
- YT_MAX_RETRIES_DEFAULT = 8
14
- YT_PAUSE_BEFORE_RETRY_DEFAULT = 3
15
- YT_TIMEOUT_DEFAULT = 2
16
- YT_TIMEOUT_INCREMENT_DEFAULT = 60
17
-
18
- def _download(self, url: str, session: bool = True, thumbnail: Optional[io.BytesIO] = None, timeout: int = 0) -> list:
19
- res = []
20
- yt = self.build_yt(url, session=session)
21
- stream = yt.streams.get_highest_resolution()
22
-
23
- if not stream:
24
- raise NotFound("No suitable video stream found")
25
-
26
- local_file = stream.download(
27
- output_path=self.DOWNLOAD_DIR,
28
- max_retries=0,
29
- timeout=timeout,
30
- skip_existing=False,
31
- filename_prefix="yt_download_"
32
- )
33
-
34
- local_file = self.rename_local_file(local_file)
35
-
36
- logging.debug("Temp filename: '%s'", local_file)
37
- res.append({
38
- "local_media_path": local_file,
39
- "performer": yt.author,
40
- "thumb": thumbnail,
41
- "canonical_name": stream.title,
42
- "media_type": JobType.VIDEO
43
- })
44
-
45
- return res
46
-
47
- def _download_yt_dlp(self, url: str, thumbnail: Optional[io.BytesIO] = None, timeout: int = 60) -> list:
48
- res = []
49
- with self.build_yt_dlp(timeout) as ydl:
50
- info = ydl.extract_info(url, download=True)
51
- local_file = ydl.prepare_filename(info)
52
- logging.debug("Temp filename: '%s'", local_file)
53
- res.append({
54
- "local_media_path": local_file,
55
- "performer": info.get("uploader", "Unknown"),
56
- "thumb": thumbnail,
57
- "canonical_name": info.get("title", ''),
58
- "media_type": JobType.VIDEO
59
- })
60
-
61
- return res
File without changes
File without changes
File without changes
File without changes
File without changes