warp-beacon 2.3.31__py3-none-any.whl → 2.3.33__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.
@@ -1,2 +1,2 @@
1
- __version__ = "2.3.31"
1
+ __version__ = "2.3.33"
2
2
 
@@ -0,0 +1,122 @@
1
+ import time
2
+ import random
3
+ from datetime import datetime
4
+
5
+ import logging
6
+
7
+ from instagrapi.types import UserShort
8
+ from warp_beacon.scraper.instagram.instagram import InstagramScraper
9
+
10
+ class InstagramHuman(object):
11
+ scrapler = None
12
+ default_profiles = ["nasa", "natgeo", "9gag", "spotify", "nba"]
13
+
14
+ def __init__(self, scrapler: InstagramScraper) -> None:
15
+ self.scrapler = scrapler
16
+
17
+ def simulate_activity(self) -> None:
18
+ now = datetime.now()
19
+ hour = now.hour
20
+
21
+ if 6 <= hour < 11:
22
+ self.morning_routine()
23
+ elif 11 <= hour < 18:
24
+ self.daytime_routine()
25
+ elif 18 <= hour < 23:
26
+ self.evening_routine()
27
+ else:
28
+ self.night_routine()
29
+
30
+ def morning_routine(self) -> None:
31
+ try:
32
+ logging.info("Starting morning activity simulation")
33
+ self.scrapler.timeline_cursor = self.scrapler.download_hndlr(self.scrapler.cl.get_timeline_feed, "pull_to_refresh", self.scrapler.timeline_cursor.get("next_max_id"))
34
+ time.sleep(random.uniform(3, 7))
35
+ if random.random() > 0.7:
36
+ self.scrapler.download_hndlr(self.scrapler.cl.direct_active_presence)
37
+ if random.random() > 0.7:
38
+ self.scrapler.download_hndlr(self.scrapler.cl.notification_like_and_comment_on_photo_user_tagged, "everyone")
39
+ self.random_pause()
40
+ if random.random() > 0.5:
41
+ logging.info("Simulation updating reels tray feed ...")
42
+ self.scrapler.download_hndlr(self.scrapler.cl.get_reels_tray_feed, "pull_to_refresh")
43
+ self.random_pause()
44
+ if random.random() > 0.8:
45
+ self.profile_view()
46
+ except Exception as e:
47
+ logging.warning("Error in morning_routine")
48
+ logging.exception(e)
49
+
50
+ def daytime_routine(self) -> None:
51
+ try:
52
+ logging.info("Starting day fast check activity simulation")
53
+ self.scrapler.download_hndlr(self.scrapler.cl.get_timeline_feed, "pull_to_refresh")
54
+ if random.random() > 0.7:
55
+ self.scrapler.download_hndlr(self.scrapler.cl.get_reels_tray_feed, "pull_to_refresh")
56
+ self.random_pause()
57
+ except Exception as e:
58
+ logging.warning("Error in daytime_routine")
59
+ logging.exception(e)
60
+
61
+ def evening_routine(self) -> None:
62
+ try:
63
+ logging.info("Starting evening active user simulation")
64
+ self.scrapler.download_hndlr(self.scrapler.cl.get_timeline_feed, "pull_to_refresh")
65
+ time.sleep(random.uniform(2, 5))
66
+ self.scrapler.download_hndlr(self.scrapler.cl.get_reels_tray_feed, "pull_to_refresh")
67
+ time.sleep(random.uniform(2, 5))
68
+ if random.random() > 0.7:
69
+ self.scrapler.download_hndlr(self.scrapler.cl.direct_active_presence)
70
+ if random.random() > 0.7:
71
+ self.scrapler.download_hndlr(self.scrapler.cl.notification_like_and_comment_on_photo_user_tagged, "everyone")
72
+ self.random_pause()
73
+ if random.random() > 0.4:
74
+ logging.info("Watching reels ...")
75
+ self.scrapler.download_hndlr(self.scrapler.cl.reels)
76
+ self.random_pause()
77
+ if random.random() > 0.6:
78
+ logging.info("Simulation profile view ...")
79
+ self.profile_view()
80
+ self.random_pause()
81
+ except Exception as e:
82
+ logging.warning("Error in evening_routine")
83
+ logging.exception(e)
84
+
85
+ def night_routine(self) -> None:
86
+ try:
87
+ logging.info("Starting night activity simulation")
88
+ if random.random() > 0.8:
89
+ self.scrapler.download_hndlr(self.scrapler.cl.direct_active_presence)
90
+ self.random_pause(short=True)
91
+ except Exception as e:
92
+ logging.warning("Error in night_routine")
93
+ logging.exception(e)
94
+
95
+ def random_pause(self, short: bool=False) -> None:
96
+ pause = random.uniform(3, 10) if short else random.uniform(10, 30)
97
+ logging.info("Pause for '%.2f' sec ...", round(pause, 2))
98
+ time.sleep(pause)
99
+
100
+ def profile_view(self) -> None:
101
+ try:
102
+ my_user_id = self.scrapler.cl.user_id
103
+ friends = list(self.scrapler.download_hndlr(self.scrapler.cl.user_following, my_user_id, amount=random.randint(5, 50)).values())
104
+ time.sleep(random.uniform(2, 5))
105
+ if not friends:
106
+ friends = self.default_profiles
107
+
108
+ random_friend = random.choice(friends)
109
+ target_user_id = ""
110
+ if isinstance(random_friend, UserShort):
111
+ target_user_id = random_friend.pk
112
+ self.scrapler.download_hndlr(self.scrapler.cl.user_info, target_user_id)
113
+ time.sleep(random.uniform(2, 5))
114
+ elif isinstance(random_friend, str):
115
+ target_user_id = self.scrapler.download_hndlr(self.scrapler.cl.user_id_from_username, random_friend)
116
+ self.scrapler.download_hndlr(self.scrapler.cl.user_info, target_user_id)
117
+
118
+ if random.random() > 0.7:
119
+ self.scrapler.download_hndlr(self.scrapler.cl.user_medias, target_user_id, amount=random.randint(1, 5))
120
+ except Exception as e:
121
+ logging.warning("Error in profile view")
122
+ logging.exception(e)
@@ -89,7 +89,7 @@ class IGScheduler(object):
89
89
  self.save_state()
