sticker-convert 2.8.3__py3-none-any.whl → 2.8.5__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
sticker_convert/cli.py CHANGED
@@ -211,6 +211,7 @@ class CLI:
211
211
  "line": args.download_line,
212
212
  "telegram": args.download_telegram,
213
213
  "kakao": args.download_kakao,
214
+ "viber": args.download_viber,
214
215
  }
215
216
 
216
217
  download_option = "local"
@@ -704,7 +704,7 @@ class StickerConvert:
704
704
  self._frames_export_pyav()
705
705
  else:
706
706
  self._frames_export_pil()
707
-
707
+
708
708
  def _check_dup(self) -> bool:
709
709
  if len(self.frames_processed) == 1:
710
710
  return False
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
  from pathlib import Path
5
5
  from typing import Any, List, Optional, Tuple
6
6
 
7
+ import anyio
7
8
  import requests
8
9
 
9
10
  from sticker_convert.job_option import CredOption
@@ -27,16 +28,50 @@ class DownloadBase:
27
28
 
28
29
  def download_multiple_files(
29
30
  self, targets: List[Tuple[str, Path]], retries: int = 3, **kwargs: Any
31
+ ) -> None:
32
+ anyio.run(self.download_multiple_files_async, targets, retries, **kwargs)
33
+
34
+ async def download_multiple_files_async(
35
+ self, targets: List[Tuple[str, Path]], retries: int = 3, **kwargs: Any
30
36
  ) -> None:
31
37
  # targets format: [(url1, dest2), (url2, dest2), ...]
32
38
  self.cb.put(
33
39
  ("bar", None, {"set_progress_mode": "determinate", "steps": len(targets)})
34
40
  )
35
41
 
36
- for url, dest in targets:
37
- self.download_file(url, dest, retries, show_progress=False, **kwargs)
42
+ async with anyio.create_task_group() as tg:
43
+ for url, dest in targets:
44
+ tg.start_soon(self.download_file_async, url, dest, retries, **kwargs)
45
+
46
+ async def download_file_async(
47
+ self,
48
+ url: str,
49
+ dest: Path,
50
+ retries: int = 3,
51
+ **kwargs: Any,
52
+ ) -> None:
53
+ for retry in range(retries):
54
+ try:
55
+ response = requests.get(url, allow_redirects=True, **kwargs)
56
+
57
+ if not response.ok:
58
+ self.cb.put("update_bar")
59
+ raise requests.exceptions.RequestException(
60
+ f"Error {response.status_code}"
61
+ )
62
+
63
+ self.cb.put(f"Downloading {url}")
64
+ with open(dest, "wb+") as f:
65
+ f.write(response.content)
66
+ self.cb.put(f"Downloaded {url}")
67
+ break
68
+
69
+ except requests.exceptions.RequestException as e:
70
+ self.cb.put(
71
+ f"Cannot download {url} (tried {retry+1}/{retries} times): {e}"
72
+ )
38
73
 
39
- self.cb.put("update_bar")
74
+ self.cb.put("update_bar")
40
75
 
41
76
  def download_file(
42
77
  self,
@@ -51,10 +86,12 @@ class DownloadBase:
51
86
 
52
87
  for retry in range(retries):
53
88
  try:
54
- response = requests.get(url, stream=True, **kwargs)
89
+ response = requests.get(
90
+ url, stream=True, allow_redirects=True, **kwargs
91
+ )
55
92
  total_length = int(response.headers.get("content-length")) # type: ignore
56
93
 
57
- if response.status_code != 200:
94
+ if not response.ok:
58
95
  return b""
59
96
  self.cb.put(f"Downloading {url}")
60
97
 
@@ -75,16 +112,16 @@ class DownloadBase:
75
112
  self.cb.put("update_bar")
76
113
 
77
114
  break
78
- except requests.exceptions.RequestException:
79
- msg = f"Cannot download {url} (tried {retry+1}/{retries} times)"
80
- self.cb.put(msg)
115
+ except requests.exceptions.RequestException as e:
116
+ self.cb.put(
117
+ f"Cannot download {url} (tried {retry+1}/{retries} times): {e}"
118
+ )
81
119
 
82
120
  if not result:
83
121
  return b""
84
122
  if dest:
85
123
  with open(dest, "wb+") as f:
86
124
  f.write(result)
87
- msg = f"Downloaded {url}"
88
- self.cb.put(msg)
125
+ self.cb.put(f"Downloaded {url}")
89
126
  return b""
90
127
  return result
@@ -3,9 +3,9 @@ from pathlib import Path
3
3
  from typing import Dict, Optional
4
4
 
5
5
  import anyio
6
- from signalstickers_client import StickersClient # type: ignore
7
- from signalstickers_client.errors import SignalException # type: ignore
8
- from signalstickers_client.models import StickerPack # type: ignore
6
+ from signalstickers_client.errors import SignalException
7
+ from signalstickers_client.models import StickerPack
8
+ from signalstickers_client.stickersclient import StickersClient
9
9
 
10
10
  from sticker_convert.downloaders.download_base import DownloadBase
11
11
  from sticker_convert.job_option import CredOption
@@ -21,7 +21,7 @@ class DownloadSignal(DownloadBase):
21
21
  @staticmethod
22
22
  async def get_pack(pack_id: str, pack_key: str) -> StickerPack:
23
23
  async with StickersClient() as client:
24
- pack = await client.get_pack(pack_id, pack_key) # type: ignore
24
+ pack = await client.get_pack(pack_id, pack_key)
25
25
 
26
26
  return pack
27
27
 
@@ -32,14 +32,14 @@ class DownloadSignal(DownloadBase):
32
32
  None,
33
33
  {
34
34
  "set_progress_mode": "determinate",
35
- "steps": len(pack.stickers), # type: ignore
35
+ "steps": len(pack.stickers),
36
36
  },
37
37
  )
