sticker-convert 2.10.9__py3-none-any.whl → 2.11.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. sticker_convert/cli.py +46 -8
  2. sticker_convert/converter.py +13 -11
  3. sticker_convert/downloaders/download_base.py +5 -5
  4. sticker_convert/downloaders/download_signal.py +4 -2
  5. sticker_convert/downloaders/download_telegram.py +19 -103
  6. sticker_convert/gui.py +12 -0
  7. sticker_convert/gui_components/frames/cred_frame.py +38 -13
  8. sticker_convert/job.py +8 -8
  9. sticker_convert/job_option.py +6 -0
  10. sticker_convert/resources/compression.json +2 -2
  11. sticker_convert/resources/help.json +3 -2
  12. sticker_convert/resources/input.json +10 -0
  13. sticker_convert/resources/output.json +16 -0
  14. sticker_convert/uploaders/compress_wastickers.py +76 -56
  15. sticker_convert/uploaders/upload_telegram.py +170 -234
  16. sticker_convert/uploaders/upload_viber.py +18 -19
  17. sticker_convert/utils/auth/telegram_api.py +670 -0
  18. sticker_convert/utils/auth/telethon_setup.py +79 -0
  19. sticker_convert/utils/files/metadata_handler.py +3 -3
  20. sticker_convert/utils/url_detect.py +1 -1
  21. sticker_convert/version.py +1 -1
  22. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/METADATA +53 -35
  23. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/RECORD +27 -25
  24. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/WHEEL +1 -1
  25. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/LICENSE +0 -0
  26. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/entry_points.txt +0 -0
  27. {sticker_convert-2.10.9.dist-info → sticker_convert-2.11.1.dist-info}/top_level.txt +0 -0
@@ -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",
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python3
2
2
  import copy
3
- import shutil
4
3
  import zipfile
5
4
  from pathlib import Path
6
5
  from typing import Any, List, Tuple
@@ -9,7 +8,6 @@ from sticker_convert.converter import StickerConvert
9
8
  from sticker_convert.job_option import CompOption, CredOption, OutputOption
10
9
  from sticker_convert.uploaders.upload_base import UploadBase
11
10
  from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
12
- from sticker_convert.utils.files.cache_store import CacheStore
13
11
  from sticker_convert.utils.files.metadata_handler import MetadataHandler
14
12
  from sticker_convert.utils.files.sanitize_filename import sanitize_filename
15
13
  from sticker_convert.utils.media.codec_info import CodecInfo
@@ -70,8 +68,65 @@ class CompressWastickers(UploadBase):
70
68
  stickers_total = 0
71
69
  for pack_title, stickers in packs.items():
72
70
  stickers_total += len(stickers)
73
- # Originally the Sticker Maker application name the files with int(time.time())
74
- with CacheStore.get_cache_store(path=self.opt_comp.cache_dir) as tempdir:
71
+ out_f = Path(
72
+ self.opt_output.dir, sanitize_filename(pack_title + ".wastickers")
73
+ ).as_posix()
74
+
75
+ MetadataHandler.set_metadata(
76
+ self.opt_output.dir, author=author, title=title, newline=True
77
+ )
78
+ with zipfile.ZipFile(out_f, "w", zipfile.ZIP_DEFLATED) as zipf:
79
+ cover_opt_comp_merged = copy.deepcopy(self.opt_comp)
80
+ cover_opt_comp_merged.merge(self.spec_cover)
81
+
82
+ cover_path_old = MetadataHandler.get_cover(self.opt_output.dir)
83
+ cover_path_new = Path("bytes.png")
84
+ if cover_path_old is None:
85
+ # First image in the directory, extracting first frame
86
+ first_image = [
87
+ i
88
+ for i in sorted(self.opt_output.dir.iterdir())
89
+ if Path(self.opt_output.dir, i.name).is_file()
90
+ and i.suffix not in (".txt", ".m4a", ".wastickers")
91
+ ][0]
92
+ self.cb.put(f"Creating cover using {first_image.name}")
93
+ success, _, cover_data, _ = StickerConvert.convert(
94
+ Path(self.opt_output.dir, first_image),
95
+ cover_path_new,
96
+ cover_opt_comp_merged,
97
+ self.cb,
98
+ self.cb_return,
99
+ )
100
+ if not success:
101
+ self.cb.put(
102
+ f"Warning: Cannot compress cover {first_image.name}, unable to create .wastickers"
103
+ )
104
+ continue
105
+ else:
106
+ if not FormatVerify.check_file(
107
+ cover_path_old, spec=self.spec_cover
108
+ ):
109
+ success, _, cover_data, _ = StickerConvert.convert(
110
+ cover_path_old,
111
+ cover_path_new,
112
+ cover_opt_comp_merged,
113
+ self.cb,
114
+ self.cb_return,
115
+ )
116
+ if not success:
117
+ self.cb.put(
118
+ f"Warning: Cannot compress cover {cover_path_old.name}, unable to create .wastickers"
119
+ )
120
+ continue
121
+ else:
122
+ with open(cover_path_old, "rb") as f:
123
+ cover_data = f.read()
124
+
125
+ assert isinstance(cover_data, bytes)
126
+ zipf.writestr("tray.png", cover_data)
127
+ zipf.write(Path(self.opt_output.dir, "author.txt"), "author.txt")
128
+ zipf.write(Path(self.opt_output.dir, "title.txt"), "title.txt")
129
+
75
130
  for num, src in enumerate(stickers):