90
90
 
91
91
  if self.state["remaining"] <= 0:
92
- self.state["remaining"] = randrange(8400, 26200)
92
+ self.state["remaining"] = randrange(4100, 22300)
93
93
  logging.info("Next scheduler activity in '%s' seconds", self.state["remaining"])
94
94
 
95
95
  start_time = time.time()
@@ -37,7 +37,7 @@ class ScraperAbstract(ABC):
37
37
  raise NotImplementedError
38
38
 
39
39
  @abstractmethod
40
- def _download_hndlr(self, func: Callable, *args: tuple[str], **kwargs: dict[str]) -> Union[str, dict]:
40
+ def download_hndlr(self, func: Callable, *args: tuple[str], **kwargs: dict[str]) -> Union[str, dict]:
41
41
  raise NotImplementedError
42
42
 
43
43
  @staticmethod
@@ -39,9 +39,6 @@ class AccountSelector(object):
39
39
  else:
40
40
  raise ValueError("Accounts file not found")
41
41
 
42
- def __del__(self) -> None:
43
- pass
44
-
45
42
  def get_account_proxy(self) -> Optional[dict]:
46
43
  if self.proxies:
47
44
  try:
@@ -59,12 +56,12 @@ class AccountSelector(object):
59
56
  if len(matched_proxy) > 1:
60
57
  random.seed(random.seed(time.time_ns() ^ int.from_bytes(os.urandom(len(matched_proxy)), "big")))
61
58
  # ensure new proxy in case if previous account required captcha
62
- last_proxy = self.accounts.get("last_proxy", None)
59
+ last_proxy = self.accounts_meta_data.get("last_proxy", None)
63
60
  if last_proxy and last_proxy in matched_proxy:
