warp-beacon 2.6.47__py3-none-any.whl → 2.6.49__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.
- warp_beacon/__version__.py +1 -1
- warp_beacon/telegram/bot.py +15 -11
- warp_beacon/telegram/edit_message.py +141 -0
- warp_beacon/telegram/progress_bar.py +66 -0
- warp_beacon/telegram/progress_file_reader.py +8 -12
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/METADATA +1 -1
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/RECORD +11 -9
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/WHEEL +1 -1
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/top_level.txt +2 -0
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/entry_points.txt +0 -0
- {warp_beacon-2.6.47.dist-info → warp_beacon-2.6.49.dist-info}/licenses/LICENSE +0 -0
warp_beacon/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "2.6.
|
1
|
+
__version__ = "2.6.49"
|
2
2
|
|
warp_beacon/telegram/bot.py
CHANGED
@@ -8,7 +8,6 @@ import logging
|
|
8
8
|
import html
|
9
9
|
|
10
10
|
import uvloop
|
11
|
-
#from contextlib import ExitStack
|
12
11
|
|
13
12
|
from pyrogram import Client, filters
|
14
13
|
from pyrogram.enums import ParseMode, ChatType
|
@@ -29,7 +28,7 @@ from warp_beacon.jobs import Origin
|
|
29
28
|
from warp_beacon.telegram.utils import Utils
|
30
29
|
from warp_beacon.telegram.caption_shortener import CaptionShortner
|
31
30
|
from warp_beacon.scheduler.scheduler import IGScheduler
|
32
|
-
from warp_beacon.telegram.
|
31
|
+
from warp_beacon.telegram.edit_message import EditMessage
|
33
32
|
|
34
33
|
class Bot(object):
|
35
34
|
should_exit = None
|
@@ -42,22 +41,19 @@ class Bot(object):
|
|
42
41
|
placeholder = None
|
43
42
|
scheduler = None
|
44
43
|
me = None
|
44
|
+
edit_message = None
|
45
45
|
|
46
46
|
def __init__(self, tg_bot_name: str, tg_token: str, tg_api_id: str, tg_api_hash: str) -> None:
|
47
47
|
# Enable logging
|
48
48
|
logging.basicConfig(
|
49
|
-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
49
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
50
|
+
level=logging.INFO
|
50
51
|
)
|
51
52
|
|
52
53
|
logging.getLogger("pyrogram").setLevel(logging.ERROR)
|
53
|
-
|
54
54
|
logging.info("Starting Warp Beacon version '%s' ...", __version__)
|
55
|
-
|
56
|
-
db_connect = DBClient()
|
57
|
-
self.storage = Storage(db_connect)
|
58
|
-
|
55
|
+
self.storage = Storage(DBClient())
|
59
56
|
self.should_exit = asyncio.Event()
|
60
|
-
|
61
57
|
workers_amount = min(32, os.cpu_count() + 4)
|
62
58
|
|
63
59
|
uvloop.install()
|
@@ -71,6 +67,8 @@ class Bot(object):
|
|
71
67
|
workers=int(os.environ.get("TG_WORKERS_POOL_SIZE", default=workers_amount))
|
72
68
|
)
|
73
69
|
|
70
|
+
self.editor = EditMessage(self.client)
|
71
|
+
|
74
72
|
self.uploader = AsyncUploader(
|
75
73
|
storage=self.storage,
|
76
74
|
admin_message_callback=self.send_text_to_admin,
|
@@ -84,7 +82,6 @@ class Bot(object):
|
|
84
82
|
)
|
85
83
|
|
86
84
|
self.scheduler = IGScheduler(self.downloader)
|
87
|
-
|
88
85
|
self.handlers = Handlers(self)
|
89
86
|
|
90
87
|
self.client.add_handler(MessageHandler(self.handlers.start, filters.command("start")))
|
@@ -405,6 +402,13 @@ class Bot(object):
|
|
405
402
|
|
406
403
|
return args
|
407
404
|
|
405
|
+
async def progress_callback(self, current: int, total: int, chat_id: int | str, message_id: int, label: str) -> None:
|
406
|
+
percents = int(current * 100 / total)
|
407
|
+
if (percents % 40) > 0 or percents == 100:
|
408
|
+
p = round(percents)
|
409
|
+
await self.client.edit_message_caption(chat_id, message_id, f"<b>{p}% <code>{label}</code> uploaded</b>", ParseMode.HTML)
|
410
|
+
logging.info("[%s] Uploaded to Telegram %d%%", label, p)
|
411
|
+
|
408
412
|
async def upload_job(self, job: UploadJob) -> list[str]:
|
409
413
|
tg_file_ids = []
|
410
414
|
try:
|
@@ -418,7 +422,7 @@ class Bot(object):
|
|
418
422
|
await Utils.ensure_me_loaded(self.client)
|
419
423
|
if job.placeholder_message_id:
|
420
424
|
try:
|
421
|
-
reply_message = await self.
|
425
|
+
reply_message = await self.editor.edit(**self.build_tg_args(job))
|
422
426
|
except MessageIdInvalid:
|
423
427
|
logging.warning("Placeholder message not found. Looks like placeholder message was deleted by administrator.")
|
424
428
|
job.placeholder_message_id = None
|
@@ -0,0 +1,141 @@
|
|
1
|
+
from pyrogram.client import Client
|
2
|
+
from pyrogram.types import InputMedia, InputMediaAudio, InputMediaPhoto, InputMediaVideo, InputMediaAnimation, InlineKeyboardMarkup
|
3
|
+
from pyrogram import raw
|
4
|
+
from pyrogram import types
|
5
|
+
|
6
|
+
#from warp_beacon.telegram.bot import Bot
|
7
|
+
from warp_beacon.telegram.progress_bar import ProgressBar
|
8
|
+
|
9
|
+
class EditMessage(object):
|
10
|
+
def __init__(self, client: Client) -> None:
|
11
|
+
self.client = client
|
12
|
+
|
13
|
+
def get_wrapped_video(self, raw_file: raw.base.InputFile, raw_thumb: raw.base.InputFile, media: InputMediaVideo, file_name: str = None) -> raw.types.InputMediaUploadedDocument:
|
14
|
+
return raw.types.InputMediaUploadedDocument(
|
15
|
+
file=raw_file,
|
16
|
+
mime_type=self.client.guess_mime_type(media.media) or "video/mp4",
|
17
|
+
thumb=raw_thumb,
|
18
|
+
spoiler=media.has_spoiler,
|
19
|
+
attributes=[
|
20
|
+
raw.types.DocumentAttributeVideo(
|
21
|
+
duration=media.duration,
|
22
|
+
w=media.width,
|
23
|
+
h=media.height,
|
24
|
+
supports_streaming=media.supports_streaming
|
25
|
+
),
|
26
|
+
raw.types.DocumentAttributeFilename(
|
27
|
+
file_name=file_name
|
28
|
+
)
|
29
|
+
]
|
30
|
+
)
|
31
|
+
|
32
|
+
def get_wrapped_photo(self, raw_file: raw.base.InputFile, media: InputMediaPhoto) -> raw.types.InputMediaUploadedPhoto:
|
33
|
+
return raw.types.InputMediaUploadedPhoto(
|
34
|
+
file=raw_file,
|
35
|
+
spoiler=media.has_spoiler
|
36
|
+
)
|
37
|
+
|
38
|
+
def get_wrapped_audio(self, raw_file: raw.base.InputFile, raw_thumb: raw.base.InputFile, media: InputMediaAudio, file_name: str = None) -> raw.types.InputMediaUploadedDocument:
|
39
|
+
return raw.types.InputMediaUploadedDocument(
|
40
|
+
mime_type=self.client.guess_mime_type(media.media) or "audio/mpeg",
|
41
|
+
thumb=raw_thumb,
|
42
|
+
file=raw_file,
|
43
|
+
attributes=[
|
44
|
+
raw.types.DocumentAttributeAudio(
|
45
|
+
duration=media.duration,
|
46
|
+
performer=media.performer,
|
47
|
+
title=media.title
|
48
|
+
),
|
49
|
+
raw.types.DocumentAttributeFilename(
|
50
|
+
file_name=file_name
|
51
|
+
)
|
52
|
+
]
|
53
|
+
)
|
54
|
+
|
55
|
+
def get_wrapped_animation(self, raw_file: raw.base.InputFile, raw_thumb: raw.base.InputFile, media: InputMediaVideo, file_name: str = None) -> raw.types.InputMediaUploadedDocument:
|
56
|
+
return raw.types.InputMediaUploadedDocument(
|
57
|
+
mime_type=self.client.guess_mime_type(media.media) or "video/mp4",
|
58
|
+
thumb=raw_thumb,
|
59
|
+
spoiler=media.has_spoiler,
|
60
|
+
file=raw_file,
|
61
|
+
attributes=[
|
62
|
+
raw.types.DocumentAttributeVideo(
|
63
|
+
supports_streaming=True,
|
64
|
+
duration=media.duration,
|
65
|
+
w=media.width,
|
66
|
+
h=media.height
|
67
|
+
),
|
68
|
+
raw.types.DocumentAttributeFilename(
|
69
|
+
file_name=file_name
|
70
|
+
),
|
71
|
+
raw.types.DocumentAttributeAnimated()
|
72
|
+
]
|
73
|
+
)
|
74
|
+
|
75
|
+
#async def upload_with_progress(self,
|
76
|
+
# media: InputMedia | InputMediaAudio | InputMediaPhoto | InputMediaVideo | InputMediaAnimation,
|
77
|
+
# chat_id: int | str,
|
78
|
+
# message_id: int,
|
79
|
+
# file_name: str
|
80
|
+
#) -> raw.base.InputFile:
|
81
|
+
# progress_bar = ProgressBar(self.client)
|
82
|
+
# progress_id = f"{chat_id}:{message_id}:{file_name}"
|
83
|
+
# self.progress_bars[progress_id] = progress_bar
|
84
|
+
# raw_file = await self.client.save_file(path=media.media, progress=progress_bar.progress_callback, progress_args=(chat_id, message_id, file_name,))
|
85
|
+
# del self.progress_bars[progress_id]
|
86
|
+
# return raw_file
|
87
|
+
|
88
|
+
async def edit(self,
|
89
|
+
chat_id: int | str,
|
90
|
+
message_id: int,
|
91
|
+
media: InputMedia | InputMediaAudio | InputMediaPhoto | InputMediaVideo | InputMediaAnimation,
|
92
|
+
reply_markup: InlineKeyboardMarkup = None,
|
93
|
+
file_name: str = None
|
94
|
+
) -> None:
|
95
|
+
progress_bar = ProgressBar(self.client)
|
96
|
+
raw_file = await self.client.save_file(path=media.media, progress=progress_bar.progress_callback, progress_args=(chat_id, message_id, file_name,))
|
97
|
+
|
98
|
+
caption = media.caption
|
99
|
+
parse_mode = media.parse_mode
|
100
|
+
|
101
|
+
message, entities = None, None
|
102
|
+
|
103
|
+
if caption is not None:
|
104
|
+
message, entities = (await self.client.parser.parse(caption, parse_mode)).values()
|
105
|
+
|
106
|
+
raw_media = None
|
107
|
+
if isinstance(media, types.InputMediaVideo):
|
108
|
+
progress_bar_thumb = ProgressBar(self.client)
|
109
|
+
raw_file_thumb = await self.client.save_file(path=media.thumb, progress=progress_bar_thumb.progress_callback, progress_args=(chat_id, message_id, "thumbnail",))
|
110
|
+
raw_media = self.get_wrapped_video(raw_file=raw_file, raw_thumb=raw_file_thumb, media=media, file_name=file_name)
|
111
|
+
elif isinstance(media, types.InputMediaPhoto):
|
112
|
+
raw_media = self.get_wrapped_photo(raw_file=raw_file, media=media)
|
113
|
+
elif isinstance(media, types.InputMediaAudio):
|
114
|
+
progress_bar_thumb = ProgressBar(self.client)
|
115
|
+
raw_file_thumb = await self.client.save_file(path=media.thumb, progress=progress_bar_thumb.progress_callback, progress_args=(chat_id, message_id, "thumbnail",))
|
116
|
+
raw_media = self.get_wrapped_audio(raw_file=raw_file, raw_thumb=raw_file_thumb, media=media, file_name=file_name)
|
117
|
+
elif isinstance(media, types.InputMediaAnimation):
|
118
|
+
progress_bar_thumb = ProgressBar(self.client)
|
119
|
+
raw_file_thumb = await self.client.save_file(path=media.thumb, progress=progress_bar_thumb.progress_callback, progress_args=(chat_id, message_id, "thumbnail",))
|
120
|
+
raw_media = self.get_wrapped_animation(raw_file=raw_file, raw_thumb=raw_file_thumb, media=media, file_name=file_name)
|
121
|
+
|
122
|
+
peer = await self.client.resolve_peer(chat_id)
|
123
|
+
|
124
|
+
r = await self.client.invoke(
|
125
|
+
raw.functions.messages.EditMessage(
|
126
|
+
peer=peer,
|
127
|
+
id=message_id,
|
128
|
+
media=raw_media,
|
129
|
+
reply_markup=await reply_markup.write(self.client) if reply_markup else None,
|
130
|
+
message=message,
|
131
|
+
entities=entities
|
132
|
+
)
|
133
|
+
)
|
134
|
+
|
135
|
+
for i in r.updates:
|
136
|
+
if isinstance(i, (raw.types.UpdateEditMessage, raw.types.UpdateEditChannelMessage)):
|
137
|
+
return await types.Message._parse(
|
138
|
+
self.client, i.message,
|
139
|
+
{i.id: i for i in r.users},
|
140
|
+
{i.id: i for i in r.chats}
|
141
|
+
)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
import hashlib
|
4
|
+
|
5
|
+
from pyrogram.enums import ParseMode
|
6
|
+
from pyrogram.errors.exceptions.bad_request_400 import MessageNotModified
|
7
|
+
from pyrogram import Client
|
8
|
+
|
9
|
+
class ProgressBar(object):
|
10
|
+
def __init__(self, client: Client) -> None:
|
11
|
+
self._next_threshold = 20
|
12
|
+
self.client = client
|
13
|
+
|
14
|
+
def make_progress_bar(self, current: int, total: int, length: int = 10) -> str:
|
15
|
+
"""
|
16
|
+
Returns string
|
17
|
+
[████▌────] 55%
|
18
|
+
length — amount of characters in bar
|
19
|
+
"""
|
20
|
+
# fraction of completed job from 0.0 to 1.0
|
21
|
+
frac = current / total if total else 0
|
22
|
+
# how much "filled" cells
|
23
|
+
filled = int(frac * length)
|
24
|
+
# part between whole cells, optional may withdraw half
|
25
|
+
half_block = ''
|
26
|
+
if (frac * length) - filled >= 0.5:
|
27
|
+
half_block = '▌' # or '▏', '▍' and etc.
|
28
|
+
# building bar
|
29
|
+
pbar = '█' * filled + half_block + '─' * (length - filled - len(half_block))
|
30
|
+
percent = frac * 100
|
31
|
+
return f"<b>[{pbar}] {round(percent)}</b>%"
|
32
|
+
|
33
|
+
def make_emoji_progress_bar(self, current: int, total: int, length: int = 10) -> str:
|
34
|
+
"""
|
35
|
+
Returns string:
|
36
|
+
[🟩🟩🟩⬜️⬜️⬜️⬜️⬜️⬜️⬜️] 30%
|
37
|
+
length — common number of emoji cells
|
38
|
+
"""
|
39
|
+
frac = (current / total) if total else 0
|
40
|
+
filled_count = int(frac * length)
|
41
|
+
empty_count = length - filled_count
|
42
|
+
pbar = "🟩" * filled_count + "⬜️" * empty_count
|
43
|
+
percent = frac * 100
|
44
|
+
return f"[{pbar}] {round(percent)}%"
|
45
|
+
|
46
|
+
async def progress_callback(self, current: int, total: int, chat_id: int | str, message_id: int, label: str) -> None:
|
47
|
+
percent = current * 100 / total
|
48
|
+
if percent >= self._next_threshold:
|
49
|
+
#pbar = self.make_progress_bar(percent, 100, 25)
|
50
|
+
pbar = self.make_emoji_progress_bar(percent, 100, 14)
|
51
|
+
logging.info("[%s] Uploaded to Telegram %d%%", label, percent)
|
52
|
+
try:
|
53
|
+
await self.client.edit_message_caption(chat_id, message_id, f"{pbar} <b>Uploading <code>{label}</code></b>", ParseMode.HTML)
|
54
|
+
except MessageNotModified:
|
55
|
+
logging.warning("bad_request_400.MessageNotModified")
|
56
|
+
except Exception as e:
|
57
|
+
logging.warning("An error occurred while updating progress bar")
|
58
|
+
logging.exception(e)
|
59
|
+
self._next_threshold += 20
|
60
|
+
|
61
|
+
@staticmethod
|
62
|
+
def make_hash(chat_id: str | int, message_id: int, algorithm: str = 'sha256') -> str:
|
63
|
+
s = f"{chat_id}:{message_id}"
|
64
|
+
# md5, sha1, sha256
|
65
|
+
h = hashlib.new(algorithm, s.encode('utf-8'))
|
66
|
+
return h.hexdigest()
|
@@ -3,27 +3,27 @@ import os
|
|
3
3
|
from types import TracebackType
|
4
4
|
from typing import Optional, Callable, Type
|
5
5
|
|
6
|
-
class ProgressFileReader(io.
|
6
|
+
class ProgressFileReader(io.FileIO):
|
7
7
|
def __init__(self, file_path: str, callback: Optional[Callable[[str, int, int], None]]) -> None:
|
8
|
-
|
9
|
-
super().__init__(raw)
|
10
|
-
self._raw = raw
|
8
|
+
super().__init__(file_path, "rb")
|
11
9
|
self.callback = callback
|
12
10
|
self._total = os.path.getsize(file_path)
|
13
11
|
self._read_bytes = 0
|
14
|
-
self.
|
12
|
+
self._display_name = os.path.basename(file_path)
|
13
|
+
|
14
|
+
def __fspath__(self) -> str:
|
15
|
+
return self._display_name
|
15
16
|
|
16
17
|
def read(self, size: int = -1) -> bytes:
|
17
18
|
chunk = super().read(size)
|
18
19
|
self._read_bytes += len(chunk)
|
19
20
|
if self.callback:
|
20
|
-
self.callback(self.
|
21
|
+
self.callback(self._display_name, self._read_bytes, self._total)
|
21
22
|
return chunk
|
22
23
|
|
23
24
|
def close(self) -> None:
|
24
25
|
if not self.closed:
|
25
26
|
super().close()
|
26
|
-
self._raw.close()
|
27
27
|
|
28
28
|
def __enter__(self) -> "ProgressFileReader":
|
29
29
|
return self
|
@@ -33,8 +33,4 @@ class ProgressFileReader(io.BufferedReader):
|
|
33
33
|
exc_val: Optional[BaseException],
|
34
34
|
exc_tb: Optional[TracebackType]
|
35
35
|
) -> None:
|
36
|
-
self.close()
|
37
|
-
|
38
|
-
@property
|
39
|
-
def name(self) -> str:
|
40
|
-
return self._name
|
36
|
+
self.close()
|
@@ -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=
|
7
|
+
warp_beacon/__version__.py,sha256=ag2-RQzilsSrTWVr6qiPwebiNNomtHUQHcGwxmjvXow,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
|
@@ -40,16 +40,18 @@ warp_beacon/scraper/youtube/youtube.py,sha256=x9v9p1coA9TvBhxjNAofGu4UBkAEdYPE2e
|
|
40
40
|
warp_beacon/storage/__init__.py,sha256=0Vajd0oITKJfu2vmNx5uQSt3-L6vwIvUYWJo8HZCjco,3398
|
41
41
|
warp_beacon/storage/mongo.py,sha256=qC4ZiO8XXvPnP0rJwz4CJx42pqFsyAjCiW10W5QdT6E,527
|
42
42
|
warp_beacon/telegram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
|
-
warp_beacon/telegram/bot.py,sha256=
|
43
|
+
warp_beacon/telegram/bot.py,sha256=GTxKEAyCzMXXMrAEw2INQED7Y4XPE0CjiTexPDNWrpA,19256
|
44
44
|
warp_beacon/telegram/caption_shortener.py,sha256=EnguNCF52ne7y4P-iJAbI6K3sqoJqJbND_dX5Fhwkv0,1549
|
45
|
+
warp_beacon/telegram/edit_message.py,sha256=XDGBbQ3c6xzQsqwJ2ufVozgDZh3oWF-JQlk3wk78soo,5556
|
45
46
|
warp_beacon/telegram/handlers.py,sha256=uvR6TPHSqdSxigp3wR-ewiE6t3TvVcbVLVcYGwkgD2s,9559
|
46
47
|
warp_beacon/telegram/placeholder_message.py,sha256=wN9-BRiyrtHG-EvXtZkGJHt2CX71munQ57ITttjt0mw,6400
|
47
|
-
warp_beacon/telegram/
|
48
|
+
warp_beacon/telegram/progress_bar.py,sha256=U3QeuENUBvemqecR0paBoszsmvwsom2XeqzsmRPtGFA,2388
|
49
|
+
warp_beacon/telegram/progress_file_reader.py,sha256=e3equyNKlKs764AD-iE9QRsh3YDHTzP78Mx5tdvPPWs,969
|
48
50
|
warp_beacon/telegram/utils.py,sha256=1Lq67aRylVJzbwSyvAgjPAGjJZFATkICvAj3TJGuJiM,4635
|
49
51
|
warp_beacon/uploader/__init__.py,sha256=j3qcuKhpchseZLGzSsSiogqe6WdMbkK8d3I-ConhNRs,5687
|
50
|
-
warp_beacon-2.6.
|
51
|
-
warp_beacon-2.6.
|
52
|
-
warp_beacon-2.6.
|
53
|
-
warp_beacon-2.6.
|
54
|
-
warp_beacon-2.6.
|
55
|
-
warp_beacon-2.6.
|
52
|
+
warp_beacon-2.6.49.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
53
|
+
warp_beacon-2.6.49.dist-info/METADATA,sha256=qXKFFlKulpEYYjlKav4lH_79B0ogvQQowAcXaSx1_yQ,22706
|
54
|
+
warp_beacon-2.6.49.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
55
|
+
warp_beacon-2.6.49.dist-info/entry_points.txt,sha256=eSB61Rb89d56WY0O-vEIQwkn18J-4CMrJcLA_R_8h3g,119
|
56
|
+
warp_beacon-2.6.49.dist-info/top_level.txt,sha256=pYstFq5qRCQuQc4fOAAc1ti5UwsYldTREx7h2dNplI4,1297
|
57
|
+
warp_beacon-2.6.49.dist-info/RECORD,,
|
@@ -34,8 +34,10 @@ warp_beacon/storage/mongo
|
|
34
34
|
warp_beacon/telegram
|
35
35
|
warp_beacon/telegram/bot
|
36
36
|
warp_beacon/telegram/caption_shortener
|
37
|
+
warp_beacon/telegram/edit_message
|
37
38
|
warp_beacon/telegram/handlers
|
38
39
|
warp_beacon/telegram/placeholder_message
|
40
|
+
warp_beacon/telegram/progress_bar
|
39
41
|
warp_beacon/telegram/progress_file_reader
|
40
42
|
warp_beacon/telegram/utils
|
41
43
|
warp_beacon/uploader
|
File without changes
|
File without changes
|