sticker-convert 2.9.1__py3-none-any.whl → 2.9.3__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.
- sticker_convert/downloaders/download_base.py +2 -2
- sticker_convert/downloaders/download_kakao.py +48 -140
- sticker_convert/gui_components/frames/cred_frame.py +2 -0
- sticker_convert/version.py +1 -1
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/METADATA +9 -8
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/RECORD +10 -10
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/WHEEL +1 -1
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/LICENSE +0 -0
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.9.1.dist-info → sticker_convert-2.9.3.dist-info}/top_level.txt +0 -0
@@ -92,10 +92,10 @@ class DownloadBase:
|
|
92
92
|
response = requests.get(
|
93
93
|
url, stream=True, allow_redirects=True, **kwargs
|
94
94
|
)
|
95
|
-
total_length = int(response.headers.get("content-length")) # type: ignore
|
96
|
-
|
97
95
|
if not response.ok:
|
98
96
|
return b""
|
97
|
+
total_length = int(response.headers.get("content-length")) # type: ignore
|
98
|
+
|
99
99
|
self.cb.put(f"Downloading {url}")
|
100
100
|
|
101
101
|
if show_progress:
|
@@ -3,16 +3,13 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
import itertools
|
5
5
|
import json
|
6
|
-
import re
|
7
|
-
import zipfile
|
8
|
-
from io import BytesIO
|
9
6
|
from pathlib import Path
|
10
7
|
from typing import Any, List, Optional, Tuple, cast
|
11
8
|
from urllib.parse import urlparse
|
12
9
|
|
13
10
|
import requests
|
14
11
|
from bs4 import BeautifulSoup
|
15
|
-
from
|
12
|
+
from py_mini_racer import MiniRacer
|
16
13
|
|
17
14
|
from sticker_convert.downloaders.download_base import DownloadBase
|
18
15
|
from sticker_convert.job_option import CredOption
|
@@ -20,94 +17,27 @@ from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
|
20
17
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
21
18
|
from sticker_convert.utils.media.decrypt_kakao import DecryptKakao
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
return -1
|
20
|
+
JSINJECT = """
|
21
|
+
class osclass {
|
22
|
+
android = true;
|
23
|
+
}
|
24
|
+
class uaclass {
|
25
|
+
os = new osclass();
|
26
|
+
}
|
27
|
+
class util {
|
28
|
+
static userAgent() {
|
29
|
+
return new uaclass();
|
30
|
+
}
|
31
|
+
}
|
32
|
+
class daumtools {
|
33
|
+
static web2app(dataDict) {
|
34
|
+
return dataDict['urlScheme'];
|
35
|
+
}
|
36
|
+
}
|
37
|
+
"""
|
42
38
|
|
43
39
|
|
44
40
|
class MetadataKakao:
|
45
|
-
@staticmethod
|
46
|
-
def get_info_from_share_link(url: str) -> Tuple[Optional[str], Optional[str]]:
|
47
|
-
headers = {"User-Agent": "Android"}
|
48
|
-
|
49
|
-
response = requests.get(url, headers=headers)
|
50
|
-
soup = BeautifulSoup(response.content.decode("utf-8", "ignore"), "html.parser")
|
51
|
-
|
52
|
-
pack_title_tag = soup.find("title") # type: ignore
|
53
|
-
if not pack_title_tag:
|
54
|
-
return None, None
|
55
|
-
|
56
|
-
pack_title: str = pack_title_tag.string # type: ignore
|
57
|
-
|
58
|
-
app_scheme_link_tag = soup.find("a", id="app_scheme_link") # type: ignore
|
59
|
-
assert isinstance(app_scheme_link_tag, Tag)
|
60
|
-
|
61
|
-
item_code_fake = cast(str, app_scheme_link_tag["data-i"])
|
62
|
-
|
63
|
-
js = ""
|
64
|
-
for script_tag in soup.find_all("script"):
|
65
|
-
js = script_tag.string
|
66
|
-
if js and "emoticonDeepLink" in js:
|
67
|
-
break
|
68
|
-
if "emoticonDeepLink" not in js:
|
69
|
-
return None, None
|
70
|
-
|
71
|
-
func_start_pos = js.find("function emoticonDeepLink(")
|
72
|
-
js = js[func_start_pos:]
|
73
|
-
bracket_start_pos = js.find("{")
|
74
|
-
func_end_pos = search_bracket(js[bracket_start_pos:]) + bracket_start_pos
|
75
|
-
js = js[bracket_start_pos + 1 : func_end_pos]
|
76
|
-
js = js.split(";")[0]
|
77
|
-
|
78
|
-
minus_num_regex = re.search(r"\-(.*?)\^", js)
|
79
|
-
if not minus_num_regex:
|
80
|
-
return None, None
|
81
|
-
minus_num_str = minus_num_regex.group(1)
|
82
|
-
if not minus_num_str.isnumeric():
|
83
|
-
return None, None
|
84
|
-
minus_num = int(minus_num_str)
|
85
|
-
|
86
|
-
xor_num_regex = re.search(r"\^(.*?)\)", js)
|
87
|
-
if not xor_num_regex:
|
88
|
-
return None, None
|
89
|
-
xor_num_str = xor_num_regex.group(1)
|
90
|
-
if not xor_num_str.isnumeric():
|
91
|
-
return None, None
|
92
|
-
xor_num = int(xor_num_str)
|
93
|
-
|
94
|
-
item_code = str(int(item_code_fake) - minus_num ^ xor_num)
|
95
|
-
|
96
|
-
# https://github.com/Nuitka/Nuitka/issues/385
|
97
|
-
# js2py not working if compiled by nuitka
|
98
|
-
# web2app_start_pos = js.find("daumtools.web2app(")
|
99
|
-
# js = js[:web2app_start_pos] + "return a;}"
|
100
|
-
# get_item_code = js2py.eval_js(js) # type: ignore
|
101
|
-
# kakao_scheme_link = cast(
|
102
|
-
# str,
|
103
|
-
# get_item_code(
|
104
|
-
# "kakaotalk://store/emoticon/${i}?referer=share_link", item_code_fake
|
105
|
-
# ),
|
106
|
-
# )
|
107
|
-
# item_code = urlparse(kakao_scheme_link).path.split("/")[-1]
|
108
|
-
|
109
|
-
return pack_title, item_code
|
110
|
-
|
111
41
|
@staticmethod
|
112
42
|
def get_item_code(title_ko: str, auth_token: str) -> Optional[str]:
|
113
43
|
headers = {
|
@@ -177,15 +107,41 @@ class DownloadKakao(DownloadBase):
|
|
177
107
|
self.pack_info_unauthed: Optional[dict[str, Any]] = None
|
178
108
|
self.pack_info_authed: Optional[dict[str, Any]] = None
|
179
109
|
|
110
|
+
def get_info_from_share_link(self, url: str) -> Tuple[Optional[str], Optional[str]]:
|
111
|
+
headers = {"User-Agent": "Android"}
|
112
|
+
|
113
|
+
response = requests.get(url, headers=headers)
|
114
|
+
soup = BeautifulSoup(response.content.decode("utf-8", "ignore"), "html.parser")
|
115
|
+
|
116
|
+
pack_title_tag = soup.find("title") # type: ignore
|
117
|
+
if not pack_title_tag:
|
118
|
+
return None, None
|
119
|
+
|
120
|
+
pack_title: str = pack_title_tag.string # type: ignore
|
121
|
+
|
122
|
+
js = ""
|
123
|
+
for script_tag in soup.find_all("script"):
|
124
|
+
js = script_tag.string
|
125
|
+
if js and "daumtools.web2app" in js:
|
126
|
+
break
|
127
|
+
if "daumtools.web2app" not in js:
|
128
|
+
return None, None
|
129
|
+
|
130
|
+
js = JSINJECT + js
|
131
|
+
|
132
|
+
ctx = MiniRacer()
|
133
|
+
kakao_url = cast(str, ctx.eval(js))
|
134
|
+
item_code = urlparse(kakao_url).path.split("/")[2]
|
135
|
+
|
136
|
+
return pack_title, item_code
|
137
|
+
|
180
138
|
def download_stickers_kakao(self) -> bool:
|
181
139
|
self.auth_token = None
|
182
140
|
if self.opt_cred:
|
183
141
|
self.auth_token = self.opt_cred.kakao_auth_token
|
184
142
|
|
185
143
|
if urlparse(self.url).netloc == "emoticon.kakao.com":
|
186
|
-
self.pack_title, item_code =
|
187
|
-
self.url
|
188
|
-
)
|
144
|
+
self.pack_title, item_code = self.get_info_from_share_link(self.url)
|
189
145
|
|
190
146
|
if item_code:
|
191
147
|
return self.download_animated(item_code)
|
@@ -268,14 +224,6 @@ class DownloadKakao(DownloadBase):
|
|
268
224
|
self.out_dir, title=self.pack_title, author=self.author
|
269
225
|
)
|
270
226
|
|
271
|
-
success = self.download_animated_zip(item_code)
|
272
|
-
if not success:
|
273
|
-
self.cb.put("Trying to download one by one")
|
274
|
-
success = self.download_animated_files(item_code)
|
275
|
-
|
276
|
-
return success
|
277
|
-
|
278
|
-
def download_animated_files(self, item_code: str) -> bool:
|
279
227
|
play_exts = [".webp", ".gif", ".png", ""]
|
280
228
|
play_types = ["emot", "emoji", ""] # emot = normal; emoji = mini
|
281
229
|
play_path_format = None
|
@@ -376,46 +324,6 @@ class DownloadKakao(DownloadBase):
|
|
376
324
|
|
377
325
|
return True
|
378
326
|
|
379
|
-
def download_animated_zip(self, item_code: str) -> bool:
|
380
|
-
pack_url = f"http://item.kakaocdn.net/dw/{item_code}.file_pack.zip"
|
381
|
-
|
382
|
-
zip_file = self.download_file(pack_url)
|
383
|
-
if zip_file:
|
384
|
-
self.cb.put(f"Downloaded {pack_url}")
|
385
|
-
else:
|
386
|
-
self.cb.put(f"Cannot download {pack_url}")
|
387
|
-
return False
|
388
|
-
|
389
|
-
with zipfile.ZipFile(BytesIO(zip_file)) as zf:
|
390
|
-
self.cb.put("Unzipping...")
|
391
|
-
self.cb.put(
|
392
|
-
(
|
393
|
-
"bar",
|
394
|
-
None,
|
395
|
-
{"set_progress_mode": "determinate", "steps": len(zf.namelist())},
|
396
|
-
)
|
397
|
-
)
|
398
|
-
|
399
|
-
for num, f_path in enumerate(sorted(zf.namelist())):
|
400
|
-
ext = Path(f_path).suffix
|
401
|
-
|
402
|
-
if ext in (".gif", ".webp"):
|
403
|
-
data = DecryptKakao.xor_data(zf.read(f_path))
|
404
|
-
self.cb.put(f"Decrypted {f_path}")
|
405
|
-
else:
|
406
|
-
data = zf.read(f_path)
|
407
|
-
self.cb.put(f"Read {f_path}")
|
408
|
-
|
409
|
-
out_path = Path(self.out_dir, str(num).zfill(3) + ext)
|
410
|
-
with open(out_path, "wb") as f:
|
411
|
-
f.write(data)
|
412
|
-
|
413
|
-
self.cb.put("update_bar")
|
414
|
-
|
415
|
-
self.cb.put(f"Finished getting {pack_url}")
|
416
|
-
|
417
|
-
return True
|
418
|
-
|
419
327
|
@staticmethod
|
420
328
|
def start(
|
421
329
|
url: str,
|
sticker_convert/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sticker-convert
|
3
|
-
Version: 2.9.
|
3
|
+
Version: 2.9.3
|
4
4
|
Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, Viber, iMessage. Written in Python.
|
5
5
|
Author-email: laggykiller <chaudominic2@gmail.com>
|
6
6
|
Maintainer-email: laggykiller <chaudominic2@gmail.com>
|
@@ -367,17 +367,18 @@ License-File: LICENSE
|
|
367
367
|
Requires-Dist: aiolimiter ~=1.1.0
|
368
368
|
Requires-Dist: anyio ~=4.4.0
|
369
369
|
Requires-Dist: apngasm-python ~=1.3.1
|
370
|
-
Requires-Dist: av ~=12.
|
370
|
+
Requires-Dist: av ~=12.2.0
|
371
371
|
Requires-Dist: beautifulsoup4 ~=4.12.3
|
372
|
-
Requires-Dist: rookiepy ~=0.5.
|
372
|
+
Requires-Dist: rookiepy ~=0.5.2
|
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
|
+
Requires-Dist: mini-racer ~=0.12.4
|
376
377
|
Requires-Dist: numpy >=1.22.4
|
377
|
-
Requires-Dist: Pillow ~=10.
|
378
|
+
Requires-Dist: Pillow ~=10.4.0
|
378
379
|
Requires-Dist: pyoxipng ~=9.0.0
|
379
380
|
Requires-Dist: python-telegram-bot ~=21.3
|
380
|
-
Requires-Dist: psutil ~=
|
381
|
+
Requires-Dist: psutil ~=6.0.0
|
381
382
|
Requires-Dist: PyMemoryEditor ~=1.5.22
|
382
383
|
Requires-Dist: requests ~=2.32.3
|
383
384
|
Requires-Dist: rlottie-python ~=1.3.6
|
@@ -392,7 +393,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
392
393
|
|
393
394
|
- A python script for creating, downloading, converting+compressing and uploading stickers from multiple instant messaging applications.
|
394
395
|
- With GUI and CLI that runs on Windows, MacOS and Linux
|
395
|
-
- Currently supports Signal, Telegram, WhatsApp (Create .wastickers), Line (Download only), Kakao (Download only), Viber
|
396
|
+
- Currently supports Signal, Telegram, WhatsApp (Create .wastickers), Line (Download only), Kakao (Download only), Viber, iMessage (Create Xcode sticker pack project)
|
396
397
|
- Supports static and animated stickers, with transparency support
|
397
398
|
|
398
399
|
## Downloads
|
@@ -430,7 +431,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
430
431
|
| [WhatsApp](docs/guide_whatsapp.md) | ⭕ (By Android or WhatsApp Web) | ⭕ (Create `.wastickers`, import by Sticker Maker) |
|
431
432
|
| [Line](docs/guide_line.md) | ✅ | 🚫 (Need to submit for manual approval) |
|
432
433
|
| [Kakao](docs/guide_kakao.md) | ✅ (Need 'share link' for animated) | 🚫 (Need to submit for manual approval) |
|
433
|
-
| [Viber](docs/guide_viber.md) | ✅ |
|
434
|
+
| [Viber](docs/guide_viber.md) | ✅ | ✅ (Require `viber_auth`) |
|
434
435
|
| [iMessage](docs/guide_imessage.md) | 🚫 | ⭕ (Create Xcode stickerpack project for sideload) |
|
435
436
|
|
436
437
|
✅ = Supported ⭕ = Partially supported 🚫 = Not supported
|
@@ -459,7 +460,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
459
460
|
- Upload: Not supported. You need to manually submit sticker pack for approval before you can use in app.
|
460
461
|
- Viber
|
461
462
|
- Download: Supported (e.g. `https://stickers.viber.com/pages/example` OR `https://stickers.viber.com/pages/custom-sticker-packs/example`)
|
462
|
-
- Upload:
|
463
|
+
- Upload: Supported. Viber authentication data required for uploading Viber stickers, which could be fetched from Viber Desktop application automatically.
|
463
464
|
- iMessage
|
464
465
|
- Download: Not supported.
|
465
466
|
- Upload: The program can create Xcode project for iMessage sticker pack, which could then be compiled and sideloaded using Xcode.
|
@@ -6,10 +6,10 @@ sticker_convert/definitions.py,sha256=ZhP2ALCEud-w9ZZD4c3TDG9eHGPZyaAL7zPUsJAbjt
|
|
6
6
|
sticker_convert/gui.py,sha256=hZOp2SyEYKbCRm9SRTItBqEk724SHtSqK_Txo0wpL8Q,31194
|
7
7
|
sticker_convert/job.py,sha256=4C2WwB3PFldacqI8UPnM10thM087VLEl9wn6P9_LtS0,26128
|
8
8
|
sticker_convert/job_option.py,sha256=yFwHEhW8Gzp9dfiXakkCREfejAIJhiOxwD4Wlg9jcPk,7805
|
9
|
-
sticker_convert/version.py,sha256
|
9
|
+
sticker_convert/version.py,sha256=-3orOmwxQLXzeq93BjsCFkrDamN1_r5Ng80gy5-PF0w,46
|
10
10
|
sticker_convert/downloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
sticker_convert/downloaders/download_base.py,sha256=
|
12
|
-
sticker_convert/downloaders/download_kakao.py,sha256=
|
11
|
+
sticker_convert/downloaders/download_base.py,sha256=WGEtri16p6GCG7hhQ603pKS8efoB72oCBHTuJ_RVmG0,4041
|
12
|
+
sticker_convert/downloaders/download_kakao.py,sha256=kE3LikphcFrFjAf-eJhmkj0Ko_JG9QpWFTp_YiWEzRA,11605
|
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
|
@@ -20,7 +20,7 @@ sticker_convert/gui_components/frames/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
20
20
|
sticker_convert/gui_components/frames/comp_frame.py,sha256=9k_UntKKi2G_g0byzoj1rdTqOq7q9mcnXiy799bYnr0,7257
|
21
21
|
sticker_convert/gui_components/frames/config_frame.py,sha256=b3X4QAnGpde0OhthXHmjSyU_Yb5tYRUFXmy04Yi8Zmo,4316
|
22
22
|
sticker_convert/gui_components/frames/control_frame.py,sha256=_XiOJ9JPUfiysDghGG04sEVLrXG9TMVlDZ60W0LhYVI,835
|
23
|
-
sticker_convert/gui_components/frames/cred_frame.py,sha256=
|
23
|
+
sticker_convert/gui_components/frames/cred_frame.py,sha256=AJHxxBdEa-xOteevVBsSfAHtcJklU3pu2TqvZny9o4w,7527
|
24
24
|
sticker_convert/gui_components/frames/input_frame.py,sha256=5Vz1d6J1jkofvvzm43DxeIW_CjWfxa2QPYFnkAAiAfM,5040
|
25
25
|
sticker_convert/gui_components/frames/output_frame.py,sha256=n2WLk22h61DoZli8WbFhd-h2CqWAebDXnBa051JBuOc,4260
|
26
26
|
sticker_convert/gui_components/frames/progress_frame.py,sha256=LWUZg_iL7iiNTfu7N5Ct_pklZdghxihENi7DP9YozOE,4915
|
@@ -98,9 +98,9 @@ sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE
|
|
98
98
|
sticker_convert/utils/media/codec_info.py,sha256=1QfW3wgZ5vOk7T4XtLHYvJK1x8RbASRPSvhKEPkcu9A,15747
|
99
99
|
sticker_convert/utils/media/decrypt_kakao.py,sha256=4wq9ZDRnFkx1WmFZnyEogBofiLGsWQM_X69HlA36578,1947
|
100
100
|
sticker_convert/utils/media/format_verify.py,sha256=MH68GLJfXeL8WFT8emtj355K5BLAtUX64tQ59nugx2c,5673
|
101
|
-
sticker_convert-2.9.
|
102
|
-
sticker_convert-2.9.
|
103
|
-
sticker_convert-2.9.
|
104
|
-
sticker_convert-2.9.
|
105
|
-
sticker_convert-2.9.
|
106
|
-
sticker_convert-2.9.
|
101
|
+
sticker_convert-2.9.3.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
102
|
+
sticker_convert-2.9.3.dist-info/METADATA,sha256=AhL6yrezU5-qhw5E2euXRDGz9fRplznnme-gVs4O0bo,51023
|
103
|
+
sticker_convert-2.9.3.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
104
|
+
sticker_convert-2.9.3.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
|
105
|
+
sticker_convert-2.9.3.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
|
106
|
+
sticker_convert-2.9.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|