76
131
  self.cb.put(f"Verifying {src} for compressing into .wastickers")
77
132
 
@@ -79,72 +134,37 @@ class CompressWastickers(UploadBase):
79
134
  ext = ".webp"
80
135
  else:
81
136
  ext = ".png"
137
+ dst = f"bytes{ext}"
82
138
 
83
- dst = Path(tempdir, f"sticker_{num+1}{ext}")
84
-
85
- if FormatVerify.check_file(
86
- src, spec=self.webp_spec
87
- ) or FormatVerify.check_file(src, spec=self.png_spec):
88
- shutil.copy(src, dst)
89
- else:
90
- StickerConvert.convert(
139
+ if not (
140
+ FormatVerify.check_file(src, spec=self.webp_spec)
141
+ or FormatVerify.check_file(src, spec=self.png_spec)
142
+ ):
143
+ success, _, image_data, _ = StickerConvert.convert(
91
144
  Path(src),
92
145
  Path(dst),
93
146
  self.opt_comp_merged,
94
147
  self.cb,
95
148
  self.cb_return,
96
149
  )
150
+ assert isinstance(image_data, bytes)
151
+ if not success:
152
+ self.cb.put(
153
+ f"Warning: Cannot compress file {Path(src).name}, skip this file..."
154
+ )
155
+ continue
156
+ else:
157
+ with open(src, "rb") as f:
158
+ image_data = f.read()
97
159
 
98
- out_f = Path(
99
- self.opt_output.dir, sanitize_filename(pack_title + ".wastickers")
100
- ).as_posix()
101
-
102
- self.add_metadata(Path(tempdir), pack_title, author)
103
- with zipfile.ZipFile(out_f, "w", zipfile.ZIP_DEFLATED) as zipf:
104
- for file in Path(tempdir).iterdir():
105
- file_path = Path(tempdir, file.name)
106
- zipf.write(file_path, arcname=file_path.name)
160
+ # Originally the Sticker Maker application name the files with int(time.time())
161
+ zipf.writestr(f"sticker_{num + 1}{ext}", image_data)
107
162
 
108
163
  self.cb.put((out_f))
109
164
  urls.append(out_f)
110
165
 
111
166
  return stickers_total, stickers_total, urls
112
167
 
113
- def add_metadata(self, pack_dir: Path, title: str, author: str) -> None:
114
- opt_comp_merged = copy.deepcopy(self.opt_comp)
115
- opt_comp_merged.merge(self.spec_cover)
116
-
117
- cover_path_old = MetadataHandler.get_cover(self.opt_output.dir)
118
- cover_path_new = Path(pack_dir, "tray.png")
119
- if cover_path_old:
120
- if FormatVerify.check_file(cover_path_old, spec=self.spec_cover):
121
- shutil.copy(cover_path_old, cover_path_new)
122
- else:
123
- StickerConvert.convert(
124
- cover_path_old,
125
- cover_path_new,
126
- opt_comp_merged,
127
- self.cb,
128
- self.cb_return,
129
- )
130
- else:
131
- # First image in the directory, extracting first frame
132
- first_image = [
133
- i
134
- for i in sorted(self.opt_output.dir.iterdir())
135
- if Path(self.opt_output.dir, i.name).is_file()
136
- and i.suffix not in (".txt", ".m4a", ".wastickers")
137
- ][0]
138
- StickerConvert.convert(
139
- Path(self.opt_output.dir, first_image),
140
- cover_path_new,
141
- opt_comp_merged,
142
- self.cb,
143
- self.cb_return,
144
- )
145
-
146
- MetadataHandler.set_metadata(pack_dir, author=author, title=title, newline=True)
147
-
148
168
  @staticmethod
149
169
  def start(
150
170
  opt_output: OutputOption,
@@ -1,20 +1,19 @@
1
1
  #!/usr/bin/env python3
2
2
  import copy
3
- import re
4
3
  from pathlib import Path
5
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,256 +69,190 @@ 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
- extra_input_stickers: List[Tuple[InputSticker, Path]] = []
157
- sticker_format = None
158
- for src in stickers:
159
- self.cb.put(f"Verifying {src} for uploading to telegram")
160
-
161
- emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
162
- if emoji == "":
163
- self.cb.put(
164
- f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
165
- )
166
- emoji_list = [self.opt_comp.default_emoji]
167
-
168
- if len(emoji) > 20:
169
- self.cb.put(
170
- f"Warning: {len(emoji)} emoji for file {Path(src).name}, exceeding limit of 20, keep first 20 only..."
171
- )
172
- emoji_list = [*emoji][:20]
173
-
174
- ext = Path(src).suffix
175
- if ext == ".tgs":
176
- spec_choice = self.tgs_spec
177
- sticker_format = "animated"
178
- elif ext == ".webm":
179
- spec_choice = self.webm_spec
180
- sticker_format = "video"
181
- else:
182
- ext = ".png"
183
- spec_choice = self.png_spec
184
- sticker_format = "static"
185
-
186
- if self.opt_output.option == "telegram_emoji":
187
- spec_choice.set_res(100)
188
-
189
- if FormatVerify.check_file(src, spec=spec_choice):
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,
199
- )
200
- 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
+ )
201
188
 
