sticker-convert 2.10.9__py3-none-any.whl → 2.11.1__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 (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