64
61
  matched_proxy.remove(last_proxy)
65
62
  prox_choice = random.choice(matched_proxy)
66
63
  # saving chosen proxy for history
67
- self.accounts["last_proxy"] = prox_choice
64
+ self.accounts_meta_data["last_proxy"] = prox_choice
68
65
  logging.info("Chosen proxy: '%s'", prox_choice)
69
66
  return prox_choice
70
67
  except Exception as e:
@@ -90,7 +87,7 @@ class AccountSelector(object):
90
87
  if module_name not in self.accounts_meta_data:
91
88
  self.accounts_meta_data[module_name] = []
92
89
  for index, _ in enumerate(lst):
93
- self.accounts_meta_data[module_name].insert(index, {"auth_fails": 0, "rate_limits": 0, "cathcha": 0})
90
+ self.accounts_meta_data[module_name].insert(index, {"auth_fails": 0, "rate_limits": 0, "captcha": 0})
94
91
 
95
92
  def set_module(self, module_origin: Origin) -> None:
96
93
  module_name = 'youtube' if next((s for s in ("yt", "youtube", "youtu_be") if s in module_origin.value), None) else 'instagram'
@@ -99,19 +96,24 @@ class AccountSelector(object):
99
96
  self.current = self.accounts[self.current_module_name][self.account_index[self.current_module_name].value]
100
97
 
101
98
  def next(self) -> dict:
102
- idx = self.account_index[self.current_module_name].value + 1
103
- if idx > len(self.accounts[self.current_module_name]) - 1:
99
+ idx = self.account_index[self.current_module_name].value
100
+ idx += 1
101
+ if idx > len(self.accounts[self.current_module_name]):
104
102
  idx = 0
105
- self.current = self.accounts[self.current_module_name][idx]
106
103
  self.account_index[self.current_module_name].value = idx
104
+ self.current = self.accounts[self.current_module_name][idx]
107
105
  logging.info("Selected account index is '%d'", idx)
108
106
  return self.current
109
-
107
+
110
108
  def bump_acc_fail(self, key: str, amount: int = 1) -> int:
111
109
  try:
112
110
  idx = self.account_index[self.current_module_name].value
111
+ meta_list = self.accounts_meta_data[self.current_module_name]
112
+ if idx >= len(meta_list):
113
+ logging.warning("Index %d out of range for module '%s' with length '%d'", idx, self.current_module_name, len(meta_list))
114
+ return 0
113
115
  self.accounts_meta_data[self.current_module_name][idx][key] += amount
114
- return self.accounts_meta_data[self.current_module_name][idx][key]
116
+ return meta_list[idx][key]
115
117
  except Exception as e:
116
118
  logging.warning("Failed to record fail stats")
117
119
  logging.exception(e)
@@ -120,14 +122,15 @@ class AccountSelector(object):
120
122
  def how_much(self, key: str) -> int:
121
123
  idx = self.account_index[self.current_module_name].value
122
124
  return self.accounts_meta_data[self.current_module_name][idx][key]
123
-
125
+
124
126
  def get_current(self) -> tuple:
125
127
  idx = self.account_index[self.current_module_name].value
126
128
  return (idx, self.accounts[self.current_module_name][idx])
127
-
129
+
128
130
  def get_meta_data(self) -> dict:
129
- return self.accounts_meta_data[self.current_module_name][self.account_index[self.current_module_name].value]
130
-
131
+ idx = self.account_index[self.current_module_name].value - 1
132
+ return self.accounts_meta_data[self.current_module_name][idx]
133
+
131
134
  def count_service_accounts(self, mod_name: Origin) -> int:
132
135
  module_name = 'youtube' if next((s for s in ("yt", "youtube", "youtu_be") if s in mod_name.value), None) else 'instagram'
133
136
  if module_name not in self.accounts:
@@ -91,7 +91,7 @@ class InstagramScraper(ScraperAbstract):
91
91
  del js["warp_timeline_cursor"]
92
92
  self.cl.set_settings(js)