38
38
  )
39
39
 
40
40
  emoji_dict: Dict[str, str] = {}
41
- for sticker in pack.stickers: # type: ignore
42
- f_id = str(sticker.id).zfill(3) # type: ignore
41
+ for sticker in pack.stickers:
42
+ f_id = str(sticker.id).zfill(3)
43
43
  f_path = Path(self.out_dir, f_id)
44
44
  with open(f_path, "wb") as f:
45
45
  f.write(sticker.image_data) # type: ignore
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env python3
2
+ import json
3
+ import zipfile
4
+ from io import BytesIO
5
+ from pathlib import Path
6
+ from typing import Optional, Tuple, cast
7
+ from urllib.parse import urlparse
8
+
9
+ import requests
10
+ from bs4 import BeautifulSoup
11
+
12
+ from sticker_convert.downloaders.download_base import DownloadBase
13
+ from sticker_convert.job_option import CredOption
14
+ from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
15
+ from sticker_convert.utils.files.metadata_handler import MetadataHandler
16
+
17
+
18
+ class DownloadViber(DownloadBase):
19
+ # def __init__(self, *args: Any, **kwargs: Any) -> None:
20
+ # super().__init__(*args, **kwargs)
21
+
22
+ def get_pack_info(self, url: str) -> Optional[Tuple[str, str]]:
23
+ r = requests.get(url, allow_redirects=True)
24
+ soup = BeautifulSoup(r.text, "html.parser")
25
+
26
+ is_custom = urlparse(url).path.startswith("/pages/custom-sticker-packs/")
27
+ if is_custom:
28
+ tag_text_search = "window.CUSTOM_STICKER_PACK"
29
+ else:
30
+ tag_text_search = "window.PRODUCT"
31
+
32
+ script_tag = soup.find(
33
+ lambda tag: tag.name == "script" and tag.text.startswith(tag_text_search)
34
+ )
35
+ if script_tag is None:
36
+ return None
37
+
38
+ pack_json = script_tag.text.replace(f"{tag_text_search} = ", "", 1)[:-1]
39
+ pack_dict = json.loads(pack_json)
40
+
41
+ title = pack_dict["title"]
42
+ first_sticker_url = cast(str, pack_dict["stickerFirstItemUrl"])
43
+ zip_url = "/".join(first_sticker_url.split("/")[:-1]) + ".zip"
44
+
45
+ return title, zip_url
46
+
47
+ def decompress(self, zip_file: bytes) -> None:
48
+ with zipfile.ZipFile(BytesIO(zip_file)) as zf:
49
+ self.cb.put("Unzipping...")
50
+
51
+ zf_files = zf.namelist()
52
+ self.cb.put(
53
+ (
54
+ "bar",
55
+ None,
56
+ {"set_progress_mode": "determinate", "steps": len(zf_files)},
57
+ )
58
+ )
59
+
60
+ for sticker in zf_files:
61
+ num = sticker.split(".")[0][-2:].zfill(3)
62
+ data = zf.read(sticker)
63
+ ext = Path(sticker).suffix
64
+ self.cb.put(f"Read {sticker}")
65
+
66
+ out_path = Path(self.out_dir, num + ext)
67
+ with open(out_path, "wb") as f:
68
+ f.write(data)
69
+
70
+ self.cb.put("update_bar")
71
+
72
+ def download_stickers_viber(self) -> bool:
73
+ pack_info = self.get_pack_info(self.url)
74
+ if pack_info is None:
75
+ self.cb.put("Download failed: Cannot get pack info")
76
+ return False
77
+ title, zip_url = pack_info
78
+
79
+ zip_file = self.download_file(zip_url)
80
+ self.decompress(zip_file)
81
+
82
+ MetadataHandler.set_metadata(self.out_dir, title=title)
83
+
84
+ return True
85
+
86
+ @staticmethod
87
+ def start(
88
+ url: str,
89
+ out_dir: Path,
90
+ opt_cred: Optional[CredOption],
91
+ cb: CallbackProtocol,
92
+ cb_return: CallbackReturn,
93
+ ) -> bool:
94
+ downloader = DownloadViber(url, out_dir, opt_cred, cb, cb_return)
95
+ return downloader.download_stickers_viber()
sticker_convert/job.py CHANGED
@@ -16,6 +16,7 @@ from sticker_convert.downloaders.download_kakao import DownloadKakao
16
16
  from sticker_convert.downloaders.download_line import DownloadLine
17
17
  from sticker_convert.downloaders.download_signal import DownloadSignal
18
18
  from sticker_convert.downloaders.download_telegram import DownloadTelegram
19
+ from sticker_convert.downloaders.download_viber import DownloadViber
19
20
  from sticker_convert.job_option import CompOption, CredOption, InputOption, OutputOption
20
21
  from sticker_convert.uploaders.compress_wastickers import CompressWastickers
21
22
  from sticker_convert.uploaders.upload_signal import UploadSignal
@@ -527,6 +528,9 @@ class Job:
527
528
  if self.opt_input.option == "kakao":
528
529
  downloaders.append(DownloadKakao.start)
529
530
 