202
- input_sticker = InputSticker(
203
- sticker=sticker_bytes,
204
- emoji_list=emoji_list,
205
- 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,
206
199
  )
200
+ sticker_bytes = cast(bytes, convert_result)
207
201
 
208
- if sticker_set is None and len(init_input_stickers) < 50:
209
- init_input_stickers.append(input_sticker)
210
- else:
211
- extra_input_stickers.append((input_sticker, src))
202
+ stickers_list.append((src, sticker_bytes, emoji_list, sticker_format))
212
203
 
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":
250
- self.cb.put(
251
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
252
- )
253
- except TelegramError as e:
254
- self.cb.put(
255
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
256
- )
257
-
258
- cover_path = MetadataHandler.get_cover(self.opt_output.dir)
259
- if cover_path:
260
- thumbnail_bytes: Union[None, bytes, Path] = None
261
- cover_ext = Path(cover_path).suffix
262
-
263
- if cover_ext == ".tgs":
264
- thumbnail_format = "animated"
265
- cover_spec_choice = self.tgs_cover_spec
266
- elif cover_ext == ".webm":
267
- thumbnail_format = "video"
268
- cover_spec_choice = self.webm_cover_spec
269
- else:
270
- cover_ext = ".png"
271
- thumbnail_format = "static"
272
- cover_spec_choice = self.png_cover_spec
273
-
274
- if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
275
- with open(cover_path, "rb") as f:
276
- thumbnail_bytes = f.read()
277
- else:
278
- _, _, thumbnail_bytes, _ = StickerConvert.convert(
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(
279
237
  cover_path,
280
238
  Path(f"bytes{cover_ext}"),
281
239
  self.opt_comp_cover_merged,
282
240
  self.cb,
283
241
  self.cb_return,
284
- )
285
-
286
- try:
287
- self.cb.put(
288
- f"Uploading cover (thumbnail) of pack {pack_short_name}"
289
- )
290
- await bot.set_sticker_set_thumbnail(
291
- name=pack_short_name,
292
- user_id=self.telegram_userid,
293
- thumbnail=thumbnail_bytes,
294
- format=thumbnail_format,
295
- )
296
- self.cb.put(f"Uploaded cover (thumbnail) of pack {pack_short_name}")
297
- except TelegramError as e:
298
- self.cb.put(
299
- f"Cannot upload cover (thumbnail) of pack {pack_short_name} due to {e}"
300
- )
301
-
302
- self.cb.put(f"Finish uploading {pack_short_name}")
242
+ ),
243
+ )
303
244
 
304
- if self.opt_output.option == "telegram_emoji":
305
- result = f"https://t.me/addemoji/{pack_short_name}"
306
- else:
307
- result = f"https://t.me/addstickers/{pack_short_name}"
308
- return result
245
+ await tg_api.pack_thumbnail(
246
+ (cover_path, thumbnail_bytes, [], thumbnail_format)
247
+ )
248
+
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
253
  def upload_stickers_telegram(self) -> Tuple[int, int, List[str]]:
311
254
  urls: List[str] = []
312
255
 
313
- if not (self.opt_cred.telegram_token and self.opt_cred.telegram_userid):
314
- self.cb.put("Token and userid required for uploading to telegram")
315
- return 0, 0, urls
316
-
317
- if self.opt_cred.telegram_userid.isnumeric():
318
- self.telegram_userid = int(self.opt_cred.telegram_userid)
319
- else:
320
- self.cb.put("Invalid userid, should contain numbers only")
321
- return 0, 0, urls
322
-
323
256
  title, _, emoji_dict = MetadataHandler.get_metadata(
324
257
  self.opt_output.dir,
325
258
  title=self.opt_output.title,
@@ -367,11 +300,14 @@ class UploadTelegram(UploadBase):
367
300
  for pack_title, stickers in packs.items():
368
301
  stickers_total += len(stickers)
369
302
  self.cb.put(f"Uploading pack {pack_title}")
370
- 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
+ )
371
306
  if result:
372
307
  self.cb.put((result))
373
308
  urls.append(result)
374
- stickers_ok += len(stickers)
309
+ stickers_total += stickers_total_pack
310
+ stickers_ok += stickers_ok_pack
375
311
 
376
312
  return stickers_ok, stickers_total, urls
377
313