warp-beacon 2.6.87__tar.gz → 2.6.89__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 (70) hide show
  1. {warp_beacon-2.6.87/warp_beacon.egg-info → warp_beacon-2.6.89}/PKG-INFO +1 -1
  2. warp_beacon-2.6.89/warp_beacon/__version__.py +2 -0
  3. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scheduler/instagram_human.py +14 -12
  4. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scheduler/scheduler.py +1 -1
  5. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/__init__.py +2 -2
  6. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/utils.py +4 -4
  7. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/youtube/abstract.py +43 -2
  8. warp_beacon-2.6.89/warp_beacon/warp_beacon.py +39 -0
  9. {warp_beacon-2.6.87 → warp_beacon-2.6.89/warp_beacon.egg-info}/PKG-INFO +1 -1
  10. warp_beacon-2.6.87/warp_beacon/__version__.py +0 -2
  11. warp_beacon-2.6.87/warp_beacon/warp_beacon.py +0 -14
  12. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/LICENSE +0 -0
  13. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/MANIFEST.in +0 -0
  14. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/README.md +0 -0
  15. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/assets/placeholder.gif +0 -0
  16. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/etc/.gitignore +0 -0
  17. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/etc/accounts.json +0 -0
  18. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/etc/proxies.json +0 -0
  19. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/etc/warp_beacon.conf +0 -0
  20. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/etc/warp_beacon.service +0 -0
  21. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/pyproject.toml +0 -0
  22. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/setup.cfg +0 -0
  23. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/setup.py +0 -0
  24. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/__init__.py +0 -0
  25. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/compress/__init__.py +0 -0
  26. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/compress/video.py +0 -0
  27. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/jobs/__init__.py +0 -0
  28. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/jobs/abstract.py +0 -0
  29. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/jobs/download_job.py +0 -0
  30. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/jobs/types.py +0 -0
  31. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/jobs/upload_job.py +0 -0
  32. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/mediainfo/__init__.py +0 -0
  33. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/mediainfo/abstract.py +0 -0
  34. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/mediainfo/audio.py +0 -0
  35. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/mediainfo/silencer.py +0 -0
  36. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/mediainfo/video.py +0 -0
  37. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scheduler/__init__.py +0 -0
  38. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/abstract.py +0 -0
  39. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/account_selector.py +0 -0
  40. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/exceptions.py +0 -0
  41. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/fail_handler.py +0 -0
  42. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/instagram/__init__.py +0 -0
  43. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/instagram/captcha.py +0 -0
  44. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/instagram/instagram.py +0 -0
  45. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/instagram/wb_instagrapi.py +0 -0
  46. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/link_resolver.py +0 -0
  47. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/youtube/__init__.py +0 -0
  48. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/youtube/music.py +0 -0
  49. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/youtube/shorts.py +0 -0
  50. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/scraper/youtube/youtube.py +0 -0
  51. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/storage/__init__.py +0 -0
  52. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/storage/mongo.py +0 -0
  53. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/__init__.py +0 -0
  54. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/bot.py +0 -0
  55. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/caption_shortener.py +0 -0
  56. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/download_status.py +0 -0
  57. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/edit_message.py +0 -0
  58. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/handlers.py +0 -0
  59. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/placeholder_message.py +0 -0
  60. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/progress_bar.py +0 -0
  61. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/progress_file_reader.py +0 -0
  62. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/types.py +0 -0
  63. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/telegram/utils.py +0 -0
  64. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/uploader/__init__.py +0 -0
  65. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon/yt_auth.py +0 -0
  66. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon.egg-info/SOURCES.txt +0 -0
  67. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon.egg-info/dependency_links.txt +0 -0
  68. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon.egg-info/entry_points.txt +0 -0
  69. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/warp_beacon.egg-info/requires.txt +0 -0
  70. {warp_beacon-2.6.87 → warp_beacon-2.6.89}/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.6.87
