warp-beacon 2.6.31__py3-none-any.whl → 2.6.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.6.31"
1
+ __version__ = "2.6.33"
2
2
 
@@ -3,10 +3,12 @@ import os
3
3
  import time
4
4
  from typing import Optional
5
5
  import multiprocessing
6
+ from multiprocessing.managers import Namespace
6
7
  from queue import Empty
7
8
 
8
9
  import logging
9
10
 
11
+ from warp_beacon.scraper.utils import Utils
10
12
  from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, FileTooBig, YoutubeLiveError, \
11
13
  YotubeAgeRestrictedError, IGRateLimitOccurred, CaptchaIssue, AllAccountsFailed, BadProxy
12
14
  from warp_beacon.mediainfo.video import VideoInfo
@@ -39,12 +41,15 @@ class AsyncDownloader(object):
39
41
  acc_selector = None
40
42
  scheduler = None
41
43
  scrolling_now = None
44
+ process_context = None
42
45
 
43
46
  def __init__(self, uploader: AsyncUploader, workers_count: int) -> None:
44
47
  self.workers = []
45
48
  self.job_queue = multiprocessing.Queue()
46
49
  self.auth_event = multiprocessing.Event()
47
50
  self.manager = multiprocessing.Manager()
51
+ self.process_context = self.manager.Namespace()
52
+ self.process_context.ig_session_client_id = Utils.get_ig_session_id()
48
53
  self.allow_loop = self.manager.Value('i', 1)
49
54
  self.scrolling_now = self.manager.Value('i', 0)
50
55
  self.acc_selector = AccountSelector(self.manager, ACC_FILE, PROXY_FILE)
@@ -58,7 +63,7 @@ class AsyncDownloader(object):
58
63
 
59
64
  def start(self) -> None:
60
65
  for _ in range(self.workers_count):
61
- proc = multiprocessing.Process(target=self.do_work, args=(self.acc_selector,))
66
+ proc = multiprocessing.Process(target=self.do_work, args=(self.acc_selector, self.process_context))
62
67
  self.workers.append(proc)
63
68
  proc.start()
64
69
 
@@ -95,7 +100,7 @@ class AsyncDownloader(object):
95
100
  job.account_switches += 1
96
101
  selector.reset_ig_request_count()
97
102
 
98
- def do_work(self, selector: AccountSelector) -> None:
103
+ def do_work(self, selector: AccountSelector, context: Namespace) -> None:
99
104
  logging.info("download worker started")
100
105
  # pymongo is not fork-safe so new connect to DB required
101
106
  fail_handler = FailHandler(DBClient())
@@ -136,7 +141,8 @@ class AsyncDownloader(object):
136
141
  proxy = selector.get_current_proxy()
137
142
  if job.job_origin is Origin.INSTAGRAM:
138
143
  from warp_beacon.scraper.instagram.instagram import InstagramScraper
139
- actor = InstagramScraper(selector.get_current(), proxy)
144
+ Utils.maybe_rotate_ig_client_session(context)
145
+ actor = InstagramScraper(client_session_id=context.ig_session_client_id, account=selector.get_current(), proxy=proxy)
140
146
  selector.inc_ig_request_count()
141
147
  if not job.scroll_content and selector.get_ig_request_count() >= int(os.environ.get("IG_REQUESTS_PER_ACCOUNT", default="10")):
142
148
  logging.info("The account request limit has been reached. Selecting the next account.")
@@ -429,6 +435,7 @@ class AsyncDownloader(object):
429
435
  def stop_all(self) -> None:
430
436
  self.allow_loop.value = 0
431
437
  self.acc_selector.save_ig_request_count()
438
+ Utils.save_ig_session_id(self.process_context.ig_session_client_id)
432
439
  for proc in self.workers:
433
440
  if proc.is_alive():
434
441
  logging.info("stopping process #%d", proc.pid)
@@ -161,7 +161,11 @@ class AccountSelector(object):
161
161
  module_name = self.get_module_name(module_origin)
162
162
  self.current_module_name = module_name
163
163
  if self.current is None:
164
- self.current = self.accounts[self.current_module_name][self.account_index[self.current_module_name].value]
164
+ idx = self.account_index[self.current_module_name].value
165
+ self.current = self.accounts[self.current_module_name][idx]
166
+ if not self.current.get("enabled", True):
167
+ logging.info("Account '%d' is disabled. Probing next ...", idx)
168
+ self.next()
165
169
  self.current_proxy = self.get_random_account_proxy()
166
170
 
167
171
  def next(self) -> dict:
@@ -171,6 +175,9 @@ class AccountSelector(object):
171
175
  idx = 0
172
176
  self.account_index[self.current_module_name].value = idx
173
177
  self.current = self.accounts[self.current_module_name][idx]
178
+ if not self.current.get("enabled", True):
179
+ logging.info("Account '%d' is disabled. Probing next ...", idx)
180
+ return self.next()
174
181
  logging.info("Selected account index is '%d'", idx)