93
93
  else:
94
- self._download_hndlr(self.login)
94
+ self.download_hndlr(self.login)
95
95
 
96
96
  def login(self) -> None:
97
97
  username = self.account["login"]
@@ -101,12 +101,10 @@ class InstagramScraper(ScraperAbstract):
101
101
  self.safe_write_session()
102
102
 
103
103
  def validate_session(self) -> None:
104
+ from warp_beacon.scheduler.instagram_human import InstagramHuman
104
105
  self.load_session()
105
- self.timeline_cursor = self._download_hndlr(self.cl.get_timeline_feed, "pull_to_refresh", self.timeline_cursor.get("next_max_id", None))
106
- self._download_hndlr(self.cl.get_reels_tray_feed, "pull_to_refresh")
107
- self._download_hndlr(self.cl.direct_active_presence)
108
- self._download_hndlr(self.cl.reels)
109
- #self._download_hndlr(self.cl.notification_like_and_comment_on_photo_user_tagged, "everyone")
106
+ inst_human = InstagramHuman(self)
107
+ inst_human.simulate_activity()
110
108
  self.safe_write_session()
111
109
 
112
110
  def scrap(self, url: str) -> tuple[str]:
@@ -146,7 +144,7 @@ class InstagramScraper(ScraperAbstract):
146
144
  logging.info("media_id is '%s'", media_id)
147
145
  return media_id
148
146
 
149
- def _download_hndlr(self, func: Callable, *args: tuple[str], **kwargs: dict[str]) -> Union[str, dict]:
147
+ def download_hndlr(self, func: Callable, *args: tuple[str], **kwargs: dict[str]) -> Union[str, dict]:
150
148
  ret_val = {}
151
149
  max_retries = int(os.environ.get("IG_MAX_RETRIES", default=5))
152
150
  retries = 0
@@ -189,12 +187,12 @@ class InstagramScraper(ScraperAbstract):
189
187
 
190
188
  def download_video(self, url: str, media_info: Media) -> dict:
191
189
  self.cl.request_timeout = int(os.environ.get("IG_REQUEST_TIMEOUT", default=60))
192
- path = self._download_hndlr(self.cl.video_download_by_url, url, folder='/tmp')
190
+ path = self.download_hndlr(self.cl.video_download_by_url, url, folder='/tmp')
193
191
  return {"local_media_path": str(path), "canonical_name": self.extract_canonical_name(media_info), \
194
192
  "media_type": JobType.VIDEO, "media_info": {"duration": round(media_info.video_duration)}}
195
193
 
196
194
  def download_photo(self, url: str, media_info: Media) -> dict:
197
- path = str(self._download_hndlr(self.cl.photo_download_by_url, url, folder='/tmp'))
195
+ path = str(self.download_hndlr(self.cl.photo_download_by_url, url, folder='/tmp'))
198
196
  path_lowered = path.lower()
199
197
  if ".webp" in path_lowered:
200
198
  path = InstagramScraper.convert_webp_to_png(path)
@@ -213,7 +211,7 @@ class InstagramScraper(ScraperAbstract):
213
211
  logging.info("Effective story id is '%s'", effective_story_id)
214
212
  effective_url = "https://www.instagram.com/stories/%s/%s/" % (story_info.user.username, effective_story_id)
215
213
  if story_info.media_type == 1: # photo
216
- path = str(self._download_hndlr(self.cl.story_download_by_url, url=story_info.thumbnail_url, folder='/tmp'))
214
+ path = str(self.download_hndlr(self.cl.story_download_by_url, url=story_info.thumbnail_url, folder='/tmp'))
217
215
  path_lowered = path.lower()
218
216
  if ".webp" in path_lowered:
219
217
  path = InstagramScraper.convert_webp_to_png(path)
@@ -221,7 +219,7 @@ class InstagramScraper(ScraperAbstract):
221
219
  path = InstagramScraper.convert_heic_to_png(path)
222
220
  media_type = JobType.IMAGE
223
221
  elif story_info.media_type == 2: # video
