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.
Files changed (32) hide show
  1. sticker_convert/cli.py +39 -1
  2. sticker_convert/converter.py +10 -6
  3. sticker_convert/downloaders/download_base.py +37 -17
  4. sticker_convert/downloaders/download_discord.py +6 -6
  5. sticker_convert/downloaders/download_kakao.py +31 -13
  6. sticker_convert/downloaders/download_line.py +6 -6
  7. sticker_convert/downloaders/download_signal.py +10 -8
  8. sticker_convert/downloaders/download_telegram.py +22 -96
  9. sticker_convert/downloaders/download_viber.py +8 -6
  10. sticker_convert/gui.py +12 -0
  11. sticker_convert/gui_components/frames/cred_frame.py +38 -13
  12. sticker_convert/job.py +84 -63
  13. sticker_convert/job_option.py +6 -0
  14. sticker_convert/resources/compression.json +2 -2
  15. sticker_convert/resources/help.json +3 -2
  16. sticker_convert/resources/input.json +10 -0
  17. sticker_convert/resources/output.json +16 -0
  18. sticker_convert/uploaders/compress_wastickers.py +8 -6
  19. sticker_convert/uploaders/upload_signal.py +10 -6
  20. sticker_convert/uploaders/upload_telegram.py +178 -231
  21. sticker_convert/uploaders/upload_viber.py +12 -8
  22. sticker_convert/uploaders/xcode_imessage.py +8 -6
  23. sticker_convert/utils/auth/telegram_api.py +668 -0
  24. sticker_convert/utils/auth/telethon_setup.py +79 -0
  25. sticker_convert/utils/url_detect.py +1 -1
  26. sticker_convert/version.py +1 -1
  27. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/METADATA +54 -36
  28. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/RECORD +32 -30
  29. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/LICENSE +0 -0
  30. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/WHEEL +0 -0
  31. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/entry_points.txt +0 -0
  32. {sticker_convert-2.10.8.dist-info → sticker_convert-2.11.0.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,19 @@
1
1
  #!/usr/bin/env python3
2
2
  import copy
3
- import re
4
3
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional, Union, cast
4
+ from typing import Any, Dict, List, Optional, Tuple, Union, cast
6
5
 
7
6
  import anyio
8
- from telegram import InputSticker, Sticker
9
- from telegram.error import BadRequest, TelegramError
10
- from telegram.ext import AIORateLimiter, ApplicationBuilder
7
+ from telegram import Sticker
11
8
 
12
9
  from sticker_convert.converter import StickerConvert
13
10
  from sticker_convert.job_option import CompOption, CredOption, OutputOption
14
11
  from sticker_convert.uploaders.upload_base import UploadBase
12
+ from sticker_convert.utils.auth.telegram_api import BotAPI, TelegramAPI, TelegramSticker, TelethonAPI
15
13
  from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
16
14
  from sticker_convert.utils.emoji import extract_emojis
17
15
  from sticker_convert.utils.files.metadata_handler import MetadataHandler
16
+ from sticker_convert.utils.media.codec_info import CodecInfo
18
17
  from sticker_convert.utils.media.format_verify import FormatVerify
19
18
 
20
19
 
@@ -70,248 +69,189 @@ class UploadTelegram(UploadBase):
70
69
 
71
70
  async def upload_pack(
72
71
  self, pack_title: str, stickers: List[Path], emoji_dict: Dict[str, str]
73
- ) -> Optional[str]:
74
- token = self.opt_cred.telegram_token.strip()
75
- assert token
76
- timeout = 10 * len(stickers)
77
-
78
- application = ( # type: ignore
79
- ApplicationBuilder()
80
- .token(self.opt_cred.telegram_token.strip())
81
- .rate_limiter(AIORateLimiter(max_retries=3))
82
- .connect_timeout(timeout)
83
- .pool_timeout(timeout)
84
- .read_timeout(timeout)
85
- .write_timeout(timeout)
86
- .connection_pool_size(len(stickers))
87
- .build()
88
- )
89
-
90
- async with application:
91
- bot = application.bot
92
- pack_short_name = (
93
- pack_title.replace(" ", "_") + "_by_" + bot.name.replace("@", "")
94
- )
95
- pack_short_name = re.sub(
96
- "[^0-9a-zA-Z]+", "_", pack_short_name
97
- ) # name used in url, only alphanum and underscore only
98
-
99
- sticker_set: Any = None
100
- try:
101
- sticker_set = await bot.get_sticker_set(
102
- pack_short_name,
103
- read_timeout=30,
104
- write_timeout=30,
105
- connect_timeout=30,
106
- pool_timeout=30,
72
+ ) -> Tuple[Optional[str], int, int]:
73
+ tg_api: TelegramAPI
74
+ if self.opt_output.option.endswith("telethon"):
75
+ tg_api = TelethonAPI()
76
+ else:
77
+ tg_api = BotAPI()
78
+
79
+ is_emoji = False
80
+ if "emoji" in self.opt_output.option:
81
+ is_emoji = True
82
+
83
+ success = await tg_api.setup(self.opt_cred, True, self.cb, self.cb_return)
84
+ if success is False:
85
+ self.cb.put("Download failed: Invalid credentials")
86
+ return None, len(stickers), 0
87
+
88
+ pack_short_name = await tg_api.set_upload_pack_short_name(pack_title)
89
+ await tg_api.set_upload_pack_type(is_emoji)
90
+ pack_exist = await tg_api.check_pack_exist()
91
+ if pack_exist:
92
+ question = f"Warning: Pack {pack_short_name} already exists.\n"
93
+ question += "Delete all stickers in pack?\n"
94
+ question += "Note: After recreating set, please wait for about 3 minutes for the set to reappear."
95
+
96
+ self.cb.put(
97
+ (
98
+ "ask_bool",
99
+ (question,),
100
+ None,
107
101
  )
108
- except TelegramError:
109
- pass
102
+ )
103
+ if self.cb_return:
104
+ response = self.cb_return.get_response()
105
+ else:
106
+ response = False
107
+
108
+ if response is True:
109
+ self.cb.put(f"Deleting all stickers from pack {pack_short_name}")
110
+ await tg_api.pack_del()
111
+ pack_exist = False
112
+ else:
113
+ self.cb.put(f"Not deleting existing pack {pack_short_name}")
114
+
115
+ if self.opt_output.option == "telegram_emoji":
116
+ sticker_type = Sticker.CUSTOM_EMOJI
117
+ else:
118
+ sticker_type = Sticker.REGULAR
110
119
 
111
- if sticker_set is not None:
112
- question = f"Warning: Pack {pack_short_name} already exists.\n"
113
- question += "Delete all stickers in pack?\n"
114
- question += "Note: After recreating set, please wait for about 3 minutes for the set to reappear."
120
+ stickers_list: List[TelegramSticker] = []
121
+ sticker_format = None
122
+ for src in stickers:
123
+ self.cb.put(f"Verifying {src} for uploading to telegram")
115
124
 
125
+ emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
126
+ if emoji == "":
116
127
  self.cb.put(
117
- (
118
- "ask_bool",
119
- (question,),
120
- None,
121
- )
128
+ f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
122
129
  )
123
- if self.cb_return:
124
- response = self.cb_return.get_response()
125
- else:
126
- response = False
127
-
128
- if response is True:
129
- self.cb.put(f"Deleting all stickers from pack {pack_short_name}")
130
- try:
131
- await bot.delete_sticker_set(pack_short_name)
132
- except BadRequest as e:
133
- self.cb.put(
134
- f"Cannot delete sticker set {pack_short_name} due to {e}"
135
- )
136
- if str(e) == "Stickerpack_not_found":
137
- self.cb.put(
138
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
139
- )
140
- return None
141
- except TelegramError as e:
142
- self.cb.put(
143
- f"Cannot delete sticker set {pack_short_name} due to {e}"
144
- )
145
- return None
146
- sticker_set = None
147
- else:
148
- self.cb.put(f"Not deleting existing pack {pack_short_name}")
130
+ emoji_list = [self.opt_comp.default_emoji]
131
+
132
+ if len(emoji) > 20:
133
+ self.cb.put(
134
+ f"Warning: {len(emoji)} emoji for file {Path(src).name}, exceeding limit of 20, keep first 20 only..."
135
+ )
136
+ emoji_list = [*emoji][:20]
137
+
138
+ ext = Path(src).suffix
139
+ if ext == ".tgs":
140
+ spec_choice = self.tgs_spec
141
+ sticker_format = "animated"
142
+ elif ext == ".webm":
143
+ spec_choice = self.webm_spec
144
+ sticker_format = "video"
145
+ else:
146
+ ext = ".png"
147
+ spec_choice = self.png_spec
148
+ sticker_format = "static"
149
149
 
150
150
  if self.opt_output.option == "telegram_emoji":
151
- sticker_type = Sticker.CUSTOM_EMOJI
151
+ spec_choice.set_res(100)
152
+
153
+ file_info = CodecInfo(src)
154
+ check_file_result = (
155
+ FormatVerify.check_file_fps(
156
+ src, fps=spec_choice.get_fps(), file_info=file_info
157
+ )
158
+ and FormatVerify.check_file_duration(
159
+ src, duration=spec_choice.get_duration(), file_info=file_info
160
+ )
161
+ and FormatVerify.check_file_size(
162
+ src, size=spec_choice.get_size_max(), file_info=file_info
163
+ )
164
+ and FormatVerify.check_format(
165
+ src, fmt=spec_choice.get_format(), file_info=file_info
166
+ )
167
+ )
168
+ if sticker_format == "video":
169
+ # For video stickers (Only)
170
+ # Allow file with one of the dimension = 512 but another <512
171
+ # https://core.telegram.org/stickers#video-requirements
172
+ check_file_result = check_file_result and (
173
+ file_info.res[0] == 512 or file_info.res[1] == 512
174
+ )
175
+ check_file_result = check_file_result and (
176
+ file_info.res[0] <= 512 and file_info.res[1] <= 512
177
+ )
152
178
  else:
153
- sticker_type = Sticker.REGULAR
154
-
155
- init_input_stickers: List[InputSticker] = []
156
- sticker_format = None
157
- for src in stickers:
158
- self.cb.put(f"Verifying {src} for uploading to telegram")
159
-
160
- emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
161
- if emoji == "":
162
- self.cb.put(
163
- f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
164
- )
165
- emoji_list = [self.opt_comp.default_emoji]
166
-
167
- if len(emoji) > 20:
168
- self.cb.put(
169
- f"Warning: {len(emoji)} emoji for file {Path(src).name}, exceeding limit of 20, keep first 20 only..."
170
- )
171
- emoji_list = [*emoji][:20]
172
-
173
- ext = Path(src).suffix
174
- if ext == ".tgs":
175
- spec_choice = self.tgs_spec
176
- sticker_format = "animated"
177
- elif ext == ".webm":
178
- spec_choice = self.webm_spec
179
- sticker_format = "video"
180
- else:
181
- ext = ".png"
182
- spec_choice = self.png_spec
183
- sticker_format = "static"
184
-
185
- if self.opt_output.option == "telegram_emoji":
186
- spec_choice.set_res(100)
187
-
188
- if FormatVerify.check_file(src, spec=spec_choice):
189
- with open(src, "rb") as f:
190
- sticker_bytes = f.read()
191
- else:
192
- _, _, convert_result, _ = StickerConvert.convert(
193
- Path(src),
194
- Path(f"bytes{ext}"),
195
- self.opt_comp_merged,
196
- self.cb,
197
- self.cb_return,
198
- )
199
- sticker_bytes = cast(bytes, convert_result)
179
+ check_file_result = (
180
+ check_file_result
181
+ and file_info.res[0] == 512
182
+ and file_info.res[1] == 512
183
+ )
184
+ # It is important to check if webp and png are static only
185
+ check_file_result = check_file_result and FormatVerify.check_animated(
186
+ src, animated=spec_choice.animated, file_info=file_info
187
+ )
200
188
 
201
- input_sticker = InputSticker(
202
- sticker=sticker_bytes,
203
- emoji_list=emoji_list,
204
- format=sticker_format,
189
+ if check_file_result:
190
+ with open(src, "rb") as f:
191
+ sticker_bytes = f.read()
192
+ else:
193
+ _, _, convert_result, _ = StickerConvert.convert(
194
+ Path(src),
195
+ Path(f"bytes{ext}"),
196
+ self.opt_comp_merged,
197
+ self.cb,
198
+ self.cb_return,
205
199
  )
200
+ sticker_bytes = cast(bytes, convert_result)
206
201
 
207
- if sticker_set is None:
208
- init_input_stickers.append(input_sticker)
209
- else:
210
- try:
211
- # We could use tg.start_soon() here
212
- # But this would disrupt the order of stickers
213
- await bot.add_sticker_to_set(
214
- user_id=self.telegram_userid,
215
- name=pack_short_name,
216
- sticker=input_sticker,
217
- )
218
- self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
219
- except BadRequest as e:
220
- self.cb.put(
221
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
222
- )
223
- if str(e) == "Stickerpack_not_found":
224
- self.cb.put(
225
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
226
- )
227
- except TelegramError as e:
228
- self.cb.put(
229
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
230
- )
231
-
232
- if sticker_set is None and len(init_input_stickers) > 0:
233
- start_msg = f"Creating pack and bulk uploading {len(init_input_stickers)} stickers with same format of {pack_short_name}"
234
- finish_msg = f"Created pack and bulk uploaded {len(init_input_stickers)} stickers with same format of {pack_short_name}"
235
- error_msg = f"Cannot create pack and bulk upload {len(init_input_stickers)} stickers with same format of {pack_short_name} due to"
236
- self.cb.put(start_msg)
237
- try:
238
- await bot.create_new_sticker_set(
239
- user_id=self.telegram_userid,
240
- name=pack_short_name,
241
- title=pack_title,
242
- stickers=init_input_stickers,
243
- sticker_type=sticker_type,
244
- )
245
- sticker_set = True
246
- self.cb.put(finish_msg)
247
- except TelegramError as e:
248
- self.cb.put(f"{error_msg} {e}")
249
- return None
250
-
251
- cover_path = MetadataHandler.get_cover(self.opt_output.dir)
252
- if cover_path:
253
- thumbnail_bytes: Union[None, bytes, Path] = None
254
- cover_ext = Path(cover_path).suffix
255
-
256
- if cover_ext == ".tgs":
257
- thumbnail_format = "animated"
258
- cover_spec_choice = self.tgs_cover_spec
259
- elif cover_ext == ".webm":
260
- thumbnail_format = "video"
261
- cover_spec_choice = self.webm_cover_spec
262
- else:
263
- cover_ext = ".png"
264
- thumbnail_format = "static"
265
- cover_spec_choice = self.png_cover_spec
266
-
267
- if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
268
- with open(cover_path, "rb") as f:
269
- thumbnail_bytes = f.read()
270
- else:
271
- _, _, thumbnail_bytes, _ = StickerConvert.convert(
202
+ stickers_list.append((src, sticker_bytes, emoji_list, sticker_format))
203
+
204
+ if pack_exist is False:
205
+ stickers_total, stickers_ok = await tg_api.pack_new(
206
+ stickers_list, sticker_type
207
+ )
208
+ pack_exist = True
209
+ else:
210
+ stickers_total, stickers_ok = await tg_api.pack_add(
211
+ stickers_list, sticker_type
212
+ )
213
+
214
+ cover_path = MetadataHandler.get_cover(self.opt_output.dir)
215
+ if cover_path:
216
+ thumbnail_bytes: Union[None, bytes, Path] = None
217
+ cover_ext = Path(cover_path).suffix
218
+
219
+ if cover_ext == ".tgs":
220
+ thumbnail_format = "animated"
221
+ cover_spec_choice = self.tgs_cover_spec
222
+ elif cover_ext == ".webm":
223
+ thumbnail_format = "video"
224
+ cover_spec_choice = self.webm_cover_spec
225
+ else:
226
+ cover_ext = ".png"
227
+ thumbnail_format = "static"
228
+ cover_spec_choice = self.png_cover_spec
229
+
230
+ if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
231
+ with open(cover_path, "rb") as f:
232
+ thumbnail_bytes = f.read()
233
+ else:
234
+ _, _, thumbnail_bytes, _ = cast(
235
+ Tuple[Any, Any, bytes, Any],
236
+ StickerConvert.convert(
272
237
  cover_path,
273
238
  Path(f"bytes{cover_ext}"),
274
239
  self.opt_comp_cover_merged,
275
240
  self.cb,
276
241
  self.cb_return,
277
- )
278
-
279
- try:
280
- self.cb.put(
281
- f"Uploading cover (thumbnail) of pack {pack_short_name}"
282
- )
283
- await bot.set_sticker_set_thumbnail(
284
- name=pack_short_name,
285
- user_id=self.telegram_userid,
286
- thumbnail=thumbnail_bytes,
287
- format=thumbnail_format,
288
- )
289
- self.cb.put(f"Uploaded cover (thumbnail) of pack {pack_short_name}")
290
- except TelegramError as e:
291
- self.cb.put(
292
- f"Cannot upload cover (thumbnail) of pack {pack_short_name} due to {e}"
293
- )
294
-
295
- self.cb.put(f"Finish uploading {pack_short_name}")
296
-
297
- if self.opt_output.option == "telegram_emoji":
298
- result = f"https://t.me/addemoji/{pack_short_name}"
299
- else:
300
- result = f"https://t.me/addstickers/{pack_short_name}"
301
- return result
242
+ ),
243
+ )
302
244
 
303
- def upload_stickers_telegram(self) -> List[str]:
304
- urls: List[str] = []
245
+ await tg_api.pack_thumbnail(
246
+ (cover_path, thumbnail_bytes, [], thumbnail_format)
247
+ )
305
248
 
306
- if not (self.opt_cred.telegram_token and self.opt_cred.telegram_userid):
307
- self.cb.put("Token and userid required for uploading to telegram")
308
- return urls
249
+ self.cb.put(f"Finish uploading {pack_short_name}")
250
+ await tg_api.exit()
251
+ return await tg_api.get_pack_url(), stickers_total, stickers_ok
309
252
 
310
- if self.opt_cred.telegram_userid.isnumeric():
311
- self.telegram_userid = int(self.opt_cred.telegram_userid)
312
- else:
313
- self.cb.put("Invalid userid, should contain numbers only")
314
- return urls
253
+ def upload_stickers_telegram(self) -> Tuple[int, int, List[str]]:
254
+ urls: List[str] = []
315
255
 
316
256
  title, _, emoji_dict = MetadataHandler.get_metadata(
317
257
  self.opt_output.dir,
@@ -355,14 +295,21 @@ class UploadTelegram(UploadBase):
355
295
  separate_image_anim=not self.opt_comp.fake_vid,
356
296
  )
357
297
 
298
+ stickers_total = 0
299
+ stickers_ok = 0
358
300
  for pack_title, stickers in packs.items():
301
+ stickers_total += len(stickers)
359
302
  self.cb.put(f"Uploading pack {pack_title}")
360
- result = anyio.run(self.upload_pack, pack_title, stickers, emoji_dict)
303
+ result, stickers_total_pack, stickers_ok_pack = anyio.run(
304
+ self.upload_pack, pack_title, stickers, emoji_dict
305
+ )
361
306
  if result:
362
307
  self.cb.put((result))
363
308
  urls.append(result)
309
+ stickers_total += stickers_total_pack
310
+ stickers_ok += stickers_ok_pack
364
311
 
365
- return urls
312
+ return stickers_ok, stickers_total, urls
366
313
 
367
314
  @staticmethod
368
315
  def start(
@@ -371,7 +318,7 @@ class UploadTelegram(UploadBase):
371
318
  opt_cred: CredOption,
372
319
  cb: CallbackProtocol,
373
320
  cb_return: CallbackReturn,
374
- ) -> List[str]:
321
+ ) -> Tuple[int, int, List[str]]:
375
322
  exporter = UploadTelegram(
376
323
  opt_output,
377
324
  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()
@@ -6,7 +6,7 @@ import plistlib
6
6
  import shutil
7
7
  import zipfile
8
8
  from pathlib import Path
9
- from typing import Any, Dict, List
9
+ from typing import Any, Dict, List, Tuple
10
10
 
11
11
  from sticker_convert.converter import StickerConvert
12
12
  from sticker_convert.definitions import ROOT_DIR
@@ -34,7 +34,7 @@ class XcodeImessage(UploadBase):
34
34
  self.large_spec = copy.deepcopy(self.base_spec)
35
35
  self.large_spec.set_res(618)
36
36
 
37
- def create_imessage_xcode(self) -> List[str]:
37
+ def create_imessage_xcode(self) -> Tuple[int, int, List[str]]:
38
38
  urls: List[str] = []
39
39
  title, author, _ = MetadataHandler.get_metadata(
40
40
  self.opt_output.dir,
@@ -43,10 +43,10 @@ class XcodeImessage(UploadBase):
43
43
  )
44
44
  if not author:
45
45
  self.cb.put("author is required for creating Xcode iMessage sticker pack")
46
- return urls
46
+ return 0, 0, urls
47
47
  if not title:
48
48
  self.cb.put("title is required for creating Xcode iMessage sticker pack")
49
- return urls
49
+ return 0, 0, urls
50
50
 
51
51
  author = author.replace(" ", "_")
52
52
  title = title.replace(" ", "_")
@@ -61,6 +61,7 @@ class XcodeImessage(UploadBase):
61
61
  spec_choice = None
62
62
  opt_comp_merged = copy.deepcopy(self.opt_comp)
63
63
 
64
+ stickers_total = 0
64
65
  for pack_title, stickers in packs.items():
65
66
  pack_title = sanitize_filename(pack_title)
66
67
 
@@ -87,6 +88,7 @@ class XcodeImessage(UploadBase):
87
88
  StickerConvert.convert(
88
89
  fpath, fpath, opt_comp_merged, self.cb, self.cb_return
89
90
  )
91
+ stickers_total += 1
90
92
 
91
93
  self.add_metadata(author, pack_title)
92
94
  self.create_xcode_proj(author, pack_title)
@@ -95,7 +97,7 @@ class XcodeImessage(UploadBase):
95
97
  self.cb.put(result)
96
98
  urls.append(result)
97
99
 
98
- return urls
100
+ return stickers_total, stickers_total, urls
99
101
 
100
102
  def add_metadata(self, author: str, title: str) -> None:
101
103
  first_image_path = Path(
@@ -279,6 +281,6 @@ class XcodeImessage(UploadBase):
279
281
  opt_cred: CredOption,
280
282
  cb: CallbackProtocol,
281
283
  cb_return: CallbackReturn,
282
- ) -> List[str]:
284
+ ) -> Tuple[int, int, List[str]]:
283
285
  exporter = XcodeImessage(opt_output, opt_comp, opt_cred, cb, cb_return)
284
286
  return exporter.create_imessage_xcode()