warp-beacon 2.3.30__py3-none-any.whl → 2.3.32__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.30"
1
+ __version__ = "2.3.32"
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)
@@ -85,8 +85,8 @@ class IGScheduler(object):
85
85
  now = datetime.datetime.now()
86
86
  if 4 <= now.hour < 7:
87
87
  logging.info("Scheduler is paused due to night hours (4:00 - 7:00)")
88
- self.event.wait(timeout=10800)
89
- continue
88
+ self.state["remaining"] = 10800
89
+ self.save_state()
90
90
 
91
91
  if self.state["remaining"] <= 0:
92
92
  self.state["remaining"] = randrange(8400, 26200)
@@ -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:
@@ -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,15 +1,13 @@
1
1
  import os
2
- import threading
3
- import multiprocessing
4
- from warp_beacon.jobs.upload_job import UploadJob
5
2
  import logging
6
-
7
- import asyncio
8
-
9
3
  from typing import Callable
4
+ import asyncio
5
+ import threading
6
+ import multiprocessing
10
7
 
11
- from warp_beacon.storage import Storage
12
8
  from warp_beacon.jobs.types import JobType
9
+ from warp_beacon.jobs.upload_job import UploadJob
10
+ from warp_beacon.storage import Storage
13
11
 
14
12
  class AsyncUploader(object):
15
13
  __JOE_BIDEN_WAKEUP = None
@@ -40,10 +38,9 @@ class AsyncUploader(object):
40
38
  self.threads.append(thread)
41
39
 
42
40
  def add_callback(self, message_id: int, callback: Callable) -> None:
43
- def callback_wrap(*args, **kwargs) -> None:
44
- ret = callback(*args, **kwargs)
41
+ async def callback_wrap(*args, **kwargs) -> None:
42
+ await callback(*args, **kwargs)
45
43
  #self.remove_callback(message_id)
46
- return ret
47
44
  self.callbacks[message_id] = {"callback": callback_wrap}
48
45
 
49
46
  def remove_callback(self, message_id: int) -> None:
@@ -83,7 +80,11 @@ class AsyncUploader(object):
83
80
  if job is self.__JOE_BIDEN_WAKEUP:
84
81
  break
85
82
  if job.is_message_to_admin and job.message_text and self.admin_message_callback:
86
- asyncio.ensure_future(self.admin_message_callback(job.message_text, job.account_admins, job.yt_auth), loop=self.loop)
83
+ #asyncio.ensure_future(self.admin_message_callback(job.message_text, job.account_admins, job.yt_auth), loop=self.loop)
84
+ self.loop.call_soon_threadsafe(
85
+ asyncio.create_task,
86
+ self.admin_message_callback(job.message_text, job.account_admins, job.yt_auth)
87
+ )
87
88
  continue
88
89
 
89
90
  path = ""
@@ -106,20 +107,29 @@ class AsyncUploader(object):
106
107
  if job.job_failed:
107
108
  logging.info("URL '%s' download failed. Skipping upload job ...", job.url)
108
109
  if job.job_failed_msg: # we want to say something to user
109
- asyncio.ensure_future(self.callbacks[message_id]["callback"](job), loop=self.loop)
110
+ self.loop.call_soon_threadsafe(
111
+ asyncio.create_task,
112
+ self.callbacks[message_id]["callback"](job)
113
+ )
110
114
  self.process_done(uniq_id)
111
115
  self.remove_callback(message_id)
112
116
  continue
113
117
 
114
118
  if job.replay:
115
- asyncio.ensure_future(self.callbacks[message_id]["callback"](job), loop=self.loop)
119
+ self.loop.call_soon_threadsafe(
120
+ asyncio.create_task,
121
+ self.callbacks[message_id]["callback"](job)
122
+ )
116
123
  self.remove_callback(message_id)
117
124
  continue
118
125
 
119
126
  if job.job_warning:
120
127
  logging.info("Job warning occurred ...")
121
128
  if job.job_warning_msg:
122
- asyncio.ensure_future(self.callbacks[message_id]["callback"](job), loop=self.loop)
129
+ self.loop.call_soon_threadsafe(
130
+ asyncio.create_task,
131
+ self.callbacks[message_id]["callback"](job)
132
+ )
123
133
  continue
124
134
  if in_process:
125
135
  db_list_dicts = self.storage.db_lookup_id(uniq_id)
@@ -131,14 +141,22 @@ class AsyncUploader(object):
131
141
  job.media_type = JobType.COLLECTION
