warp-beacon 2.1.6__tar.gz → 2.1.8__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.
- {warp_beacon-2.1.6/warp_beacon.egg-info → warp_beacon-2.1.8}/PKG-INFO +1 -1
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/setup.py +3 -1
- warp_beacon-2.1.8/warp_beacon/__init__.py +7 -0
- warp_beacon-2.1.8/warp_beacon/__version__.py +2 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/jobs/abstract.py +2 -0
- warp_beacon-2.1.8/warp_beacon/scheduler/scheduler.py +62 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/__init__.py +24 -8
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/exceptions.py +1 -1
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/instagram/instagram.py +8 -4
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/telegram/bot.py +1 -4
- {warp_beacon-2.1.6 → warp_beacon-2.1.8/warp_beacon.egg-info}/PKG-INFO +1 -1
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon.egg-info/SOURCES.txt +2 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon.egg-info/top_level.txt +2 -0
- warp_beacon-2.1.6/warp_beacon/__version__.py +0 -2
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/LICENSE +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/MANIFEST.in +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/README.md +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/assets/placeholder.gif +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/etc/.gitignore +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/etc/accounts.json +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/etc/warp_beacon.conf +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/etc/warp_beacon.service +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/pyproject.toml +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/setup.cfg +0 -0
- {warp_beacon-2.1.6/warp_beacon → warp_beacon-2.1.8/warp_beacon/compress}/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/compress/video.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/jobs/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/jobs/download_job.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/jobs/types.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/jobs/upload_job.py +0 -0
- {warp_beacon-2.1.6/warp_beacon/compress → warp_beacon-2.1.8/warp_beacon/mediainfo}/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/mediainfo/abstract.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/mediainfo/audio.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/mediainfo/silencer.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/mediainfo/video.py +0 -0
- {warp_beacon-2.1.6/warp_beacon/mediainfo → warp_beacon-2.1.8/warp_beacon/scheduler}/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/abstract.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/account_selector.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/instagram/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/youtube/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/youtube/abstract.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/youtube/music.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/youtube/shorts.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/scraper/youtube/youtube.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/storage/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/telegram/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/telegram/handlers.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/telegram/placeholder_message.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/telegram/utils.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/uploader/__init__.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon/warp_beacon.py +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon.egg-info/dependency_links.txt +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon.egg-info/entry_points.txt +0 -0
- {warp_beacon-2.1.6 → warp_beacon-2.1.8}/warp_beacon.egg-info/requires.txt +0 -0
@@ -54,7 +54,8 @@ setup(
|
|
54
54
|
'warp_beacon/scraper/youtube',
|
55
55
|
'warp_beacon/mediainfo',
|
56
56
|
'warp_beacon/jobs',
|
57
|
-
'warp_beacon/compress'
|
57
|
+
'warp_beacon/compress',
|
58
|
+
'warp_beacon/scheduler'
|
58
59
|
],
|
59
60
|
py_modules=[
|
60
61
|
"warp_beacon/__version__",
|
@@ -71,6 +72,7 @@ setup(
|
|
71
72
|
"warp_beacon/mediainfo/audio",
|
72
73
|
"warp_beacon/mediainfo/silencer",
|
73
74
|
"warp_beacon/compress/video",
|
75
|
+
"warp_beacon/scheduler/scheduler",
|
74
76
|
"warp_beacon/scraper/abstract",
|
75
77
|
"warp_beacon/scraper/exceptions",
|
76
78
|
"warp_beacon/scraper/types",
|
@@ -36,6 +36,7 @@ class JobSettings(TypedDict):
|
|
36
36
|
geoblock_error_count: int
|
37
37
|
account_switches: int
|
38
38
|
yt_auth: bool
|
39
|
+
session_validation: bool
|
39
40
|
|
40
41
|
class AbstractJob(ABC):
|
41
42
|
job_id: uuid.UUID = None
|
@@ -66,6 +67,7 @@ class AbstractJob(ABC):
|
|
66
67
|
geoblock_error_count: int = 0
|
67
68
|
account_switches: int = 0
|
68
69
|
yt_auth: bool = False
|
70
|
+
session_validation: bool = False
|
69
71
|
|
70
72
|
def __init__(self, **kwargs: Unpack[JobSettings]) -> None:
|
71
73
|
if kwargs:
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import threading
|
2
|
+
|
3
|
+
import warp_beacon
|
4
|
+
|
5
|
+
import logging
|
6
|
+
|
7
|
+
class IGScheduler(object):
|
8
|
+
downloader = None
|
9
|
+
running = True
|
10
|
+
thread = None
|
11
|
+
event = None
|
12
|
+
|
13
|
+
def __init__(self, downloader: "warp_beacon.scraper.AsyncDownloader") -> None:
|
14
|
+
self.downloader = downloader
|
15
|
+
self.event = threading.Event()
|
16
|
+
|
17
|
+
def __del__(self) -> None:
|
18
|
+
self.stop()
|
19
|
+
|
20
|
+
def start(self) -> None:
|
21
|
+
self.thread = threading.Thread(target=self.do_work)
|
22
|
+
self.thread.start()
|
23
|
+
|
24
|
+
def stop(self) -> None:
|
25
|
+
self.running = False
|
26
|
+
if self.thread:
|
27
|
+
t_id = self.thread.native_id
|
28
|
+
logging.info("Stopping scheduler thread #'%s'", t_id)
|
29
|
+
self.thread.join()
|
30
|
+
logging.info("Scheduler thread #'%s' stopped", t_id)
|
31
|
+
self.thread = None
|
32
|
+
|
33
|
+
def post_image(self, image) -> None:
|
34
|
+
pass
|
35
|
+
|
36
|
+
def post_story(self) -> None:
|
37
|
+
pass
|
38
|
+
|
39
|
+
def download_random_image(self) -> None:
|
40
|
+
pass
|
41
|
+
|
42
|
+
def validate_ig_session(self) -> bool:
|
43
|
+
try:
|
44
|
+
self.downloader.queue_task(warp_beacon.jobs.download_job.DownloadJob.build(
|
45
|
+
session_validation=True
|
46
|
+
))
|
47
|
+
except Exception as e:
|
48
|
+
logging.warning("An error occurred while validating instagram session!")
|
49
|
+
logging.exception(e)
|
50
|
+
|
51
|
+
return False
|
52
|
+
|
53
|
+
def do_work(self) -> None:
|
54
|
+
logging.info("Scheduler thread started ...")
|
55
|
+
while self.running:
|
56
|
+
try:
|
57
|
+
logging.info("Scheduler waking up")
|
58
|
+
self.validate_ig_session()
|
59
|
+
self.event.wait(timeout=3600)
|
60
|
+
except Exception as e:
|
61
|
+
logging.error("An error occurred in scheduler thread!")
|
62
|
+
logging.exception(e)
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
4
4
|
import multiprocessing
|
5
5
|
from queue import Empty
|
6
6
|
|
7
|
-
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, FileTooBig, YotubeLiveError, YotubeAgeRestrictedError,
|
7
|
+
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, Unavailable, FileTooBig, YotubeLiveError, YotubeAgeRestrictedError, IGRateLimitOccurred, CaptchaIssue, AllAccountsFailed
|
8
8
|
from warp_beacon.mediainfo.video import VideoInfo
|
9
9
|
from warp_beacon.mediainfo.audio import AudioInfo
|
10
10
|
from warp_beacon.mediainfo.silencer import Silencer
|
@@ -15,10 +15,11 @@ from warp_beacon.jobs.download_job import DownloadJob
|
|
15
15
|
from warp_beacon.jobs.upload_job import UploadJob
|
16
16
|
from warp_beacon.jobs.types import JobType
|
17
17
|
from warp_beacon.scraper.account_selector import AccountSelector
|
18
|
+
from warp_beacon.scheduler.scheduler import IGScheduler
|
18
19
|
|
19
20
|
import logging
|
20
21
|
|
21
|
-
ACC_FILE = os.environ.get("SERVICE_ACCOUNTS_FILE", default="/var/warp_beacon/
|
22
|
+
ACC_FILE = os.environ.get("SERVICE_ACCOUNTS_FILE", default="/var/warp_beacon/accounts.json")
|
22
23
|
|
23
24
|
class AsyncDownloader(object):
|
24
25
|
__JOE_BIDEN_WAKEUP = None
|
@@ -29,12 +30,15 @@ class AsyncDownloader(object):
|
|
29
30
|
workers_count = 0
|
30
31
|
auth_event = multiprocessing.Event()
|
31
32
|
acc_selector = None
|
33
|
+
scheduler = None
|
32
34
|
|
33
35
|
def __init__(self, uploader: AsyncUploader, workers_count: int) -> None:
|
34
36
|
self.allow_loop = multiprocessing.Value('i', 1)
|
35
37
|
self.uploader = uploader
|
36
38
|
self.workers_count = workers_count
|
37
39
|
self.acc_selector = AccountSelector(ACC_FILE)
|
40
|
+
self.scheduler = IGScheduler(self)
|
41
|
+
self.scheduler.start()
|
38
42
|
|
39
43
|
def __del__(self) -> None:
|
40
44
|
self.stop_all()
|
@@ -104,13 +108,17 @@ class AsyncDownloader(object):
|
|
104
108
|
elif job.job_origin is Origin.YOUTUBE:
|
105
109
|
from warp_beacon.scraper.youtube.youtube import YoutubeScraper
|
106
110
|
actor = YoutubeScraper(self.acc_selector.get_current())
|
107
|
-
#self.auth_event = multiprocessing.Event()
|
108
111
|
actor.send_message_to_admin_func = self.send_message_to_admin
|
109
112
|
actor.auth_event = self.auth_event
|
110
113
|
while True:
|
111
114
|
try:
|
112
|
-
|
113
|
-
|
115
|
+
if job.session_validation:
|
116
|
+
logging.info("Validating '%s' session ...", job.origin.value)
|
117
|
+
actor.validate_session()
|
118
|
+
logging.info("done")
|
119
|
+
else:
|
120
|
+
logging.info("Downloading URL '%s'", job.url)
|
121
|
+
items = actor.download(job.url)
|
114
122
|
break
|
115
123
|
except NotFound as e:
|
116
124
|
logging.warning("Not found error occurred!")
|
@@ -159,14 +167,14 @@ class AsyncDownloader(object):
|
|
159
167
|
f"Task {job.job_id} failed. URL: '{job.url}'. Reason: 'FileTooBig'."
|
160
168
|
)
|
161
169
|
break
|
162
|
-
except
|
163
|
-
logging.warning("IG ratelimit
|
170
|
+
except IGRateLimitOccurred as e:
|
171
|
+
logging.warning("IG ratelimit occurred :(")
|
164
172
|
logging.exception(e)
|
165
173
|
self.try_next_account(job, report_error="rate_limits")
|
166
174
|
self.job_queue.put(job)
|
167
175
|
break
|
168
176
|
except CaptchaIssue as e:
|
169
|
-
logging.warning("Challange
|
177
|
+
logging.warning("Challange occurred!")
|
170
178
|
logging.exception(e)
|
171
179
|
self.try_next_account(job)
|
172
180
|
self.job_queue.put(job)
|
@@ -215,6 +223,9 @@ class AsyncDownloader(object):
|
|
215
223
|
job_failed=True,
|
216
224
|
job_failed_msg="This content does not accessible for all yout bot accounts. Seems like author blocked certain regions.")
|
217
225
|
)
|
226
|
+
self.send_message_to_admin(
|
227
|
+
f"Task {job.job_id} failed. URL: '{job.url}'. Reason: 'geoblock_required'."
|
228
|
+
)
|
218
229
|
break
|
219
230
|
job.geoblock_error_count += 1
|
220
231
|
logging.info("Trying to switch account")
|
@@ -225,6 +236,10 @@ class AsyncDownloader(object):
|
|
225
236
|
job_failed=True,
|
226
237
|
job_failed_msg="WOW, unknown error occured! Please [create issue](https://github.com/sb0y/warp_beacon/issues) with service logs.")
|
227
238
|
)
|
239
|
+
self.send_message_to_admin(
|
240
|
+
f"Task {job.job_id} failed. URL: '{job.url}'. Reason: 'UnknownError'."
|
241
|
+
f"Exception:\n```\n{exception_msg}\n```"
|
242
|
+
)
|
228
243
|
break
|
229
244
|
|
230
245
|
if items:
|
@@ -312,6 +327,7 @@ class AsyncDownloader(object):
|
|
312
327
|
|
313
328
|
def stop_all(self) -> None:
|
314
329
|
self.allow_loop.value = 0
|
330
|
+
self.scheduler.stop()
|
315
331
|
for proc in self.workers:
|
316
332
|
if proc.is_alive():
|
317
333
|
logging.info("stopping process #%d", proc.pid)
|
@@ -19,7 +19,7 @@ from instagrapi import Client
|
|
19
19
|
from instagrapi.mixins.challenge import ChallengeChoice
|
20
20
|
from instagrapi.exceptions import LoginRequired, PleaseWaitFewMinutes, MediaNotFound, ClientNotFoundError, UserNotFound, ChallengeRequired, ChallengeSelfieCaptcha, UnknownError as IGUnknownError
|
21
21
|
|
22
|
-
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut,
|
22
|
+
from warp_beacon.scraper.exceptions import NotFound, UnknownError, TimeOut, IGRateLimitOccurred, CaptchaIssue, extract_exception_message
|
23
23
|
from warp_beacon.scraper.abstract import ScraperAbstract
|
24
24
|
from warp_beacon.jobs.types import JobType
|
25
25
|
from warp_beacon.telegram.utils import Utils
|
@@ -85,9 +85,13 @@ class InstagramScraper(ScraperAbstract):
|
|
85
85
|
self.cl.login(username=username, password=password, verification_code="")
|
86
86
|
self.safe_write_session()
|
87
87
|
|
88
|
-
def
|
88
|
+
def validate_session(self) -> None:
|
89
89
|
self.load_session()
|
90
90
|
self._download_hndlr(self.cl.get_timeline_feed)
|
91
|
+
self._download_hndlr(self.cl.get_reels_tray_feed)
|
92
|
+
|
93
|
+
def scrap(self, url: str) -> tuple[str]:
|
94
|
+
self.load_session()
|
91
95
|
def _scrap() -> tuple[str]:
|
92
96
|
if "stories" in url:
|
93
97
|
# remove URL options
|
@@ -258,8 +262,8 @@ class InstagramScraper(ScraperAbstract):
|
|
258
262
|
logging.warning("Please wait a few minutes error. Trying to relogin ...")
|
259
263
|
logging.exception(e)
|
260
264
|
if please_wait_few_minutes_count >= ratelimit_threshold:
|
261
|
-
logging.warning("IG ratelimit
|
262
|
-
raise
|
265
|
+
logging.warning("IG ratelimit occurred")
|
266
|
+
raise IGRateLimitOccurred()
|
263
267
|
wait_timeout += timeout_increment
|
264
268
|
logging.info("Waiting %d seconds according configuration option `IG_WAIT_TIMEOUT` with `IG_TIMEOUT_INCREMENT`", wait_timeout)
|
265
269
|
if res:
|
@@ -2,7 +2,6 @@ import os, io
|
|
2
2
|
import signal
|
3
3
|
|
4
4
|
import uvloop
|
5
|
-
import asyncio
|
6
5
|
|
7
6
|
from pyrogram import Client, filters
|
8
7
|
from pyrogram.enums import ParseMode
|
@@ -10,15 +9,13 @@ from pyrogram.handlers import MessageHandler, CallbackQueryHandler
|
|
10
9
|
from pyrogram.types import Message, InputMedia, InputMediaAudio, InputMediaPhoto, InputMediaVideo, InputMediaAnimation, InputMediaDocument, InlineKeyboardButton, InlineKeyboardMarkup
|
11
10
|
from pyrogram.errors import RPCError, FloodWait, NetworkMigrate, BadRequest, MultiMediaTooLong, MessageIdInvalid
|
12
11
|
|
12
|
+
import warp_beacon
|
13
13
|
from warp_beacon.__version__ import __version__
|
14
14
|
from warp_beacon.telegram.handlers import Handlers
|
15
|
-
import warp_beacon.scraper
|
16
15
|
from warp_beacon.telegram.placeholder_message import PlaceholderMessage
|
17
16
|
from warp_beacon.storage import Storage
|
18
17
|
from warp_beacon.uploader import AsyncUploader
|
19
|
-
from warp_beacon.jobs.download_job import DownloadJob
|
20
18
|
from warp_beacon.jobs.upload_job import UploadJob
|
21
|
-
from warp_beacon.jobs import Origin
|
22
19
|
from warp_beacon.jobs.types import JobType
|
23
20
|
from warp_beacon.telegram.utils import Utils
|
24
21
|
|
@@ -30,6 +30,8 @@ warp_beacon/mediainfo/abstract.py
|
|
30
30
|
warp_beacon/mediainfo/audio.py
|
31
31
|
warp_beacon/mediainfo/silencer.py
|
32
32
|
warp_beacon/mediainfo/video.py
|
33
|
+
warp_beacon/scheduler/__init__.py
|
34
|
+
warp_beacon/scheduler/scheduler.py
|
33
35
|
warp_beacon/scraper/__init__.py
|
34
36
|
warp_beacon/scraper/abstract.py
|
35
37
|
warp_beacon/scraper/account_selector.py
|
@@ -11,6 +11,8 @@ warp_beacon/mediainfo/abstract
|
|
11
11
|
warp_beacon/mediainfo/audio
|
12
12
|
warp_beacon/mediainfo/silencer
|
13
13
|
warp_beacon/mediainfo/video
|
14
|
+
warp_beacon/scheduler
|
15
|
+
warp_beacon/scheduler/scheduler
|
14
16
|
warp_beacon/scraper
|
15
17
|
warp_beacon/scraper/abstract
|
16
18
|
warp_beacon/scraper/account_selector
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{warp_beacon-2.1.6/warp_beacon/compress → warp_beacon-2.1.8/warp_beacon/mediainfo}/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{warp_beacon-2.1.6/warp_beacon/mediainfo → warp_beacon-2.1.8/warp_beacon/scheduler}/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|