sticker-convert 2.10.9__py3-none-any.whl → 2.11.0__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.
- sticker_convert/cli.py +39 -1
- sticker_convert/converter.py +8 -5
- sticker_convert/downloaders/download_base.py +3 -3
- sticker_convert/downloaders/download_signal.py +4 -2
- sticker_convert/downloaders/download_telegram.py +19 -103
- sticker_convert/gui.py +12 -0
- sticker_convert/gui_components/frames/cred_frame.py +38 -13
- sticker_convert/job.py +6 -6
- sticker_convert/job_option.py +6 -0
- sticker_convert/resources/compression.json +2 -2
- sticker_convert/resources/help.json +3 -2
- sticker_convert/resources/input.json +10 -0
- sticker_convert/resources/output.json +16 -0
- sticker_convert/uploaders/upload_telegram.py +170 -234
- sticker_convert/utils/auth/telegram_api.py +668 -0
- sticker_convert/utils/auth/telethon_setup.py +79 -0
- sticker_convert/utils/url_detect.py +1 -1
- sticker_convert/version.py +1 -1
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/METADATA +49 -31
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/RECORD +24 -22
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/LICENSE +0 -0
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/WHEEL +0 -0
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,668 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
import re
|
3
|
+
import time
|
4
|
+
from collections import defaultdict
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import Any, Dict, List, Optional, Protocol, Tuple, Union, cast
|
7
|
+
|
8
|
+
import anyio
|
9
|
+
from telegram import InputSticker, PhotoSize, Sticker
|
10
|
+
from telegram import StickerSet as TGStickerSet
|
11
|
+
from telegram.error import BadRequest, TelegramError
|
12
|
+
from telegram.ext import AIORateLimiter, ApplicationBuilder
|
13
|
+
from telethon.errors.rpcerrorlist import StickersetInvalidError # type: ignore
|
14
|
+
from telethon.functions import messages # type: ignore
|
15
|
+
from telethon.tl.types.messages import StickerSet as TLStickerSet # type: ignore
|
16
|
+
from telethon.types import DocumentAttributeFilename, InputStickerSetShortName, InputStickerSetThumb, Message, TypeDocument # type: ignore
|
17
|
+
|
18
|
+
from sticker_convert.job_option import CredOption
|
19
|
+
from sticker_convert.utils.auth.telethon_setup import TelethonSetup
|
20
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
21
|
+
|
22
|
+
# sticker_path: Path, sticker_bytes: bytes, emoji_list: List[str], sticker_format: str
|
23
|
+
TelegramSticker = Tuple[Path, bytes, List[str], str]
|
24
|
+
|
25
|
+
|
26
|
+
class TelegramAPI(Protocol):
|
27
|
+
async def setup(
|
28
|
+
self,
|
29
|
+
opt_cred: CredOption,
|
30
|
+
is_upload: bool,
|
31
|
+
cb: CallbackProtocol,
|
32
|
+
cb_return: CallbackReturn,
|
33
|
+
) -> bool: ...
|
34
|
+
async def exit(self) -> None: ...
|
35
|
+
async def set_upload_pack_type(self, is_emoji: bool) -> None: ...
|
36
|
+
async def set_upload_pack_short_name(self, pack_title: str) -> str: ...
|
37
|
+
async def check_pack_exist(self) -> bool: ...
|
38
|
+
async def pack_del(self) -> bool: ...
|
39
|
+
async def pack_new(
|
40
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
41
|
+
) -> Tuple[int, int]: ...
|
42
|
+
async def pack_add(
|
43
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
44
|
+
) -> Tuple[int, int]: ...
|
45
|
+
async def pack_thumbnail(self, thumbnail: TelegramSticker) -> bool: ...
|
46
|
+
async def get_pack_url(self) -> str: ...
|
47
|
+
async def pack_dl(
|
48
|
+
self, pack_short_name: str, out_dir: Path
|
49
|
+
) -> Tuple[Dict[str, bool], Dict[str, str]]: ...
|
50
|
+
|
51
|
+
|
52
|
+
class BotAPI(TelegramAPI):
|
53
|
+
async def setup(
|
54
|
+
self,
|
55
|
+
opt_cred: CredOption,
|
56
|
+
is_upload: bool,
|
57
|
+
cb: CallbackProtocol,
|
58
|
+
cb_return: CallbackReturn,
|
59
|
+
) -> bool:
|
60
|
+
self.timeout = 30
|
61
|
+
self.cb = cb
|
62
|
+
|
63
|
+
if is_upload and not (opt_cred.telegram_token and opt_cred.telegram_userid):
|
64
|
+
self.cb.put("Token and userid required for uploading to telegram")
|
65
|
+
return False
|
66
|
+
elif is_upload is False and not opt_cred.telegram_token:
|
67
|
+
self.cb.put("Token required for downloading from telegram")
|
68
|
+
return False
|
69
|
+
|
70
|
+
if opt_cred.telegram_userid.isnumeric():
|
71
|
+
self.telegram_userid = int(opt_cred.telegram_userid)
|
72
|
+
else:
|
73
|
+
self.cb.put("Invalid userid, should contain numbers only")
|
74
|
+
return False
|
75
|
+
|
76
|
+
self.application = ( # type: ignore
|
77
|
+
ApplicationBuilder()
|
78
|
+
.token(opt_cred.telegram_token)
|
79
|
+
.rate_limiter(AIORateLimiter(max_retries=3))
|
80
|
+
.connect_timeout(self.timeout)
|
81
|
+
.pool_timeout(self.timeout)
|
82
|
+
.read_timeout(self.timeout)
|
83
|
+
.write_timeout(self.timeout)
|
84
|
+
.build()
|
85
|
+
)
|
86
|
+
await self.application.initialize()
|
87
|
+
|
88
|
+
return True
|
89
|
+
|
90
|
+
async def exit(self) -> None:
|
91
|
+
await self.application.shutdown()
|
92
|
+
|
93
|
+
async def set_upload_pack_short_name(self, pack_title: str) -> str:
|
94
|
+
self.pack_title = pack_title
|
95
|
+
bot_name = self.application.bot.name
|
96
|
+
self.pack_short_name = (
|
97
|
+
pack_title.replace(" ", "_") + "_by_" + bot_name.replace("@", "")
|
98
|
+
)
|
99
|
+
self.pack_short_name = re.sub(
|
100
|
+
"[^0-9a-zA-Z]+", "_", self.pack_short_name
|
101
|
+
) # name used in url, only alphanum and underscore only
|
102
|
+
return self.pack_short_name
|
103
|
+
|
104
|
+
async def set_upload_pack_type(self, is_emoji: bool) -> None:
|
105
|
+
self.is_emoji = is_emoji
|
106
|
+
|
107
|
+
async def check_pack_exist(self) -> bool:
|
108
|
+
sticker_set: Any = None
|
109
|
+
try:
|
110
|
+
sticker_set = await self.application.bot.get_sticker_set(
|
111
|
+
self.pack_short_name,
|
112
|
+
read_timeout=30,
|
113
|
+
write_timeout=30,
|
114
|
+
connect_timeout=30,
|
115
|
+
pool_timeout=30,
|
116
|
+
)
|
117
|
+
except TelegramError:
|
118
|
+
pass
|
119
|
+
|
120
|
+
if sticker_set is not None:
|
121
|
+
return True
|
122
|
+
return False
|
123
|
+
|
124
|
+
async def pack_del(self) -> bool:
|
125
|
+
try:
|
126
|
+
await self.application.bot.delete_sticker_set(self.pack_short_name)
|
127
|
+
except BadRequest as e:
|
128
|
+
msg = f"Cannot delete sticker set {self.pack_short_name} due to {e}"
|
129
|
+
if str(e) == "Stickerpack_not_found":
|
130
|
+
msg += "\nHint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
|
131
|
+
self.cb.put(msg)
|
132
|
+
return False
|
133
|
+
except TelegramError as e:
|
134
|
+
self.cb.put(f"Cannot delete sticker set {self.pack_short_name} due to {e}")
|
135
|
+
return False
|
136
|
+
return True
|
137
|
+
|
138
|
+
async def pack_new(
|
139
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
140
|
+
) -> Tuple[int, int]:
|
141
|
+
init_input_stickers: List[InputSticker] = []
|
142
|
+
for i in stickers_list[:50]:
|
143
|
+
init_input_stickers.append(
|
144
|
+
InputSticker(
|
145
|
+
sticker=i[1],
|
146
|
+
emoji_list=i[2],
|
147
|
+
format=i[3],
|
148
|
+
)
|
149
|
+
)
|
150
|
+
|
151
|
+
try:
|
152
|
+
self.cb.put(
|
153
|
+
f"Creating pack and bulk uploading {len(init_input_stickers)} stickers of {self.pack_short_name}"
|
154
|
+
)
|
155
|
+
await self.application.bot.create_new_sticker_set(
|
156
|
+
self.telegram_userid,
|
157
|
+
self.pack_short_name,
|
158
|
+
self.pack_title,
|
159
|
+
init_input_stickers,
|
160
|
+
sticker_type,
|
161
|
+
)
|
162
|
+
self.cb.put(
|
163
|
+
f"Created pack and bulk uploaded {len(init_input_stickers)} stickers of {self.pack_short_name}"
|
164
|
+
)
|
165
|
+
_, success_add = await self.pack_add(stickers_list[50:], sticker_type)
|
166
|
+
return len(stickers_list), len(init_input_stickers) + success_add
|
167
|
+
except TelegramError as e:
|
168
|
+
self.cb.put(
|
169
|
+
f"Cannot create pack and bulk upload {len(init_input_stickers)} stickers of {self.pack_short_name} due to {e}"
|
170
|
+
)
|
171
|
+
return len(stickers_list), 0
|
172
|
+
|
173
|
+
async def pack_add(
|
174
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
175
|
+
) -> Tuple[int, int]:
|
176
|
+
stickers_ok = 0
|
177
|
+
self.cb.put(
|
178
|
+
(
|
179
|
+
"bar",
|
180
|
+
None,
|
181
|
+
{
|
182
|
+
"set_progress_mode": "determinate",
|
183
|
+
"steps": len(stickers_list),
|
184
|
+
},
|
185
|
+
)
|
186
|
+
)
|
187
|
+
for i in stickers_list:
|
188
|
+
input_sticker = InputSticker(
|
189
|
+
sticker=i[1],
|
190
|
+
emoji_list=i[2],
|
191
|
+
format=i[3],
|
192
|
+
)
|
193
|
+
try:
|
194
|
+
# We could use tg.start_soon() here
|
195
|
+
# But this would disrupt the order of stickers
|
196
|
+
await self.application.bot.add_sticker_to_set(
|
197
|
+
self.telegram_userid,
|
198
|
+
self.pack_short_name,
|
199
|
+
input_sticker,
|
200
|
+
)
|
201
|
+
self.cb.put(f"Uploaded sticker {i[0]} of {self.pack_short_name}")
|
202
|
+
stickers_ok += 1
|
203
|
+
except BadRequest as e:
|
204
|
+
self.cb.put(
|
205
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {e}"
|
206
|
+
)
|
207
|
+
if str(e) == "Stickerpack_not_found":
|
208
|
+
self.cb.put(
|
209
|
+
"Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
|
210
|
+
)
|
211
|
+
except TelegramError as e:
|
212
|
+
self.cb.put(
|
213
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {e}"
|
214
|
+
)
|
215
|
+
self.cb.put("update_bar")
|
216
|
+
|
217
|
+
self.cb.put(("bar", None, {"set_progress_mode": "indeterminate"}))
|
218
|
+
return len(stickers_list), stickers_ok
|
219
|
+
|
220
|
+
async def pack_thumbnail(self, thumbnail: TelegramSticker) -> bool:
|
221
|
+
try:
|
222
|
+
self.cb.put(f"Uploading cover (thumbnail) of pack {self.pack_short_name}")
|
223
|
+
await self.application.bot.set_sticker_set_thumbnail(
|
224
|
+
self.pack_short_name,
|
225
|
+
self.telegram_userid,
|
226
|
+
thumbnail[3],
|
227
|
+
thumbnail[1],
|
228
|
+
)
|
229
|
+
self.cb.put(f"Uploaded cover (thumbnail) of pack {self.pack_short_name}")
|
230
|
+
return True
|
231
|
+
except TelegramError as e:
|
232
|
+
self.cb.put(
|
233
|
+
f"Cannot upload cover (thumbnail) of pack {self.pack_short_name} due to {e}"
|
234
|
+
)
|
235
|
+
return False
|
236
|
+
|
237
|
+
async def get_pack_url(self) -> str:
|
238
|
+
if self.is_emoji:
|
239
|
+
return f"https://t.me/addemoji/{self.pack_short_name}"
|
240
|
+
else:
|
241
|
+
return f"https://t.me/addstickers/{self.pack_short_name}"
|
242
|
+
|
243
|
+
async def _download_sticker(
|
244
|
+
self,
|
245
|
+
sticker: Union[PhotoSize, Sticker],
|
246
|
+
f_id: str,
|
247
|
+
out_dir: Path,
|
248
|
+
results: Dict[str, bool],
|
249
|
+
emoji_dict: Dict[str, str],
|
250
|
+
) -> None:
|
251
|
+
try:
|
252
|
+
sticker_file = await sticker.get_file(
|
253
|
+
read_timeout=self.timeout,
|
254
|
+
write_timeout=self.timeout,
|
255
|
+
connect_timeout=self.timeout,
|
256
|
+
pool_timeout=self.timeout,
|
257
|
+
)
|
258
|
+
except TelegramError as e:
|
259
|
+
self.cb.put(f"Failed to download {f_id}: {str(e)}")
|
260
|
+
results[f_id] = False
|
261
|
+
return
|
262
|
+
fpath = sticker_file.file_path
|
263
|
+
assert fpath is not None
|
264
|
+
ext = Path(fpath).suffix
|
265
|
+
f_name = f_id + ext
|
266
|
+
f_path = Path(out_dir, f_name)
|
267
|
+
await sticker_file.download_to_drive(
|
268
|
+
custom_path=f_path,
|
269
|
+
read_timeout=self.timeout,
|
270
|
+
write_timeout=self.timeout,
|
271
|
+
connect_timeout=self.timeout,
|
272
|
+
pool_timeout=self.timeout,
|
273
|
+
)
|
274
|
+
if isinstance(sticker, Sticker) and sticker.emoji is not None:
|
275
|
+
emoji_dict[f_id] = sticker.emoji
|
276
|
+
self.cb.put(f"Downloaded {f_name}")
|
277
|
+
results[f_id] = True
|
278
|
+
if f_id != "cover":
|
279
|
+
self.cb.put("update_bar")
|
280
|
+
|
281
|
+
async def pack_dl(
|
282
|
+
self, pack_short_name: str, out_dir: Path
|
283
|
+
) -> Tuple[Dict[str, bool], Dict[str, str]]:
|
284
|
+
results: Dict[str, bool] = {}
|
285
|
+
emoji_dict: Dict[str, str] = {}
|
286
|
+
|
287
|
+
try:
|
288
|
+
sticker_set: TGStickerSet = await self.application.bot.get_sticker_set(
|
289
|
+
pack_short_name,
|
290
|
+
read_timeout=self.timeout,
|
291
|
+
write_timeout=self.timeout,
|
292
|
+
connect_timeout=self.timeout,
|
293
|
+
pool_timeout=self.timeout,
|
294
|
+
)
|
295
|
+
except TelegramError as e:
|
296
|
+
self.cb.put(
|
297
|
+
f"Failed to download telegram sticker set {pack_short_name} due to: {e}"
|
298
|
+
)
|
299
|
+
return results, emoji_dict
|
300
|
+
|
301
|
+
self.cb.put(
|
302
|
+
(
|
303
|
+
"bar",
|
304
|
+
None,
|
305
|
+
{
|
306
|
+
"set_progress_mode": "determinate",
|
307
|
+
"steps": len(sticker_set.stickers),
|
308
|
+
},
|
309
|
+
)
|
310
|
+
)
|
311
|
+
|
312
|
+
async with anyio.create_task_group() as tg:
|
313
|
+
for num, sticker in enumerate(sticker_set.stickers):
|
314
|
+
f_id = str(num).zfill(3)
|
315
|
+
tg.start_soon(
|
316
|
+
self._download_sticker, sticker, f_id, out_dir, results, emoji_dict
|
317
|
+
)
|
318
|
+
|
319
|
+
if sticker_set.thumbnail is not None:
|
320
|
+
results_thumb: Dict[str, bool] = {}
|
321
|
+
tg.start_soon(
|
322
|
+
self._download_sticker,
|
323
|
+
sticker_set.thumbnail,
|
324
|
+
"cover",
|
325
|
+
out_dir,
|
326
|
+
results_thumb,
|
327
|
+
emoji_dict,
|
328
|
+
)
|
329
|
+
|
330
|
+
return results, emoji_dict
|
331
|
+
|
332
|
+
|
333
|
+
class TelethonAPI(TelegramAPI):
|
334
|
+
async def setup(
|
335
|
+
self,
|
336
|
+
opt_cred: CredOption,
|
337
|
+
is_upload: bool,
|
338
|
+
cb: CallbackProtocol,
|
339
|
+
cb_return: CallbackReturn,
|
340
|
+
) -> bool:
|
341
|
+
self.opt_cred = opt_cred
|
342
|
+
self.cb = cb
|
343
|
+
self.cb_return = cb_return
|
344
|
+
|
345
|
+
success, self.client, _, _ = await TelethonSetup(
|
346
|
+
self.opt_cred, self.cb_ask_str
|
347
|
+
).start_async()
|
348
|
+
|
349
|
+
return success
|
350
|
+
|
351
|
+
async def exit(self) -> None:
|
352
|
+
self.client.disconnect()
|
353
|
+
|
354
|
+
def cb_ask_str(
|
355
|
+
self, msg: Optional[str] = None, initialvalue: Optional[str] = None
|
356
|
+
) -> str:
|
357
|
+
self.cb.put(("ask_str", (msg,), None))
|
358
|
+
response = self.cb_return.get_response()
|
359
|
+
|
360
|
+
assert isinstance(response, str)
|
361
|
+
return response
|
362
|
+
|
363
|
+
async def set_upload_pack_short_name(self, pack_title: str) -> str:
|
364
|
+
self.pack_title = pack_title
|
365
|
+
self.pack_short_name = re.sub(
|
366
|
+
"[^0-9a-zA-Z]+", "_", pack_title
|
367
|
+
) # name used in url, only alphanum and underscore only
|
368
|
+
return self.pack_short_name
|
369
|
+
|
370
|
+
async def set_upload_pack_type(self, is_emoji: bool) -> None:
|
371
|
+
self.is_emoji = is_emoji
|
372
|
+
|
373
|
+
async def check_pack_exist(self) -> bool:
|
374
|
+
try:
|
375
|
+
await self.client(
|
376
|
+
messages.GetStickerSetRequest(
|
377
|
+
InputStickerSetShortName(self.pack_short_name), 0
|
378
|
+
)
|
379
|
+
)
|
380
|
+
except StickersetInvalidError:
|
381
|
+
return False
|
382
|
+
|
383
|
+
return True
|
384
|
+
|
385
|
+
async def _send_and_recv(self, msg: Union[str, Path]) -> str:
|
386
|
+
if isinstance(msg, str):
|
387
|
+
sent_message = await self.client.send_message("Stickers", msg)
|
388
|
+
else:
|
389
|
+
sent_message = cast(Message, await self.client.send_file("Stickers", msg)) # type: ignore
|
390
|
+
|
391
|
+
for _ in range(5):
|
392
|
+
last_message = cast(
|
393
|
+
List[Message],
|
394
|
+
await self.client.get_messages("Stickers", 1), # type: ignore
|
395
|
+
)[0]
|
396
|
+
if sent_message.id != last_message.id:
|
397
|
+
return last_message.message
|
398
|
+
time.sleep(1)
|
399
|
+
|
400
|
+
return "timeout"
|
401
|
+
|
402
|
+
async def pack_del(self) -> bool:
|
403
|
+
msg_fail = "Cannot delete pack of {} due to {}"
|
404
|
+
if self.is_emoji:
|
405
|
+
repl = await self._send_and_recv("/delemoji")
|
406
|
+
else:
|
407
|
+
repl = await self._send_and_recv("/delpack")
|
408
|
+
if repl != "Choose the sticker set you want to delete.":
|
409
|
+
self.cb.put(msg_fail.format(self.pack_short_name, repl))
|
410
|
+
return False
|
411
|
+
repl = await self._send_and_recv(self.pack_short_name)
|
412
|
+
if "Yes, I am totally sure." not in repl:
|
413
|
+
self.cb.put(msg_fail.format(self.pack_short_name, repl))
|
414
|
+
return False
|
415
|
+
repl = await self._send_and_recv("Yes, I am totally sure.")
|
416
|
+
if "Done!" not in repl:
|
417
|
+
self.cb.put(msg_fail.format(self.pack_short_name, repl))
|
418
|
+
return False
|
419
|
+
|
420
|
+
return True
|
421
|
+
|
422
|
+
async def pack_new(
|
423
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
424
|
+
) -> Tuple[int, int]:
|
425
|
+
stickers_ok = 0
|
426
|
+
if self.is_emoji:
|
427
|
+
repl = await self._send_and_recv("/newemojipack")
|
428
|
+
elif stickers_list[0][3] == "static":
|
429
|
+
repl = await self._send_and_recv("/newsticker")
|
430
|
+
elif stickers_list[0][3] == "video":
|
431
|
+
repl = await self._send_and_recv("/newvideo")
|
432
|
+
elif stickers_list[0][3] == "animated":
|
433
|
+
repl = await self._send_and_recv("/newanimated")
|
434
|
+
else:
|
435
|
+
self.cb.put(
|
436
|
+
f"Cannot upload any sticker to {self.pack_short_name} due to invalid sticker format {stickers_list[0][3]}"
|
437
|
+
)
|
438
|
+
return len(stickers_list), 0
|
439
|
+
if "Yay!" not in repl:
|
440
|
+
self.cb.put(f"Cannot upload any sticker due to {repl}")
|
441
|
+
return len(stickers_list), 0
|
442
|
+
|
443
|
+
if self.is_emoji:
|
444
|
+
repl = await self._send_and_recv(
|
445
|
+
f"{stickers_list[0][3].capitalize()} emoji"
|
446
|
+
)
|
447
|
+
if "Yay!" not in repl:
|
448
|
+
self.cb.put(f"Cannot upload any sticker due to {repl}")
|
449
|
+
return len(stickers_list), 0
|
450
|
+
|
451
|
+
repl = await self._send_and_recv(self.pack_title)
|
452
|
+
if "Alright!" not in repl:
|
453
|
+
self.cb.put(f"Cannot upload any sticker due to {repl}")
|
454
|
+
return len(stickers_list), 0
|
455
|
+
self.cb.put(
|
456
|
+
(
|
457
|
+
"bar",
|
458
|
+
None,
|
459
|
+
{
|
460
|
+
"set_progress_mode": "determinate",
|
461
|
+
"steps": len(stickers_list),
|
462
|
+
},
|
463
|
+
)
|
464
|
+
)
|
465
|
+
for i in stickers_list:
|
466
|
+
repl = await self._send_and_recv(i[0])
|
467
|
+
if "Thanks!" not in repl:
|
468
|
+
self.cb.put(
|
469
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {repl}"
|
470
|
+
)
|
471
|
+
self.cb.put("update_bar")
|
472
|
+
continue
|
473
|
+
repl = await self._send_and_recv("".join(i[2]))
|
474
|
+
if "Congratulations." not in repl:
|
475
|
+
self.cb.put(
|
476
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {repl}"
|
477
|
+
)
|
478
|
+
self.cb.put("update_bar")
|
479
|
+
continue
|
480
|
+
stickers_ok += 1
|
481
|
+
self.cb.put("update_bar")
|
482
|
+
repl = await self._send_and_recv("/publish")
|
483
|
+
if "icon" not in repl:
|
484
|
+
self.cb.put(f"Cannot upload pack {self.pack_short_name} due to {repl}")
|
485
|
+
return len(stickers_list), 0
|
486
|
+
repl = await self._send_and_recv("/skip")
|
487
|
+
if "Please provide a short name" not in repl:
|
488
|
+
self.cb.put(f"Cannot upload pack {self.pack_short_name} due to {repl}")
|
489
|
+
return len(stickers_list), 0
|
490
|
+
repl = await self._send_and_recv(self.pack_short_name)
|
491
|
+
if "Kaboom!" not in repl:
|
492
|
+
self.cb.put(f"Cannot upload pack {self.pack_short_name} due to {repl}")
|
493
|
+
return len(stickers_list), 0
|
494
|
+
|
495
|
+
self.cb.put(("bar", None, {"set_progress_mode": "indeterminate"}))
|
496
|
+
|
497
|
+
return len(stickers_list), stickers_ok
|
498
|
+
|
499
|
+
async def pack_add(
|
500
|
+
self, stickers_list: List[TelegramSticker], sticker_type: str
|
501
|
+
) -> Tuple[int, int]:
|
502
|
+
stickers_ok = 0
|
503
|
+
if self.is_emoji:
|
504
|
+
repl = await self._send_and_recv("/addemoji")
|
505
|
+
else:
|
506
|
+
repl = await self._send_and_recv("/addsticker")
|
507
|
+
if "Choose" not in repl:
|
508
|
+
self.cb.put(
|
509
|
+
f"Cannot upload any sticker to {self.pack_short_name} due to {repl}"
|
510
|
+
)
|
511
|
+
return len(stickers_list), 0
|
512
|
+
repl = await self._send_and_recv(self.pack_short_name)
|
513
|
+
if "Alright!" not in repl:
|
514
|
+
self.cb.put(
|
515
|
+
f"Cannot upload any sticker to {self.pack_short_name} due to {repl}"
|
516
|
+
)
|
517
|
+
return len(stickers_list), 0
|
518
|
+
|
519
|
+
self.cb.put(
|
520
|
+
(
|
521
|
+
"bar",
|
522
|
+
None,
|
523
|
+
{
|
524
|
+
"set_progress_mode": "determinate",
|
525
|
+
"steps": len(stickers_list),
|
526
|
+
},
|
527
|
+
)
|
528
|
+
)
|
529
|
+
for i in stickers_list:
|
530
|
+
repl = await self._send_and_recv(i[0])
|
531
|
+
if "Thanks!" not in repl:
|
532
|
+
self.cb.put(
|
533
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {repl}"
|
534
|
+
)
|
535
|
+
self.cb.put("update_bar")
|
536
|
+
continue
|
537
|
+
repl = await self._send_and_recv("".join(i[2]))
|
538
|
+
if "There we go." not in repl:
|
539
|
+
self.cb.put(
|
540
|
+
f"Cannot upload sticker {i[0]} of {self.pack_short_name} due to {repl}"
|
541
|
+
)
|
542
|
+
self.cb.put("update_bar")
|
543
|
+
continue
|
544
|
+
self.cb.put("update_bar")
|
545
|
+
stickers_ok += 1
|
546
|
+
|
547
|
+
self.cb.put(("bar", None, {"set_progress_mode": "indeterminate"}))
|
548
|
+
|
549
|
+
repl = await self._send_and_recv("/done")
|
550
|
+
if "OK" not in repl:
|
551
|
+
self.cb.put(
|
552
|
+
f"Cannot upload any sticker to {self.pack_short_name} due to {repl}"
|
553
|
+
)
|
554
|
+
return len(stickers_list), 0
|
555
|
+
|
556
|
+
return len(stickers_list), stickers_ok
|
557
|
+
|
558
|
+
async def pack_thumbnail(self, thumbnail: TelegramSticker) -> bool:
|
559
|
+
repl = await self._send_and_recv("/setpackicon")
|
560
|
+
if "OK" not in repl:
|
561
|
+
self.cb.put(
|
562
|
+
f"Cannot set pack icon for {self.pack_short_name} due to {repl}"
|
563
|
+
)
|
564
|
+
return False
|
565
|
+
repl = await self._send_and_recv(thumbnail[0])
|
566
|
+
if "Enjoy!" not in repl:
|
567
|
+
self.cb.put(
|
568
|
+
f"Cannot set pack icon for {self.pack_short_name} due to {repl}"
|
569
|
+
)
|
570
|
+
return False
|
571
|
+
return True
|
572
|
+
|
573
|
+
async def get_pack_url(self) -> str:
|
574
|
+
if self.is_emoji:
|
575
|
+
return f"https://t.me/addemoji/{self.pack_short_name}"
|
576
|
+
else:
|
577
|
+
return f"https://t.me/addstickers/{self.pack_short_name}"
|
578
|
+
|
579
|
+
async def _download_sticker(
|
580
|
+
self,
|
581
|
+
sticker: TypeDocument,
|
582
|
+
f_id: str,
|
583
|
+
out_dir: Path,
|
584
|
+
id_to_emoji: Dict[int, str],
|
585
|
+
emoji_dict: Dict[str, str],
|
586
|
+
results: Dict[str, bool],
|
587
|
+
) -> None:
|
588
|
+
fpath_attr = [
|
589
|
+
attr
|
590
|
+
for attr in sticker.attributes # type: ignore
|
591
|
+
if isinstance(attr, DocumentAttributeFilename)
|
592
|
+
]
|
593
|
+
assert len(fpath_attr) > 0
|
594
|
+
fpath = fpath_attr[0].file_name
|
595
|
+
ext = Path(fpath).suffix
|
596
|
+
f_name = f_id + ext
|
597
|
+
f_path = Path(out_dir, f_name)
|
598
|
+
|
599
|
+
try:
|
600
|
+
await self.client.download_media(sticker, file=f_path) # type: ignore
|
601
|
+
except Exception as e:
|
602
|
+
self.cb.put(f"Failed to download {f_id}: {str(e)}")
|
603
|
+
results[f_id] = False
|
604
|
+
return
|
605
|
+
|
606
|
+
emoji_dict[f_id] = id_to_emoji[sticker.id]
|
607
|
+
self.cb.put(f"Downloaded {f_name}")
|
608
|
+
results[f_id] = True
|
609
|
+
self.cb.put("update_bar")
|
610
|
+
|
611
|
+
async def pack_dl(
|
612
|
+
self, pack_short_name: str, out_dir: Path
|
613
|
+
) -> Tuple[Dict[str, bool], Dict[str, str]]:
|
614
|
+
results: Dict[str, bool] = {}
|
615
|
+
emoji_dict: Dict[str, str] = {}
|
616
|
+
id_to_emoji: Dict[int, str] = defaultdict(str)
|
617
|
+
|
618
|
+
sticker_set = cast(
|
619
|
+
TLStickerSet,
|
620
|
+
await self.client(
|
621
|
+
messages.GetStickerSetRequest(
|
622
|
+
InputStickerSetShortName(pack_short_name), 0
|
623
|
+
)
|
624
|
+
),
|
625
|
+
)
|
626
|
+
|
627
|
+
self.cb.put(
|
628
|
+
(
|
629
|
+
"bar",
|
630
|
+
None,
|
631
|
+
{
|
632
|
+
"set_progress_mode": "determinate",
|
633
|
+
"steps": len(sticker_set.documents),
|
634
|
+
},
|
635
|
+
)
|
636
|
+
)
|
637
|
+
|
638
|
+
for pack in sticker_set.packs:
|
639
|
+
for document_id in pack.documents:
|
640
|
+
id_to_emoji[document_id] += pack.emoticon
|
641
|
+
|
642
|
+
ext = ""
|
643
|
+
async with anyio.create_task_group() as tg:
|
644
|
+
for num, sticker in enumerate(sticker_set.documents):
|
645
|
+
f_id = str(num).zfill(3)
|
646
|
+
tg.start_soon(
|
647
|
+
self._download_sticker,
|
648
|
+
sticker,
|
649
|
+
f_id,
|
650
|
+
out_dir,
|
651
|
+
id_to_emoji,
|
652
|
+
emoji_dict,
|
653
|
+
results,
|
654
|
+
)
|
655
|
+
|
656
|
+
if sticker_set.set.thumb_version and ext:
|
657
|
+
try:
|
658
|
+
await self.client.download_file( # type: ignore
|
659
|
+
InputStickerSetThumb(
|
660
|
+
InputStickerSetShortName(pack_short_name),
|
661
|
+
thumb_version=sticker_set.set.thumb_version,
|
662
|
+
),
|
663
|
+
f"cover{ext}",
|
664
|
+
)
|
665
|
+
except Exception as e:
|
666
|
+
self.cb.put(f"Failed to download cover{ext}: {str(e)}")
|
667
|
+
|
668
|
+
return results, emoji_dict
|