132
142
  elif dlds_len:
133
143
  job.tg_file_id = ",".join(tg_file_ids)
134
- job.media_type = JobType[db_list_dicts.pop()["media_type"].upper()]
135
- asyncio.ensure_future(self.callbacks[message_id]["callback"](job), loop=self.loop)
144
+ db_data = db_list_dicts.pop()
145
+ job.media_type = JobType[db_data["media_type"].upper()]
146
+ job.canonical_name = db_data.get("canonical_name", "")
147
+ self.loop.call_soon_threadsafe(
148
+ asyncio.create_task,
149
+ self.callbacks[message_id]["callback"](job)
150
+ )
136
151
  self.process_done(uniq_id)
137
152
  self.remove_callback(message_id)
138
153
  else:
139
154
  self.queue_task(job)
140
155
  else:
141
- asyncio.ensure_future(self.callbacks[message_id]["callback"](job), loop=self.loop)
156
+ self.loop.call_soon_threadsafe(
157
+ asyncio.create_task,
158
+ self.callbacks[message_id]["callback"](job)
159
+ )
142
160
  self.process_done(uniq_id)
143
161
  self.remove_callback(message_id)
144
162
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: warp_beacon
3
- Version: 2.3.30
3
+ Version: 2.3.32
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=cSmfFyGYM7UJoGqEAT0K9D1NV7L4Ep57nP19s355w5Y,24
7
+ warp_beacon/__version__.py,sha256=TmzvPiiRzO7WaFqgS-HlMj8zsmWY25iUmd_agVFhxoo,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=gcV-e-9MjL8JEfu7T3Gy1imUrXz266ub9Ub4O27W5Hw,2786
22
+ warp_beacon/scheduler/instagram_human.py,sha256=pTYH6RHWSXcLN3lW2XW33rZvfzEDbhIofGAZLNy34Vk,4536
23
+ warp_beacon/scheduler/scheduler.py,sha256=WFfV5flS4xtqNjalM95KW4jLMJ70PskRpP9e7cUQM2U,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=dMy-2e7dOQfPDky7uS-CABNctxjk8pJUpHBb_DkcZBk,5293
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
@@ -41,10 +42,10 @@ warp_beacon/telegram/caption_shortener.py,sha256=EnguNCF52ne7y4P-iJAbI6K3sqoJqJb
41
42
  warp_beacon/telegram/handlers.py,sha256=XXIfdV_RCj7tyZMPXchuKmGoDdweOaR08ADDaBPWo_U,9426
42
43
  warp_beacon/telegram/placeholder_message.py,sha256=wN9-BRiyrtHG-EvXtZkGJHt2CX71munQ57ITttjt0mw,6400
43
44
  warp_beacon/telegram/utils.py,sha256=9uebX53G16mV7ER7WgfdWBLFHHw14S8HBt9URrIskg0,4440
44
- warp_beacon/uploader/__init__.py,sha256=5KRWsxPRGuQ56YhCEnJsXnb-yQp8dpvWEsPDf0dD-fw,4964
45
- warp_beacon-2.3.30.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
46
- warp_beacon-2.3.30.dist-info/METADATA,sha256=IcCO7CHThGGOOcmKujEo04FVRsnksDoecjuBSpLSFkI,21723
47
- warp_beacon-2.3.30.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
48
- warp_beacon-2.3.30.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
49
- warp_beacon-2.3.30.dist-info/top_level.txt,sha256=2iKFlYwJ-meO9sCX4OGEP1hhQN17t2KFksQ5dXMhXUA,1103
50
- warp_beacon-2.3.30.dist-info/RECORD,,
45
+ warp_beacon/uploader/__init__.py,sha256=E9rlZIf7xlQz6MutMOwJ8S5Vm2uheR5nv23Kv8duRQg,5427
46
+ warp_beacon-2.3.32.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
+ warp_beacon-2.3.32.dist-info/METADATA,sha256=wPSUnvtAq7R-FhOJ1e_myE7zdaBD1iLZ8N5Wq-7DfwY,21723
48
+ warp_beacon-2.3.32.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
49
+ warp_beacon-2.3.32.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
50
+ warp_beacon-2.3.32.dist-info/top_level.txt,sha256=qGjHVVfyf6lTmbdSA-fQq0rHS1YVS4HoJT3rag5xgPE,1141
51
+ warp_beacon-2.3.32.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