531
+ if self.opt_input.option == "viber":
532
+ downloaders.append(DownloadViber.start)
533
+
530
534
  if len(downloaders) > 0:
531
535
  self.executor.cb("Downloading...")
532
536
  else:
@@ -328,6 +328,53 @@
328
328
  "quantize_method": "imagequant",
329
329
  "default_emoji": "😀"
330
330
  },
331
+ "viber": {
332
+ "size_max": {
333
+ "img": 0,
334
+ "vid": 0
335
+ },
336
+ "format": {
337
+ "img": ".png",
338
+ "vid": ".png"
339
+ },
340
+ "fps": {
341
+ "min": 1,
342
+ "max": 1,
343
+ "power": 1
344
+ },
345
+ "res": {
346
+ "w": {
347
+ "min": 490,
348
+ "max": 490
349
+ },
350
+ "h": {
351
+ "min": 490,
352
+ "max": 490
353
+ },
354
+ "power": 1
355
+ },
356
+ "quality": {
357
+ "min": 95,
358
+ "max": 95,
359
+ "power": 1
360
+ },
361
+ "color": {
362
+ "min": 257,
363
+ "max": 257,
364
+ "power": 1
365
+ },
366
+ "duration": {
367
+ "min": 0,
368
+ "max": 0
369
+ },
370
+ "padding_percent": 0,
371
+ "bg_color": "",
372
+ "steps": 1,
373
+ "fake_vid": false,
374
+ "scale_filter": "bicubic",
375
+ "quantize_method": "imagequant",
376
+ "default_emoji": "😀"
377
+ },
331
378
  "imessage_small": {
332
379
  "size_max": {
333
380
  "img": 500000,
@@ -49,6 +49,16 @@
49
49
  "author": true
50
50
  }
51
51
  },
52
+ "viber": {
53
+ "full_name": "Download from Viber",
54
+ "help": "Download viber stickers from a URL as input",
55
+ "example": "Example: https://stickers.viber.com/pages/example OR https://stickers.viber.com/pages/custom-sticker-packs/example",
56
+ "address_lbls": "URL address / ID",
57
+ "metadata_provides": {
58
+ "title": true,
59
+ "author": false
60
+ }
61
+ },
52
62
  "local": {
53
63
  "full_name": "From local directory",
54
64
  "help": "Load files from local directory on computer",
@@ -4,9 +4,9 @@ from pathlib import Path
4
4
  from typing import Any, Dict, List
5
5
 
6
6
  import anyio
7
- from signalstickers_client import StickersClient # type: ignore
8
- from signalstickers_client.errors import SignalException # type: ignore
9
- from signalstickers_client.models import LocalStickerPack, Sticker # type: ignore
7
+ from signalstickers_client.errors import SignalException
8
+ from signalstickers_client.models import LocalStickerPack, Sticker
9
+ from signalstickers_client.stickersclient import StickersClient
10
10
 
11
11
  from sticker_convert.converter import StickerConvert
12
12
  from sticker_convert.job_option import CompOption, CredOption, OutputOption
@@ -39,7 +39,7 @@ class UploadSignal(UploadBase):
39
39
  @staticmethod
40
40
  async def upload_pack(pack: LocalStickerPack, uuid: str, password: str) -> str:
41
41
  async with StickersClient(uuid, password) as client:
42
- pack_id, pack_key = await client.upload_pack(pack) # type: ignore
42
+ pack_id, pack_key = await client.upload_pack(pack)
43
43
 
44
44
  result = (
45
45
  f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
@@ -53,7 +53,7 @@ class UploadSignal(UploadBase):
53
53
  self.cb.put(f"Verifying {src} for uploading to signal")
54
54
 
55
55
  sticker = Sticker()
56
- sticker.id = pack.nb_stickers # type: ignore
56
+ sticker.id = pack.nb_stickers
57
57
 
58
58
  emoji = emoji_dict.get(Path(src).stem, None)
59
59
  if not emoji:
@@ -61,7 +61,7 @@ class UploadSignal(UploadBase):
61
61
  f"Warning: Cannot find emoji for file {Path(src).name}, skip uploading this file..."
62
62
  )
63
63
  continue
64
- sticker.emoji = emoji[:1] # type: ignore
64
+ sticker.emoji = emoji[:1]
65
65
 
66
66
  if Path(src).suffix == ".webp":
67
67
  spec_choice = self.webp_spec
@@ -84,10 +84,10 @@ class UploadSignal(UploadBase):
84
84
 
85
85
  assert isinstance(image_data, bytes)
86
86
 
87
- sticker.image_data = image_data # type: ignore
87
+ sticker.image_data = image_data
88
88
  else:
89
89
  with open(src, "rb") as f:
90
- sticker.image_data = f.read() # type: ignore
90
+ sticker.image_data = f.read()
91
91
 
92
92
  pack._addsticker(sticker) # type: ignore
93
93
 
@@ -140,8 +140,8 @@ class UploadSignal(UploadBase):
140
140
  )
141
141
  for pack_title, stickers in packs.items():
142
142
  pack = LocalStickerPack()
143
- pack.title = pack_title # type: ignore
144
- pack.author = author # type: ignore
143
+ pack.title = pack_title
144
+ pack.author = author
145
145
 
146
146
  self.add_stickers_to_pack(pack, stickers, emoji_dict)
147
147
  self.cb.put(f"Uploading pack {pack_title}")
@@ -2,7 +2,7 @@
2
2
  import copy
3
3
  import re
4
4
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional, Tuple, Union, cast
5
+ from typing import Any, Dict, List, Optional, Union, cast
6
6
 