3
+ Version: 2.6.89
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.6.89"
2
+
@@ -17,7 +17,9 @@ class InstagramHuman(object):
17
17
  self.operations_count = 0
18
18
 
19
19
  def watch_content(self, media: list) -> None:
20
- for m in media[:random.randint(1, 15)]:
20
+ if not media:
21
+ return
22
+ for m in media[:random.randint(1, len(media))]:
21
23
  try:
22
24
  logging.info("Wathing content with pk '%s'", str(m.pk))
23
25
  content = self.scrapler.cl.media_info_v1(m.pk)
@@ -30,7 +32,7 @@ class InstagramHuman(object):
30
32
 
31
33
  def scroll_content(self, last_pk: int) -> None:
32
34
  timeline_initialized = False
33
- if random.random() > 0.7:
35
+ if random.random() > 0.5:
34
36
  timeline_initialized = True
35
37
  self.scrapler.timeline_cursor = self.scrapler.download_hndlr(self.scrapler.cl.get_timeline_feed, reason="cold_start_fetch")
36
38
  logging.info("Starting to watch related reels with media_pk '%d'", last_pk)
@@ -38,7 +40,7 @@ class InstagramHuman(object):
38
40
  self.operations_count += 1
39
41
  self.watch_content(media)
40
42
 
41
- if random.random() > 0.9:
43
+ if random.random() > 0.7:
42
44
  time.sleep(random.uniform(2, 20))
43
45
  if not timeline_initialized:
44
46
  self.scrapler.timeline_cursor = self.scrapler.download_hndlr(self.scrapler.cl.get_timeline_feed, reason="cold_start_fetch")
@@ -75,7 +77,7 @@ class InstagramHuman(object):
75
77
  self.scrapler.download_hndlr(self.scrapler.cl.notification_like_and_comment_on_photo_user_tagged, "everyone")
76
78
  self.operations_count += 1
77
79
  self.random_pause()
78
- if random.random() > 0.5:
80
+ if random.random() > 0.2:
79
81
  logging.info("Simulation updating reels tray feed ...")
80
82
  self.scrapler.download_hndlr(self.scrapler.cl.get_reels_tray_feed, "pull_to_refresh")
81
83
  self.operations_count += 1
@@ -98,7 +100,7 @@ class InstagramHuman(object):
98
100
  self.random_pause()
99
101
  if random.random() > 0.4:
100
102
  logging.info("Watching reels ...")
101
- reels = self.scrapler.download_hndlr(self.scrapler.cl.reels)
103
+ reels = self.scrapler.download_hndlr(self.scrapler.cl.reels, amount=random.randint(4, 15))
102
104
  self.operations_count += 1
103
105
  self.watch_content(reels)
104
106
  self.random_pause()
@@ -126,11 +128,11 @@ class InstagramHuman(object):
126
128
  self.random_pause()
127
129
  if random.random() > 0.4:
128
130
  logging.info("Watching reels ...")
129
- reels = self.scrapler.download_hndlr(self.scrapler.cl.reels)
131
+ reels = self.scrapler.download_hndlr(self.scrapler.cl.reels, amount=random.randint(4, 15))
130
132
  self.operations_count += 1
131
133
  self.watch_content(reels)
132
134
  self.random_pause()
133
- if random.random() > 0.6:
135
+ if random.random() > 0.4:
134
136
  logging.info("Simulation profile view ...")
135
137
  self.profile_view()
136
138
  self.random_pause()
@@ -145,9 +147,9 @@ class InstagramHuman(object):
145
147
  self.scrapler.download_hndlr(self.scrapler.cl.direct_active_presence)
146
148
  self.operations_count += 1
147
149
  self.random_pause(short=True)
148
- if random.random() > 0.8:
150
+ if random.random() > 0.5:
149
151
  logging.info("Watching reels ...")
150
- reels = self.scrapler.download_hndlr(self.scrapler.cl.reels)
152
+ reels = self.scrapler.download_hndlr(self.scrapler.cl.reels, amount=random.randint(4, 15))
151
153
  self.operations_count += 1
