sticker-convert 2.10.7__py3-none-any.whl → 2.10.9__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/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
@@ -372,7 +389,7 @@ class Job:
372
389
  response = self.executor.cb_return.get_response()
373
390
 
374
391
  if response is False:
375
- return False
392
+ return False, None
376
393
 
377
394
  for param, value in (
378
395
  ("fps_power", self.opt_comp.fps_power),
@@ -431,7 +448,7 @@ class Job:
431
448
  response = self.executor.cb_return.get_response()
432
449
 
433
450
  if response is False:
434
- return False
451
+ return False, None
435
452
 
436
453
  # Warn about in/output directories that might contain other files
437
454
  # Directory is safe if the name is stickers_input/stickers_output, or
@@ -468,13 +485,13 @@ class Job:
468
485
  response = self.executor.cb_return.get_response()
469
486
 
470
487
  if response is False:
471
- return False
488
+ return False, None
472
489
 
473
490
  break
474
491
 
475
- return True
492
+ return True, None
476
493
 
477
- def cleanup(self) -> bool:
494
+ def cleanup(self) -> Tuple[bool, None]:
478
495
  # If input is 'From local directory', then we should keep files in input/output directory as it maybe edited by user
479
496
  # If input is not 'From local directory', then we should move files in input/output directory as new files will be downloaded
480
497
  # Output directory should be cleanup unless no_compress is true (meaning files in output directory might be edited by user)
@@ -523,10 +540,10 @@ class Job:
523
540
  new_path = Path(archive_dir, old_path.name)
524
541
  old_path.rename(new_path)
525
542
 
526
- return True
543
+ return True, None
527
544
 
528
- def download(self) -> bool:
529
- downloaders: List[Callable[..., bool]] = []
545
+ def download(self) -> Tuple[bool, str]:
546
+ downloaders: List[Callable[..., Tuple[int, int]]] = []
530
547
 
531
548
  if self.opt_input.option == "signal":
532
549
  downloaders.append(DownloadSignal.start)
@@ -549,8 +566,8 @@ class Job:
549
566
  if len(downloaders) > 0:
550
567
  self.executor.cb("Downloading...")
551
568
  else:
552
- self.executor.cb("Nothing to download")
553
- return True
569
+ self.executor.cb("Skipped download (No files to download)")
570
+ return True, "Download: Skipped (No files to download)"
554
571
 
555
572
  self.executor.start_workers(processes=1)
556
573
 
@@ -563,15 +580,24 @@ class Job:
563
580
  self.executor.join_workers()
564
581
 
565
582
  # Return False if any of the job returns failure
583
+ stickers_ok = 0
584
+ stickers_total = 0
585
+ success = True
566
586
  for result in self.executor.results_list:
567
- if result is False:
568
- return False
587
+ stickers_ok += result[0]
588
+ stickers_total += result[1]
589
+ success = (
590
+ success if stickers_ok == stickers_total and stickers_ok > 0 else False
591
+ )
569
592
 
570
- return True
593
+ return (
594
+ success,
595
+ f"Download: {stickers_ok}/{stickers_total} stickers success",
596
+ )
571
597
 
572
- def compress(self) -> bool:
598
+ def compress(self) -> Tuple[bool, str]:
573
599
  if self.opt_comp.no_compress is True:
574
- self.executor.cb("no_compress is set to True, skip compression")
600
+ self.executor.cb("Skipped compression (no_compress is set to True)")
575
601
  in_dir_files = [
576
602
  i
577
603
  for i in sorted(self.opt_input.dir.iterdir())
@@ -598,7 +624,7 @@ class Job:
598
624
  src_f = Path(self.opt_input.dir, i.name)
599
625
  dst_f = Path(self.opt_output.dir, i.name)
600
626
  shutil.copy(src_f, dst_f)
601
- return True
627
+ return True, "Compress: Skipped (no_compress is set to True)"
602
628
  msg = "Compressing..."
603
629
 
604
630
  input_dir = Path(self.opt_input.dir)
@@ -620,8 +646,8 @@ class Job:
620
646
 
621
647
  in_fs_count = len(in_fs)
622
648
  if in_fs_count == 0:
623
- self.executor.cb("No files to compress")
624
- return True
649
+ self.executor.cb("Skipped compression (No files to compress)")
650
+ return True, "Compress: Skipped (No files to compress)"
625
651
 
626
652
  self.executor.cb(msg)
627
653
  self.executor.cb(
@@ -640,21 +666,35 @@ class Job:
640
666
 
641
667
  self.executor.join_workers()
642
668
 
643
- # Return False if any of the job returns failure
669
+ success = True
670
+ stickers_ok = 0
671
+ stickers_total = 0
672
+ fails: List[str] = []
644
673
  for result in self.executor.results_list:
674
+ stickers_total += 1
645
675
  if result[0] is False:
646
- return False
676
+ success = False
677
+ fails.append(str(result[1]))
678
+ else:
679
+ stickers_ok += 1
680
+
681
+ msg_append = ""
682
+ if success is False:
683
+ msg_append = " (Failed: " + ", ".join(fails) + ")"
647
684
 
648
- return True
685
+ return (
686
+ success,
687
+ f"Compress: {stickers_ok}/{stickers_total} stickers success" + msg_append,
688
+ )
649
689
 
650
- def export(self) -> bool:
690
+ def export(self) -> Tuple[bool, str]:
651
691
  if self.opt_output.option == "local":
652
- self.executor.cb("Saving to local directory only, nothing to export")
653
- return True
692
+ self.executor.cb("Skipped export (Saving to local directory only)")
693
+ return True, "Export: Skipped (Saving to local directory only)"
654
694
 
655
695
  self.executor.cb("Exporting...")
656
696
 
657
- exporters: List[Callable[..., List[str]]] = []
697
+ exporters: List[Callable[..., Tuple[int, int, List[str]]]] = []
658
698
 
659
699
  if self.opt_output.option == "whatsapp":
660
700
  exporters.append(CompressWastickers.start)
@@ -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
- self.out_urls.extend(result)
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"
@@ -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()
@@ -2,7 +2,7 @@
2
2
  import copy
3
3
  import re
4
4
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional, Union, cast
5
+ from typing import Any, Dict, List, Optional, Tuple, Union, cast
6
6
 
7
7
  import anyio
8
8
  from telegram import InputSticker, Sticker
@@ -153,9 +153,9 @@ class UploadTelegram(UploadBase):
153
153
  sticker_type = Sticker.REGULAR
154
154
 
155
155
  init_input_stickers: List[InputSticker] = []
156
+ extra_input_stickers: List[Tuple[InputSticker, Path]] = []
156
157
  sticker_format = None
157
- sticker_format_prev = None
158
- for count, src in enumerate(stickers):
158
+ for src in stickers:
159
159
  self.cb.put(f"Verifying {src} for uploading to telegram")
160
160
 
161
161
  emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
@@ -205,54 +205,55 @@ class UploadTelegram(UploadBase):
205
205
  format=sticker_format,
206
206
  )
207
207
 
208
- if sticker_set is None:
209
- if count < 50 and (
210
- sticker_format_prev is None
211
- or sticker_format_prev == sticker_format
212
- ):
213
- init_input_stickers.append(input_sticker)
214
- else:
215
- start_msg = f"Creating pack and bulk uploading {count} stickers with same format of {pack_short_name}"
216
- finish_msg = f"Created pack and bulk uploaded {count} stickers with same format of {pack_short_name}"
217
- error_msg = f"Cannot create pack and bulk upload {count} stickers with same format of {pack_short_name} due to"
218
- self.cb.put(start_msg)
219
- try:
220
- await bot.create_new_sticker_set(
221
- user_id=self.telegram_userid,
222
- name=pack_short_name,
223
- title=pack_title,
224
- stickers=init_input_stickers,
225
- sticker_type=sticker_type,
226
- )
227
- sticker_set = True
228
- self.cb.put(finish_msg)
229
- except TelegramError as e:
230
- self.cb.put(f"{error_msg} {e}")
231
- return None
208
+ if sticker_set is None and len(init_input_stickers) < 50:
209
+ init_input_stickers.append(input_sticker)
232
210
  else:
233
- try:
234
- # We could use tg.start_soon() here
235
- # But this would disrupt the order of stickers
236
- await bot.add_sticker_to_set(
237
- user_id=self.telegram_userid,
238
- name=pack_short_name,
239
- sticker=input_sticker,
240
- )
241
- self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
242
- except BadRequest as e:
243
- self.cb.put(
244
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
245
- )
246
- if str(e) == "Stickerpack_not_found":
247
- self.cb.put(
248
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
249
- )
250
- except TelegramError as e:
211
+ extra_input_stickers.append((input_sticker, src))
212
+
213
+ if len(init_input_stickers) > 0:
214
+ self.cb.put(
215
+ f"Creating pack and bulk uploading {len(init_input_stickers)} stickers of {pack_short_name}"
216
+ )
217
+ try:
218
+ await bot.create_new_sticker_set(
219
+ user_id=self.telegram_userid,
220
+ name=pack_short_name,
221
+ title=pack_title,
222
+ stickers=init_input_stickers,
223
+ sticker_type=sticker_type,
224
+ )
225
+ sticker_set = True
226
+ self.cb.put(
227
+ f"Created pack and bulk uploaded {len(init_input_stickers)} stickers of {pack_short_name}"
228
+ )
229
+ except TelegramError as e:
230
+ self.cb.put(
231
+ f"Cannot create pack and bulk upload {len(init_input_stickers)} stickers of {pack_short_name} due to {e}"
232
+ )
233
+ return None
234
+
235
+ for input_sticker, src in extra_input_stickers:
236
+ try:
237
+ # We could use tg.start_soon() here
238
+ # But this would disrupt the order of stickers
239
+ await bot.add_sticker_to_set(
240
+ user_id=self.telegram_userid,
241
+ name=pack_short_name,
242
+ sticker=input_sticker,
243
+ )
244
+ self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
245
+ except BadRequest as e:
246
+ self.cb.put(
247
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
248
+ )
249
+ if str(e) == "Stickerpack_not_found":
251
250
  self.cb.put(
252
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
251
+ "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
253
252
  )
254
-
255
- sticker_format_prev = sticker_format
253
+ except TelegramError as e:
254
+ self.cb.put(
255
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
256
+ )
256
257
 
257
258
  cover_path = MetadataHandler.get_cover(self.opt_output.dir)
258
259
  if cover_path:
@@ -306,18 +307,18 @@ class UploadTelegram(UploadBase):
306
307
  result = f"https://t.me/addstickers/{pack_short_name}"
307
308
  return result
308
309
 
309
- def upload_stickers_telegram(self) -> List[str]:
310
+ def upload_stickers_telegram(self) -> Tuple[int, int, List[str]]:
310
311
  urls: List[str] = []
311
312
 
312
313
  if not (self.opt_cred.telegram_token and self.opt_cred.telegram_userid):
313
314
  self.cb.put("Token and userid required for uploading to telegram")
314
- return urls
315
+ return 0, 0, urls
315
316
 
316
317
  if self.opt_cred.telegram_userid.isnumeric():
317
318
  self.telegram_userid = int(self.opt_cred.telegram_userid)
318
319
  else:
319
320
  self.cb.put("Invalid userid, should contain numbers only")
320
- return urls
321
+ return 0, 0, urls
321
322
 
322
323
  title, _, emoji_dict = MetadataHandler.get_metadata(
323
324
  self.opt_output.dir,
@@ -361,14 +362,18 @@ class UploadTelegram(UploadBase):
361
362
  separate_image_anim=not self.opt_comp.fake_vid,
362
363
  )
363
364
 
365
+ stickers_total = 0
366
+ stickers_ok = 0
364
367
  for pack_title, stickers in packs.items():
368
+ stickers_total += len(stickers)
365
369
  self.cb.put(f"Uploading pack {pack_title}")
366
370
  result = anyio.run(self.upload_pack, pack_title, stickers, emoji_dict)
367
371
  if result:
368
372
  self.cb.put((result))
369
373
  urls.append(result)
374
+ stickers_ok += len(stickers)
370
375
 
371
- return urls
376
+ return stickers_ok, stickers_total, urls
372
377
 
373
378
  @staticmethod
374
379
  def start(
@@ -377,7 +382,7 @@ class UploadTelegram(UploadBase):
377
382
  opt_cred: CredOption,
378
383
  cb: CallbackProtocol,
379
384
  cb_return: CallbackReturn,
380
- ) -> List[str]:
385
+ ) -> Tuple[int, int, List[str]]:
381
386
  exporter = UploadTelegram(
382
387
  opt_output,
383
388
  opt_comp,
@@ -4,7 +4,7 @@ import json
4
4
  import shutil
5
5
  import zipfile
6
6
  from pathlib import Path
7
- from typing import Any, Dict, List
7
+ from typing import Any, Dict, List, Tuple
8
8
 
9
9
  import requests
10
10
 
@@ -35,12 +35,12 @@ class UploadViber(UploadBase):
35
35
  self.opt_comp_merged = copy.deepcopy(self.opt_comp)
36
36
  self.opt_comp_merged.merge(self.png_spec)
37
37
 
38
- def upload_stickers_viber(self) -> List[str]:
38
+ def upload_stickers_viber(self) -> Tuple[int, int, List[str]]:
39
39
  urls: List[str] = []
40
40
 
41
41
  if not self.opt_cred.viber_auth:
42
42
  self.cb.put("Viber auth required for uploading to viber")
43
- return urls
43
+ return 0, 0, urls
44
44
 
45
45
  upload_data_base: Dict[str, str] = {}
46
46
  for i in self.opt_cred.viber_auth.split(";"):
@@ -49,13 +49,13 @@ class UploadViber(UploadBase):
49
49
 
50
50
  if upload_data_base.get("member_id") is None:
51
51
  self.cb.put("Invalid Viber auth: Missing member_id")
52
- return urls
52
+ return 0, 0, urls
53
53
  if upload_data_base.get("m_token") is None:
54
54
  self.cb.put("Invalid Viber auth: Missing m_token")
55
- return urls
55
+ return 0, 0, urls
56
56
  if upload_data_base.get("m_ts") is None:
57
57
  self.cb.put("Invalid Viber auth: Missing m_ts")
58
- return urls
58
+ return 0, 0, urls
59
59
 
60
60
  title, author, _ = MetadataHandler.get_metadata(
61
61
  self.opt_output.dir,
@@ -92,7 +92,10 @@ class UploadViber(UploadBase):
92
92
  self.cb_return,
93
93
  )
94
94
 
95
+ stickers_total = 0
96
+ stickers_ok = 0
95
97
  for pack_title, stickers in packs.items():
98
+ stickers_total += len(stickers)
96
99
  with CacheStore.get_cache_store(path=self.opt_comp.cache_dir) as tempdir:
97
100
  for num, src in enumerate(stickers):
98
101
  self.cb.put(f"Verifying {src} for uploading to Viber")
@@ -141,6 +144,7 @@ class UploadViber(UploadBase):
141
144
  url = f"https://stickers.viber.com/pages/custom-sticker-packs/{pack_id}"
142
145
  urls.append(url)
143
146
  self.cb.put(f"Uploaded {pack_title}")
147
+ stickers_ok += len(stickers)
144
148
  else:
145
149
  self.cb.put(
146
150
  f"Failed to upload {pack_title}: {r.status_code} {r.text}"
@@ -152,7 +156,7 @@ class UploadViber(UploadBase):
152
156
  else:
153
157
  self.cb.put(f"Failed to upload {pack_title}: {r.status_code} {r.text}")
154
158
 
155
- return urls
159
+ return stickers_ok, stickers_total, urls
156
160
 
157
161
  @staticmethod
158
162
  def start(
@@ -161,6 +165,6 @@ class UploadViber(UploadBase):
161
165
  opt_cred: CredOption,
162
166
  cb: CallbackProtocol,
163
167
  cb_return: CallbackReturn,
164
- ) -> List[str]:
168
+ ) -> Tuple[int, int, List[str]]:
165
169
  exporter = UploadViber(opt_output, opt_comp, opt_cred, cb, cb_return)
166
170
  return exporter.upload_stickers_viber()