175
182
  return self.current
176
183
 
@@ -36,8 +36,10 @@ class InstagramScraper(ScraperAbstract):
36
36
  cl = None
37
37
  inst_session_file = ""
38
38
  timeline_cursor = {}
39
+ client_session_id = ""
39
40
 
40
- def __init__(self, account: tuple, proxy: dict=None) -> None:
41
+ def __init__(self, client_session_id: str, account: tuple, proxy: dict=None) -> None:
42
+ self.client_session_id = client_session_id
41
43
  super().__init__(account, proxy)
42
44
  #
43
45
  self.inst_session_file = INST_SESSION_FILE_TPL % self.account_index
@@ -53,6 +55,8 @@ class InstagramScraper(ScraperAbstract):
53
55
  self.cl.change_password_handler = self.change_password_handler
54
56
 
55
57
  def setup_device(self) -> None:
58
+ if not self.client_session_id:
59
+ self.client_session_id = self.cl.generate_uuid()
56
60
  details = self.account.get("auth_details", {})
57
61
  self.cl.delay_range = details.get("delay_range", [1, 3])
58
62
  self.cl.set_country_code(details.get("country_code", 1))
@@ -76,7 +80,7 @@ class InstagramScraper(ScraperAbstract):
76
80
  self.cl.set_uuids({
77
81
  "phone_id": uuids.get("phone_id", self.cl.generate_uuid()),
78
82
  "uuid": uuids.get("uuid", self.cl.generate_uuid()),
79
- "client_session_id": uuids.get("client_session_id", self.cl.generate_uuid()),
83
+ "client_session_id": self.client_session_id,
80
84
  "advertising_id": uuids.get("advertising_id", self.cl.generate_uuid()),
81
85
  "device_id": uuids.get("device_id", self.cl.generate_uuid())
82
86
  })
@@ -0,0 +1,40 @@
1
+ import os
2
+ from multiprocessing.managers import Namespace
3
+ import random
4
+ import uuid
5
+ import logging
6
+
7
+ class Utils(object):
8
+ session_dir = "/var/warp_beacon"
9
+
10
+ @staticmethod
11
+ def get_ig_session_id() -> str:
12
+ ig_session_client_id = ""
13
+ try:
14
+ sess_file = f"{Utils.session_dir}/ig_session_client_id"
15
+ if os.path.exists(sess_file):
16
+ with open(sess_file, 'r', encoding="utf-8") as f:
17
+ ig_session_client_id = f.read().strip()
18
+ except Exception as e:
19
+ logging.warning("Failed to read session ig_session_client_id!")
20
+ logging.exception(e)
21
+
22
+ if not ig_session_client_id:
23
+ ig_session_client_id = str(uuid.uuid4())
24
+
25
+ return ig_session_client_id
26
+
27
+ @staticmethod
28
+ def save_ig_session_id(ig_session_client_id: str) -> None:
29
+ try:
30
+ with open(f"{Utils.session_dir}/ig_session_client_id", "w+", encoding="utf-8") as f:
31
+ f.write(ig_session_client_id)
32
+ except Exception as e:
33
+ logging.warning("Failed to save session ig_session_client_id!")
34
+ logging.exception(e)
35
+
36
+ @staticmethod
37
+ def maybe_rotate_ig_client_session(context: Namespace) -> None:
38
+ if random.random() > 0.95:
39
+ context.ig_session_client_id = str(uuid.uuid4())
40
+ logging.info("Rotated client_session_id — simulating app restart")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warp_beacon
3
- Version: 2.6.31
3
+ Version: 2.6.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=i4mn5ueT4BUBjWT8wNPTPpy1rqb9IOQ-juTm6FCv-zs,24
7
+ warp_beacon/__version__.py,sha256=EhSBAgTsvMy3ocyZX2oGpI8vIL6KfXQjHozyx-Obe9Y,24
8
8
  warp_beacon/warp_beacon.py,sha256=ED43vNzdjDUJ_9qLCbri0bjWLWEJ69BENGj9i7G6AvM,342
9
9
  warp_beacon/yt_auth.py,sha256=GUTKqYr_tzDC-07Lx_ahWXSag8EyLxXBUnQbDBIkEmk,6022
10
10
  warp_beacon/compress/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,15 +22,16 @@ warp_beacon/mediainfo/video.py,sha256=UBZrhTN5IDI-aYu6tsJEILo9nFkjHhkldGVFmvV7tE
22
22
  warp_beacon/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  warp_beacon/scheduler/instagram_human.py,sha256=0LaRUu0MBBuEOQeFzuq22HIYfJL9pTK_7udsXfef0Fk,8204
24
24
  warp_beacon/scheduler/scheduler.py,sha256=9OCh7Ta4wY_aTHGAOOZmaKXg56Ftx1N_aV1g6E3ZLKA,4941