152
154
  self.watch_content(reels)
153
155
  self.random_pause()
@@ -179,14 +181,14 @@ class InstagramHuman(object):
179
181
  #self.scrapler.download_hndlr(self.scrapler.cl.user_info, target_user_id)
180
182
  self.scrapler.download_hndlr(self.scrapler.cl.user_info_v1, target_user_id)
181
183
  self.operations_count += 1
182
- time.sleep(random.uniform(2, 5))
184
+ self.random_pause()
183
185
  elif isinstance(random_friend, str):
184
186
  target_user_id = self.scrapler.download_hndlr(self.scrapler.cl.user_id_from_username, random_friend)
185
187
  logging.info("user_info with target_user_id = '%s' ...", target_user_id)
186
188
  #self.scrapler.download_hndlr(self.scrapler.cl.user_info, target_user_id)
187
189
  self.scrapler.download_hndlr(self.scrapler.cl.user_info_v1, target_user_id)
188
190
  self.operations_count += 1
189
- time.sleep(random.uniform(2, 5))
191
+ self.random_pause()
190
192
 
191
193
  if random.random() > 0.5:
192
194
  logging.info("Checking direct ...")
@@ -202,7 +204,7 @@ class InstagramHuman(object):
202
204
 
203
205
  if random.random() > 0.5:
204
206
  logging.info("user_medias with target_user_id = '%s' ...", target_user_id)
205
- self.scrapler.download_hndlr(self.scrapler.cl.user_medias_v1, target_user_id, amount=random.randint(1, 5))
207
+ self.scrapler.download_hndlr(self.scrapler.cl.user_medias_v1, target_user_id, amount=random.randint(1, 10))
206
208
  self.operations_count += 1
207
209
  self.random_pause()
208
210
  except Exception as e:
@@ -126,7 +126,7 @@ class IGScheduler(object):
126
126
 
127
127
  def handle_time_planning(self) -> None:
128
128
  if int(self.state.get("remaining", 0)) <= 0:
129
- self.state["remaining"] = randrange(9292, 26200)
129
+ self.state["remaining"] = randrange(5292, 12253)
130
130
 
131
131
  def do_work(self) -> None:
132
132
  logging.info("Scheduler thread started ...")
@@ -130,7 +130,7 @@ class AsyncDownloader(object):
130
130
  proxy = selector.get_current_proxy()
131
131
  if job.job_origin is Origin.INSTAGRAM:
132
132
  from warp_beacon.scraper.instagram.instagram import InstagramScraper
133
- if not job.scroll_content and selector.get_ig_request_count() >= int(os.environ.get("IG_REQUESTS_PER_ACCOUNT", default="10")):
133
+ if not job.scroll_content and selector.get_ig_request_count() >= int(os.environ.get("IG_REQUESTS_PER_ACCOUNT", default="20")):
134
134
  logging.info("The account request limit has been reached. Selecting the next account.")
135
135
  selector.reset_ig_request_count()
136
136
  selector.next()
@@ -164,7 +164,7 @@ class AsyncDownloader(object):
164
164
  break
165
165
  if job.session_validation and job.job_origin in (Origin.INSTAGRAM, Origin.YOUTUBE):
166
166
  if job.job_origin is Origin.INSTAGRAM:
167
- if selector.get_ig_request_count() >= int(os.environ.get("IG_REQUESTS_PER_ACCOUNT", default="10")):
167
+ if selector.get_ig_request_count() >= int(os.environ.get("IG_REQUESTS_PER_ACCOUNT", default="20")):
168
168
  logging.info("The account request limit has been reached. Selecting the next account.")
169
169
  selector.reset_ig_request_count()
170
170
  selector.next()
@@ -4,10 +4,10 @@ from fake_useragent import UserAgent
4
4
 
5
5
  class ScraperUtils(object):
6
6
  @staticmethod
