sticker-convert 2.10.8__py3-none-any.whl → 2.11.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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()