224
- path = str(self._download_hndlr(self.cl.story_download_by_url, url=story_info.video_url, folder='/tmp'))
222
+ path = str(self.download_hndlr(self.cl.story_download_by_url, url=story_info.video_url, folder='/tmp'))
225
223
  media_type = JobType.VIDEO
226
224
  media_info["duration"] = story_info.video_duration
227
225
 
@@ -242,7 +240,7 @@ class InstagramScraper(ScraperAbstract):
242
240
  for media_chunk in Utils.chunker(media_info.resources, 10):
243
241
  chunk = []
244
242
  for media in media_chunk:
245
- _media_info = self._download_hndlr(self.cl.media_info, media.pk)
243
+ _media_info = self.download_hndlr(self.cl.media_info, media.pk)
246
244
  if media.media_type == 1: # photo
247
245
  chunk.append(self.download_photo(url=_media_info.thumbnail_url, media_info=_media_info))
248
246
  elif media.media_type == 2: # video
@@ -270,7 +268,7 @@ class InstagramScraper(ScraperAbstract):
270
268
  try:
271
269
  scrap_type, media_id = self.scrap(job.url)
272
270
  if scrap_type == "media":
273
- media_info = self._download_hndlr(self.cl.media_info, media_id)
271
+ media_info = self.download_hndlr(self.cl.media_info, media_id)
274
272
  logging.info("media_type is '%d', product_type is '%s'", media_info.media_type, media_info.product_type)
275
273
  if media_info.media_type == 2 and media_info.product_type == "clips": # Reels
276
274
  res.append(self.download_video(url=media_info.video_url, media_info=media_info))
@@ -181,7 +181,7 @@ class YoutubeAbstract(ScraperAbstract):
181
181
 
182
182
  return None
183
183
 
184
- def _download_hndlr(self, func: Callable, *args: tuple[Union[str, int, dict, tuple]], **kwargs: dict[Union[str, int, dict, tuple]]) -> Union[str, dict, io.BytesIO]:
184
+ def download_hndlr(self, func: Callable, *args: tuple[Union[str, int, dict, tuple]], **kwargs: dict[Union[str, int, dict, tuple]]) -> Union[str, dict, io.BytesIO]:
185
185
  ret_val = ''
186
186
  max_retries = int(os.environ.get("YT_MAX_RETRIES", default=self.YT_MAX_RETRIES_DEFAULT))
187
187
  pause_secs = int(os.environ.get("YT_PAUSE_BEFORE_RETRY", default=self.YT_PAUSE_BEFORE_RETRY_DEFAULT))
@@ -247,4 +247,4 @@ class YoutubeAbstract(ScraperAbstract):
247
247
  raise NotImplementedError("Implement _download method")
248
248
 
249
249
  def download(self, job: DownloadJob) -> list:
250
- return self._download_hndlr(self._download, job.url)
250
+ return self.download_hndlr(self._download, job.url)
@@ -16,7 +16,7 @@ class YoutubeMusicScraper(YoutubeAbstract):
16
16
  yt = self.build_yt(url)
17
17
 
18
18
  if yt:
19
- thumbnail = self._download_hndlr(self.download_thumbnail, yt.video_id)
19
+ thumbnail = self.download_hndlr(self.download_thumbnail, yt.video_id)
20
20
 
21
21
  stream = yt.streams.get_audio_only()
22
22
 
@@ -31,7 +31,7 @@ class YoutubeShortsScraper(YoutubeAbstract):
31
31
 
32
32
  local_file = self.rename_local_file(local_file)
33
33
  vinfo = VideoInfo(local_file)
34
- thumbnail = self._download_hndlr(self.download_thumbnail, video_id=yt.video_id, crop_center=vinfo.get_demensions())
34
+ thumbnail = self.download_hndlr(self.download_thumbnail, video_id=yt.video_id, crop_center=vinfo.get_demensions())
35
35
 
36
36
  logging.debug("Temp filename: '%s'", local_file)