7
- def get_ua_dict() -> dict:
7
+ def get_ua_dict(browsers: list = ['Facebook', 'Android'], platforms: list = ['mobile', 'tablet'], os: list =['Android', 'iOS']) -> dict:
8
8
  random_client = None
9
9
  try:
10
- ua = UserAgent(browsers=['Facebook', 'Android'], platforms=['mobile', 'tablet'], os=['Android', 'iOS'])
10
+ ua = UserAgent(browsers=browsers, platforms=platforms, os=os)
11
11
  random_client = ua.getRandom
12
12
  logging.info("Select random UA: %s", random_client)
13
13
  except Exception as e:
@@ -16,5 +16,5 @@ class ScraperUtils(object):
16
16
  return random_client
17
17
 
18
18
  @staticmethod
19
- def get_ua() -> str:
20
- return ScraperUtils.get_ua_dict()["useragent"]
19
+ def get_ua(browsers: list = ['Facebook', 'Android'], platforms: list = ['mobile', 'tablet'], os: list =['Android', 'iOS']) -> str:
20
+ return ScraperUtils.get_ua_dict(browsers=browsers, platforms=platforms, os=os)["useragent"]
@@ -29,6 +29,7 @@ from warp_beacon.scraper.abstract import ScraperAbstract
29
29
  from warp_beacon.scraper.exceptions import (BadProxy, TimeOut, Unavailable,
30
30
  extract_exception_message)
31
31
  from warp_beacon.yt_auth import YtAuth
32
+ from warp_beacon.scraper.utils import ScraperUtils
32
33
 
33
34
  class YoutubeAbstract(ScraperAbstract):
34
35
  DOWNLOAD_DIR = "/tmp"
@@ -226,7 +227,10 @@ class YoutubeAbstract(ScraperAbstract):
226
227
  return ret_val
227
228
 
228
229
  def yt_on_progress(self, stream: Stream, chunk: bytes, bytes_remaining: int) -> None:
229
- total_size = stream.filesize or stream.filesize_approx
230
+ total_size = int(stream.filesize or stream.filesize_approx or 0)
231
+ if not total_size:
232
+ logging.warning("[Download worker]: total_size is '%d'", total_size)
233
+ return
230
234
  bytes_downloaded = total_size - bytes_remaining
231
235
  percentage_of_completion = bytes_downloaded / (total_size or 1) * 100
232
236
  if total_size == 0 or percentage_of_completion >= self._download_progress_threshold:
@@ -286,6 +290,28 @@ class YoutubeAbstract(ScraperAbstract):
286
290
  yt_opts["proxies"] = self.build_proxies(proxy_dsn)
287
291
  return YouTube(**yt_opts)
288
292
 
293
+ def yt_dlp_on_progress(self, params: dict) -> None:
294
+ if params.get("status", "") == "downloading":
295
+ total_size = int(params.get("total_bytes") or params.get("total_bytes_estimate") or 0)
296
+ if not total_size or total_size < 0:
297
+ logging.warning("[Download worker][yt_dlp]: total_size is '%d'", total_size)
298
+ return
299
+ bytes_downloaded = int(params.get("downloaded_bytes", 0))
300
+ percentage_of_completion = bytes_downloaded / (total_size or 1) * 100
301
+ if total_size == 0 or percentage_of_completion >= self._download_progress_threshold:
302
+ msg = {
303
+ "action": "report_download_status",
304
+ "current": bytes_downloaded,
305
+ "total": total_size,
306
+ "message_id": self.job.placeholder_message_id,
307
+ "chat_id": self.job.chat_id,
308
+ "completed": percentage_of_completion >= 100
309
+ }
310
+ self.status_pipe.send(msg)
311
+ logging.debug("[Download worker][yt_dlp] Downloaded %d%%", percentage_of_completion)
312
+ if total_size > 0:
313
+ self._download_progress_threshold += 20
314
+
289
315
  def build_yt_dlp(self, timeout: int = 60) -> yt_dlp.YoutubeDL:
290
316
  auth_data = {}
291
317
  with open(self.YT_SESSION_FILE % self.account_index, 'r', encoding="utf-8") as f:
