sticker-convert 2.9.0__py3-none-any.whl → 2.9.2__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 +92 -140
- sticker_convert/gui_components/frames/cred_frame.py +2 -0
- sticker_convert/gui_components/windows/viber_get_auth_window.py +8 -2
- sticker_convert/resources/memdump_windows.ps1 +8 -0
- sticker_convert/utils/auth/get_viber_auth.py +266 -140
- sticker_convert/version.py +1 -1
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.dist-info}/METADATA +12 -10
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.dist-info}/RECORD +14 -13
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.dist-info}/WHEEL +1 -1
- /sticker_convert/resources/{memdump.sh → memdump_linux.sh} +0 -0
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.dist-info}/LICENSE +0 -0
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.9.0.dist-info → sticker_convert-2.9.2.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,20 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
import itertools
|
5
5
|
import json
|
6
|
-
import
|
7
|
-
import zipfile
|
8
|
-
from io import BytesIO
|
6
|
+
import webbrowser
|
9
7
|
from pathlib import Path
|
8
|
+
from tempfile import TemporaryDirectory
|
10
9
|
from typing import Any, List, Optional, Tuple, cast
|
11
10
|
from urllib.parse import urlparse
|
12
11
|
|
12
|
+
import chromedriver_autoinstaller # type: ignore
|
13
13
|
import requests
|
14
14
|
from bs4 import BeautifulSoup
|
15
|
-
from
|
15
|
+
from selenium import webdriver
|
16
|
+
from selenium.webdriver.chrome.options import Options
|
17
|
+
from selenium.webdriver.common.by import By
|
18
|
+
from selenium.webdriver.support import expected_conditions as EC
|
19
|
+
from selenium.webdriver.support.wait import WebDriverWait
|
16
20
|
|
17
21
|
from sticker_convert.downloaders.download_base import DownloadBase
|
18
22
|
from sticker_convert.job_option import CredOption
|
@@ -20,94 +24,38 @@ from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
|
20
24
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
21
25
|
from sticker_convert.utils.media.decrypt_kakao import DecryptKakao
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
JSINJECT = """
|
28
|
+
class osclass {
|
29
|
+
android = true;
|
30
|
+
}
|
31
|
+
class uaclass {
|
32
|
+
os = new osclass();
|
33
|
+
}
|
34
|
+
class util {
|
35
|
+
static userAgent() {
|
36
|
+
return new uaclass();
|
37
|
+
}
|
38
|
+
}
|
39
|
+
class daumtools {
|
40
|
+
static web2app(dataDict) {
|
41
|
+
return dataDict['urlScheme'];
|
42
|
+
}
|
43
|
+
}
|
44
|
+
"""
|
45
|
+
|
46
|
+
HTMLPAGE = """
|
47
|
+
<html>
|
48
|
+
<body>
|
49
|
+
<p id="p1"></p>
|
50
|
+
<script>
|
51
|
+
{}
|
52
|
+
</script>
|
53
|
+
</body>
|
54
|
+
</html>
|
55
|
+
"""
|
42
56
|
|
43
57
|
|
44
58
|
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
59
|
@staticmethod
|
112
60
|
def get_item_code(title_ko: str, auth_token: str) -> Optional[str]:
|
113
61
|
headers = {
|
@@ -177,15 +125,67 @@ class DownloadKakao(DownloadBase):
|
|
177
125
|
self.pack_info_unauthed: Optional[dict[str, Any]] = None
|
178
126
|
self.pack_info_authed: Optional[dict[str, Any]] = None
|
179
127
|
|
128
|
+
def get_info_from_share_link(self, url: str) -> Tuple[Optional[str], Optional[str]]:
|
129
|
+
headers = {"User-Agent": "Android"}
|
130
|
+
|
131
|
+
response = requests.get(url, headers=headers)
|
132
|
+
soup = BeautifulSoup(response.content.decode("utf-8", "ignore"), "html.parser")
|
133
|
+
|
134
|
+
pack_title_tag = soup.find("title") # type: ignore
|
135
|
+
if not pack_title_tag:
|
136
|
+
return None, None
|
137
|
+
|
138
|
+
pack_title: str = pack_title_tag.string # type: ignore
|
139
|
+
|
140
|
+
js = ""
|
141
|
+
for script_tag in soup.find_all("script"):
|
142
|
+
js = script_tag.string
|
143
|
+
if js and "daumtools.web2app" in js:
|
144
|
+
break
|
145
|
+
if "daumtools.web2app" not in js:
|
146
|
+
return None, None
|
147
|
+
|
148
|
+
js = js.replace(
|
149
|
+
"daumtools.web2app",
|
150
|
+
'document.getElementById("p1").innerHTML = daumtools.web2app',
|
151
|
+
)
|
152
|
+
js = JSINJECT + js
|
153
|
+
|
154
|
+
with TemporaryDirectory() as tempdir:
|
155
|
+
html_page_path = Path(tempdir, "page.html")
|
156
|
+
html_page = HTMLPAGE.format(js)
|
157
|
+
with open(html_page_path, "w+") as f:
|
158
|
+
f.write(html_page)
|
159
|
+
|
160
|
+
try:
|
161
|
+
chromedriver_autoinstaller.install()
|
162
|
+
chrome_options = Options()
|
163
|
+
chrome_options.add_argument("--headless") # type: ignore
|
164
|
+
driver = webdriver.Chrome(options=chrome_options)
|
165
|
+
driver.get(html_page_path.as_posix())
|
166
|
+
wait = WebDriverWait(driver, 10)
|
167
|
+
wait.until(EC.text_to_be_present_in_element((By.ID, "p1"), "kakaotalk")) # type: ignore
|
168
|
+
kakao_url_elm = driver.find_element(By.ID, "p1")
|
169
|
+
kakao_url = cast(str, kakao_url_elm.text) # type: ignore
|
170
|
+
driver.close()
|
171
|
+
except ValueError:
|
172
|
+
webbrowser.open(html_page_path.as_posix())
|
173
|
+
prompt = "Chrome not installed, using manual method.\n"
|
174
|
+
prompt += "Please copy and paste the url you see in the browser"
|
175
|
+
self.cb.put(("ask_str", (prompt,), None))
|
176
|
+
kakao_url = cast(str, self.cb_return.get_response())
|
177
|
+
|
178
|
+
item_code = urlparse(kakao_url).path.split("/")[2]
|
179
|
+
|
180
|
+
return pack_title, item_code
|
181
|
+
|
180
182
|
def download_stickers_kakao(self) -> bool:
|
181
183
|
self.auth_token = None
|
182
184
|
if self.opt_cred:
|
183
185
|
self.auth_token = self.opt_cred.kakao_auth_token
|
184
186
|
|
185
187
|
if urlparse(self.url).netloc == "emoticon.kakao.com":
|
186
|
-
self.pack_title, item_code =
|
187
|
-
self.url
|
188
|
-
)
|
188
|
+
self.pack_title, item_code = self.get_info_from_share_link(self.url)
|
189
189
|
|
190
190
|
if item_code:
|
191
191
|
return self.download_animated(item_code)
|
@@ -268,14 +268,6 @@ class DownloadKakao(DownloadBase):
|
|
268
268
|
self.out_dir, title=self.pack_title, author=self.author
|
269
269
|
)
|
270
270
|
|
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
271
|
play_exts = [".webp", ".gif", ".png", ""]
|
280
272
|
play_types = ["emot", "emoji", ""] # emot = normal; emoji = mini
|
281
273
|
play_path_format = None
|
@@ -376,46 +368,6 @@ class DownloadKakao(DownloadBase):
|
|
376
368
|
|
377
369
|
return True
|
378
370
|
|
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
371
|
@staticmethod
|
420
372
|
def start(
|
421
373
|
url: str,
|
@@ -51,11 +51,17 @@ class ViberGetAuthWindow(BaseWindow):
|
|
51
51
|
justify="left",
|
52
52
|
anchor="w",
|
53
53
|
)
|
54
|
+
else:
|
55
|
+
self.explanation_lbl2 = Label(
|
56
|
+
self.frame_info,
|
57
|
+
text="You may be asked for admin password.",
|
58
|
+
justify="left",
|
59
|
+
anchor="w",
|
60
|
+
)
|
54
61
|
|
55
62
|
self.explanation_lbl0.grid(column=0, row=0, sticky="w", padx=3, pady=3)
|
56
63
|
self.explanation_lbl1.grid(column=0, row=1, sticky="w", padx=3, pady=3)
|
57
|
-
|
58
|
-
self.explanation_lbl2.grid(column=0, row=2, sticky="w", padx=3, pady=3)
|
64
|
+
self.explanation_lbl2.grid(column=0, row=2, sticky="w", padx=3, pady=3)
|
59
65
|
|
60
66
|
# Start button frame
|
61
67
|
self.launch_btn = Button(
|
@@ -0,0 +1,8 @@
|
|
1
|
+
param($processId)
|
2
|
+
$dumpFilePath = "$Env:TEMP\memdump.bin.$processId"
|
3
|
+
|
4
|
+
Powershell -c rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump $processId $dumpFilePath full
|
5
|
+
|
6
|
+
icacls $dumpFilePath /remove "Everyone"
|
7
|
+
icacls $dumpFilePath /grant "Everyone:(r)"
|
8
|
+
icacls $dumpFilePath /grant "Everyone:(w)"
|
@@ -1,137 +1,183 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
|
+
import importlib.util
|
2
3
|
import os
|
3
4
|
import platform
|
4
5
|
import shutil
|
6
|
+
import signal
|
5
7
|
import subprocess
|
6
8
|
import time
|
7
9
|
from getpass import getpass
|
8
10
|
from pathlib import Path
|
9
|
-
from typing import Callable, Optional, Tuple, cast
|
11
|
+
from typing import Callable, List, Optional, Tuple, cast
|
10
12
|
|
11
13
|
from sticker_convert.definitions import ROOT_DIR
|
12
14
|
|
13
|
-
# psutil is missing on arm64 linux appimage
|
14
|
-
# Note: There is no Viber Desktop on arm64 linux anyway
|
15
|
-
try:
|
16
|
-
import psutil
|
17
|
-
|
18
|
-
PSUTIL_LOADED = True
|
19
|
-
except ModuleNotFoundError:
|
20
|
-
PSUTIL_LOADED = False # type: ignore
|
21
|
-
|
22
15
|
MSG_NO_BIN = """Viber Desktop not detected.
|
23
16
|
Download and install Viber Desktop,
|
24
17
|
then login to Viber Desktop and try again."""
|
25
|
-
|
26
18
|
MSG_NO_AUTH = """Viber Desktop installed,
|
27
19
|
but viber_auth not found.
|
28
20
|
Please login to Viber Desktop and try again."""
|
29
|
-
|
30
21
|
MSG_SIP_ENABLED = """You need to disable SIP:
|
31
22
|
1. Restart computer in Recovery mode
|
32
23
|
2. Launch Terminal from the Utilities menu
|
33
24
|
3. Run the command `csrutil disable`
|
34
25
|
4. Restart your computer"""
|
26
|
+
MSG_NO_PGREP = "pgrep command or psutil python package is necessary"
|
27
|
+
MSG_LAUNCH_FAIL = "Failed to launch Viber"
|
28
|
+
MSG_PERMISSION_ERROR = "Failed to read Viber process memory"
|
35
29
|
|
36
|
-
MSG_NO_PSUTIL = "Python package psutil is necessary"
|
37
30
|
|
38
|
-
|
39
|
-
|
40
|
-
if
|
31
|
+
def check_admin_windows() -> bool:
|
32
|
+
username = os.getenv("username")
|
33
|
+
if username is None:
|
41
34
|
return False
|
42
35
|
|
36
|
+
s = subprocess.run(
|
37
|
+
["net", "user", username],
|
38
|
+
capture_output=True,
|
39
|
+
text=True,
|
40
|
+
).stdout
|
41
|
+
|
42
|
+
return True if "*Administrators" in s else False
|
43
|
+
|
44
|
+
|
45
|
+
def check_admin_linux() -> bool:
|
46
|
+
s = subprocess.run(
|
47
|
+
["sudo", "-l"],
|
48
|
+
capture_output=True,
|
49
|
+
text=True,
|
50
|
+
).stdout
|
51
|
+
|
52
|
+
return True if "may run the following commands" in s else False
|
53
|
+
|
54
|
+
|
55
|
+
def killall(name: str) -> bool:
|
43
56
|
result = False
|
44
57
|
|
45
|
-
|
46
|
-
|
47
|
-
|
58
|
+
while True:
|
59
|
+
pid = find_pid_by_name(name)
|
60
|
+
if pid is not None:
|
61
|
+
os.kill(pid, signal.SIGTERM)
|
48
62
|
result = True
|
63
|
+
else:
|
64
|
+
break
|
49
65
|
|
50
66
|
return result
|
51
67
|
|
52
68
|
|
53
69
|
def find_pid_by_name(name: str) -> Optional[int]:
|
54
|
-
if
|
70
|
+
if platform.system() == "Windows":
|
71
|
+
s = subprocess.run(
|
72
|
+
["powershell", "-c", "Get-Process", f"*{name}*"],
|
73
|
+
capture_output=True,
|
74
|
+
text=True,
|
75
|
+
).stdout
|
76
|
+
|
77
|
+
for line in s.split("\n"):
|
78
|
+
if name in line.lower():
|
79
|
+
info = name.split()
|
80
|
+
pid = info[5]
|
81
|
+
if pid.isnumeric():
|
82
|
+
return int(pid)
|
83
|
+
|
55
84
|
return None
|
85
|
+
else:
|
86
|
+
if platform.system() == "Darwin":
|
87
|
+
pattern = "Viber"
|
88
|
+
else:
|
89
|
+
pattern = ".*[Vv]iber.*"
|
90
|
+
pid = (
|
91
|
+
subprocess.run(["pgrep", pattern], capture_output=True, text=True)
|
92
|
+
.stdout.split("\n")[0]
|
93
|
+
.strip()
|
94
|
+
)
|
95
|
+
if pid == "" or pid.isnumeric() is False:
|
96
|
+
return None
|
97
|
+
else:
|
98
|
+
return int(pid)
|
99
|
+
|
100
|
+
|
101
|
+
if importlib.util.find_spec("psutil"):
|
102
|
+
import psutil
|
103
|
+
|
104
|
+
def killall(name: str) -> bool:
|
105
|
+
result = False
|
56
106
|
|
57
|
-
|
58
|
-
|
59
|
-
|
107
|
+
for proc in psutil.process_iter(): # type: ignore
|
108
|
+
if name in proc.name().lower():
|
109
|
+
proc.kill()
|
110
|
+
result = True
|
60
111
|
|
61
|
-
|
112
|
+
return result
|
113
|
+
|
114
|
+
def find_pid_by_name(name: str) -> Optional[int]:
|
115
|
+
for proc in psutil.process_iter(): # type: ignore
|
116
|
+
if name in proc.name().lower():
|
117
|
+
return proc.pid
|
118
|
+
|
119
|
+
return None
|
62
120
|
|
63
121
|
|
64
122
|
class GetViberAuth:
|
65
123
|
def __init__(self, cb_ask_str: Callable[..., str] = input):
|
66
124
|
self.cb_ask_str = cb_ask_str
|
67
125
|
|
68
|
-
def
|
69
|
-
if not PSUTIL_LOADED:
|
70
|
-
return None, MSG_NO_PSUTIL
|
71
|
-
|
72
|
-
member_id = None
|
73
|
-
m_token = None
|
74
|
-
m_ts = None
|
75
|
-
|
126
|
+
def relaunch_viber(self, viber_bin_path: str) -> Optional[int]:
|
76
127
|
killed = killall("viber")
|
77
128
|
if killed:
|
78
129
|
time.sleep(5)
|
79
|
-
|
130
|
+
|
131
|
+
if platform.system() == "Darwin":
|
132
|
+
cmd = ["open", "-n", viber_bin_path]
|
133
|
+
else:
|
134
|
+
cmd = [viber_bin_path]
|
135
|
+
subprocess.Popen(cmd)
|
80
136
|
time.sleep(10)
|
81
137
|
|
82
|
-
|
138
|
+
return find_pid_by_name("viber")
|
83
139
|
|
84
|
-
|
85
|
-
|
86
|
-
for address in process.search_by_value(str, 18, "X-Viber-Auth-Mid: "): # type: ignore
|
87
|
-
member_id_addr = cast(int, address) + 18
|
88
|
-
member_id_bytes = process.read_process_memory(member_id_addr, bytes, 20)
|
89
|
-
member_id_term = member_id_bytes.find(b"\x0d\x0a")
|
90
|
-
if member_id_term == -1:
|
91
|
-
continue
|
92
|
-
member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
|
93
|
-
break
|
94
|
-
if member_id is None:
|
95
|
-
return None, MSG_NO_AUTH
|
140
|
+
def get_mem_windows(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
|
141
|
+
from pathlib import WindowsPath
|
96
142
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
143
|
+
memdump_ps_path = str(WindowsPath(ROOT_DIR / "resources/memdump_windows.ps1"))
|
144
|
+
arglist = (
|
145
|
+
f'-NoProfile -ExecutionPolicy Bypass -File "{memdump_ps_path}" {viber_pid}'
|
146
|
+
)
|
147
|
+
dump_fpath = os.path.expandvars(f"%temp%/memdump.bin.{viber_pid}")
|
148
|
+
|
149
|
+
cmd = [
|
150
|
+
"powershell",
|
151
|
+
"-NoProfile",
|
152
|
+
"-ExecutionPolicy",
|
153
|
+
"Bypass",
|
154
|
+
"-Command",
|
155
|
+
f"Start-Process -Verb RunAs powershell -ArgumentList '{arglist}'",
|
156
|
+
]
|
157
|
+
|
158
|
+
subprocess.run(cmd, capture_output=True, text=True)
|
159
|
+
|
160
|
+
while True:
|
161
|
+
try:
|
162
|
+
with open(dump_fpath, "rb") as f:
|
163
|
+
s = f.read()
|
164
|
+
if len(s) != 0:
|
165
|
+
break
|
166
|
+
time.sleep(1)
|
167
|
+
except (FileNotFoundError, PermissionError):
|
168
|
+
pass
|
169
|
+
|
170
|
+
while True:
|
171
|
+
try:
|
172
|
+
os.remove(dump_fpath)
|
107
173
|
break
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
killall("viber")
|
112
|
-
|
113
|
-
viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
|
114
|
-
msg = "Got viber_auth successfully:\n"
|
115
|
-
msg += f"{viber_auth=}\n"
|
116
|
-
|
117
|
-
return viber_auth, msg
|
118
|
-
|
119
|
-
def get_auth_linux(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
|
120
|
-
if not PSUTIL_LOADED:
|
121
|
-
return None, MSG_NO_PSUTIL
|
122
|
-
|
123
|
-
member_id = None
|
124
|
-
m_token = None
|
125
|
-
m_ts = None
|
174
|
+
except PermissionError:
|
175
|
+
pass
|
126
176
|
|
127
|
-
|
128
|
-
if killed:
|
129
|
-
time.sleep(5)
|
130
|
-
subprocess.Popen([viber_bin_path])
|
131
|
-
time.sleep(10)
|
177
|
+
return s, ""
|
132
178
|
|
133
|
-
|
134
|
-
memdump_sh_path = (ROOT_DIR / "resources/
|
179
|
+
def get_mem_linux(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
|
180
|
+
memdump_sh_path = (ROOT_DIR / "resources/memdump_linux.sh").as_posix()
|
135
181
|
|
136
182
|
s = subprocess.run(
|
137
183
|
[
|
@@ -141,7 +187,7 @@ class GetViberAuth:
|
|
141
187
|
capture_output=True,
|
142
188
|
).stdout
|
143
189
|
|
144
|
-
if s
|
190
|
+
if len(s) > 1000:
|
145
191
|
pass
|
146
192
|
elif shutil.which("pkexec") and os.getenv("DISPLAY"):
|
147
193
|
s = subprocess.run(
|
@@ -174,27 +220,80 @@ class GetViberAuth:
|
|
174
220
|
stdin=sudo_password_pipe.stdout,
|
175
221
|
).stdout
|
176
222
|
|
177
|
-
|
178
|
-
m_token_addr = s.find(b"X-Viber-Auth-Token: ")
|
179
|
-
m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")
|
223
|
+
return s, ""
|
180
224
|
|
181
|
-
|
182
|
-
|
225
|
+
def get_mem_darwin(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
|
226
|
+
subprocess.run(
|
227
|
+
[
|
228
|
+
"lldb",
|
229
|
+
"--attach-pid",
|
230
|
+
str(viber_pid),
|
231
|
+
"-o",
|
232
|
+
"process save-core /tmp/viber.dmp",
|
233
|
+
"-o",
|
234
|
+
"quit",
|
235
|
+
],
|
236
|
+
stdout=subprocess.DEVNULL,
|
237
|
+
stderr=subprocess.DEVNULL,
|
238
|
+
)
|
183
239
|
|
184
|
-
|
185
|
-
|
186
|
-
m_ts_addr += 24
|
240
|
+
with open("/tmp/viber.dmp", "rb") as f:
|
241
|
+
s = f.read()
|
187
242
|
|
188
|
-
|
189
|
-
member_id_term = member_id_bytes.find(b"\x0d\x0a")
|
190
|
-
if member_id_term == -1:
|
191
|
-
return None, MSG_NO_AUTH
|
192
|
-
member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
|
243
|
+
os.remove("/tmp/viber.dmp")
|
193
244
|
|
194
|
-
|
195
|
-
m_ts = s[m_ts_addr : m_ts_addr + 13].decode(encoding="ascii")
|
245
|
+
return s, ""
|
196
246
|
|
197
|
-
|
247
|
+
def get_auth_by_pme(
|
248
|
+
self, viber_bin_path: str, relaunch: bool = True
|
249
|
+
) -> Tuple[Optional[str], str]:
|
250
|
+
from PyMemoryEditor import OpenProcess # type: ignore
|
251
|
+
|
252
|
+
member_id = None
|
253
|
+
m_token = None
|
254
|
+
m_ts = None
|
255
|
+
|
256
|
+
if relaunch:
|
257
|
+
viber_pid = self.relaunch_viber(viber_bin_path)
|
258
|
+
else:
|
259
|
+
viber_pid = find_pid_by_name("viber")
|
260
|
+
if viber_pid is None:
|
261
|
+
return None, MSG_LAUNCH_FAIL
|
262
|
+
|
263
|
+
try:
|
264
|
+
with OpenProcess(pid=int(viber_pid)) as process:
|
265
|
+
for address in process.search_by_value(str, 18, "X-Viber-Auth-Mid: "): # type: ignore
|
266
|
+
member_id_addr = cast(int, address) + 18
|
267
|
+
member_id_bytes = process.read_process_memory(
|
268
|
+
member_id_addr, bytes, 20
|
269
|
+
)
|
270
|
+
member_id_term = member_id_bytes.find(b"\x0d\x0a")
|
271
|
+
if member_id_term == -1:
|
272
|
+
continue
|
273
|
+
member_id = member_id_bytes[:member_id_term].decode(
|
274
|
+
encoding="ascii"
|
275
|
+
)
|
276
|
+
break
|
277
|
+
if member_id is None:
|
278
|
+
return None, MSG_NO_AUTH
|
279
|
+
|
280
|
+
for address in process.search_by_value(str, 20, "X-Viber-Auth-Token: "): # type: ignore
|
281
|
+
m_token_addr = cast(int, address) + 20
|
282
|
+
m_token = process.read_process_memory(m_token_addr, str, 64)
|
283
|
+
break
|
284
|
+
if m_token is None:
|
285
|
+
return None, MSG_NO_AUTH
|
286
|
+
|
287
|
+
for address in process.search_by_value( # type: ignore
|
288
|
+
str, 24, "X-Viber-Auth-Timestamp: "
|
289
|
+
):
|
290
|
+
m_ts_addr = cast(int, address) + 24
|
291
|
+
m_ts = process.read_process_memory(m_ts_addr, str, 13)
|
292
|
+
break
|
293
|
+
if m_ts is None:
|
294
|
+
return None, MSG_NO_AUTH
|
295
|
+
except PermissionError:
|
296
|
+
return None, MSG_PERMISSION_ERROR
|
198
297
|
|
199
298
|
viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
|
200
299
|
msg = "Got viber_auth successfully:\n"
|
@@ -202,50 +301,43 @@ class GetViberAuth:
|
|
202
301
|
|
203
302
|
return viber_auth, msg
|
204
303
|
|
205
|
-
def
|
304
|
+
def get_auth_by_dump(
|
305
|
+
self, viber_bin_path: str, relaunch: bool = True
|
306
|
+
) -> Tuple[Optional[str], str]:
|
206
307
|
member_id = None
|
207
308
|
m_token = None
|
208
309
|
m_ts = None
|
209
310
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
if "enabled" in csrutil_status:
|
215
|
-
return None, MSG_SIP_ENABLED
|
216
|
-
|
217
|
-
killed = killall("viber")
|
218
|
-
if killed:
|
219
|
-
time.sleep(5)
|
220
|
-
subprocess.run(
|
221
|
-
["open", "-n", viber_bin_path],
|
222
|
-
stdout=subprocess.DEVNULL,
|
223
|
-
stderr=subprocess.DEVNULL,
|
224
|
-
)
|
225
|
-
time.sleep(10)
|
311
|
+
if platform.system() == "Darwin":
|
312
|
+
csrutil_status = subprocess.run(
|
313
|
+
["csrutil", "status"], capture_output=True, text=True
|
314
|
+
).stdout
|
226
315
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
)
|
316
|
+
if "enabled" in csrutil_status:
|
317
|
+
return None, MSG_SIP_ENABLED
|
318
|
+
elif (
|
319
|
+
platform.system() != "Windows"
|
320
|
+
and shutil.which("pgrep") is None
|
321
|
+
and importlib.find_loader("psutil") is None
|
322
|
+
):
|
323
|
+
return None, MSG_NO_PGREP
|
324
|
+
|
325
|
+
if relaunch:
|
326
|
+
viber_pid = self.relaunch_viber(viber_bin_path)
|
327
|
+
else:
|
328
|
+
viber_pid = find_pid_by_name("viber")
|
329
|
+
if viber_pid is None:
|
330
|
+
return None, MSG_LAUNCH_FAIL
|
243
331
|
|
244
|
-
|
245
|
-
s =
|
332
|
+
if platform.system() == "Windows":
|
333
|
+
s, msg = self.get_mem_windows(viber_pid)
|
334
|
+
elif platform.system() == "Darwin":
|
335
|
+
s, msg = self.get_mem_darwin(viber_pid)
|
336
|
+
else:
|
337
|
+
s, msg = self.get_mem_linux(viber_pid)
|
246
338
|
|
247
|
-
|
248
|
-
|
339
|
+
if s is None:
|
340
|
+
return None, msg
|
249
341
|
|
250
342
|
member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
|
251
343
|
m_token_addr = s.find(b"X-Viber-Auth-Token: ")
|
@@ -307,9 +399,43 @@ class GetViberAuth:
|
|
307
399
|
if not viber_bin_path:
|
308
400
|
return None, MSG_NO_BIN
|
309
401
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
402
|
+
# get_auth_by_dump()
|
403
|
+
# + Fast
|
404
|
+
# - Requires admin
|
405
|
+
|
406
|
+
# get_auth_by_pme()
|
407
|
+
# + No admin (If have permission to read process)
|
408
|
+
# - Slow
|
409
|
+
# - Cannot run on macOS
|
410
|
+
|
411
|
+
# If admin, prefer get_auth_by_dump() over get_auth_by_pme(), vice versa
|
412
|
+
methods: List[Callable[[str, bool], Tuple[Optional[str], str]]] = []
|
413
|
+
relaunch = True
|
414
|
+
viber_auth = None
|
415
|
+
msg = ""
|
416
|
+
|
417
|
+
pme_present = importlib.util.find_spec("PyMemoryEditor") is not None
|
418
|
+
if platform.system() == "Darwin":
|
419
|
+
methods.append(self.get_auth_by_dump)
|
420
|
+
elif platform.system() == "Windows":
|
421
|
+
methods.append(self.get_auth_by_dump)
|
422
|
+
if pme_present:
|
423
|
+
methods.append(self.get_auth_by_pme)
|
424
|
+
if check_admin_windows() is False:
|
425
|
+
methods.reverse()
|
314
426
|
else:
|
315
|
-
|
427
|
+
if not os.path.isfile("/.dockerenv"):
|
428
|
+
methods.append(self.get_auth_by_dump)
|
429
|
+
if pme_present:
|
430
|
+
methods.append(self.get_auth_by_pme)
|
431
|
+
if check_admin_linux() is False:
|
432
|
+
methods.reverse()
|
433
|
+
|
434
|
+
for method in methods:
|
435
|
+
viber_auth, msg = method(viber_bin_path, relaunch)
|
436
|
+
relaunch = False
|
437
|
+
if viber_auth is not None:
|
438
|
+
break
|
439
|
+
|
440
|
+
killall("viber")
|
441
|
+
return viber_auth, msg
|
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.2
|
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,20 +367,22 @@ 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:
|
372
|
+
Requires-Dist: chromedriver-autoinstaller ~=0.6.4
|
373
|
+
Requires-Dist: rookiepy ~=0.5.2
|
373
374
|
Requires-Dist: imagequant ~=1.1.1
|
374
375
|
Requires-Dist: memory-tempfile ~=2.2.3
|
375
376
|
Requires-Dist: mergedeep ~=1.3.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
|
-
Requires-Dist: python-telegram-bot ~=21.
|
380
|
-
Requires-Dist: psutil ~=
|
380
|
+
Requires-Dist: python-telegram-bot ~=21.3
|
381
|
+
Requires-Dist: psutil ~=6.0.0
|
381
382
|
Requires-Dist: PyMemoryEditor ~=1.5.22
|
382
383
|
Requires-Dist: requests ~=2.32.3
|
383
|
-
Requires-Dist: rlottie-python ~=1.3.
|
384
|
+
Requires-Dist: rlottie-python ~=1.3.6
|
385
|
+
Requires-Dist: selenium ~=4.22.0
|
384
386
|
Requires-Dist: signalstickers-client-fork-laggykiller ~=3.3.0.post2
|
385
387
|
Requires-Dist: sqlcipher3-wheels ~=0.5.2.post1
|
386
388
|
Requires-Dist: tqdm ~=4.66.4
|
@@ -392,7 +394,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
392
394
|
|
393
395
|
- A python script for creating, downloading, converting+compressing and uploading stickers from multiple instant messaging applications.
|
394
396
|
- 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
|
397
|
+
- Currently supports Signal, Telegram, WhatsApp (Create .wastickers), Line (Download only), Kakao (Download only), Viber, iMessage (Create Xcode sticker pack project)
|
396
398
|
- Supports static and animated stickers, with transparency support
|
397
399
|
|
398
400
|
## Downloads
|
@@ -430,7 +432,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
430
432
|
| [WhatsApp](docs/guide_whatsapp.md) | ⭕ (By Android or WhatsApp Web) | ⭕ (Create `.wastickers`, import by Sticker Maker) |
|
431
433
|
| [Line](docs/guide_line.md) | ✅ | 🚫 (Need to submit for manual approval) |
|
432
434
|
| [Kakao](docs/guide_kakao.md) | ✅ (Need 'share link' for animated) | 🚫 (Need to submit for manual approval) |
|
433
|
-
| [Viber](docs/guide_viber.md) | ✅ |
|
435
|
+
| [Viber](docs/guide_viber.md) | ✅ | ✅ (Require `viber_auth`) |
|
434
436
|
| [iMessage](docs/guide_imessage.md) | 🚫 | ⭕ (Create Xcode stickerpack project for sideload) |
|
435
437
|
|
436
438
|
✅ = Supported ⭕ = Partially supported 🚫 = Not supported
|
@@ -459,7 +461,7 @@ Requires-Dist: ttkbootstrap-fork-laggykiller ~=1.5.1
|
|
459
461
|
- Upload: Not supported. You need to manually submit sticker pack for approval before you can use in app.
|
460
462
|
- Viber
|
461
463
|
- Download: Supported (e.g. `https://stickers.viber.com/pages/example` OR `https://stickers.viber.com/pages/custom-sticker-packs/example`)
|
462
|
-
- Upload:
|
464
|
+
- Upload: Supported. Viber authentication data required for uploading Viber stickers, which could be fetched from Viber Desktop application automatically.
|
463
465
|
- iMessage
|
464
466
|
- Download: Not supported.
|
465
467
|
- 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=KtHdsdkHNKLnGLbDOZKFG0OukVKP9IeWcQlHYhF_lg0,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=msUUUR-2JdeAO_pQPJBFuA9xVfh1Gwl19WYN_6WLA-Y,13324
|
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
|
@@ -31,7 +31,7 @@ sticker_convert/gui_components/windows/base_window.py,sha256=xBE1peGMPvWsdrFej0C
|
|
31
31
|
sticker_convert/gui_components/windows/kakao_get_auth_window.py,sha256=AvXB2Q8pAPkKILHTvlLGV9jfBcvskCA4arko4nvBTdo,7115
|
32
32
|
sticker_convert/gui_components/windows/line_get_auth_window.py,sha256=S4ES_lk2-GDvPokZtYALnUc5zW1VbS4WulNqO9K1aSs,3375
|
33
33
|
sticker_convert/gui_components/windows/signal_get_auth_window.py,sha256=kbJPe558lLP4PbPT2mCw4Xgh06FX5mBEZXoW-Q1LvWY,4584
|
34
|
-
sticker_convert/gui_components/windows/viber_get_auth_window.py,sha256=
|
34
|
+
sticker_convert/gui_components/windows/viber_get_auth_window.py,sha256=Ne0DG4wog7Pzw-fPsbr7HX40okFFo1INusVCSwSAQdQ,5051
|
35
35
|
sticker_convert/ios-message-stickers-template/.gitignore,sha256=4uuTph_9eHfqXHUavLOmGOji6aIHOif2bUEU_hCBn4Y,9
|
36
36
|
sticker_convert/ios-message-stickers-template/README.md,sha256=oN0FvJkCWWjSZ3PMrCvY3T1zCsdkZYFgGHAoFh0Kmt8,467
|
37
37
|
sticker_convert/ios-message-stickers-template/.github/FUNDING.yml,sha256=3LlmdSAGDsBA2o_C1iBYTNLwkABnyZuN0zxgPPyd-f8,70
|
@@ -72,7 +72,8 @@ sticker_convert/resources/compression.json,sha256=tNBGCmFqZ4Bsik1-xtvkOSlRu1uF6K
|
|
72
72
|
sticker_convert/resources/emoji.json,sha256=sXSuKusyG1L2Stuf9BL5ZqfzOIOdeAeE3RXcrXAsLdY,413367
|
73
73
|
sticker_convert/resources/help.json,sha256=VgRYw5iNQGn_CDA4pTnk5QUO21lsx0JIvWgUV2kHPvY,6906
|
74
74
|
sticker_convert/resources/input.json,sha256=S3CkInBMLrk5OS9aJfuTCDsf_64NOjNT3IKQr7d1hM0,2665
|
75
|
-
sticker_convert/resources/
|
75
|
+
sticker_convert/resources/memdump_linux.sh,sha256=YbdX5C5RyCnoeDUE6JgTo8nQXKhrUw5-kFDx5bQp9tY,651
|
76
|
+
sticker_convert/resources/memdump_windows.ps1,sha256=CfyNSSEW3HJOkTu-mKrP3qh5aprN-1VCBfj-R1fELA0,302
|
76
77
|
sticker_convert/resources/output.json,sha256=V4OseXEm3O16cAjHDVZRq8-SY-0_7cFFR_cyF-0Y_eQ,1570
|
77
78
|
sticker_convert/uploaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
78
79
|
sticker_convert/uploaders/compress_wastickers.py,sha256=SMPf1_ir30ZKO2ChHspDFuyaufx0XeVBVLOlHmawEdY,6021
|
@@ -86,7 +87,7 @@ sticker_convert/utils/url_detect.py,sha256=L2QwE2jwN85MoyYsW_4GvBHuoedrlhoIdAmzw
|
|
86
87
|
sticker_convert/utils/auth/get_kakao_auth.py,sha256=ipAZ1DUd5CMTpUoxRXHVOFC3DKIpxwxpTYAfrOJ6UZ8,9829
|
87
88
|
sticker_convert/utils/auth/get_line_auth.py,sha256=8l8ha2vQmk3rHGvDE7PkcxQXbH3oe62LKbI3qVUtvqc,2196
|
88
89
|
sticker_convert/utils/auth/get_signal_auth.py,sha256=6Sx-lMuyBHeX1RpjAWI8u03qnRu9fmO4p89pd7fowOE,4925
|
89
|
-
sticker_convert/utils/auth/get_viber_auth.py,sha256=
|
90
|
+
sticker_convert/utils/auth/get_viber_auth.py,sha256=UUdnESATVGj-mrDuM_5wq75ouQFqPvFtdyqjGDqxi5Y,13734
|
90
91
|
sticker_convert/utils/files/cache_store.py,sha256=etfe614OAhAyrnM5fGeESKq6R88YLNqkqkxSzEmZ0V0,1047
|
91
92
|
sticker_convert/utils/files/json_manager.py,sha256=Vr6pZJdLMkrJJWN99210aduVHb0ILyf0SSTaw4TZqgc,541
|
92
93
|
sticker_convert/utils/files/json_resources_loader.py,sha256=flZFixUXRTrOAhvRQpuSQgmJ69yXL94sxukcowLT1JQ,1049
|
@@ -97,9 +98,9 @@ sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE
|
|
97
98
|
sticker_convert/utils/media/codec_info.py,sha256=1QfW3wgZ5vOk7T4XtLHYvJK1x8RbASRPSvhKEPkcu9A,15747
|
98
99
|
sticker_convert/utils/media/decrypt_kakao.py,sha256=4wq9ZDRnFkx1WmFZnyEogBofiLGsWQM_X69HlA36578,1947
|
99
100
|
sticker_convert/utils/media/format_verify.py,sha256=MH68GLJfXeL8WFT8emtj355K5BLAtUX64tQ59nugx2c,5673
|
100
|
-
sticker_convert-2.9.
|
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.
|
101
|
+
sticker_convert-2.9.2.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
102
|
+
sticker_convert-2.9.2.dist-info/METADATA,sha256=09ZbSV3QNFOUGbBUrWrWHZ6Qac7awAGPB5RAFpQiCTk,51071
|
103
|
+
sticker_convert-2.9.2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
104
|
+
sticker_convert-2.9.2.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
|
105
|
+
sticker_convert-2.9.2.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
|
106
|
+
sticker_convert-2.9.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|