37
37
  res.append({
@@ -38,7 +38,7 @@ class YoutubeScraper(YoutubeAbstract):
38
38
  raise YoutubeLiveError("Youtube Live is not supported")
39
39
 
40
40
  if yt:
41
- thumbnail = self._download_hndlr(self.download_thumbnail, yt.video_id)
41
+ thumbnail = self.download_hndlr(self.download_thumbnail, yt.video_id)
42
42
 
43
43
  stream = yt.streams.get_highest_resolution()
44
44
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: warp_beacon
3
- Version: 2.3.31
3
+ Version: 2.3.33
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
@@ -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=6WuiVqC37jmvlGi1GNaJkQDAVLgaOvkYIZwJr1WO5FM,24
7
+ warp_beacon/__version__.py,sha256=WAgFhMhZGBLKDYqTRfciJPsMCU1ZjYeOKqmTRtjDVLI,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
@@ -19,20 +19,21 @@ warp_beacon/mediainfo/audio.py,sha256=ous88kwQj4bDIChN5wnGil5LqTs0IQHH0d-nyrL0-Z
19
19
  warp_beacon/mediainfo/silencer.py,sha256=qxMuViOoVwUYb60uCVvqHiGrqByR1_4_rqMT-XdMkwc,1813
20
20
  warp_beacon/mediainfo/video.py,sha256=UBZrhTN5IDI-aYu6tsJEILo9nFkjHhkldGVFmvV7tEI,2480
21
21
  warp_beacon/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- warp_beacon/scheduler/scheduler.py,sha256=WFfV5flS4xtqNjalM95KW4jLMJ70PskRpP9e7cUQM2U,2796
22
+ warp_beacon/scheduler/instagram_human.py,sha256=pTYH6RHWSXcLN3lW2XW33rZvfzEDbhIofGAZLNy34Vk,4536
23
+ warp_beacon/scheduler/scheduler.py,sha256=2y2eDBxkE5vHRpSVcV-mwYnxFuueMalK3LOhgUecNSA,2796
23
24
  warp_beacon/scraper/__init__.py,sha256=V_C5SmAmRtjFfVBtTotOHCW3ILMQ8m_ulrBF6ry59_A,16944
24
- warp_beacon/scraper/abstract.py,sha256=6A6KuBUHZhu8VAyBwLgmnxMPHJcLpgwLapmULy8hpoA,2726
25
- warp_beacon/scraper/account_selector.py,sha256=zv5ci_Y7W-tzKeFklffpLts19a1wFg69fqefK-_i_pk,5122
25
+ warp_beacon/scraper/abstract.py,sha256=28a0aBKZpi8IKptLWdB6RuVbOkrUbrhT7LSZX7QRQtg,2725
26
+ warp_beacon/scraper/account_selector.py,sha256=D_L9zwmRmvGBBEg5uUU3DmLwXnKnADwF16-QGXvlrjc,5313
26
27
  warp_beacon/scraper/exceptions.py,sha256=Qkz76yo-X5kucEZIP9tWaK-oYO-kvsPEl8Y0W63oDhU,1300
27
28
  warp_beacon/scraper/fail_handler.py,sha256=_blvckfTZ4xWVancQKVRXH5ClKGwfrBxMwvXIFZh1qA,975
28
29
  warp_beacon/scraper/link_resolver.py,sha256=Rc9ZuMyOo3iPywDHwjngy-WRQ2SXhJwxcg-5ripx7tM,2447
29
30
  warp_beacon/scraper/instagram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- warp_beacon/scraper/instagram/instagram.py,sha256=coAYqsiWUKhsI_azNYNuAbR9bE36gYC0OD4ah-SUedM,14086
31
+ warp_beacon/scraper/instagram/instagram.py,sha256=TpIBS9S3zcLbeGax4CENVo6WP75EE6oIttc-MjWYVjs,13815
31
32
  warp_beacon/scraper/youtube/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- warp_beacon/scraper/youtube/abstract.py,sha256=cBtExei2Cb3o4YBtHqi8If_FdmE6NyJqNKacm5aw7S0,9243
33
- warp_beacon/scraper/youtube/music.py,sha256=qbijpSv54fsrIYHeY-nfmw4vo6oBmedQHsVG8pXNfrc,1380
34
- warp_beacon/scraper/youtube/shorts.py,sha256=ujGEV7ILXHqBRa99SyITsnR7ulAHJDtumAh51kVX880,1231
35
- warp_beacon/scraper/youtube/youtube.py,sha256=fGrbjBngvvNdpzhb1yZVedNW0_tCrLc31VSYMSHzcQY,2135
33
+ warp_beacon/scraper/youtube/abstract.py,sha256=fF22knm5h4V9PupGP-vcJ_KPXrW3_qNpSSG5DvQFZAk,9241
34
+ warp_beacon/scraper/youtube/music.py,sha256=MObH7rU6qmg6xG3rRkO4iqmhm8uF4UlF2OqfF4G1eec,1379
35
+ warp_beacon/scraper/youtube/shorts.py,sha256=Ij4IVCOfYGHvmbRbrE4Zli0GiHlM4qhd9wiUzr6qeUE,1230
36
+ warp_beacon/scraper/youtube/youtube.py,sha256=Fz_svj9h7tam4UIfyYgxu6kRgPgdTmPeULmefLE-z2c,2134
36
37
  warp_beacon/storage/__init__.py,sha256=0Vajd0oITKJfu2vmNx5uQSt3-L6vwIvUYWJo8HZCjco,3398
37
38
  warp_beacon/storage/mongo.py,sha256=qC4ZiO8XXvPnP0rJwz4CJx42pqFsyAjCiW10W5QdT6E,527
38
39
  warp_beacon/telegram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -42,9 +43,9 @@ warp_beacon/telegram/handlers.py,sha256=XXIfdV_RCj7tyZMPXchuKmGoDdweOaR08ADDaBPW
42
43
  warp_beacon/telegram/placeholder_message.py,sha256=wN9-BRiyrtHG-EvXtZkGJHt2CX71munQ57ITttjt0mw,6400
43
44
  warp_beacon/telegram/utils.py,sha256=9uebX53G16mV7ER7WgfdWBLFHHw14S8HBt9URrIskg0,4440
44
45
  warp_beacon/uploader/__init__.py,sha256=E9rlZIf7xlQz6MutMOwJ8S5Vm2uheR5nv23Kv8duRQg,5427
45
- warp_beacon-2.3.31.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
46
- warp_beacon-2.3.31.dist-info/METADATA,sha256=NJdQjwobTeXr3CfN4u7ojakyoLlIbPXXghSbVBHj3uc,21723
47
- warp_beacon-2.3.31.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
48
- warp_beacon-2.3.31.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
49
- warp_beacon-2.3.31.dist-info/top_level.txt,sha256=2iKFlYwJ-meO9sCX4OGEP1hhQN17t2KFksQ5dXMhXUA,1103
50
- warp_beacon-2.3.31.dist-info/RECORD,,
46
+ warp_beacon-2.3.33.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
+ warp_beacon-2.3.33.dist-info/METADATA,sha256=A68uP9xrdhTEoCYMdYFWlYVTCJqJvJll1d0XfpXA40Y,21723
48
+ warp_beacon-2.3.33.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
49
+ warp_beacon-2.3.33.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
50
+ warp_beacon-2.3.33.dist-info/top_level.txt,sha256=qGjHVVfyf6lTmbdSA-fQq0rHS1YVS4HoJT3rag5xgPE,1141
51
+ warp_beacon-2.3.33.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (76.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -12,6 +12,7 @@ warp_beacon/mediainfo/audio
12
12
  warp_beacon/mediainfo/silencer
13
13
  warp_beacon/mediainfo/video
14
14
  warp_beacon/scheduler
15
+ warp_beacon/scheduler/instagram_human
15
16
  warp_beacon/scheduler/scheduler
16
17
  warp_beacon/scraper
17
18
  warp_beacon/scraper/abstract