@@ -297,9 +323,24 @@ class YoutubeAbstract(ScraperAbstract):
297
323
  'format': 'bestvideo+bestaudio/best',
298
324
  'merge_output_format': 'mp4',
299
325
  'noplaylist': True,
300
- 'tv_auth': auth_data
326
+ 'progress_hooks': [self.yt_dlp_on_progress],
327
+ 'http_headers': {
328
+ "Accept-Language": "en-US,en;q=0.9",
329
+ 'User-Agent': ScraperUtils.get_ua(
330
+ browsers=["Google", "Chrome", "Firefox"],
331
+ os=["Windows", "Linux", "Ubuntu", "Chrome OS", "Mac OS X"],
332
+ platforms=["desktop"]
333
+ )
334
+ }
301
335
  }
302
336
 
337
+ if auth_data and auth_data.get("access_token", None):
338
+ ydl_opts["http_headers"]["Authorization"] = f'Bearer {auth_data["access_token"]}'
339
+
340
+ yt_dlp_cookies_file = os.environ.get("YT_DLP_COOKIES_FILE", default="/var/warp_beacon/yt_dlp_cookies.txt")
341
+ if yt_dlp_cookies_file and os.path.exists(yt_dlp_cookies_file):
342
+ ydl_opts['cookiefile'] = yt_dlp_cookies_file
343
+
303
344
  if self.proxy:
304
345
  proxy_dsn = self.proxy.get("dsn", "")
305
346
  logging.info("Using proxy DSN '%s'", proxy_dsn)
@@ -0,0 +1,39 @@
1
+ import os
2
+ import sys
3
+ import uuid
4
+ import secrets
5
+ import hashlib
6
+ import argparse
7
+
8
+ from warp_beacon.telegram.bot import Bot
9
+
10
+ #import logging
11
+
12
+ def generate_uuid() -> str:
13
+ return str(uuid.uuid4())
14
+
15
+ def generate_device_id(seed: str = None) -> str:
16
+ raw = secrets.token_hex(8) if not seed else seed.encode()
17
+ hex_part = hashlib.md5(raw).hexdigest()[:16]
18
+ return f"android-{hex_part}"
19
+
20
+ def main() -> None:
21
+ parser = argparse.ArgumentParser(description="Warp Beacon Telegram bot.")
22
+ parser.add_argument("--uuid", action="store_true", help="Generate UUID")
23
+ parser.add_argument("--generate-device-id", type=str, metavar="INSTAGRAM_LOGIN", help="Generate device_id with account login")
24
+
25
+ args = parser.parse_args()
26
+
27
+ if args.uuid:
28
+ print(generate_uuid())
29
+ elif args.generate_device_id:
30
+ print(generate_device_id(args.generate_device_id))
31
+ else:
32
+ bot = Bot(
33
+ tg_bot_name=os.environ.get("TG_BOT_NAME", default=None),
34
+ tg_token=os.environ.get("TG_TOKEN", default=None),
35
+ tg_api_id=os.environ.get("TG_API_ID", default=None),
36
+ tg_api_hash=os.environ.get("TG_API_HASH", default=None)
37
+ )
38
+ bot.start()
39
+ sys.exit(0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warp_beacon
3
- Version: 2.6.87
3
+ Version: 2.6.89
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.6.87"
2
-
@@ -1,14 +0,0 @@
1
- import os
2
-
3
- from warp_beacon.telegram.bot import Bot
4
-
5
- #import logging
6
-
7
- def main() -> None:
8
- bot = Bot(
9
- tg_bot_name=os.environ.get("TG_BOT_NAME", default=None),
10
- tg_token=os.environ.get("TG_TOKEN", default=None),
11
- tg_api_id=os.environ.get("TG_API_ID", default=None),
12
- tg_api_hash=os.environ.get("TG_API_HASH", default=None)
13
- )
14
- bot.start()
File without changes
File without changes
File without changes
File without changes
File without changes