sticker-convert 2.8.4__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"
@@ -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
@@ -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",
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.4"
3
+ __version__ = "2.8.5"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.4
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
@@ -369,7 +369,7 @@ 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.7
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
@@ -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
3
+ sticker_convert/cli.py,sha256=QGCpCSVt6ChVGXkX7Ngivl-CDUewqklqz2GRJKPFlsg,18621
4
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=c0IeULfsh0KUhBozwZM7ez3i-QW6-94_KuLYYaHKJNM,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
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,10 +67,10 @@ 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
@@ -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.4.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
96
- sticker_convert-2.8.4.dist-info/METADATA,sha256=CY_kjWENOtI_N6utqwA3JcVYqf83hd2JGzxHGRdtA8Q,49307
97
- sticker_convert-2.8.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
98
- sticker_convert-2.8.4.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
99
- sticker_convert-2.8.4.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
100
- sticker_convert-2.8.4.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,,