7
7
  import anyio
8
8
  from telegram import InputSticker, Sticker
@@ -96,7 +96,7 @@ class UploadTelegram(UploadBase):
96
96
  "[^0-9a-zA-Z]+", "_", pack_short_name
97
97
  ) # name used in url, only alphanum and underscore only
98
98
 
99
- sticker_set = None
99
+ sticker_set: Any = None
100
100
  try:
101
101
  sticker_set = await bot.get_sticker_set(
102
102
  pack_short_name,
@@ -152,11 +152,10 @@ class UploadTelegram(UploadBase):
152
152
  else:
153
153
  sticker_type = Sticker.REGULAR
154
154
 
155
- input_stickers: List[Tuple[Path, InputSticker]] = []
155
+ init_input_stickers: List[InputSticker] = []
156
156
  sticker_format = None
157
- cover_spec_choice = None
158
- ext = None
159
- for src in stickers:
157
+ sticker_format_prev = None
158
+ for count, src in enumerate(stickers):
160
159
  self.cb.put(f"Verifying {src} for uploading to telegram")
161
160
 
162
161
  emoji = emoji_dict.get(Path(src).stem, None)
@@ -175,16 +174,13 @@ class UploadTelegram(UploadBase):
175
174
  ext = Path(src).suffix
176
175
  if ext == ".tgs":
177
176
  spec_choice = self.tgs_spec
178
- cover_spec_choice = self.tgs_cover_spec
179
177
  sticker_format = "animated"
180
178
  elif ext == ".webm":
181
179
  spec_choice = self.webm_spec
182
- cover_spec_choice = self.webm_cover_spec
183
180
  sticker_format = "video"
184
181
  else:
185
182
  ext = ".png"
186
183
  spec_choice = self.png_spec
187
- cover_spec_choice = self.png_cover_spec
188
184
  sticker_format = "static"
189
185
 
190
186
  if self.opt_output.option == "telegram_emoji":
@@ -203,81 +199,98 @@ class UploadTelegram(UploadBase):
203
199
  )
204
200
  sticker_bytes = cast(bytes, convert_result)
205
201
 
