sticker-convert 2.12.3__py3-none-any.whl → 2.13.0__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/cli.py +3 -0
- sticker_convert/converter.py +61 -54
- sticker_convert/downloaders/download_band.py +110 -0
- sticker_convert/downloaders/download_kakao.py +84 -22
- sticker_convert/gui.py +14 -3
- sticker_convert/gui_components/windows/advanced_compression_window.py +17 -0
- sticker_convert/gui_components/windows/discord_get_auth_window.py +3 -3
- sticker_convert/gui_components/windows/kakao_get_auth_window.py +2 -6
- sticker_convert/gui_components/windows/signal_get_auth_window.py +3 -3
- sticker_convert/gui_components/windows/viber_get_auth_window.py +1 -1
- sticker_convert/job.py +6 -0
- sticker_convert/job_option.py +2 -0
- sticker_convert/resources/compression.json +47 -0
- sticker_convert/resources/help.json +1 -0
- sticker_convert/resources/input.json +10 -0
- sticker_convert/resources/memdump_linux.sh +0 -1
- sticker_convert/utils/auth/get_discord_auth.py +1 -1
- sticker_convert/utils/auth/get_kakao_desktop_auth.py +119 -35
- sticker_convert/utils/auth/get_signal_auth.py +2 -2
- sticker_convert/utils/auth/get_viber_auth.py +1 -1
- sticker_convert/utils/auth/telethon_setup.py +3 -1
- sticker_convert/utils/chrome_remotedebug.py +25 -13
- sticker_convert/utils/media/codec_info.py +1 -1
- sticker_convert/utils/singletons.py +18 -0
- sticker_convert/utils/url_detect.py +3 -0
- sticker_convert/version.py +1 -1
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/METADATA +35 -27
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/RECORD +32 -30
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/WHEEL +1 -1
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {sticker_convert-2.12.3.dist-info → sticker_convert-2.13.0.dist-info}/top_level.txt +0 -0
sticker_convert/cli.py
CHANGED
@@ -139,6 +139,7 @@ class CLI:
|
|
139
139
|
"cache_dir",
|
140
140
|
"scale_filter",
|
141
141
|
"quantize_method",
|
142
|
+
"chromium_path",
|
142
143
|
)
|
143
144
|
flags_comp_bool = ("fake_vid",)
|
144
145
|
keyword_args: Dict[str, Any]
|
@@ -231,6 +232,7 @@ class CLI:
|
|
231
232
|
"telegram": args.download_telegram,
|
232
233
|
"telegram_telethon": args.download_telegram_telethon,
|
233
234
|
"kakao": args.download_kakao,
|
235
|
+
"band": args.download_band,
|
234
236
|
"viber": args.download_viber,
|
235
237
|
"discord": args.download_discord,
|
236
238
|
"discord_emoji": args.download_discord_emoji,
|
@@ -427,6 +429,7 @@ class CLI:
|
|
427
429
|
fake_vid=self.compression_presets[preset]["fake_vid"]
|
428
430
|
if args.fake_vid is None
|
429
431
|
else args.fake_vid,
|
432
|
+
chromium_path=args.chromium_path,
|
430
433
|
cache_dir=args.cache_dir,
|
431
434
|
scale_filter=self.compression_presets[preset]["scale_filter"]
|
432
435
|
if args.scale_filter is None
|
sticker_convert/converter.py
CHANGED
@@ -19,6 +19,7 @@ from sticker_convert.utils.chrome_remotedebug import CRD
|
|
19
19
|
from sticker_convert.utils.files.cache_store import CacheStore
|
20
20
|
from sticker_convert.utils.media.codec_info import CodecInfo, rounding
|
21
21
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
22
|
+
from sticker_convert.utils.singletons import singletons
|
22
23
|
|
23
24
|
if TYPE_CHECKING:
|
24
25
|
from av.video.frame import VideoFrame
|
@@ -435,22 +436,30 @@ class StickerConvert:
|
|
435
436
|
width = self.codec_info_orig.res[0]
|
436
437
|
height = self.codec_info_orig.res[1]
|
437
438
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
439
|
+
if singletons.objs.get("crd") is None:
|
440
|
+
chrome_path: Optional[str]
|
441
|
+
if self.opt_comp.chromium_path:
|
442
|
+
chrome_path = self.opt_comp.chromium_path
|
443
|
+
else:
|
444
|
+
chrome_path = CRD.get_chrome_path()
|
445
|
+
args = [
|
446
|
+
"--headless",
|
447
|
+
"--kiosk",
|
448
|
+
"--disable-extensions",
|
449
|
+
"--disable-infobars",
|
450
|
+
"--disable-gpu",
|
451
|
+
"--disable-gpu-rasterization",
|
452
|
+
"--hide-scrollbars",
|
453
|
+
"--force-device-scale-factor=1",
|
454
|
+
"about:blank",
|
455
|
+
]
|
456
|
+
if chrome_path is None:
|
457
|
+
raise RuntimeError("[F] Chrome/Chromium required for importing svg")
|
458
|
+
self.cb.put("[W] Importing SVG takes long time")
|
459
|
+
singletons.objs["crd"] = CRD(chrome_path, args=args)
|
460
|
+
singletons.objs["crd"].connect(-1) # type: ignore
|
461
|
+
|
462
|
+
crd = cast(CRD, singletons.objs["crd"])
|
454
463
|
if isinstance(self.in_f, bytes):
|
455
464
|
svg = self.in_f.decode()
|
456
465
|
else:
|
@@ -465,39 +474,35 @@ class StickerConvert:
|
|
465
474
|
svg_tag["height"] = height
|
466
475
|
svg = str(soup)
|
467
476
|
|
468
|
-
crd
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
self.frames_raw.append(np.asarray(crd.screenshot(clip).convert("RGBA")))
|
498
|
-
finally:
|
499
|
-
if crd is not None:
|
500
|
-
crd.close()
|
477
|
+
crd.open_html_str(svg)
|
478
|
+
crd.set_transparent_bg()
|
479
|
+
init_js = 'svg = document.getElementsByTagName("svg")[0];'
|
480
|
+
if self.codec_info_orig.fps > 0:
|
481
|
+
init_js += "svg.pauseAnimations();"
|
482
|
+
init_js += "JSON.stringify(svg.getBoundingClientRect());"
|
483
|
+
bound = json.loads(
|
484
|
+
json.loads(crd.exec_js(init_js))["result"]["result"]["value"]
|
485
|
+
)
|
486
|
+
clip = {
|
487
|
+
"x": bound["x"],
|
488
|
+
"y": bound["y"],
|
489
|
+
"width": width,
|
490
|
+
"height": height,
|
491
|
+
"scale": 1,
|
492
|
+
}
|
493
|
+
|
494
|
+
if self.codec_info_orig.fps > 0:
|
495
|
+
for i in range(self.codec_info_orig.frames):
|
496
|
+
curr_time = (
|
497
|
+
i
|
498
|
+
/ self.codec_info_orig.frames
|
499
|
+
* self.codec_info_orig.duration
|
500
|
+
/ 1000
|
501
|
+
)
|
502
|
+
crd.exec_js(f"svg.setCurrentTime({curr_time})")
|
503
|
+
self.frames_raw.append(np.asarray(crd.screenshot(clip)))
|
504
|
+
else:
|
505
|
+
self.frames_raw.append(np.asarray(crd.screenshot(clip)))
|
501
506
|
|
502
507
|
def _frames_import_pillow(self) -> None:
|
503
508
|
with Image.open(self.in_f) as im:
|
@@ -559,7 +564,7 @@ class StickerConvert:
|
|
559
564
|
container = cast(InputContainer, container)
|
560
565
|
context = container.streams.video[0].codec_context
|
561
566
|
if context.name == "vp8":
|
562
|
-
context =
|
567
|
+
context = CodecContext.create("libvpx", "r")
|
563
568
|
elif context.name == "vp9":
|
564
569
|
context = cast(
|
565
570
|
VideoCodecContext, CodecContext.create("libvpx-vp9", "r")
|
@@ -592,7 +597,12 @@ class StickerConvert:
|
|
592
597
|
else:
|
593
598
|
frame_resized = frame
|
594
599
|
|
595
|
-
|
600
|
+
# yuva420p may cause crash for pyav < 14
|
601
|
+
# Not safe to directly call frame.to_ndarray(format="rgba")
|
602
|
+
# https://github.com/PyAV-Org/PyAV/discussions/1510
|
603
|
+
if int(av.__version__.split(".")[0]) >= 14:
|
604
|
+
rgba_array = frame_resized.to_ndarray(format="rgba")
|
605
|
+
elif frame_resized.format.name == "yuv420p":
|
596
606
|
rgb_array = frame_resized.to_ndarray(format="rgb24")
|
597
607
|
rgba_array = np.dstack(
|
598
608
|
(
|
@@ -604,9 +614,6 @@ class StickerConvert:
|
|
604
614
|
)
|
605
615
|
)
|
606
616
|
else:
|
607
|
-
# yuva420p may cause crash
|
608
|
-
# Not safe to directly call frame.to_ndarray(format="rgba")
|
609
|
-
# https://github.com/laggykiller/sticker-convert/issues/114
|
610
617
|
frame_resized = frame_resized.reformat(
|
611
618
|
format="yuva420p",
|
612
619
|
dst_colorspace=1,
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import json
|
5
|
+
import zipfile
|
6
|
+
from io import BytesIO
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import Any, Dict, Optional, Tuple
|
9
|
+
from urllib.parse import urlparse
|
10
|
+
|
11
|
+
import requests
|
12
|
+
|
13
|
+
from sticker_convert.downloaders.download_base import DownloadBase
|
14
|
+
from sticker_convert.job_option import CredOption, InputOption
|
15
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
16
|
+
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
17
|
+
|
18
|
+
|
19
|
+
class DownloadBand(DownloadBase):
|
20
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
21
|
+
super().__init__(*args, **kwargs)
|
22
|
+
|
23
|
+
def decompress(self, zip_file: bytes) -> int:
|
24
|
+
with zipfile.ZipFile(BytesIO(zip_file)) as zf:
|
25
|
+
self.cb.put("Unzipping...")
|
26
|
+
|
27
|
+
zf_files = zf.namelist()
|
28
|
+
animated = [i for i in zf_files if "animation/" in i]
|
29
|
+
if len(animated) > 0:
|
30
|
+
pack_files = animated
|
31
|
+
else:
|
32
|
+
pack_files = [
|
33
|
+
i
|
34
|
+
for i in zf_files
|
35
|
+
if i.endswith(".meta") is False and "_key" not in i
|
36
|
+
]
|
37
|
+
|
38
|
+
self.cb.put(
|
39
|
+
(
|
40
|
+
"bar",
|
41
|
+
None,
|
42
|
+
{"set_progress_mode": "determinate", "steps": len(pack_files)},
|
43
|
+
)
|
44
|
+
)
|
45
|
+
|
46
|
+
for num, sticker in enumerate(pack_files):
|
47
|
+
data = zf.read(sticker)
|
48
|
+
self.cb.put(f"Read {sticker}")
|
49
|
+
ext = sticker.split(".")[-1]
|
50
|
+
|
51
|
+
out_path = Path(self.out_dir, str(num).zfill(3) + f".{ext}")
|
52
|
+
with open(out_path, "wb") as f:
|
53
|
+
f.write(data)
|
54
|
+
|
55
|
+
self.cb.put("update_bar")
|
56
|
+
|
57
|
+
return len(pack_files)
|
58
|
+
|
59
|
+
def get_metadata(self, pack_no: str) -> Optional[Dict[Any, Any]]:
|
60
|
+
r = requests.get(
|
61
|
+
f"https://sapi.band.us/v1.0.0/get_sticker_info?pack_no={pack_no}"
|
62
|
+
)
|
63
|
+
if r.text:
|
64
|
+
return json.loads(r.text)
|
65
|
+
else:
|
66
|
+
return None
|
67
|
+
|
68
|
+
def download_stickers_band(self) -> Tuple[int, int]:
|
69
|
+
if urlparse(self.url).netloc != "www.band.us" and self.url.isnumeric() is False:
|
70
|
+
self.cb.put("Download failed: Unsupported URL format")
|
71
|
+
return 0, 0
|
72
|
+
|
73
|
+
if self.url.isnumeric():
|
74
|
+
pack_no = self.url
|
75
|
+
else:
|
76
|
+
pack_no = urlparse(self.url).path.split("/")[-1]
|
77
|
+
metadata = self.get_metadata(pack_no)
|
78
|
+
if metadata:
|
79
|
+
self.title = metadata["result_data"]["sticker"]["name"]
|
80
|
+
else:
|
81
|
+
self.cb.put("Download failed: Failed to get metadata")
|
82
|
+
return 0, 0
|
83
|
+
|
84
|
+
MetadataHandler.set_metadata(self.out_dir, title=self.title)
|
85
|
+
|
86
|
+
pack_url = f"http://s.cmstatic.net/band/sticker/v2/{pack_no}/shop/pack"
|
87
|
+
zip_file = self.download_file(pack_url)
|
88
|
+
|
89
|
+
if zip_file:
|
90
|
+
self.cb.put(f"Downloaded {pack_url}")
|
91
|
+
else:
|
92
|
+
self.cb.put(f"Cannot download {pack_url}")
|
93
|
+
return 0, 0
|
94
|
+
|
95
|
+
pack_files_no = self.decompress(zip_file)
|
96
|
+
|
97
|
+
cover_url = f"http://s.cmstatic.net/band/sticker/v2/{pack_no}/shop/main"
|
98
|
+
self.download_file(cover_url, self.out_dir / "cover.png")
|
99
|
+
|
100
|
+
return pack_files_no, pack_files_no
|
101
|
+
|
102
|
+
@staticmethod
|
103
|
+
def start(
|
104
|
+
opt_input: InputOption,
|
105
|
+
opt_cred: Optional[CredOption],
|
106
|
+
cb: CallbackProtocol,
|
107
|
+
cb_return: CallbackReturn,
|
108
|
+
) -> Tuple[int, int]:
|
109
|
+
downloader = DownloadBand(opt_input, opt_cred, cb, cb_return)
|
110
|
+
return downloader.download_stickers_band()
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
4
4
|
import itertools
|
5
5
|
import json
|
6
6
|
from pathlib import Path
|
7
|
-
from typing import Any, List, Optional, Tuple
|
7
|
+
from typing import Any, Dict, List, Optional, Tuple
|
8
8
|
from urllib.parse import urlparse
|
9
9
|
|
10
10
|
import requests
|
@@ -17,6 +17,13 @@ from sticker_convert.utils.media.decrypt_kakao import DecryptKakao
|
|
17
17
|
|
18
18
|
|
19
19
|
class MetadataKakao:
|
20
|
+
@staticmethod
|
21
|
+
def share_link_to_public_link(share_link: str) -> str:
|
22
|
+
# Share link redirect to preview link if use desktop headers
|
23
|
+
headers_desktop = {"User-Agent": "Chrome"}
|
24
|
+
r = requests.get(share_link, headers=headers_desktop, allow_redirects=True)
|
25
|
+
return r.url
|
26
|
+
|
20
27
|
@staticmethod
|
21
28
|
def get_item_code_from_hash(hash: str, auth_token: str) -> Optional[str]:
|
22
29
|
headers = {
|
@@ -40,12 +47,14 @@ class MetadataKakao:
|
|
40
47
|
return item_code
|
41
48
|
|
42
49
|
@staticmethod
|
43
|
-
def
|
50
|
+
def get_item_code_from_search(
|
51
|
+
pack_title: str, search_term: str, by_author: bool, auth_token: str
|
52
|
+
) -> str:
|
44
53
|
headers = {
|
45
54
|
"Authorization": auth_token,
|
46
55
|
}
|
47
56
|
|
48
|
-
data = {"query":
|
57
|
+
data = {"query": search_term}
|
49
58
|
|
50
59
|
response = requests.post(
|
51
60
|
"https://talk-pilsner.kakao.com/emoticon/item_store/instant_search",
|
@@ -54,12 +63,53 @@ class MetadataKakao:
|
|
54
63
|
)
|
55
64
|
|
56
65
|
if response.status_code != 200:
|
57
|
-
return
|
66
|
+
return "auth_error"
|
67
|
+
|
68
|
+
def check_pack_match(pack_info: Dict[str, Any]) -> bool:
|
69
|
+
share_link = pack_info["itemMetaInfo"]["shareData"]["linkUrl"]
|
70
|
+
public_url = MetadataKakao.share_link_to_public_link(share_link)
|
71
|
+
if pack_title == urlparse(public_url).path.split("/")[-1]:
|
72
|
+
return True
|
73
|
+
return False
|
58
74
|
|
59
75
|
response_json = json.loads(response.text)
|
60
|
-
|
76
|
+
for emoticon in response_json["emoticons"]:
|
77
|
+
item_code = emoticon["item_code"]
|
78
|
+
pack_info = MetadataKakao.get_pack_info_authed(item_code, auth_token)
|
79
|
+
if pack_info is None:
|
80
|
+
continue
|
81
|
+
if check_pack_match(pack_info):
|
82
|
+
return item_code
|
83
|
+
if by_author:
|
84
|
+
cid = pack_info["itemMetaInfo"]["itemMetaData"]["cid"]
|
85
|
+
for item_code in MetadataKakao.get_items_by_creator(cid, auth_token):
|
86
|
+
pack_info = MetadataKakao.get_pack_info_authed(
|
87
|
+
item_code, auth_token
|
88
|
+
)
|
89
|
+
if pack_info is None:
|
90
|
+
continue
|
91
|
+
if check_pack_match(pack_info):
|
92
|
+
return item_code
|
61
93
|
|
62
|
-
return
|
94
|
+
return "code_not_found"
|
95
|
+
|
96
|
+
@staticmethod
|
97
|
+
def get_items_by_creator(cid: str, auth_token: str) -> List[str]:
|
98
|
+
headers = {"Authorization": auth_token}
|
99
|
+
|
100
|
+
params = {
|
101
|
+
"itemSort": "NEW",
|
102
|
+
"offset": "0",
|
103
|
+
"size": "30",
|
104
|
+
}
|
105
|
+
|
106
|
+
response = requests.get(
|
107
|
+
f"https://talk-pilsner.kakao.com/emoticon/api/store/v3/creators/{cid}",
|
108
|
+
headers=headers,
|
109
|
+
params=params,
|
110
|
+
)
|
111
|
+
|
112
|
+
return [i["item_id"] for i in json.loads(response.text)["items"]]
|
63
113
|
|
64
114
|
@staticmethod
|
65
115
|
def get_pack_info_unauthed(
|
@@ -119,13 +169,8 @@ class DownloadKakao(DownloadBase):
|
|
119
169
|
hash = urlparse(self.url).path.split("/")[-1]
|
120
170
|
item_code = MetadataKakao.get_item_code_from_hash(hash, self.auth_token)
|
121
171
|
|
122
|
-
|
123
|
-
|
124
|
-
headers_desktop = {"User-Agent": "Chrome"}
|
125
|
-
|
126
|
-
r = requests.get(self.url, headers=headers_desktop, allow_redirects=True)
|
127
|
-
|
128
|
-
self.pack_title = urlparse(r.url).path.split("/")[-1]
|
172
|
+
public_url = MetadataKakao.share_link_to_public_link(self.url)
|
173
|
+
self.pack_title = urlparse(public_url).path.split("/")[-1]
|
129
174
|
pack_info_unauthed = MetadataKakao.get_pack_info_unauthed(self.pack_title)
|
130
175
|
if pack_info_unauthed is None:
|
131
176
|
self.cb.put(
|
@@ -184,14 +229,33 @@ class DownloadKakao(DownloadBase):
|
|
184
229
|
thumbnail_urls = self.pack_info_unauthed["result"]["thumbnailUrls"]
|
185
230
|
|
186
231
|
if self.auth_token:
|
187
|
-
item_code = MetadataKakao.
|
188
|
-
title_ko, self.auth_token
|
232
|
+
item_code = MetadataKakao.get_item_code_from_search(
|
233
|
+
self.pack_title, title_ko, False, self.auth_token
|
189
234
|
)
|
190
|
-
if item_code:
|
235
|
+
if item_code == "auth_error":
|
236
|
+
msg = "Warning: Cannot get item code.\n"
|
237
|
+
msg += "Is auth_token invalid / expired? Try to regenerate it.\n"
|
238
|
+
msg += "Continue to download static stickers instead?"
|
239
|
+
elif item_code == "code_not_found":
|
240
|
+
self.cb.put(
|
241
|
+
"Cannot get item code, trying to search by author name, this may take long time..."
|
242
|
+
)
|
243
|
+
self.cb.put(
|
244
|
+
"Hint: Use share link instead to download more reliably"
|
245
|
+
)
|
246
|
+
if self.author is not None:
|
247
|
+
item_code = MetadataKakao.get_item_code_from_search(
|
248
|
+
self.pack_title, self.author, True, self.auth_token
|
249
|
+
)
|
250
|
+
if item_code == "code_not_found":
|
251
|
+
msg = "Warning: Cannot get item code.\n"
|
252
|
+
msg += "Please use share link instead.\n"
|
253
|
+
msg += "Continue to download static stickers instead?"
|
254
|
+
else:
|
255
|
+
return self.download_animated(item_code)
|
256
|
+
else:
|
191
257
|
return self.download_animated(item_code)
|
192
|
-
|
193
|
-
msg += "Is auth_token invalid / expired? Try to regenerate it.\n"
|
194
|
-
msg += "Continue to download static stickers instead?"
|
258
|
+
|
195
259
|
self.cb.put(("ask_bool", (msg,), None))
|
196
260
|
if self.cb_return:
|
197
261
|
response = self.cb_return.get_response()
|
@@ -249,9 +313,7 @@ class DownloadKakao(DownloadBase):
|
|
249
313
|
if not self.pack_info_unauthed:
|
250
314
|
public_url = None
|
251
315
|
if urlparse(self.url).netloc == "emoticon.kakao.com":
|
252
|
-
|
253
|
-
# Share url would redirect to public url without headers
|
254
|
-
public_url = r.url
|
316
|
+
public_url = MetadataKakao.share_link_to_public_link(self.url)
|
255
317
|
elif urlparse(self.url).netloc == "e.kakao.com":
|
256
318
|
public_url = self.url
|
257
319
|
if public_url:
|
sticker_convert/gui.py
CHANGED
@@ -137,6 +137,7 @@ class GUI(Window):
|
|
137
137
|
self.fake_vid_var = BooleanVar()
|
138
138
|
self.scale_filter_var = StringVar(self)
|
139
139
|
self.quantize_method_var = StringVar(self)
|
140
|
+
self.chromium_path_var = StringVar(self)
|
140
141
|
self.cache_dir_var = StringVar(self)
|
141
142
|
self.default_emoji_var = StringVar(self)
|
142
143
|
self.steps_var = IntVar(self)
|
@@ -321,6 +322,7 @@ class GUI(Window):
|
|
321
322
|
"comp": {
|
322
323
|
"no_compress": self.no_compress_var.get(),
|
323
324
|
"preset": self.comp_preset_var.get(),
|
325
|
+
"chromium_path": self.chromium_path_var.get(),
|
324
326
|
"cache_dir": self.cache_dir_var.get(),
|
325
327
|
"processes": self.processes_var.get(),
|
326
328
|
},
|
@@ -377,6 +379,9 @@ class GUI(Window):
|
|
377
379
|
self.compression_presets["custom"], comp_custom
|
378
380
|
)
|
379
381
|
self.cache_dir_var.set(self.settings.get("comp", {}).get("cache_dir", ""))
|
382
|
+
self.chromium_path_var.set(
|
383
|
+
self.settings.get("comp", {}).get("chromium_path", "")
|
384
|
+
)
|
380
385
|
self.processes_var.set(
|
381
386
|
self.settings.get("comp", {}).get("processes", ceil(cpu_count() / 2))
|
382
387
|
)
|
@@ -568,6 +573,9 @@ class GUI(Window):
|
|
568
573
|
fake_vid=self.fake_vid_var.get(),
|
569
574
|
scale_filter=self.scale_filter_var.get(),
|
570
575
|
quantize_method=self.quantize_method_var.get(),
|
576
|
+
chromium_path=self.chromium_path_var.get()
|
577
|
+
if self.chromium_path_var.get() != ""
|
578
|
+
else None,
|
571
579
|
cache_dir=self.cache_dir_var.get()
|
572
580
|
if self.cache_dir_var.get() != ""
|
573
581
|
else None,
|
@@ -706,9 +714,9 @@ class GUI(Window):
|
|
706
714
|
set_progress_mode, steps, update_bar, *args, **kwargs
|
707
715
|
)
|
708
716
|
|
709
|
-
def highlight_fields(self):
|
717
|
+
def highlight_fields(self) -> bool:
|
710
718
|
if not self.init_done:
|
711
|
-
return
|
719
|
+
return True
|
712
720
|
|
713
721
|
input_option = self.get_input_name()
|
714
722
|
input_option_display = self.get_input_display_name()
|
@@ -754,7 +762,8 @@ class GUI(Window):
|
|
754
762
|
download_option is None
|
755
763
|
or input_option.startswith(download_option) is False
|
756
764
|
and not (
|
757
|
-
input_option
|
765
|
+
input_option
|
766
|
+
in ("kakao", "band", "line", "discord", "discord_emoji")
|
758
767
|
and url.isnumeric()
|
759
768
|
)
|
760
769
|
):
|
@@ -858,3 +867,5 @@ class GUI(Window):
|
|
858
867
|
else:
|
859
868
|
self.comp_frame.comp_preset_opt.config(bootstyle="secondary") # type: ignore
|
860
869
|
self.output_frame.output_option_opt.config(bootstyle="secondary") # type: ignore
|
870
|
+
|
871
|
+
return True
|
@@ -293,6 +293,17 @@ class AdvancedCompressionWindow(BaseWindow):
|
|
293
293
|
bootstyle="secondary", # type: ignore
|
294
294
|
)
|
295
295
|
|
296
|
+
self.chromium_path_help_btn = self.add_help_btn(
|
297
|
+
self.gui.help["comp"]["chromium_path"]
|
298
|
+
)
|
299
|
+
self.chromium_path_lbl = Label(
|
300
|
+
self.frame_advcomp, text="Chromium/Chrome directory"
|
301
|
+
)
|
302
|
+
self.chromium_path_entry = Entry(
|
303
|
+
self.frame_advcomp, textvariable=self.gui.chromium_path_var, width=30
|
304
|
+
)
|
305
|
+
self.chromium_path_entry.bind("<Button-3><ButtonRelease-3>", RightClicker)
|
306
|
+
|
296
307
|
self.cache_dir_help_btn = self.add_help_btn(self.gui.help["comp"]["cache_dir"])
|
297
308
|
self.cache_dir_lbl = Label(self.frame_advcomp, text="Custom cache directory")
|
298
309
|
self.cache_dir_entry = Entry(
|
@@ -412,6 +423,12 @@ class AdvancedCompressionWindow(BaseWindow):
|
|
412
423
|
column=2, row=r, columnspan=4, sticky="nes", padx=3, pady=3
|
413
424
|
)
|
414
425
|
r += 1
|
426
|
+
self.chromium_path_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
|
427
|
+
self.chromium_path_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
|
428
|
+
self.chromium_path_entry.grid(
|
429
|
+
column=2, row=r, columnspan=4, sticky="nes", padx=3, pady=3
|
430
|
+
)
|
431
|
+
r += 1
|
415
432
|
self.cache_dir_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
|
416
433
|
self.cache_dir_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
|
417
434
|
self.cache_dir_entry.grid(
|
@@ -11,7 +11,7 @@ from sticker_convert.utils.auth.get_discord_auth import GetDiscordAuth
|
|
11
11
|
|
12
12
|
|
13
13
|
class DiscordGetAuthWindow(BaseWindow):
|
14
|
-
def __init__(self, *args: Any, **kwargs: Any):
|
14
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
15
15
|
super(DiscordGetAuthWindow, self).__init__(*args, **kwargs)
|
16
16
|
|
17
17
|
self.title("Get Discord token")
|
@@ -64,10 +64,10 @@ class DiscordGetAuthWindow(BaseWindow):
|
|
64
64
|
|
65
65
|
GUIUtils.finalize_window(self)
|
66
66
|
|
67
|
-
def cb_login(self):
|
67
|
+
def cb_login(self) -> None:
|
68
68
|
Thread(target=self.cb_login_thread, daemon=True).start()
|
69
69
|
|
70
|
-
def cb_login_thread(self, *args: Any):
|
70
|
+
def cb_login_thread(self, *args: Any) -> None:
|
71
71
|
m = GetDiscordAuth(cb_msg=self.gui.cb_msg)
|
72
72
|
discord_token, msg = m.get_cred()
|
73
73
|
if discord_token:
|
@@ -1,6 +1,4 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
|
-
import platform
|
3
|
-
import subprocess
|
4
2
|
from functools import partial
|
5
3
|
from threading import Thread
|
6
4
|
from typing import Any, Optional
|
@@ -37,7 +35,7 @@ class KakaoGetAuthWindow(BaseWindow):
|
|
37
35
|
# Method 1 frame
|
38
36
|
self.explanation1_1_lbl = Label(
|
39
37
|
self.frame_from_desktop,
|
40
|
-
text="This will get Kakao auth_token from Kakao Desktop
|
38
|
+
text="This will get Kakao auth_token from Kakao Desktop",
|
41
39
|
justify="left",
|
42
40
|
anchor="w",
|
43
41
|
)
|
@@ -70,14 +68,12 @@ class KakaoGetAuthWindow(BaseWindow):
|
|
70
68
|
command=self.cb_launch_desktop,
|
71
69
|
width=24,
|
72
70
|
bootstyle="secondary", # type: ignore
|
73
|
-
state="normal" if platform.system() == "Windows" else "disabled",
|
74
71
|
)
|
75
72
|
self.get_auth_desktop_btn = Button(
|
76
73
|
self.frame_from_desktop,
|
77
74
|
text="Get auth_token",
|
78
75
|
command=self.cb_from_desktop,
|
79
76
|
width=24,
|
80
|
-
state="normal" if platform.system() == "Windows" else "disabled",
|
81
77
|
)
|
82
78
|
|
83
79
|
self.explanation1_1_lbl.grid(
|
@@ -270,7 +266,7 @@ class KakaoGetAuthWindow(BaseWindow):
|
|
270
266
|
bin_path = m.get_kakao_desktop()
|
271
267
|
|
272
268
|
if bin_path is not None:
|
273
|
-
|
269
|
+
m.launch_kakao(bin_path)
|
274
270
|
else:
|
275
271
|
self.cb_msg_block_kakao(
|
276
272
|
"Error: Cannot launch Kakao Desktop. Is it installed?"
|
@@ -11,7 +11,7 @@ from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
|
|
11
11
|
|
12
12
|
|
13
13
|
class SignalGetAuthWindow(BaseWindow):
|
14
|
-
def __init__(self, *args: Any, **kwargs: Any):
|
14
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
15
15
|
super(SignalGetAuthWindow, self).__init__(*args, **kwargs)
|
16
16
|
|
17
17
|
self.title("Get Signal uuid and password")
|
@@ -64,10 +64,10 @@ class SignalGetAuthWindow(BaseWindow):
|
|
64
64
|
|
65
65
|
GUIUtils.finalize_window(self)
|
66
66
|
|
67
|
-
def cb_login(self):
|
67
|
+
def cb_login(self) -> None:
|
68
68
|
Thread(target=self.cb_login_thread, daemon=True).start()
|
69
69
|
|
70
|
-
def cb_login_thread(self, *args: Any):
|
70
|
+
def cb_login_thread(self, *args: Any) -> None:
|
71
71
|
m = GetSignalAuth(cb_msg=self.gui.cb_msg, cb_ask_str=self.cb_ask_str_signal)
|
72
72
|
|
73
73
|
uuid, password = m.get_cred()
|
@@ -109,7 +109,7 @@ class ViberGetAuthWindow(BaseWindow):
|
|
109
109
|
|
110
110
|
GUIUtils.finalize_window(self)
|
111
111
|
|
112
|
-
def cb_get_cred(self):
|
112
|
+
def cb_get_cred(self) -> None:
|
113
113
|
Thread(target=self.cb_get_cred_thread, daemon=True).start()
|
114
114
|
|
115
115
|
def cb_get_cred_thread(self) -> None:
|