warp-beacon 1.1.1__tar.gz → 1.1.2__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 (40) hide show
  1. {warp_beacon-1.1.1/warp_beacon.egg-info → warp_beacon-1.1.2}/PKG-INFO +1 -1
  2. warp_beacon-1.1.2/warp_beacon/__version__.py +2 -0
  3. warp_beacon-1.1.2/warp_beacon/mediainfo/abstract.py +28 -0
  4. warp_beacon-1.1.2/warp_beacon/mediainfo/audio.py +19 -0
  5. warp_beacon-1.1.2/warp_beacon/scraper/youtube/music.py +110 -0
  6. {warp_beacon-1.1.1 → warp_beacon-1.1.2/warp_beacon.egg-info}/PKG-INFO +1 -1
  7. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon.egg-info/SOURCES.txt +3 -0
  8. warp_beacon-1.1.1/warp_beacon/__version__.py +0 -2
  9. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/LICENSE +0 -0
  10. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/MANIFEST.in +0 -0
  11. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/README.md +0 -0
  12. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/assets/placeholder.gif +0 -0
  13. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/etc/.gitignore +0 -0
  14. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/etc/warp_beacon.conf +0 -0
  15. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/etc/warp_beacon.service +0 -0
  16. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/pyproject.toml +0 -0
  17. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/setup.cfg +0 -0
  18. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/setup.py +0 -0
  19. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/__init__.py +0 -0
  20. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/compress/__init__.py +0 -0
  21. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/compress/video.py +0 -0
  22. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/jobs/__init__.py +0 -0
  23. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/jobs/abstract.py +0 -0
  24. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/jobs/download_job.py +0 -0
  25. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/jobs/upload_job.py +0 -0
  26. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/mediainfo/__init__.py +0 -0
  27. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/mediainfo/video.py +0 -0
  28. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/__init__.py +0 -0
  29. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/abstract.py +0 -0
  30. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/exceptions.py +0 -0
  31. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/instagram.py +0 -0
  32. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/youtube/__init__.py +0 -0
  33. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/scraper/youtube/shorts.py +0 -0
  34. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/storage/__init__.py +0 -0
  35. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/uploader/__init__.py +0 -0
  36. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon/warp_beacon.py +0 -0
  37. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon.egg-info/dependency_links.txt +0 -0
  38. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon.egg-info/entry_points.txt +0 -0
  39. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon.egg-info/requires.txt +0 -0
  40. {warp_beacon-1.1.1 → warp_beacon-1.1.2}/warp_beacon.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: warp_beacon