206
- input_stickers.append(
207
- (src, InputSticker(sticker=sticker_bytes, emoji_list=emoji_list))
202
+ input_sticker = InputSticker(
203
+ sticker=sticker_bytes,
204
+ emoji_list=emoji_list,
205
+ format=sticker_format,
208
206
  )
209
207
 
208
+ if sticker_set is None:
209
+ if count < 50 and (
210
+ sticker_format_prev is None
211
+ or sticker_format_prev == sticker_format
212
+ ):
213
+ init_input_stickers.append(input_sticker)
214
+ else:
215
+ start_msg = f"Creating pack and bulk uploading {count} stickers with same format of {pack_short_name}"
216
+ finish_msg = f"Created pack and bulk uploaded {count} stickers with same format of {pack_short_name}"
217
+ error_msg = f"Cannot create pack and bulk upload {count} stickers with same format of {pack_short_name} due to"
218
+ self.cb.put(start_msg)
219
+ try:
220
+ await bot.create_new_sticker_set(
221
+ user_id=self.telegram_userid,
222
+ name=pack_short_name,
223
+ title=pack_title,
224
+ stickers=init_input_stickers,
225
+ sticker_type=sticker_type,
226
+ )
227
+ sticker_set = True
228
+ self.cb.put(finish_msg)
229
+ except TelegramError as e:
230
+ self.cb.put(f"{error_msg} {e}")
231
+ return None
232
+ else:
233
+ try:
234
+ # We could use tg.start_soon() here
235
+ # But this would disrupt the order of stickers
236
+ await bot.add_sticker_to_set(
237
+ user_id=self.telegram_userid,
238
+ name=pack_short_name,
239
+ sticker=input_sticker,
240
+ )
241
+ self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
242
+ except BadRequest as e:
243
+ self.cb.put(
244
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
245
+ )
246
+ if str(e) == "Stickerpack_not_found":
247
+ self.cb.put(
248
+ "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
249
+ )
250
+ except TelegramError as e:
251
+ self.cb.put(
252
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
253
+ )
254
+
255
+ sticker_format_prev = sticker_format
256
+
210
257
  cover_path = MetadataHandler.get_cover(self.opt_output.dir)
211
- thumbnail_bytes: Union[None, bytes, Path] = None
212
- if cover_path and cover_spec_choice and ext:
258
+ if cover_path:
259
+ thumbnail_bytes: Union[None, bytes, Path] = None
260
+ cover_ext = Path(cover_path).suffix
261
+
262
+ if cover_ext == ".tgs":
263
+ thumbnail_format = "animated"
264
+ cover_spec_choice = self.tgs_cover_spec
265
+ elif cover_ext == ".webm":
266
+ thumbnail_format = "video"
267
+ cover_spec_choice = self.webm_cover_spec
268
+ else:
269
+ cover_ext = ".png"
270
+ thumbnail_format = "static"
271
+ cover_spec_choice = self.png_cover_spec
272
+
213
273
  if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
214
274
  with open(cover_path, "rb") as f:
215
275
  thumbnail_bytes = f.read()
216
276
  else:
217
277
  _, _, thumbnail_bytes, _ = StickerConvert.convert(
218
278
  cover_path,
219
- Path(f"bytes{ext}"),
279
+ Path(f"bytes{cover_ext}"),
220
280
  self.opt_comp_cover_merged,
221
281
  self.cb,
222
282
  self.cb_return,
223
283
  )
224
284
 
225
- if sticker_set is None and sticker_format is not None:
226
- if len(input_stickers) > 50:
227
- amount_str = "first 50"
228
- else:
229
- amount_str = "all"
230
- start_msg = f"Creating pack and bulk uploading {amount_str} stickers of {pack_short_name}"
231
- finish_msg = f"Created pack and bulk uploaded {amount_str} stickers of {pack_short_name}"
232
- error_msg = f"Cannot create pack and bulk upload {amount_str} stickers of {pack_short_name} due to"
233
- self.cb.put(start_msg)
234
- try:
235
- await bot.create_new_sticker_set(
236
- user_id=self.opt_cred.telegram_userid,
237
- name=pack_short_name,
238
- title=pack_title,
239
- stickers=[a for _, a in input_stickers[:50]],
240
- sticker_format=sticker_format,
241
- sticker_type=sticker_type,
242
- )
243
- self.cb.put(finish_msg)
244
- input_stickers = input_stickers[50:]
245
- except TelegramError as e:
246
- self.cb.put(f"{error_msg} {e}")
247
- return None
248
-
249
- for src, sticker in input_stickers:
250
- try:
251
- # We could use tg.start_soon() here
252
- # But this would disrupt the order of stickers
253
- await bot.add_sticker_to_set(
254
- user_id=self.opt_cred.telegram_userid,
255
- name=pack_short_name,
256
- sticker=sticker,
257
- )
258
- self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
259
- except BadRequest as e:
260
- self.cb.put(
261
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
262
- )
263
- if str(e) == "Stickerpack_not_found":
264
- self.cb.put(
265
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
266
- )
267
- except TelegramError as e:
268
- self.cb.put(
269
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
270
- )
271
-
272
- if thumbnail_bytes is not None:
273
285
  try:
274
286
  self.cb.put(
275
287
  f"Uploading cover (thumbnail) of pack {pack_short_name}"
276
288
  )
277
289
  await bot.set_sticker_set_thumbnail(
278
290
  name=pack_short_name,
279
- user_id=self.opt_cred.telegram_userid,
291
+ user_id=self.telegram_userid,
280
292
  thumbnail=thumbnail_bytes,
293
+ format=thumbnail_format,
281
294
  )
282
295
  self.cb.put(f"Uploaded cover (thumbnail) of pack {pack_short_name}")
283
296
  except TelegramError as e:
@@ -300,6 +313,12 @@ class UploadTelegram(UploadBase):
300
313
  self.cb.put("Token and userid required for uploading to telegram")
301
314
  return urls
302
315
 
316
+ if self.opt_cred.telegram_userid.isnumeric():
317
+ self.telegram_userid = int(self.opt_cred.telegram_userid)
318
+ else:
319
+ self.cb.put("Invalid userid, should contain numbers only")
320
+ return urls
321
+
303
322
  title, _, emoji_dict = MetadataHandler.get_metadata(
304
323
  self.opt_output.dir,
305
324
  title=self.opt_output.title,
@@ -327,11 +346,18 @@ class UploadTelegram(UploadBase):
327
346
  )
328
347
 
329
348
  assert title is not None
349
+ assert emoji_dict is not None
350
+
351
+ if self.opt_output.option == "telegram_emoji":
352
+ file_per_pack = 200
353
+ else:
354
+ file_per_pack = 120
355
+
330
356
  packs = MetadataHandler.split_sticker_packs(
331
357
  self.opt_output.dir,
332
358
  title=title,
333
- file_per_anim_pack=50,
334
- file_per_image_pack=120,
359
+ file_per_anim_pack=file_per_pack,
360
+ file_per_image_pack=file_per_pack,
335
361
  separate_image_anim=not self.opt_comp.fake_vid,
336
362
  )
337
363
 
@@ -5,41 +5,35 @@ from http.cookiejar import CookieJar
5
5
  from typing import Any, Callable, Dict, List, Optional, Union
6
6
 
7
7
  import requests
8
- import rookiepy # type: ignore
8
+ import rookiepy
9
9
 
10
10
 
11
11
  class GetLineAuth:
12
12
  def get_cred(self) -> Optional[str]:
13
13
  browsers: List[Callable[..., Any]] = [
14
- rookiepy.load, # type: ignore # Supposed to load from any browser, but may fail
15
- rookiepy.firefox, # type: ignore
16
- rookiepy.libre_wolf, # type: ignore
17
- rookiepy.chrome, # type: ignore
18
- rookiepy.chromium, # type: ignore
19
- rookiepy.brave, # type: ignore
20
- rookiepy.edge, # type: ignore
21
- rookiepy.opera, # type: ignore
22
- rookiepy.vivaldi, # type: ignore
14
+ rookiepy.load, # Supposed to load from any browser, but may fail
15
+ rookiepy.firefox,
16
+ rookiepy.librewolf,
17
+ rookiepy.chrome,
18
+ rookiepy.chromium,
19
+ rookiepy.brave,
20
+ rookiepy.edge,
21
+ rookiepy.opera,
22
+ rookiepy.vivaldi,
23
23
  ]
24
24
 
25
- # https://github.com/thewh1teagle/rookie/pull/24
26
- if "libre_wolf" in rookiepy.__all__:
27
- browsers.extend(rookiepy.libre_wolf) # type: ignore
28
- else:
29
- browsers.extend(rookiepy.librewolf) # type: ignore
30
-
31
25
  if platform.system() == "Windows":
32
26
  browsers.extend(
33
27
  [
34
- rookiepy.opera_gx, # type: ignore
35
- rookiepy.internet_explorer, # type: ignore
28
+ rookiepy.opera_gx,
29
+ rookiepy.internet_explorer,
36
30
  ]
37
31
  )
38
32
  elif platform.system() == "Darwin":
39
33
  browsers.extend(
40
34
  [
41
- rookiepy.opera_gx, # type: ignore
42
- rookiepy.safari, # type: ignore
35
+ rookiepy.opera_gx,
36
+ rookiepy.safari,
43
37
  ]
44
38
  )
45
39
 
@@ -48,7 +42,7 @@ class GetLineAuth:
48
42
  for browser in browsers:
49
43
  try:
50
44
  cookies_dict = browser(["store.line.me"])
51
- cookies_jar = rookiepy.to_cookiejar(cookies_dict) # type: ignore
45
+ cookies_jar = rookiepy.to_cookiejar(cookies_dict)
52
46
 
53
47
  if GetLineAuth.validate_cookies(cookies_jar):
54
48
  break
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.3"
3
+ __version__ = "2.8.5"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.3
3
+ Version: 2.8.5
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -349,7 +349,7 @@ Project-URL: Source, https://github.com/laggykiller/sticker-convert
349
349
  Project-URL: Documentation, https://github.com/laggykiller/sticker-convert
350
350
  Project-URL: Tracker, https://github.com/laggykiller/sticker-convert/issues
351
351
  Project-URL: Repository, https://github.com/laggykiller/sticker-convert
352
- Keywords: telegram,line,tgs,whatsapp,kakao,signal,imessage,wastickers
352
+ Keywords: telegram,line,tgs,whatsapp,kakao,signal,imessage,wastickers,viber
353
353
  Classifier: Development Status :: 5 - Production/Stable
354
354
  Classifier: Intended Audience :: End Users/Desktop
355
355
  Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
@@ -365,21 +365,21 @@ Requires-Python: >=3.8
365
365
  Description-Content-Type: text/markdown
366
366
  License-File: LICENSE
367
367
  Requires-Dist: aiolimiter ~=1.1.0
368
- Requires-Dist: anyio ~=3.7.1
368
+ Requires-Dist: anyio ~=4.3.0
369
369
  Requires-Dist: apngasm-python ~=1.2.3
370
370
  Requires-Dist: av ~=12.0.0
371
371
  Requires-Dist: beautifulsoup4 ~=4.12.3
372
- Requires-Dist: rookiepy ~=0.3.6
372
+ Requires-Dist: rookiepy ~=0.4.0
373
373
  Requires-Dist: imagequant ~=1.1.1
374
374
  Requires-Dist: memory-tempfile ~=2.2.3
375
375
  Requires-Dist: mergedeep ~=1.3.4
376
376
  Requires-Dist: numpy >=1.22.4
377
- Requires-Dist: Pillow ==10.1.0
377
+ Requires-Dist: Pillow ~=10.3.0
378
378
  Requires-Dist: pyoxipng ~=9.0.0
379
- Requires-Dist: python-telegram-bot ~=20.5
379
+ Requires-Dist: python-telegram-bot ~=21.1
380
380
  Requires-Dist: requests ~=2.31.0
381
381
  Requires-Dist: rlottie-python ~=1.3.4
382
- Requires-Dist: signalstickers-client ~=3.3.0
382
+ Requires-Dist: signalstickers-client-fork-laggykiller ~=3.3.0.post1
383
383
  Requires-Dist: sqlcipher3-wheels ~=0.5.2.post1
384
384
  Requires-Dist: tqdm ~=4.66.2
385
385
  Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
@@ -391,7 +391,7 @@ Requires-Dist: webp ~=0.3.0
391
391
 
392
392
  - A python script for creating, downloading, converting+compressing and uploading stickers from multiple instant messaging applications.
393
393
  - With GUI and CLI that runs on Windows, MacOS and Linux
394
- - Currently supports Signal, Telegram, WhatsApp (Create .wastickers), Line (Download only), Kakao (Download only), iMessage (Create Xcode sticker pack project)
394
+ - Currently supports Signal, Telegram, WhatsApp (Create .wastickers), Line (Download only), Kakao (Download only), Viber (Download only), iMessage (Create Xcode sticker pack project)
395
395
  - Supports static and animated stickers, with transparency support
396
396
 
397
397
  ## Downloads
@@ -429,6 +429,7 @@ Requires-Dist: webp ~=0.3.0
429
429
  | [WhatsApp](docs/guide_whatsapp.md) | ⭕ (By Android or WhatsApp Web) | ⭕ (Create `.wastickers`, import by Sticker Maker) |
430
430
  | [Line](docs/guide_line.md) | ✅ | 🚫 (Need to submit for manual approval) |
431
431
  | [Kakao](docs/guide_kakao.md) | ✅ (Need 'share link' for animated) | 🚫 (Need to submit for manual approval) |
432
+ | [Viber](docs/guide_viber.md) | ✅ | 🚫 (Manually upload through Viber app) |
432
433
  | [iMessage](docs/guide_imessage.md) | 🚫 | ⭕ (Create Xcode stickerpack project for sideload) |
433
434
 
434
435
  ✅ = Supported ⭕ = Partially supported 🚫 = Not supported
@@ -455,6 +456,9 @@ Requires-Dist: webp ~=0.3.0
455
456
  - Kakao
456
457
  - Download: Supported (e.g. `https://e.kakao.com/t/xxxxx` OR `kakaotalk://store/emoticon/4404400` OR `https://emoticon.kakao.com/items/xxxxx` OR `4404400`). It is rather complicated, learn more from [docs/guide_kakao.md](docs/guide_kakao.md)
457
458
  - Upload: Not supported. You need to manually submit sticker pack for approval before you can use in app.
459
+ - Viber
460
+ - Download: Supported (e.g. `https://stickers.viber.com/pages/example` OR `https://stickers.viber.com/pages/custom-sticker-packs/example`)
461
+ - Upload: The program can convert images to png with 490x490 for uploading to viber manually. It should be noted that Viber is able to resize images for you, so it may not be necessary to use sticker-convert for creating Viber sticker pack.
458
462
  - iMessage
459
463
  - Download: Not supported.
460
464
  - Upload: The program can create Xcode project for iMessage sticker pack, which could then be compiled and sideloaded using Xcode.
@@ -1,18 +1,19 @@
1
1
  sticker_convert/__init__.py,sha256=iQnv6UOOA69c3soAn7ZOnAIubTIQSUxtq1Uhh8xRWvU,102
2
2
  sticker_convert/__main__.py,sha256=6RJauR-SCSSTT3TU7FFB6B6PVwsCxO2xZXtmZ3jc2Is,463
3
- sticker_convert/cli.py,sha256=KMl8G25rTpSko46SC-WdI5YDBykyluQL13PYpZW_O8M,18579
4
- sticker_convert/converter.py,sha256=CwhOuH8Os5zU_cLKmK0IKLAurA_-9-4E0cccQNHLp8Y,37357
3
+ sticker_convert/cli.py,sha256=QGCpCSVt6ChVGXkX7Ngivl-CDUewqklqz2GRJKPFlsg,18621
4
+ sticker_convert/converter.py,sha256=cmUCq_bAsDGYNDBnajxibqcgMrCND1w3icjUTDZSJRA,37353
5
5
  sticker_convert/definitions.py,sha256=ZhP2ALCEud-w9ZZD4c3TDG9eHGPZyaAL7zPUsJAbjtE,2073
6
6
  sticker_convert/gui.py,sha256=TRPGwMhSMPHnZppHmw2OWHKTJtGoeLpGWD0eRYi4_yk,30707
7
- sticker_convert/job.py,sha256=dBo98c5dIbg5ZUY8CEE1XQOSoBuf5VOZc-8pmq0Y1Js,25608
7
+ sticker_convert/job.py,sha256=vKv1--y4MVmZV_IBpUhEfNEiUeEqrTR1umzlALPXKdw,25775
8
8
  sticker_convert/job_option.py,sha256=JHAFCxp7-dDwD-1PbpYLAFRF3OoJu8cj_BjOm5r8Gp8,7732
9
- sticker_convert/version.py,sha256=s6EC7_A6bcTAEEXvg8UKbvmODYWmAfNLeSy3bqzdqAY,46
9
+ sticker_convert/version.py,sha256=e6mePgSboDriG7gF-dXdRqwITrYd0E04plj8K5a_YxM,46
10
10
  sticker_convert/downloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- sticker_convert/downloaders/download_base.py,sha256=CcrgZiBOYJbYcDGCPDHp-ECGXSpfmGtQCzS7KRbBl1E,2726
11
+ sticker_convert/downloaders/download_base.py,sha256=rYoUijl_pKldzD8SJGFetDwgMWPSQSfQwzLDObEMGow,3980
12
12
  sticker_convert/downloaders/download_kakao.py,sha256=UFp7EpMea62fIePY5DfhH4jThAwdeazfoC5iW1g4dAo,8516
13
13
  sticker_convert/downloaders/download_line.py,sha256=9WzOWujTbZdAqBi52k21OUEfRmcV1loCaJiDmg6dklw,17853
14
- sticker_convert/downloaders/download_signal.py,sha256=A-paX51kRvXIs6tY9aXv77_DJhBPcTfqZ8ib31yk5ks,3160
14
+ sticker_convert/downloaders/download_signal.py,sha256=PfwscdbcEd_5C3Ecs0F8Qc8si1sLzLodAdnsHVwXgac,3063
15
15
  sticker_convert/downloaders/download_telegram.py,sha256=jufMqc78aXOPDr7fQf9ykkNyhQ7KVCp4gRBxs09NgMo,4614
16
+ sticker_convert/downloaders/download_viber.py,sha256=mrM1XIuXuon4hlkYQc8vYqjYr1KAZGdWUI9n85W5vpU,3090
16
17
  sticker_convert/gui_components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
18
  sticker_convert/gui_components/gui_utils.py,sha256=okho2cA1Scem_m6rPiYifreFzpFrM21-yUkiAv64EUI,3431
18
19
  sticker_convert/gui_components/frames/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -66,21 +67,21 @@ sticker_convert/resources/NotoColorEmoji.ttf,sha256=LurIVaCIA8bSCfjrdO1feYr0bhKL
66
67
  sticker_convert/resources/appicon.icns,sha256=FB2DVTOQcFfQNZ9RcyG3z9c9k7eOiI1qw0IJhXMRFg4,5404
67
68
  sticker_convert/resources/appicon.ico,sha256=-ldugcl2Yq2pBRTktnhGKWInpKyWzRjCiPvMr3XPTlc,38078
68
69
  sticker_convert/resources/appicon.png,sha256=6XBEQz7PnerqS43aRkwpWolFG4WvKMuQ-st1ly-_JPg,5265
69
- sticker_convert/resources/compression.json,sha256=gWD7339773learbiFMGpTzNJVCVj8tS6ELi7yR7yKl8,11163
70
+ sticker_convert/resources/compression.json,sha256=8SAv5m7_R2QFaU656W7gpliCJF9ZmGdE_XfnJU3D0ZE,12156
70
71
  sticker_convert/resources/emoji.json,sha256=sXSuKusyG1L2Stuf9BL5ZqfzOIOdeAeE3RXcrXAsLdY,413367
71
72
  sticker_convert/resources/help.json,sha256=7VKc4Oxw6e4zv2IIeYRQ5e_aa88UlsgIHSBm9Tf-V70,6541
72
- sticker_convert/resources/input.json,sha256=sRz8qWaLh2KTjjlPIxz2UfynVn2Bn0olywbb8-qT_Hc,2251
73
+ sticker_convert/resources/input.json,sha256=5nc3US6WXAJzjqWqtDy7R2nBZ5VKVFZlKDAadE-q7SI,2657
73
74
  sticker_convert/resources/output.json,sha256=QYP2gqDvEaAm5I9bH4NReaB1XMLboevv69u-V8YdZUs,1373
74
75
  sticker_convert/uploaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
76
  sticker_convert/uploaders/compress_wastickers.py,sha256=SMPf1_ir30ZKO2ChHspDFuyaufx0XeVBVLOlHmawEdY,6021
76
77
  sticker_convert/uploaders/upload_base.py,sha256=uQupPn6r4zrlAzpKzzX7CgvZb69ATyrwPKahWOQj0ds,1203
77
- sticker_convert/uploaders/upload_signal.py,sha256=vFMvQ4TwDNliPuQ7ecXHzTT-qrTwPAORbSxZ7Nk9VM4,6541
78
- sticker_convert/uploaders/upload_telegram.py,sha256=KXQskywHjiVWLDz6qjzJhZk14PNRD3vQ-HNORNa1vNI,14634
78
+ sticker_convert/uploaders/upload_signal.py,sha256=eZNfTwnZzPmJcl_UCfJT6rrmLlNpD2EKfxrO2jdi1yg,6396
79
+ sticker_convert/uploaders/upload_telegram.py,sha256=XnspO9VVbKND0gybUwdFTSzDBVDxLw9O_R7chnVQ0t0,15695
79
80
  sticker_convert/uploaders/xcode_imessage.py,sha256=1gvOljf6kYsq_11tYhnF19Yf4oGY5y34te2DWBRMwf0,11254
80
81
  sticker_convert/utils/callback.py,sha256=_w_dZ3DZTA9m4TjEg6NH_VOa5Dl2YHXdXAlwx_tBdoY,6061
81
82
  sticker_convert/utils/url_detect.py,sha256=Cw3SzHj0xQTgCY8KvXbgFGRn_VhDJuZvH0mWsiQOg5s,769
82
83
  sticker_convert/utils/auth/get_kakao_auth.py,sha256=ipAZ1DUd5CMTpUoxRXHVOFC3DKIpxwxpTYAfrOJ6UZ8,9829
83
- sticker_convert/utils/auth/get_line_auth.py,sha256=CAg5oAyqnzyAr1sP0iaecJPpmreeERiZnVxIX9X_Ib0,2682
84
+ sticker_convert/utils/auth/get_line_auth.py,sha256=8l8ha2vQmk3rHGvDE7PkcxQXbH3oe62LKbI3qVUtvqc,2196
84
85
  sticker_convert/utils/auth/get_signal_auth.py,sha256=6Sx-lMuyBHeX1RpjAWI8u03qnRu9fmO4p89pd7fowOE,4925
85
86
  sticker_convert/utils/files/cache_store.py,sha256=etfe614OAhAyrnM5fGeESKq6R88YLNqkqkxSzEmZ0V0,1047
86
87
  sticker_convert/utils/files/json_manager.py,sha256=Vr6pZJdLMkrJJWN99210aduVHb0ILyf0SSTaw4TZqgc,541
@@ -92,9 +93,9 @@ sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE
92
93
  sticker_convert/utils/media/codec_info.py,sha256=SJSFvQzXHnGkj7MH9xJ5xiC4cqiOjFKckFKE_FICdT4,15562
93
94
  sticker_convert/utils/media/decrypt_kakao.py,sha256=4wq9ZDRnFkx1WmFZnyEogBofiLGsWQM_X69HlA36578,1947
94
95
  sticker_convert/utils/media/format_verify.py,sha256=Xf94jyqk_6M9IlFGMy0wYIgQKn_yg00nD4XW0CgAbew,5732
95
- sticker_convert-2.8.3.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
96
- sticker_convert-2.8.3.dist-info/METADATA,sha256=1Z_8zjVrd5RMAilj-dAEVVGBtbYzkchvTDgzeWsfCTA,49284
97
- sticker_convert-2.8.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
98
- sticker_convert-2.8.3.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
99
- sticker_convert-2.8.3.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
100
- sticker_convert-2.8.3.dist-info/RECORD,,
96
+ sticker_convert-2.8.5.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
97
+ sticker_convert-2.8.5.dist-info/METADATA,sha256=CWigvu2m37fdj14o8MqqmahgYDfUrbzG2zPbEO1KdCU,49868
98
+ sticker_convert-2.8.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
+ sticker_convert-2.8.5.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
100
+ sticker_convert-2.8.5.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
101
+ sticker_convert-2.8.5.dist-info/RECORD,,