25
- warp_beacon/scraper/__init__.py,sha256=y6_26l18Bdrms9jeW1mJipmj6lKCpPQNZlieoXFnqLc,19822
25
+ warp_beacon/scraper/__init__.py,sha256=O8L8KIKt7Xszql0tUPCNMiaxyZduMZjfADAP4V5s9bk,20286
26
26
  warp_beacon/scraper/abstract.py,sha256=yP76ae9U73LYW2lDN6XWkXDkWX1h2UVOrkqv0Sqpu2Y,2985
27
- warp_beacon/scraper/account_selector.py,sha256=nFqN-fPWxx7H7tOcdweZpGuv2TVN9isnziqb-HXsSmc,7888
27
+ warp_beacon/scraper/account_selector.py,sha256=7sog5tFPNv6jWJ5m-7nAglAyzd3Qc3G4dfjk8iYFONI,8163
28
28
  warp_beacon/scraper/exceptions.py,sha256=EKwoF0oH2xZWbNU-v8DOaWK5skKwa3s1yTIBdlcfMpc,1452
29
29
  warp_beacon/scraper/fail_handler.py,sha256=zcPK3ZVEsu6JmHYcWP7L3naTRK3gWFVRkpP84VBOtJs,964
30
30
  warp_beacon/scraper/link_resolver.py,sha256=Rc9ZuMyOo3iPywDHwjngy-WRQ2SXhJwxcg-5ripx7tM,2447
31
+ warp_beacon/scraper/utils.py,sha256=BI0X6Wu2pZ8hKaiOAYooBKjhqE-tl3FfgOTAmzgMp6M,1208
31
32
  warp_beacon/scraper/instagram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
33
  warp_beacon/scraper/instagram/captcha.py,sha256=9UYziuqB3Tsat_ET6ex-cnZDbi6yCnsXHSpmE8MuUHk,4651
33
- warp_beacon/scraper/instagram/instagram.py,sha256=eyYAveSVoAvDm0rOF187bieqy-i3tsw0KBsLbzPvYDM,15443
34
+ warp_beacon/scraper/instagram/instagram.py,sha256=zbkF-1lU5lxJ_2m8i8mGRX0EQMLVSflsOafBM1FEC6s,15588
34
35
  warp_beacon/scraper/youtube/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
36
  warp_beacon/scraper/youtube/abstract.py,sha256=QUSHR3aJjIykuRlBpGnmw3tq3m82AQeeZeWQUdJRvgQ,12538
36
37
  warp_beacon/scraper/youtube/music.py,sha256=5AeSBQyUgVCJT2hoBCV2WvlyuV9US09SYJhmBG_P9F8,2755
@@ -45,9 +46,9 @@ warp_beacon/telegram/handlers.py,sha256=uvR6TPHSqdSxigp3wR-ewiE6t3TvVcbVLVcYGwkg
45
46
  warp_beacon/telegram/placeholder_message.py,sha256=wN9-BRiyrtHG-EvXtZkGJHt2CX71munQ57ITttjt0mw,6400
46
47
  warp_beacon/telegram/utils.py,sha256=1Lq67aRylVJzbwSyvAgjPAGjJZFATkICvAj3TJGuJiM,4635
47
48
  warp_beacon/uploader/__init__.py,sha256=j3qcuKhpchseZLGzSsSiogqe6WdMbkK8d3I-ConhNRs,5687
48
- warp_beacon-2.6.31.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
- warp_beacon-2.6.31.dist-info/METADATA,sha256=XmMkA3SZJW5WkrIGNPUNpgjI5c6-r08V622-E2zTA_o,22706
50
- warp_beacon-2.6.31.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
51
- warp_beacon-2.6.31.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
52
- warp_beacon-2.6.31.dist-info/top_level.txt,sha256=4ML0-mXsezLtRXyxQUntL_ktc5HX9npTeQWzvV8kFvA,1161
53
- warp_beacon-2.6.31.dist-info/RECORD,,
49
+ warp_beacon-2.6.33.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
50
+ warp_beacon-2.6.33.dist-info/METADATA,sha256=txwoubgNiyIrmstWZBebz0CvW8QIJY_lcuQNh1AYeAo,22706
51
+ warp_beacon-2.6.33.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
52
+ warp_beacon-2.6.33.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
53
+ warp_beacon-2.6.33.dist-info/top_level.txt,sha256=aFsWDQBplsMOyVMGGJ8iu-auZ25z1e_IB4tM2M8kW1A,1187
54
+ warp_beacon-2.6.33.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.1.0)
2
+ Generator: setuptools (80.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -23,6 +23,7 @@ warp_beacon/scraper/instagram
23
23
  warp_beacon/scraper/instagram/instagram
24
24
  warp_beacon/scraper/link_resolver
25
25
  warp_beacon/scraper/types
26
+ warp_beacon/scraper/utils
26
27
  warp_beacon/scraper/youtube
27
28
  warp_beacon/scraper/youtube/abstract
28
29
  warp_beacon/scraper/youtube/music