3
- Version: 1.1.1
3
+ Version: 1.1.2
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__ = "1.1.2"
2
+
@@ -0,0 +1,28 @@
1
+ import os
2
+ from abc import ABC, abstractmethod
3
+
4
+ import av
5
+
6
+ class MediaInfoAbstract(ABC):
7
+ filename = ""
8
+ container = None
9
+ duration = 0.0
10
+
11
+ def __init__(self, filename: str) -> None:
12
+ self.filename = filename
13
+ self.container = av.open(file=self.filename, mode='r')
14
+
15
+ def __del__(self) -> None:
16
+ if self.container:
17
+ self.container.close()
18
+
19
+ def get_duration(self) -> float:
20
+ return self.duration
21
+
22
+ @staticmethod
23
+ def get_filesize(filename: str) -> float:
24
+ return os.stat(filename).st_size
25
+
26
+ @abstractmethod
27
+ def get_finfo(cls, except_info: tuple=()) -> dict:
28
+ raise NotImplementedError
@@ -0,0 +1,19 @@
1
+ from warp_beacon.mediainfo.abstract import MediaInfoAbstract
2
+
3
+ class AudioInfo(MediaInfoAbstract):
4
+ def __init__(self, filename: str) -> None:
5
+ super(AudioInfo, self).__init__(filename)
6
+ if self.container:
7
+ stream_list = self.container.streams.get(audio=0)
8
+ if stream_list:
9
+ stream = stream_list[0]
10
+ time_base = stream.time_base
11
+ self.duration = float(stream.duration * time_base)
12
+
13
+ def get_finfo(self, except_info: tuple=()) -> dict:
14
+ res = {}
15
+ if "duration" not in except_info:
16
+ res["duration"] = round(self.get_duration())
17
+ if "filesize" not in except_info:
18
+ res["filesize"] = AudioInfo.get_filesize(self.filename)
19
+ return res
@@ -0,0 +1,110 @@
1
+ import os
2
+ import pathlib
3
+ import time
4
+
5
+ import socket
6
+ import ssl
7
+
8
+ from typing import Callable, Union
9
+
10
+ import requests
11
+ import urllib
12
+ import http.client
13
+
14
+ from pytubefix import YouTube
15
+ from pytubefix.exceptions import VideoUnavailable, VideoPrivate, MaxRetriesExceeded
16
+
17
+ from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, extract_exception_message
18
+ from warp_beacon.scraper.abstract import ScraperAbstract
19
+
20
+ import logging
21
+
22
+ DOWNLOAD_DIR = "/tmp"
23
+
24
+ class YoutubeMusicScraper(ScraperAbstract):
25
+
26
+ def __init__(self) -> None:
27
+ pass
28
+
29
+ def __del__(self) -> None:
30
+ pass
31
+
32
+ def remove_tmp_files(self) -> None:
33
+ for i in os.listdir(DOWNLOAD_DIR):
34
+ if "yt_download_" in i:
35
+ os.unlink("%s/%s" % (DOWNLOAD_DIR, i))
36
+
37
+ def _download_hndlr(self, func: Callable, *args: tuple[str], **kwargs: dict[str]) -> Union[str, dict]:
38
+ ret_val = ''
39
+ max_retries = int(os.environ.get("YT_MUSIC_MAX_RETRIES", default=6))
40
+ pause_secs = int(os.environ.get("YT_MUSIC_PAUSE_BEFORE_RETRY", default=3))
41
+ timeout = int(os.environ.get("YT_MUSIC_TIMEOUT", default=60))
42
+ timeout_increment = int(os.environ.get("YT_MUSIC_TIMEOUT_INCREMENT", default=60))
43
+ retries = 0
44
+ while max_retries >= retries:
45
+ try:
46
+ kwargs["timeout"] = timeout
47
+ ret_val = func(*args, **kwargs)
48
+ break
49
+ except MaxRetriesExceeded:
50
+ # do noting, not interested
51
+ pass
52
+ #except http.client.IncompleteRead as e:
53
+ except (socket.timeout,
54
+ ssl.SSLError,
55
+ http.client.IncompleteRead,
56
+ http.client.HTTPException,
57
+ requests.RequestException,
58
+ urllib.error.URLError,
59
+ urllib.error.HTTPError) as e:
60
+ if hasattr(e, "code") and int(e.code) == 403:
61
+ raise Unavailable(extract_exception_message(e))
62
+ logging.warning("Youtube read timeout! Retrying in %d seconds ...", pause_secs)
63
+ logging.info("Your `YT_MUSIC_MAX_RETRIES` values is %d", max_retries)
64
+ logging.exception(extract_exception_message(e))
65
+ if max_retries <= retries:
66
+ self.remove_tmp_files()
67
+ raise TimeOut(extract_exception_message(e))
68
+ retries += 1
69
+ timeout += timeout_increment
70
+ time.sleep(pause_secs)
71
+ except (VideoUnavailable, VideoPrivate) as e:
72
+ raise Unavailable(extract_exception_message(e))
73
+
74
+ return ret_val
75
+
76
+ def rename_local_file(self, filename: str) -> str:
77
+ if not os.path.exists(filename):
78
+ raise NameError("No file provided")
79
+ path_info = pathlib.Path(filename)
80
+ ext = path_info.suffix
81
+ old_filename = path_info.stem
82
+ time_name = str(time.time()).replace('.', '_')
83
+ new_filename = "%s%s" % (time_name, ext)
84
+ new_filepath = "%s/%s" % (os.path.dirname(filename), new_filename)
85
+
86
+ os.rename(filename, new_filepath)
87
+
88
+ return new_filepath
89
+
90
+ def _download(self, url: str, timeout: int = 0) -> list:
91
+ res = []
92
+ yt = YouTube(url)
93
+ stream = yt.streams.get_audio_only()
94
+ if stream:
95
+ logging.info("Operation timeout is '%d'", timeout)
96
+ local_file = stream.download(
97
+ output_path=DOWNLOAD_DIR,
98
+ max_retries=0,
99
+ timeout=timeout,
100
+ skip_existing=False,
101
+ filename_prefix='yt_download_',
102
+ mp3=True
103
+ )
104
+ logging.info("Temp filename: '%s'", local_file)
105
+ res.append({"local_media_path": self.rename_local_file(local_file), "canonical_name": stream.title, "media_type": "audio"})
106
+
107
+ return res
108
+
109
+ def download(self, url: str) -> list:
110
+ return self._download_hndlr(self._download, url)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: warp_beacon
3
- Version: 1.1.1
3
+ Version: 1.1.2
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
@@ -24,12 +24,15 @@ warp_beacon/jobs/abstract.py
24
24
  warp_beacon/jobs/download_job.py
25
25
  warp_beacon/jobs/upload_job.py
26
26
  warp_beacon/mediainfo/__init__.py
27
+ warp_beacon/mediainfo/abstract.py
28
+ warp_beacon/mediainfo/audio.py
27
29
  warp_beacon/mediainfo/video.py
28
30
  warp_beacon/scraper/__init__.py
29
31
  warp_beacon/scraper/abstract.py
30
32
  warp_beacon/scraper/exceptions.py
31
33
  warp_beacon/scraper/instagram.py
32
34
  warp_beacon/scraper/youtube/__init__.py
35
+ warp_beacon/scraper/youtube/music.py
33
36
  warp_beacon/scraper/youtube/shorts.py
34
37
  warp_beacon/storage/__init__.py
35
38
  warp_beacon/uploader/__init__.py
@@ -1,2 +0,0 @@
1
- __version__ = "1.1.1"
2
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes