warp-beacon 2.0.4__py3-none-any.whl → 2.0.6__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/__init__.py +9 -1
- warp_beacon/scraper/abstract.py +18 -0
- warp_beacon/scraper/exceptions.py +3 -0
- warp_beacon/scraper/instagram.py +7 -2
- warp_beacon/scraper/youtube/youtube.py +41 -16
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/METADATA +18 -2
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/RECORD +12 -12
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/LICENSE +0 -0
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/WHEEL +0 -0
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/entry_points.txt +0 -0
- {warp_beacon-2.0.4.dist-info → warp_beacon-2.0.6.dist-info}/top_level.txt +0 -0
warp_beacon/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "2.0.
|
1
|
+
__version__ = "2.0.6"
|
2
2
|
|
warp_beacon/scraper/__init__.py
CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
|
|
5
5
|
import multiprocessing
|
6
6
|
from queue import Empty
|
7
7
|
|
8
|
-
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, FileTooBig
|
8
|
+
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, FileTooBig, YotubeLiveError
|
9
9
|
from warp_beacon.mediainfo.video import VideoInfo
|
10
10
|
from warp_beacon.mediainfo.audio import AudioInfo
|
11
11
|
from warp_beacon.mediainfo.silencer import Silencer
|
@@ -115,6 +115,14 @@ class AsyncDownloader(object):
|
|
115
115
|
job_failed_msg="Unfortunately this file has exceeded the Telegram limits. A file cannot be larger than 2 gigabytes.")
|
116
116
|
)
|
117
117
|
break
|
118
|
+
except YotubeLiveError as e:
|
119
|
+
logging.warning("Youtube Live videos are not supported. Skipping.")
|
120
|
+
logging.exception(e)
|
121
|
+
self.uploader.queue_task(job.to_upload_job(
|
122
|
+
job_failed=True,
|
123
|
+
job_failed_msg="Youtube Live videos are not supported. Please wait until the live broadcast ends.")
|
124
|
+
)
|
125
|
+
break
|
118
126
|
except (UnknownError, Exception) as e:
|
119
127
|
logging.warning("UnknownError occurred!")
|
120
128
|
logging.exception(e)
|
warp_beacon/scraper/abstract.py
CHANGED
@@ -5,6 +5,7 @@ from abc import ABC, abstractmethod
|
|
5
5
|
from typing import Callable, Union
|
6
6
|
|
7
7
|
from PIL import Image
|
8
|
+
from pillow_heif import register_heif_opener
|
8
9
|
|
9
10
|
import logging
|
10
11
|
|
@@ -41,4 +42,21 @@ class ScraperAbstract(ABC):
|
|
41
42
|
|
42
43
|
return ''
|
43
44
|
|
45
|
+
@staticmethod
|
46
|
+
def convert_heic_to_png(src_file: str) -> str:
|
47
|
+
try:
|
48
|
+
if os.path.exists(src_file):
|
49
|
+
register_heif_opener()
|
50
|
+
path_info = pathlib.Path(src_file)
|
51
|
+
old_filename = path_info.stem
|
52
|
+
new_filename = "%s_converted.%s" % (old_filename, "png")
|
53
|
+
new_filepath = "%s/%s" % (os.path.dirname(src_file), new_filename)
|
54
|
+
with Image.open(src_file).convert('RGB') as img:
|
55
|
+
img.save(new_filepath, 'png')
|
56
|
+
os.unlink(src_file)
|
57
|
+
return new_filepath
|
58
|
+
except Exception as e:
|
59
|
+
logging.error("Failed to convert webp file to png!")
|
60
|
+
logging.exception(e)
|
44
61
|
|
62
|
+
return ''
|
warp_beacon/scraper/instagram.py
CHANGED
@@ -126,8 +126,11 @@ class InstagramScraper(ScraperAbstract):
|
|
126
126
|
|
127
127
|
def download_photo(self, url: str) -> dict:
|
128
128
|
path = str(self._download_hndlr(self.cl.photo_download_by_url, url, folder='/tmp'))
|
129
|
-
|
129
|
+
path_lowered = path.lower()
|
130
|
+
if ".webp" in path_lowered:
|
130
131
|
path = InstagramScraper.convert_webp_to_png(path)
|
132
|
+
if ".heic" in path_lowered:
|
133
|
+
path = InstagramScraper.convert_heic_to_png(path)
|
131
134
|
return {"local_media_path": path, "media_type": JobType.IMAGE}
|
132
135
|
|
133
136
|
def download_story(self, story_info: Story) -> dict:
|
@@ -142,8 +145,10 @@ class InstagramScraper(ScraperAbstract):
|
|
142
145
|
effective_url = "https://www.instagram.com/stories/%s/%s/" % (story_info.user.username, effective_story_id)
|
143
146
|
if story_info.media_type == 1: # photo
|
144
147
|
path = str(self._download_hndlr(self.cl.story_download_by_url, url=story_info.thumbnail_url, folder='/tmp'))
|
145
|
-
if ".webp" in
|
148
|
+
if ".webp" in path_lowered:
|
146
149
|
path = InstagramScraper.convert_webp_to_png(path)
|
150
|
+
if ".heic" in path_lowered:
|
151
|
+
path = InstagramScraper.convert_heic_to_png(path)
|
147
152
|
media_type = JobType.IMAGE
|
148
153
|
elif story_info.media_type == 2: # video
|
149
154
|
path = str(self._download_hndlr(self.cl.story_download_by_url, url=story_info.video_url, folder='/tmp'))
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from warp_beacon.jobs.types import JobType
|
2
2
|
from warp_beacon.scraper.youtube.abstract import YoutubeAbstract
|
3
|
+
from warp_beacon.scraper.exceptions import YotubeLiveError, NotFound
|
3
4
|
|
4
5
|
from pytubefix import YouTube
|
5
6
|
|
@@ -11,29 +12,53 @@ class YoutubeScraper(YoutubeAbstract):
|
|
11
12
|
YT_TIMEOUT_DEFAULT = 2
|
12
13
|
YT_TIMEOUT_INCREMENT_DEFAULT = 60
|
13
14
|
|
15
|
+
def is_live(self, data: dict) -> bool:
|
16
|
+
'''
|
17
|
+
x.contents.twoColumnWatchNextResults.results.results.contents[0].videoPrimaryInfoRenderer.viewCount.videoViewCountRenderer.isLive
|
18
|
+
'''
|
19
|
+
try:
|
20
|
+
contents = data.get("contents", {}).get("twoColumnWatchNextResults", {}).get("results", {}).get("results", {}).get("contents", [])
|
21
|
+
for i in contents:
|
22
|
+
video_view_count_renderer = i.get("videoPrimaryInfoRenderer", {}).get("viewCount", {}).get("videoViewCountRenderer", {})
|
23
|
+
if video_view_count_renderer:
|
24
|
+
return video_view_count_renderer.get("isLive", False)
|
25
|
+
except Exception as e:
|
26
|
+
logging.warning("Failed to check if stream is live!")
|
27
|
+
logging.exception(e)
|
28
|
+
|
29
|
+
return False
|
30
|
+
|
14
31
|
def _download(self, url: str, timeout: int = 0) -> list:
|
15
32
|
res = []
|
16
33
|
thumbnail = None
|
17
34
|
yt = YouTube(url)
|
35
|
+
|
36
|
+
if self.is_live(yt.initial_data):
|
37
|
+
raise YotubeLiveError("Youtube Live is not supported")
|
38
|
+
|
18
39
|
if yt and yt.thumbnail_url:
|
19
40
|
thumbnail = self.download_thumbnail(yt.thumbnail_url)
|
41
|
+
|
20
42
|
stream = yt.streams.get_highest_resolution()
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
43
|
+
|
44
|
+
if not stream:
|
45
|
+
raise NotFound("No suitable video stream found")
|
46
|
+
|
47
|
+
local_file = stream.download(
|
48
|
+
output_path=self.DOWNLOAD_DIR,
|
49
|
+
max_retries=0,
|
50
|
+
timeout=timeout,
|
51
|
+
skip_existing=False,
|
52
|
+
filename_prefix="yt_download_"
|
53
|
+
)
|
54
|
+
logging.debug("Temp filename: '%s'", local_file)
|
55
|
+
res.append({
|
56
|
+
"local_media_path": self.rename_local_file(local_file),
|
57
|
+
"performer": yt.author,
|
58
|
+
"thumb": thumbnail,
|
59
|
+
"canonical_name": stream.title,
|
60
|
+
"media_type": JobType.VIDEO
|
61
|
+
})
|
37
62
|
|
38
63
|
return res
|
39
64
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: warp_beacon
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.6
|
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
|
@@ -228,6 +228,7 @@ Requires-Dist: ffmpeg-python
|
|
228
228
|
Requires-Dist: uvloop
|
229
229
|
Requires-Dist: tgcrypto
|
230
230
|
Requires-Dist: pyrogram
|
231
|
+
Requires-Dist: pillow-heif
|
231
232
|
Requires-Dist: pytubefix
|
232
233
|
Requires-Dist: av
|
233
234
|
Requires-Dist: urlextract
|
@@ -242,7 +243,12 @@ Works with a links in personal messages and also with group chats.
|
|
242
243
|
|
243
244
|
Just send a media link to the chat with bot and get a video or audio reply.
|
244
245
|
|
245
|
-
|
246
|
+
| | | |
|
247
|
+
|:-------------------------:|:-------------------------:|:-------------------------:|
|
248
|
+
|<img width="700" alt="Yotube Video usage example" src="https://github.com/user-attachments/assets/280b058f-325b-4386-9556-f145f6db9cfa"> Yotube Video usage example |<img width="700" alt="Youtube Music usage example" src="https://github.com/user-attachments/assets/3a462a3b-8c80-460f-aa66-c39db24f7a24"> Youtube Music usage example|<img width="703" alt="image" src="https://github.com/user-attachments/assets/384206ea-1371-48d5-a717-92aff06fa339"> Instagram Reels usage example |
|
249
|
+
|<img width="700" alt="Instagram Photo post usage example" src="https://github.com/user-attachments/assets/29324b94-7314-4a38-8790-3483011d355d"> Instagram Photo post usage example|<img width="700" alt="Instagram Photo Carousel usage" src="https://github.com/user-attachments/assets/2598e329-e16e-455e-91e9-a027e8994283"> Instagram Photo Carousel usage example|<img width="757" alt="Instagram Photo bulk Strories download usage example" src="https://github.com/user-attachments/assets/2c8c91ac-6ade-4d1d-a677-2b36bb40ff39"> Instagram Photo bulk Strories download usage example|
|
250
|
+
|<img width="700" alt="Instagram specific Story download usage example" src="https://github.com/user-attachments/assets/03dc70c5-6933-4122-9c7c-5f7d734d117b"> Instagram specific Story download usage example|<img width="700" alt="Group chat usage example" src="https://github.com/user-attachments/assets/649fcb1e-785b-4efd-9153-69644c6d898b"> Group chat usage example|
|
251
|
+
|
246
252
|
|
247
253
|
In order to setup your own instance, you will need:
|
248
254
|
|
@@ -320,6 +326,16 @@ Check logs
|
|
320
326
|
```bash
|
321
327
|
sudo docker compose logs warp_beacon -f
|
322
328
|
```
|
329
|
+
## Upgrading ##
|
330
|
+
If you are using `image-prod` (set in `docker-compose.yml` by default), just rebuild your image:
|
331
|
+
```bash
|
332
|
+
cd your_warp_beacon_sources_directory/
|
333
|
+
sudo docker compose build --no-cache
|
334
|
+
```
|
335
|
+
Recreate existing container:
|
336
|
+
```bash
|
337
|
+
sudo docker compose up -d
|
338
|
+
```
|
323
339
|
|
324
340
|
## How to install from PIP ##
|
325
341
|
|
@@ -2,7 +2,7 @@ etc/warp_beacon/warp_beacon.conf,sha256=xihOuNBqVXGNdmMO14wwYNrqSQ4Z1wlAjp-xJk5S
|
|
2
2
|
lib/systemd/system/warp_beacon.service,sha256=lPmHqLqcI2eIV7nwHS0qcALQrznixqJuwwPfa2mDLUA,372
|
3
3
|
var/warp_beacon/placeholder.gif,sha256=cE5CGJVaop4Sx21zx6j4AyoHU0ncmvQuS2o6hJfEH88,6064
|
4
4
|
warp_beacon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
warp_beacon/__version__.py,sha256=
|
5
|
+
warp_beacon/__version__.py,sha256=ycdCnd2XTie5w0oCnBhoWDLIIgj5v308ri5GainqujU,23
|
6
6
|
warp_beacon/warp_beacon.py,sha256=7KEtZDj-pdhtl6m-zFLsSojs1ZR4o7L0xbqtdmYPvfE,342
|
7
7
|
warp_beacon/compress/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
warp_beacon/compress/video.py,sha256=_PDMVYCyzLYxHv1uZmmzGcG_8rjaZr7BTXsXTTy_oS4,2846
|
@@ -16,15 +16,15 @@ warp_beacon/mediainfo/abstract.py,sha256=ZR2JMuRpoh7nDNov9a8YkAfr6BI2HXnXzQtVrLg
|
|
16
16
|
warp_beacon/mediainfo/audio.py,sha256=ous88kwQj4bDIChN5wnGil5LqTs0IQHH0d-nyrL0-ZM,651
|
17
17
|
warp_beacon/mediainfo/silencer.py,sha256=yn9w1LVHG8JQy_D45_RzrlEWID1zbj3ecx7nYGUP4ZE,1647
|
18
18
|
warp_beacon/mediainfo/video.py,sha256=AIRy_op_BvehsjarM1rvT5Qo0QWwf-Q6xVVd_aCnbJ4,2505
|
19
|
-
warp_beacon/scraper/__init__.py,sha256=
|
20
|
-
warp_beacon/scraper/abstract.py,sha256=
|
21
|
-
warp_beacon/scraper/exceptions.py,sha256=
|
22
|
-
warp_beacon/scraper/instagram.py,sha256=
|
19
|
+
warp_beacon/scraper/__init__.py,sha256=zO6klAFVrA8z1HaYmSPZeN4ANI8phq7kwMF1zBw-QsA,10245
|
20
|
+
warp_beacon/scraper/abstract.py,sha256=c4pjblhwnCdp_kGs0Zoq4k-VH_EpQBIqIGLN-PGdr60,1668
|
21
|
+
warp_beacon/scraper/exceptions.py,sha256=9mXnk0sqnOJ3UmP-wc7dcKr_CuxRlrM6usXdQiQMzl8,1138
|
22
|
+
warp_beacon/scraper/instagram.py,sha256=GCSuW5u77UUPIRAWDc8YtTO_kKNWsDAcNnh72tiEJjQ,8549
|
23
23
|
warp_beacon/scraper/youtube/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
warp_beacon/scraper/youtube/abstract.py,sha256=XnVhF1DVSYDMuZ34A6T9hyRlUhjJ7-_JPRF9TOaZ_eo,3358
|
25
25
|
warp_beacon/scraper/youtube/music.py,sha256=Gg1J6QnvpplTOcT_KSiNFZAqZyMyy3Gjgo62e9VcRLM,1404
|
26
26
|
warp_beacon/scraper/youtube/shorts.py,sha256=co4lpNTnncIEScVB9htAT2Hy4fvx56z5xgDo6scu6n4,1162
|
27
|
-
warp_beacon/scraper/youtube/youtube.py,sha256=
|
27
|
+
warp_beacon/scraper/youtube/youtube.py,sha256=oZGhQRNtQmx-PHzC5ZH8OvS4U7X_1U-eeoC68m5FXl0,2001
|
28
28
|
warp_beacon/storage/__init__.py,sha256=8XsJXq9X7GDlTaWREF4W1PDX9PH5utwhjf5c5M8Bb7o,3378
|
29
29
|
warp_beacon/telegram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
warp_beacon/telegram/bot.py,sha256=Jvude0RxL_-muB4uQtapeE2kNKxtWPdOuGgmBE7qSuA,12062
|
@@ -32,9 +32,9 @@ warp_beacon/telegram/handlers.py,sha256=7-uaRuUgOPAE0fX-fSbn0N02Pv5uELnEIBFxHPj3
|
|
32
32
|
warp_beacon/telegram/placeholder_message.py,sha256=u5kVfTjGmVYkwA5opniRltHXGpsdSxI41WEde8J5os0,6418
|
33
33
|
warp_beacon/telegram/utils.py,sha256=1tm_DH1F2snDxSqwZnKD4ijvTrobv_kscgt3w-bWa6g,2027
|
34
34
|
warp_beacon/uploader/__init__.py,sha256=chX9oOrwO05O7DFmUfskTAnoKse66r3sY2s4NFF7bmM,4442
|
35
|
-
warp_beacon-2.0.
|
36
|
-
warp_beacon-2.0.
|
37
|
-
warp_beacon-2.0.
|
38
|
-
warp_beacon-2.0.
|
39
|
-
warp_beacon-2.0.
|
40
|
-
warp_beacon-2.0.
|
35
|
+
warp_beacon-2.0.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
36
|
+
warp_beacon-2.0.6.dist-info/METADATA,sha256=eOmr5ABFh_1AwgLvi-qYyzt8b2BouniDzTfYVHd9cbY,20987
|
37
|
+
warp_beacon-2.0.6.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
38
|
+
warp_beacon-2.0.6.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
|
39
|
+
warp_beacon-2.0.6.dist-info/top_level.txt,sha256=pu6xG8OO_nCGllnOfAZ6QpVfivtmHVxPlYK8SZzUDqA,840
|
40
|
+
warp_beacon-2.0.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|