sticker-convert 2.10.8__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 +10 -6
- sticker_convert/downloaders/download_base.py +37 -17
- sticker_convert/downloaders/download_discord.py +6 -6
- sticker_convert/downloaders/download_kakao.py +31 -13
- sticker_convert/downloaders/download_line.py +6 -6
- sticker_convert/downloaders/download_signal.py +10 -8
- sticker_convert/downloaders/download_telegram.py +22 -96
- sticker_convert/downloaders/download_viber.py +8 -6
- sticker_convert/gui.py +12 -0
- sticker_convert/gui_components/frames/cred_frame.py +38 -13
- sticker_convert/job.py +84 -63
- 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/compress_wastickers.py +8 -6
- sticker_convert/uploaders/upload_signal.py +10 -6
- sticker_convert/uploaders/upload_telegram.py +178 -231
- sticker_convert/uploaders/upload_viber.py +12 -8
- sticker_convert/uploaders/xcode_imessage.py +8 -6
- 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.8.dist-info → sticker_convert-2.11.0.dist-info}/METADATA +54 -36
- {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/RECORD +32 -30
- {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/LICENSE +0 -0
- {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/WHEEL +0 -0
- {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/top_level.txt +0 -0
@@ -44,7 +44,7 @@ class DownloadViber(DownloadBase):
|
|
44
44
|
|
45
45
|
return title, zip_url
|
46
46
|
|
47
|
-
def decompress(self, zip_file: bytes) ->
|
47
|
+
def decompress(self, zip_file: bytes) -> int:
|
48
48
|
with zipfile.ZipFile(BytesIO(zip_file)) as zf:
|
49
49
|
self.cb.put("Unzipping...")
|
50
50
|
|
@@ -69,19 +69,21 @@ class DownloadViber(DownloadBase):
|
|
69
69
|
|
70
70
|
self.cb.put("update_bar")
|
71
71
|
|
72
|
-
|
72
|
+
return len(zf_files)
|
73
|
+
|
74
|
+
def download_stickers_viber(self) -> Tuple[int, int]:
|
73
75
|
pack_info = self.get_pack_info(self.url)
|
74
76
|
if pack_info is None:
|
75
77
|
self.cb.put("Download failed: Cannot get pack info")
|
76
|
-
return
|
78
|
+
return 0, 0
|
77
79
|
title, zip_url = pack_info
|
78
80
|
|
79
81
|
zip_file = self.download_file(zip_url)
|
80
|
-
self.decompress(zip_file)
|
82
|
+
count = self.decompress(zip_file)
|
81
83
|
|
82
84
|
MetadataHandler.set_metadata(self.out_dir, title=title)
|
83
85
|
|
84
|
-
return
|
86
|
+
return count, count
|
85
87
|
|
86
88
|
@staticmethod
|
87
89
|
def start(
|
@@ -89,6 +91,6 @@ class DownloadViber(DownloadBase):
|
|
89
91
|
opt_cred: Optional[CredOption],
|
90
92
|
cb: CallbackProtocol,
|
91
93
|
cb_return: CallbackReturn,
|
92
|
-
) ->
|
94
|
+
) -> Tuple[int, int]:
|
93
95
|
downloader = DownloadViber(opt_input, opt_cred, cb, cb_return)
|
94
96
|
return downloader.download_stickers_viber()
|
sticker_convert/gui.py
CHANGED
@@ -154,6 +154,8 @@ class GUI(Window):
|
|
154
154
|
self.signal_password_var = StringVar(self)
|
155
155
|
self.telegram_token_var = StringVar(self)
|
156
156
|
self.telegram_userid_var = StringVar(self)
|
157
|
+
self.telethon_api_id_var = IntVar(self)
|
158
|
+
self.telethon_api_hash_var = StringVar(self)
|
157
159
|
self.kakao_auth_token_var = StringVar(self)
|
158
160
|
self.kakao_username_var = StringVar(self)
|
159
161
|
self.kakao_password_var = StringVar(self)
|
@@ -406,6 +408,10 @@ class GUI(Window):
|
|
406
408
|
self.signal_password_var.set(self.creds.get("signal", {}).get("password", ""))
|
407
409
|
self.telegram_token_var.set(self.creds.get("telegram", {}).get("token", ""))
|
408
410
|
self.telegram_userid_var.set(self.creds.get("telegram", {}).get("userid", ""))
|
411
|
+
self.telethon_api_id_var.set(self.creds.get("telethon", {}).get("api_id", 0))
|
412
|
+
self.telethon_api_hash_var.set(
|
413
|
+
self.creds.get("telethon", {}).get("api_hash", "")
|
414
|
+
)
|
409
415
|
self.kakao_auth_token_var.set(self.creds.get("kakao", {}).get("auth_token", ""))
|
410
416
|
self.kakao_username_var.set(self.creds.get("kakao", {}).get("username", ""))
|
411
417
|
self.kakao_password_var.set(self.creds.get("kakao", {}).get("password", ""))
|
@@ -451,6 +457,10 @@ class GUI(Window):
|
|
451
457
|
selection = self.comp_preset_var.get()
|
452
458
|
if selection == "auto":
|
453
459
|
output_option = self.get_output_name()
|
460
|
+
if "telegram_emoji" in output_option:
|
461
|
+
return "telegram_emoji"
|
462
|
+
if "telegram" in output_option:
|
463
|
+
return "telegram"
|
454
464
|
if output_option == "imessage":
|
455
465
|
return "imessage_small"
|
456
466
|
if output_option == "local":
|
@@ -572,6 +582,8 @@ class GUI(Window):
|
|
572
582
|
signal_password=self.signal_password_var.get(),
|
573
583
|
telegram_token=self.telegram_token_var.get(),
|
574
584
|
telegram_userid=self.telegram_userid_var.get(),
|
585
|
+
telethon_api_id=self.telethon_api_id_var.get(),
|
586
|
+
telethon_api_hash=self.telethon_api_hash_var.get(),
|
575
587
|
kakao_auth_token=self.kakao_auth_token_var.get(),
|
576
588
|
kakao_username=self.kakao_username_var.get(),
|
577
589
|
kakao_password=self.kakao_password_var.get(),
|
@@ -10,6 +10,7 @@ from sticker_convert.gui_components.windows.kakao_get_auth_window import KakaoGe
|
|
10
10
|
from sticker_convert.gui_components.windows.line_get_auth_window import LineGetAuthWindow
|
11
11
|
from sticker_convert.gui_components.windows.signal_get_auth_window import SignalGetAuthWindow
|
12
12
|
from sticker_convert.gui_components.windows.viber_get_auth_window import ViberGetAuthWindow
|
13
|
+
from sticker_convert.utils.auth.telethon_setup import TelethonSetup
|
13
14
|
|
14
15
|
if TYPE_CHECKING:
|
15
16
|
from sticker_convert.gui import GUI # type: ignore
|
@@ -77,6 +78,16 @@ class CredFrame(LabelFrame):
|
|
77
78
|
)
|
78
79
|
self.telegram_userid_entry.bind("<Button-3><ButtonRelease-3>", RightClicker)
|
79
80
|
|
81
|
+
self.telethon_auth_lbl = Label(
|
82
|
+
self, text="Telethon authorization", justify="left", anchor="w"
|
83
|
+
)
|
84
|
+
self.telethon_auth_btn = Button(
|
85
|
+
self,
|
86
|
+
text="Generate",
|
87
|
+
command=self.cb_telethon_get_auth,
|
88
|
+
bootstyle="secondary", # type: ignore
|
89
|
+
)
|
90
|
+
|
80
91
|
self.kakao_auth_token_lbl = Label(
|
81
92
|
self, text="Kakao auth_token", justify="left", anchor="w"
|
82
93
|
)
|
@@ -157,19 +168,21 @@ class CredFrame(LabelFrame):
|
|
157
168
|
self.telegram_userid_entry.grid(
|
158
169
|
column=1, row=4, columnspan=2, sticky="w", padx=3, pady=3
|
159
170
|
)
|
160
|
-
self.
|
161
|
-
self.
|
162
|
-
self.
|
163
|
-
self.
|
164
|
-
self.
|
165
|
-
self.
|
166
|
-
self.
|
167
|
-
self.
|
168
|
-
self.
|
169
|
-
self.
|
170
|
-
self.
|
171
|
-
self.
|
172
|
-
self.
|
171
|
+
self.telethon_auth_lbl.grid(column=0, row=5, sticky="w", padx=3, pady=3)
|
172
|
+
self.telethon_auth_btn.grid(column=2, row=5, sticky="e", padx=3, pady=3)
|
173
|
+
self.kakao_auth_token_lbl.grid(column=0, row=6, sticky="w", padx=3, pady=3)
|
174
|
+
self.kakao_auth_token_entry.grid(column=1, row=6, sticky="w", padx=3, pady=3)
|
175
|
+
self.kakao_get_auth_btn.grid(column=2, row=6, sticky="e", padx=3, pady=3)
|
176
|
+
self.line_cookies_lbl.grid(column=0, row=7, sticky="w", padx=3, pady=3)
|
177
|
+
self.line_cookies_entry.grid(column=1, row=7, sticky="w", padx=3, pady=3)
|
178
|
+
self.line_get_auth_btn.grid(column=2, row=7, sticky="e", padx=3, pady=3)
|
179
|
+
self.viber_auth_lbl.grid(column=0, row=8, sticky="w", padx=3, pady=3)
|
180
|
+
self.viber_auth_entry.grid(column=1, row=8, sticky="w", padx=3, pady=3)
|
181
|
+
self.viber_get_auth_btn.grid(column=2, row=8, sticky="e", padx=3, pady=3)
|
182
|
+
self.discord_token_lbl.grid(column=0, row=9, sticky="w", padx=3, pady=3)
|
183
|
+
self.discord_token_entry.grid(column=1, row=9, sticky="w", padx=3, pady=3)
|
184
|
+
self.discord_get_auth_btn.grid(column=2, row=9, sticky="e", padx=3, pady=3)
|
185
|
+
self.help_btn.grid(column=2, row=10, sticky="e", padx=3, pady=3)
|
173
186
|
|
174
187
|
def cb_cred_help(self, *_: Any) -> None:
|
175
188
|
faq_site = "https://github.com/laggykiller/sticker-convert#faq"
|
@@ -177,6 +190,18 @@ class CredFrame(LabelFrame):
|
|
177
190
|
if not success:
|
178
191
|
self.gui.cb_ask_str("You can get help from:", initialvalue=faq_site)
|
179
192
|
|
193
|
+
def cb_telethon_get_auth(self, *_: Any) -> None:
|
194
|
+
success, _client, api_id, api_hash = TelethonSetup(
|
195
|
+
self.gui.get_opt_cred(), self.gui.cb_ask_str
|
196
|
+
).start()
|
197
|
+
if success:
|
198
|
+
self.gui.telethon_api_id_var.set(api_id)
|
199
|
+
self.gui.telethon_api_hash_var.set(api_hash)
|
200
|
+
self.gui.save_creds()
|
201
|
+
self.gui.cb_msg_block("Telethon setup successful")
|
202
|
+
else:
|
203
|
+
self.gui.cb_msg_block("Telethon setup failed")
|
204
|
+
|
180
205
|
def cb_kakao_get_auth(self, *_: Any) -> None:
|
181
206
|
KakaoGetAuthWindow(self.gui)
|
182
207
|
|
sticker_convert/job.py
CHANGED
@@ -216,7 +216,6 @@ class Job:
|
|
216
216
|
self.cb_ask_bool = cb_ask_bool
|
217
217
|
self.cb_ask_str = cb_ask_str
|
218
218
|
|
219
|
-
self.compress_fails: List[str] = []
|
220
219
|
self.out_urls: List[str] = []
|
221
220
|
|
222
221
|
self.executor = Executor(
|
@@ -236,19 +235,21 @@ class Job:
|
|
236
235
|
|
237
236
|
self.executor.cb("msg", kwargs={"cls": True})
|
238
237
|
|
239
|
-
tasks = (
|
238
|
+
tasks: Tuple[Callable[..., Tuple[bool, Optional[str]]], ...] = (
|
240
239
|
self.verify_input,
|
241
240
|
self.cleanup,
|
242
241
|
self.download,
|
243
242
|
self.compress,
|
244
243
|
self.export,
|
245
|
-
self.report,
|
246
244
|
)
|
247
245
|
|
248
246
|
code = 0
|
247
|
+
summaries: List[str] = []
|
249
248
|
for task in tasks:
|
250
249
|
self.executor.cb("bar", kwargs={"set_progress_mode": "indeterminate"})
|
251
|
-
success = task()
|
250
|
+
success, summary = task()
|
251
|
+
if summary is not None:
|
252
|
+
summaries.append(summary)
|
252
253
|
|
253
254
|
if self.executor.is_cancel_job.value == 1: # type: ignore
|
254
255
|
code = 2
|
@@ -258,6 +259,22 @@ class Job:
|
|
258
259
|
self.executor.cb("An error occured during this run.")
|
259
260
|
break
|
260
261
|
|
262
|
+
msg = "##########\n"
|
263
|
+
msg += "Summary:\n"
|
264
|
+
msg += "##########\n"
|
265
|
+
|
266
|
+
msg += "\n"
|
267
|
+
msg += "\n".join(summaries)
|
268
|
+
msg += "\n"
|
269
|
+
|
270
|
+
if self.out_urls:
|
271
|
+
msg += "Export results:\n"
|
272
|
+
msg += "\n".join(self.out_urls)
|
273
|
+
else:
|
274
|
+
msg += "Export result: None"
|
275
|
+
|
276
|
+
self.executor.cb(msg)
|
277
|
+
|
261
278
|
self.executor.cleanup()
|
262
279
|
|
263
280
|
return code
|
@@ -265,7 +282,7 @@ class Job:
|
|
265
282
|
def cancel(self, *_: Any, **_kwargs: Any) -> None:
|
266
283
|
self.executor.kill_workers()
|
267
284
|
|
268
|
-
def verify_input(self) -> bool:
|
285
|
+
def verify_input(self) -> Tuple[bool, None]:
|
269
286
|
info_msg = ""
|
270
287
|
error_msg = ""
|
271
288
|
|
@@ -352,7 +369,7 @@ class Job:
|
|
352
369
|
|
353
370
|
if error_msg != "":
|
354
371
|
self.executor.cb(error_msg)
|
355
|
-
return False
|
372
|
+
return False, None
|
356
373
|
|
357
374
|
# Check if preset not equal to export option
|
358
375
|
# Only warn if the compression option is available in export preset
|
@@ -362,7 +379,10 @@ class Job:
|
|
362
379
|
not self.opt_comp.no_compress
|
363
380
|
and self.opt_output.option != "local"
|
364
381
|
and self.opt_comp.preset != "custom"
|
365
|
-
and
|
382
|
+
and (
|
383
|
+
self.opt_output.option not in self.opt_comp.preset
|
384
|
+
and self.opt_comp.preset not in self.opt_output.option
|
385
|
+
)
|
366
386
|
):
|
367
387
|
msg = "Compression preset does not match export option\n"
|
368
388
|
msg += "You may continue, but the files will need to be compressed again before export\n"
|
@@ -372,7 +392,7 @@ class Job:
|
|
372
392
|
response = self.executor.cb_return.get_response()
|
373
393
|
|
374
394
|
if response is False:
|
375
|
-
return False
|
395
|
+
return False, None
|
376
396
|
|
377
397
|
for param, value in (
|
378
398
|
("fps_power", self.opt_comp.fps_power),
|
@@ -431,7 +451,7 @@ class Job:
|
|
431
451
|
response = self.executor.cb_return.get_response()
|
432
452
|
|
433
453
|
if response is False:
|
434
|
-
return False
|
454
|
+
return False, None
|
435
455
|
|
436
456
|
# Warn about in/output directories that might contain other files
|
437
457
|
# Directory is safe if the name is stickers_input/stickers_output, or
|
@@ -468,13 +488,13 @@ class Job:
|
|
468
488
|
response = self.executor.cb_return.get_response()
|
469
489
|
|
470
490
|
if response is False:
|
471
|
-
return False
|
491
|
+
return False, None
|
472
492
|
|
473
493
|
break
|
474
494
|
|
475
|
-
return True
|
495
|
+
return True, None
|
476
496
|
|
477
|
-
def cleanup(self) -> bool:
|
497
|
+
def cleanup(self) -> Tuple[bool, None]:
|
478
498
|
# If input is 'From local directory', then we should keep files in input/output directory as it maybe edited by user
|
479
499
|
# If input is not 'From local directory', then we should move files in input/output directory as new files will be downloaded
|
480
500
|
# Output directory should be cleanup unless no_compress is true (meaning files in output directory might be edited by user)
|
@@ -523,10 +543,10 @@ class Job:
|
|
523
543
|
new_path = Path(archive_dir, old_path.name)
|
524
544
|
old_path.rename(new_path)
|
525
545
|
|
526
|
-
return True
|
546
|
+
return True, None
|
527
547
|
|
528
|
-
def download(self) -> bool:
|
529
|
-
downloaders: List[Callable[...,
|
548
|
+
def download(self) -> Tuple[bool, str]:
|
549
|
+
downloaders: List[Callable[..., Tuple[int, int]]] = []
|
530
550
|
|
531
551
|
if self.opt_input.option == "signal":
|
532
552
|
downloaders.append(DownloadSignal.start)
|
@@ -534,7 +554,7 @@ class Job:
|
|
534
554
|
if self.opt_input.option == "line":
|
535
555
|
downloaders.append(DownloadLine.start)
|
536
556
|
|
537
|
-
if self.opt_input.option
|
557
|
+
if self.opt_input.option.startswith("telegram"):
|
538
558
|
downloaders.append(DownloadTelegram.start)
|
539
559
|
|
540
560
|
if self.opt_input.option == "kakao":
|
@@ -549,8 +569,8 @@ class Job:
|
|
549
569
|
if len(downloaders) > 0:
|
550
570
|
self.executor.cb("Downloading...")
|
551
571
|
else:
|
552
|
-
self.executor.cb("
|
553
|
-
return True
|
572
|
+
self.executor.cb("Skipped download (No files to download)")
|
573
|
+
return True, "Download: Skipped (No files to download)"
|
554
574
|
|
555
575
|
self.executor.start_workers(processes=1)
|
556
576
|
|
@@ -563,15 +583,24 @@ class Job:
|
|
563
583
|
self.executor.join_workers()
|
564
584
|
|
565
585
|
# Return False if any of the job returns failure
|
586
|
+
stickers_ok = 0
|
587
|
+
stickers_total = 0
|
588
|
+
success = True
|
566
589
|
for result in self.executor.results_list:
|
567
|
-
|
568
|
-
|
590
|
+
stickers_ok += result[0]
|
591
|
+
stickers_total += result[1]
|
592
|
+
success = (
|
593
|
+
success if stickers_ok == stickers_total and stickers_ok > 0 else False
|
594
|
+
)
|
569
595
|
|
570
|
-
return
|
596
|
+
return (
|
597
|
+
success,
|
598
|
+
f"Download: {stickers_ok}/{stickers_total} stickers success",
|
599
|
+
)
|
571
600
|
|
572
|
-
def compress(self) -> bool:
|
601
|
+
def compress(self) -> Tuple[bool, str]:
|
573
602
|
if self.opt_comp.no_compress is True:
|
574
|
-
self.executor.cb("no_compress is set to True
|
603
|
+
self.executor.cb("Skipped compression (no_compress is set to True)")
|
575
604
|
in_dir_files = [
|
576
605
|
i
|
577
606
|
for i in sorted(self.opt_input.dir.iterdir())
|
@@ -598,7 +627,7 @@ class Job:
|
|
598
627
|
src_f = Path(self.opt_input.dir, i.name)
|
599
628
|
dst_f = Path(self.opt_output.dir, i.name)
|
600
629
|
shutil.copy(src_f, dst_f)
|
601
|
-
return True
|
630
|
+
return True, "Compress: Skipped (no_compress is set to True)"
|
602
631
|
msg = "Compressing..."
|
603
632
|
|
604
633
|
input_dir = Path(self.opt_input.dir)
|
@@ -620,8 +649,8 @@ class Job:
|
|
620
649
|
|
621
650
|
in_fs_count = len(in_fs)
|
622
651
|
if in_fs_count == 0:
|
623
|
-
self.executor.cb("No files to compress")
|
624
|
-
return True
|
652
|
+
self.executor.cb("Skipped compression (No files to compress)")
|
653
|
+
return True, "Compress: Skipped (No files to compress)"
|
625
654
|
|
626
655
|
self.executor.cb(msg)
|
627
656
|
self.executor.cb(
|
@@ -640,21 +669,35 @@ class Job:
|
|
640
669
|
|
641
670
|
self.executor.join_workers()
|
642
671
|
|
643
|
-
|
672
|
+
success = True
|
673
|
+
stickers_ok = 0
|
674
|
+
stickers_total = 0
|
675
|
+
fails: List[str] = []
|
644
676
|
for result in self.executor.results_list:
|
677
|
+
stickers_total += 1
|
645
678
|
if result[0] is False:
|
646
|
-
|
679
|
+
success = False
|
680
|
+
fails.append(str(result[1]))
|
681
|
+
else:
|
682
|
+
stickers_ok += 1
|
647
683
|
|
648
|
-
|
684
|
+
msg_append = ""
|
685
|
+
if success is False:
|
686
|
+
msg_append = " (Failed: " + ", ".join(fails) + ")"
|
649
687
|
|
650
|
-
|
688
|
+
return (
|
689
|
+
success,
|
690
|
+
f"Compress: {stickers_ok}/{stickers_total} stickers success" + msg_append,
|
691
|
+
)
|
692
|
+
|
693
|
+
def export(self) -> Tuple[bool, str]:
|
651
694
|
if self.opt_output.option == "local":
|
652
|
-
self.executor.cb("Saving to local directory only
|
653
|
-
return True
|
695
|
+
self.executor.cb("Skipped export (Saving to local directory only)")
|
696
|
+
return True, "Export: Skipped (Saving to local directory only)"
|
654
697
|
|
655
698
|
self.executor.cb("Exporting...")
|
656
699
|
|
657
|
-
exporters: List[Callable[..., List[str]]] = []
|
700
|
+
exporters: List[Callable[..., Tuple[int, int, List[str]]]] = []
|
658
701
|
|
659
702
|
if self.opt_output.option == "whatsapp":
|
660
703
|
exporters.append(CompressWastickers.start)
|
@@ -662,10 +705,7 @@ class Job:
|
|
662
705
|
if self.opt_output.option == "signal":
|
663
706
|
exporters.append(UploadSignal.start)
|
664
707
|
|
665
|
-
if self.opt_output.option
|
666
|
-
exporters.append(UploadTelegram.start)
|
667
|
-
|
668
|
-
if self.opt_output.option == "telegram_emoji":
|
708
|
+
if self.opt_output.option.startswith("telegram"):
|
669
709
|
exporters.append(UploadTelegram.start)
|
670
710
|
|
671
711
|
if self.opt_output.option == "imessage":
|
@@ -684,8 +724,12 @@ class Job:
|
|
684
724
|
|
685
725
|
self.executor.join_workers()
|
686
726
|
|
727
|
+
stickers_ok = 0
|
728
|
+
stickers_total = 0
|
687
729
|
for result in self.executor.results_list:
|
688
|
-
|
730
|
+
stickers_ok += result[0]
|
731
|
+
stickers_total += result[1]
|
732
|
+
self.out_urls.extend(result[2])
|
689
733
|
|
690
734
|
if self.out_urls:
|
691
735
|
with open(
|
@@ -694,29 +738,6 @@ class Job:
|
|
694
738
|
f.write("\n".join(self.out_urls))
|
695
739
|
else:
|
696
740
|
self.executor.cb("An error occured while exporting stickers")
|
697
|
-
return False
|
698
|
-
|
699
|
-
return True
|
700
|
-
|
701
|
-
def report(self) -> bool:
|
702
|
-
msg = "##########\n"
|
703
|
-
msg += "Summary:\n"
|
704
|
-
msg += "##########\n"
|
705
|
-
msg += "\n"
|
706
|
-
|
707
|
-
if self.compress_fails:
|
708
|
-
msg += f'Warning: Could not compress the following {len(self.compress_fails)} file{"s" if len(self.compress_fails) > 1 else ""}:\n'
|
709
|
-
msg += "\n".join(self.compress_fails)
|
710
|
-
msg += "\n"
|
711
|
-
msg += "\nConsider adjusting compression parameters"
|
712
|
-
msg += "\n"
|
713
|
-
|
714
|
-
if self.out_urls:
|
715
|
-
msg += "Export results:\n"
|
716
|
-
msg += "\n".join(self.out_urls)
|
717
|
-
else:
|
718
|
-
msg += "Export result: None"
|
719
|
-
|
720
|
-
self.executor.cb(msg)
|
741
|
+
return False, f"Export: {stickers_ok}/{stickers_total} stickers success"
|
721
742
|
|
722
|
-
return True
|
743
|
+
return True, f"Export: {stickers_ok}/{stickers_total} stickers success"
|
sticker_convert/job_option.py
CHANGED
@@ -214,6 +214,8 @@ class CredOption(BaseOption):
|
|
214
214
|
signal_password: str = ""
|
215
215
|
telegram_token: str = ""
|
216
216
|
telegram_userid: str = ""
|
217
|
+
telethon_api_id: int = 0
|
218
|
+
telethon_api_hash: str = ""
|
217
219
|
kakao_auth_token: str = ""
|
218
220
|
kakao_username: str = ""
|
219
221
|
kakao_password: str = ""
|
@@ -227,6 +229,10 @@ class CredOption(BaseOption):
|
|
227
229
|
return {
|
228
230
|
"signal": {"uuid": self.signal_uuid, "password": self.signal_password},
|
229
231
|
"telegram": {"token": self.telegram_token, "userid": self.telegram_userid},
|
232
|
+
"telethon": {
|
233
|
+
"api_id": self.telethon_api_id,
|
234
|
+
"api_hash": self.telethon_api_hash,
|
235
|
+
},
|
230
236
|
"kakao": {
|
231
237
|
"auth_token": self.kakao_auth_token,
|
232
238
|
"username": self.kakao_username,
|
@@ -59,7 +59,8 @@
|
|
59
59
|
"signal_password": "Set Signal password. Required for uploading Signal stickers.",
|
60
60
|
"signal_get_auth": "Generate Signal uuid and password.",
|
61
61
|
"telegram_token": "Set Telegram token. Required for uploading and downloading Telegram stickers.",
|
62
|
-
"telegram_userid": "Set
|
62
|
+
"telegram_userid": "Set Telegram user_id (From real account, not bot account). Required for uploading Telegram stickers.",
|
63
|
+
"telethon_setup": "Setup Telethon",
|
63
64
|
"kakao_auth_token": "Set Kakao auth_token. Required for downloading animated stickers from https://e.kakao.com/t/xxxxx",
|
64
65
|
"kakao_get_auth": "Generate Kakao auth_token by simulating login. Kakao username, password, country code and phone number are also required.",
|
65
66
|
"kakao_get_auth_desktop": "Get Kakao auth_token from Kakao Desktop application.\n(Only working on Windows.)",
|
@@ -75,6 +76,6 @@
|
|
75
76
|
"viber_bin_path": "Specify location of Viber Desktop application.\nUseful for portable installation.",
|
76
77
|
"discord_get_auth": "Get Discord token.",
|
77
78
|
"discord_token": "Set Discord token. Required for downloading Discord stickers and emojis.",
|
78
|
-
"save_cred": "Save
|
79
|
+
"save_cred": "Save credentials."
|
79
80
|
}
|
80
81
|
}
|
@@ -29,6 +29,16 @@
|
|
29
29
|
"author": false
|
30
30
|
}
|
31
31
|
},
|
32
|
+
"telegram_telethon": {
|
33
|
+
"full_name": "Download from Telegram with Telethon",
|
34
|
+
"help": "Download telegram stickers from a URL as input with Telethon",
|
35
|
+
"example": "Example: https://telegram.me/addstickers/xxxxx\n OR https://telegram.me/addemoji/xxxxx",
|
36
|
+
"address_lbls": "URL address",
|
37
|
+
"metadata_provides": {
|
38
|
+
"title": true,
|
39
|
+
"author": false
|
40
|
+
}
|
41
|
+
},
|
32
42
|
"line": {
|
33
43
|
"full_name": "Download from Line",
|
34
44
|
"help": "Download line stickers from a URL / ID as input",
|
@@ -23,6 +23,22 @@
|
|
23
23
|
"author": false
|
24
24
|
}
|
25
25
|
},
|
26
|
+
"telegram_telethon": {
|
27
|
+
"full_name": "Upload to Telegram with Telethon",
|
28
|
+
"help": "Upload to Telegram with Telethon *Not recommended, but allow link not end with _by_xxxbot*",
|
29
|
+
"metadata_requirements": {
|
30
|
+
"title": true,
|
31
|
+
"author": false
|
32
|
+
}
|
33
|
+
},
|
34
|
+
"telegram_emoji_telethon": {
|
35
|
+
"full_name": "Upload to Telegram with Telethon (Custom emoji)",
|
36
|
+
"help": "Upload to Telegram with Telethon (Custom emoji) *Not recommended, but allow link not end with _by_xxxbot*",
|
37
|
+
"metadata_requirements": {
|
38
|
+
"title": true,
|
39
|
+
"author": false
|
40
|
+
}
|
41
|
+
},
|
26
42
|
"viber": {
|
27
43
|
"full_name": "Upload to Viber",
|
28
44
|
"help": "Upload to Viber",
|
@@ -3,7 +3,7 @@ import copy
|
|
3
3
|
import shutil
|
4
4
|
import zipfile
|
5
5
|
from pathlib import Path
|
6
|
-
from typing import Any, List
|
6
|
+
from typing import Any, List, Tuple
|
7
7
|
|
8
8
|
from sticker_convert.converter import StickerConvert
|
9
9
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
@@ -47,7 +47,7 @@ class CompressWastickers(UploadBase):
|
|
47
47
|
self.opt_comp_merged = copy.deepcopy(self.opt_comp)
|
48
48
|
self.opt_comp_merged.merge(self.base_spec)
|
49
49
|
|
50
|
-
def compress_wastickers(self) -> List[str]:
|
50
|
+
def compress_wastickers(self) -> Tuple[int, int, List[str]]:
|
51
51
|
urls: List[str] = []
|
52
52
|
title, author, _ = MetadataHandler.get_metadata(
|
53
53
|
self.opt_output.dir,
|
@@ -56,10 +56,10 @@ class CompressWastickers(UploadBase):
|
|
56
56
|
)
|
57
57
|
if not title:
|
58
58
|
self.cb.put("Title is required for compressing .wastickers")
|
59
|
-
return urls
|
59
|
+
return 0, 0, urls
|
60
60
|
if not author:
|
61
61
|
self.cb.put("Author is required for compressing .wastickers")
|
62
|
-
return urls
|
62
|
+
return 0, 0, urls
|
63
63
|
packs = MetadataHandler.split_sticker_packs(
|
64
64
|
self.opt_output.dir,
|
65
65
|
title=title,
|
@@ -67,7 +67,9 @@ class CompressWastickers(UploadBase):
|
|
67
67
|
separate_image_anim=not self.opt_comp.fake_vid,
|
68
68
|
)
|
69
69
|
|
70
|
+
stickers_total = 0
|
70
71
|
for pack_title, stickers in packs.items():
|
72
|
+
stickers_total += len(stickers)
|
71
73
|
# Originally the Sticker Maker application name the files with int(time.time())
|
72
74
|
with CacheStore.get_cache_store(path=self.opt_comp.cache_dir) as tempdir:
|
73
75
|
for num, src in enumerate(stickers):
|
@@ -106,7 +108,7 @@ class CompressWastickers(UploadBase):
|
|
106
108
|
self.cb.put((out_f))
|
107
109
|
urls.append(out_f)
|
108
110
|
|
109
|
-
return urls
|
111
|
+
return stickers_total, stickers_total, urls
|
110
112
|
|
111
113
|
def add_metadata(self, pack_dir: Path, title: str, author: str) -> None:
|
112
114
|
opt_comp_merged = copy.deepcopy(self.opt_comp)
|
@@ -150,6 +152,6 @@ class CompressWastickers(UploadBase):
|
|
150
152
|
opt_cred: CredOption,
|
151
153
|
cb: CallbackProtocol,
|
152
154
|
cb_return: CallbackReturn,
|
153
|
-
) -> List[str]:
|
155
|
+
) -> Tuple[int, int, List[str]]:
|
154
156
|
exporter = CompressWastickers(opt_output, opt_comp, opt_cred, cb, cb_return)
|
155
157
|
return exporter.compress_wastickers()
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
import copy
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Any, Dict, List
|
4
|
+
from typing import Any, Dict, List, Tuple
|
5
5
|
|
6
6
|
import anyio
|
7
7
|
from signalstickers_client.errors import SignalException
|
@@ -91,15 +91,15 @@ class UploadSignal(UploadBase):
|
|
91
91
|
|
92
92
|
pack._addsticker(sticker) # type: ignore
|
93
93
|
|
94
|
-
def upload_stickers_signal(self) -> List[str]:
|
94
|
+
def upload_stickers_signal(self) -> Tuple[int, int, List[str]]:
|
95
95
|
urls: List[str] = []
|
96
96
|
|
97
97
|
if not self.opt_cred.signal_uuid:
|
98
98
|
self.cb.put("uuid required for uploading to Signal")
|
99
|
-
return urls
|
99
|
+
return 0, 0, urls
|
100
100
|
if not self.opt_cred.signal_password:
|
101
101
|
self.cb.put("password required for uploading to Signal")
|
102
|
-
return urls
|
102
|
+
return 0, 0, urls
|
103
103
|
|
104
104
|
title, author, emoji_dict = MetadataHandler.get_metadata(
|
105
105
|
self.opt_output.dir,
|
@@ -138,7 +138,10 @@ class UploadSignal(UploadBase):
|
|
138
138
|
file_per_pack=200,
|
139
139
|
separate_image_anim=False,
|
140
140
|
)
|
141
|
+
stickers_total = 0
|
142
|
+
stickers_ok = 0
|
141
143
|
for pack_title, stickers in packs.items():
|
144
|
+
stickers_total += len(stickers)
|
142
145
|
pack = LocalStickerPack()
|
143
146
|
pack.title = pack_title
|
144
147
|
pack.author = author
|
@@ -155,11 +158,12 @@ class UploadSignal(UploadBase):
|
|
155
158
|
)
|
156
159
|
self.cb.put((result))
|
157
160
|
urls.append(result)
|
161
|
+
stickers_ok += len(stickers)
|
158
162
|
|
159
163
|
except SignalException as e:
|
160
164
|
self.cb.put(f"Failed to upload pack {pack_title} due to {repr(e)}")
|
161
165
|
|
162
|
-
return urls
|
166
|
+
return stickers_ok, stickers_total, urls
|
163
167
|
|
164
168
|
@staticmethod
|
165
169
|
def start(
|
@@ -168,6 +172,6 @@ class UploadSignal(UploadBase):
|
|
168
172
|
opt_cred: CredOption,
|
169
173
|
cb: CallbackProtocol,
|
170
174
|
cb_return: CallbackReturn,
|
171
|
-
) -> List[str]:
|
175
|
+
) -> Tuple[int, int, List[str]]:
|
172
176
|
exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb, cb_return)
|
173
177
|
return exporter.upload_stickers_signal()
|