sticker-convert 2.7.2__py3-none-any.whl → 2.7.4__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/__init__.py +1 -0
- sticker_convert/__main__.py +3 -1
- sticker_convert/cli.py +20 -24
- sticker_convert/converter.py +108 -119
- sticker_convert/definitions.py +8 -12
- sticker_convert/downloaders/download_base.py +14 -31
- sticker_convert/downloaders/download_kakao.py +25 -39
- sticker_convert/downloaders/download_line.py +24 -33
- sticker_convert/downloaders/download_signal.py +7 -16
- sticker_convert/downloaders/download_telegram.py +6 -15
- sticker_convert/gui.py +53 -61
- sticker_convert/gui_components/frames/comp_frame.py +11 -20
- sticker_convert/gui_components/frames/config_frame.py +9 -9
- sticker_convert/gui_components/frames/control_frame.py +3 -3
- sticker_convert/gui_components/frames/cred_frame.py +12 -18
- sticker_convert/gui_components/frames/input_frame.py +9 -15
- sticker_convert/gui_components/frames/output_frame.py +9 -15
- sticker_convert/gui_components/frames/progress_frame.py +8 -8
- sticker_convert/gui_components/frames/right_clicker.py +2 -2
- sticker_convert/gui_components/gui_utils.py +6 -8
- sticker_convert/gui_components/windows/advanced_compression_window.py +23 -32
- sticker_convert/gui_components/windows/base_window.py +6 -6
- sticker_convert/gui_components/windows/kakao_get_auth_window.py +5 -11
- sticker_convert/gui_components/windows/line_get_auth_window.py +5 -5
- sticker_convert/gui_components/windows/signal_get_auth_window.py +6 -6
- sticker_convert/job.py +84 -90
- sticker_convert/job_option.py +36 -32
- sticker_convert/resources/emoji.json +334 -70
- sticker_convert/resources/help.json +1 -1
- sticker_convert/uploaders/compress_wastickers.py +19 -30
- sticker_convert/uploaders/upload_base.py +19 -13
- sticker_convert/uploaders/upload_signal.py +20 -33
- sticker_convert/uploaders/upload_telegram.py +21 -28
- sticker_convert/uploaders/xcode_imessage.py +30 -95
- sticker_convert/utils/auth/get_kakao_auth.py +7 -8
- sticker_convert/utils/auth/get_line_auth.py +5 -6
- sticker_convert/utils/auth/get_signal_auth.py +7 -7
- sticker_convert/utils/callback.py +31 -23
- sticker_convert/utils/files/cache_store.py +6 -8
- sticker_convert/utils/files/json_manager.py +6 -7
- sticker_convert/utils/files/json_resources_loader.py +12 -0
- sticker_convert/utils/files/metadata_handler.py +93 -84
- sticker_convert/utils/files/run_bin.py +11 -10
- sticker_convert/utils/files/sanitize_filename.py +30 -28
- sticker_convert/utils/media/apple_png_normalize.py +3 -2
- sticker_convert/utils/media/codec_info.py +41 -44
- sticker_convert/utils/media/decrypt_kakao.py +7 -7
- sticker_convert/utils/media/format_verify.py +14 -14
- sticker_convert/utils/url_detect.py +4 -5
- sticker_convert/version.py +2 -1
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/METADATA +19 -17
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/RECORD +56 -55
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/WHEEL +1 -1
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/LICENSE +0 -0
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
from queue import Queue
|
3
|
-
from typing import
|
3
|
+
from typing import Union
|
4
4
|
|
5
5
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
6
|
-
from sticker_convert.utils.callback import Callback, CallbackReturn
|
6
|
+
from sticker_convert.utils.callback import Callback, CallbackReturn, CbQueueItemType
|
7
7
|
|
8
8
|
|
9
9
|
class UploadBase:
|
@@ -12,18 +12,9 @@ class UploadBase:
|
|
12
12
|
opt_output: OutputOption,
|
13
13
|
opt_comp: CompOption,
|
14
14
|
opt_cred: CredOption,
|
15
|
-
cb: Union[
|
16
|
-
Queue[
|
17
|
-
Union[
|
18
|
-
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
|
19
|
-
str,
|
20
|
-
None,
|
21
|
-
]
|
22
|
-
],
|
23
|
-
Callback,
|
24
|
-
],
|
15
|
+
cb: "Union[Queue[CbQueueItemType], Callback]",
|
25
16
|
cb_return: CallbackReturn,
|
26
|
-
):
|
17
|
+
) -> None:
|
27
18
|
if not cb:
|
28
19
|
cb = Callback(silent=True)
|
29
20
|
cb_return = CallbackReturn()
|
@@ -33,3 +24,18 @@ class UploadBase:
|
|
33
24
|
self.opt_cred = opt_cred
|
34
25
|
self.cb = cb
|
35
26
|
self.cb_return = cb_return
|
27
|
+
|
28
|
+
self.base_spec = CompOption(
|
29
|
+
fps_power=self.opt_comp.fps_power,
|
30
|
+
res_power=self.opt_comp.res_power,
|
31
|
+
quality_min=self.opt_comp.quality_min,
|
32
|
+
quality_max=self.opt_comp.quality_max,
|
33
|
+
quality_power=self.opt_comp.quality_power,
|
34
|
+
color_min=self.opt_comp.color_min,
|
35
|
+
color_max=self.opt_comp.color_max,
|
36
|
+
color_power=self.opt_comp.color_power,
|
37
|
+
quantize_method=self.opt_comp.quantize_method,
|
38
|
+
scale_filter=self.opt_comp.scale_filter,
|
39
|
+
steps=self.opt_comp.steps,
|
40
|
+
cache_dir=self.opt_comp.cache_dir,
|
41
|
+
)
|
@@ -2,47 +2,43 @@
|
|
2
2
|
import copy
|
3
3
|
from pathlib import Path
|
4
4
|
from queue import Queue
|
5
|
-
from typing import Any,
|
5
|
+
from typing import Any, Dict, List, Union
|
6
6
|
|
7
7
|
import anyio
|
8
8
|
from signalstickers_client import StickersClient # type: ignore
|
9
9
|
from signalstickers_client.errors import SignalException # type: ignore
|
10
|
-
from signalstickers_client.models import
|
11
|
-
LocalStickerPack,
|
12
|
-
Sticker,
|
13
|
-
)
|
10
|
+
from signalstickers_client.models import LocalStickerPack, Sticker # type: ignore
|
14
11
|
|
15
12
|
from sticker_convert.converter import StickerConvert
|
16
13
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
17
14
|
from sticker_convert.uploaders.upload_base import UploadBase
|
18
|
-
from sticker_convert.utils.callback import Callback, CallbackReturn
|
15
|
+
from sticker_convert.utils.callback import Callback, CallbackReturn, CbQueueItemType
|
19
16
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
20
17
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
21
18
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
22
19
|
|
23
20
|
|
24
21
|
class UploadSignal(UploadBase):
|
25
|
-
def __init__(self, *args: Any, **kwargs: Any):
|
26
|
-
super(
|
22
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
23
|
+
super().__init__(*args, **kwargs)
|
27
24
|
|
28
|
-
base_spec
|
29
|
-
base_spec.
|
30
|
-
base_spec.
|
31
|
-
base_spec.
|
32
|
-
base_spec.square = True
|
25
|
+
self.base_spec.set_size_max(300000)
|
26
|
+
self.base_spec.set_res_max(512)
|
27
|
+
self.base_spec.duration_max = 3000
|
28
|
+
self.base_spec.square = True
|
33
29
|
|
34
|
-
self.png_spec = copy.deepcopy(base_spec)
|
30
|
+
self.png_spec = copy.deepcopy(self.base_spec)
|
35
31
|
self.png_spec.set_format((".apng",))
|
36
32
|
|
37
|
-
self.webp_spec = copy.deepcopy(base_spec)
|
33
|
+
self.webp_spec = copy.deepcopy(self.base_spec)
|
38
34
|
self.webp_spec.format_img = (".webp",)
|
39
35
|
self.webp_spec.animated = False
|
40
36
|
|
41
37
|
self.opt_comp_merged = copy.deepcopy(self.opt_comp)
|
42
|
-
self.opt_comp_merged.merge(base_spec)
|
38
|
+
self.opt_comp_merged.merge(self.base_spec)
|
43
39
|
|
44
40
|
@staticmethod
|
45
|
-
async def upload_pack(pack: LocalStickerPack, uuid: str, password: str):
|
41
|
+
async def upload_pack(pack: LocalStickerPack, uuid: str, password: str) -> str:
|
46
42
|
async with StickersClient(uuid, password) as client:
|
47
43
|
pack_id, pack_key = await client.upload_pack(pack) # type: ignore
|
48
44
|
|
@@ -52,8 +48,8 @@ class UploadSignal(UploadBase):
|
|
52
48
|
return result
|
53
49
|
|
54
50
|
def add_stickers_to_pack(
|
55
|
-
self, pack: LocalStickerPack, stickers:
|
56
|
-
):
|
51
|
+
self, pack: LocalStickerPack, stickers: List[Path], emoji_dict: Dict[str, str]
|
52
|
+
) -> None:
|
57
53
|
for src in stickers:
|
58
54
|
self.cb.put(f"Verifying {src} for uploading to signal")
|
59
55
|
|
@@ -96,8 +92,8 @@ class UploadSignal(UploadBase):
|
|
96
92
|
|
97
93
|
pack._addsticker(sticker) # type: ignore
|
98
94
|
|
99
|
-
def upload_stickers_signal(self) ->
|
100
|
-
urls:
|
95
|
+
def upload_stickers_signal(self) -> List[str]:
|
96
|
+
urls: List[str] = []
|
101
97
|
|
102
98
|
if not self.opt_cred.signal_uuid:
|
103
99
|
self.cb.put("uuid required for uploading to Signal")
|
@@ -121,7 +117,7 @@ class UploadSignal(UploadBase):
|
|
121
117
|
msg_block += f"Default emoji is set to {self.opt_comp.default_emoji}.\n"
|
122
118
|
msg_block += "Please edit emoji.txt now, then continue"
|
123
119
|
MetadataHandler.generate_emoji_file(
|
124
|
-
|
120
|
+
directory=self.opt_output.dir, default_emoji=self.opt_comp.default_emoji
|
125
121
|
)
|
126
122
|
|
127
123
|
self.cb.put(("msg_block", (msg_block,), None))
|
@@ -171,17 +167,8 @@ class UploadSignal(UploadBase):
|
|
171
167
|
opt_output: OutputOption,
|
172
168
|
opt_comp: CompOption,
|
173
169
|
opt_cred: CredOption,
|
174
|
-
cb: Union[
|
175
|
-
Queue[
|
176
|
-
Union[
|
177
|
-
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
|
178
|
-
str,
|
179
|
-
None,
|
180
|
-
]
|
181
|
-
],
|
182
|
-
Callback,
|
183
|
-
],
|
170
|
+
cb: "Union[Queue[CbQueueItemType], Callback]",
|
184
171
|
cb_return: CallbackReturn,
|
185
|
-
) ->
|
172
|
+
) -> List[str]:
|
186
173
|
exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb, cb_return)
|
187
174
|
return exporter.upload_stickers_signal()
|
@@ -3,7 +3,7 @@ import copy
|
|
3
3
|
import re
|
4
4
|
from pathlib import Path
|
5
5
|
from queue import Queue
|
6
|
-
from typing import Any,
|
6
|
+
from typing import Any, Dict, List, Union, cast
|
7
7
|
|
8
8
|
import anyio
|
9
9
|
from telegram import Bot, InputSticker, Sticker
|
@@ -12,38 +12,39 @@ from telegram.error import TelegramError
|
|
12
12
|
from sticker_convert.converter import StickerConvert
|
13
13
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
14
14
|
from sticker_convert.uploaders.upload_base import UploadBase
|
15
|
-
from sticker_convert.utils.callback import Callback, CallbackReturn
|
15
|
+
from sticker_convert.utils.callback import Callback, CallbackReturn, CbQueueItemType
|
16
16
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
17
17
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
18
18
|
|
19
19
|
|
20
20
|
class UploadTelegram(UploadBase):
|
21
|
-
def __init__(self, *args: Any, **kwargs: Any):
|
22
|
-
super(
|
21
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
22
|
+
super().__init__(*args, **kwargs)
|
23
23
|
|
24
|
-
base_spec =
|
25
|
-
|
26
|
-
|
27
|
-
base_spec.
|
24
|
+
self.base_spec.size_max_img = 512000
|
25
|
+
self.base_spec.size_max_vid = 256000
|
26
|
+
self.base_spec.square = True
|
27
|
+
self.base_spec.duration_max = 3000
|
28
|
+
self.base_spec.set_res(512)
|
28
29
|
|
29
|
-
self.png_spec = copy.deepcopy(base_spec)
|
30
|
+
self.png_spec = copy.deepcopy(self.base_spec)
|
30
31
|
self.png_spec.set_format((".png",))
|
31
32
|
self.png_spec.animated = False
|
32
33
|
|
33
|
-
self.tgs_spec = copy.deepcopy(base_spec)
|
34
|
+
self.tgs_spec = copy.deepcopy(self.base_spec)
|
34
35
|
self.tgs_spec.set_format((".tgs",))
|
35
36
|
self.tgs_spec.fps_min = 60
|
36
37
|
self.tgs_spec.fps_max = 60
|
37
38
|
self.tgs_spec.size_max_img = 64000
|
38
39
|
self.tgs_spec.size_max_vid = 64000
|
39
40
|
|
40
|
-
self.webm_spec = copy.deepcopy(base_spec)
|
41
|
+
self.webm_spec = copy.deepcopy(self.base_spec)
|
41
42
|
self.webm_spec.set_format((".webm",))
|
42
43
|
self.webm_spec.fps_max = 30
|
43
44
|
self.webm_spec.animated = None if self.opt_comp.fake_vid else True
|
44
45
|
|
45
46
|
self.opt_comp_merged = copy.deepcopy(self.opt_comp)
|
46
|
-
self.opt_comp_merged.merge(base_spec)
|
47
|
+
self.opt_comp_merged.merge(self.base_spec)
|
47
48
|
|
48
49
|
base_cover_spec = CompOption(
|
49
50
|
size_max_img=128000, size_max_vid=32000, square=True, duration_max=3000
|
@@ -65,10 +66,10 @@ class UploadTelegram(UploadBase):
|
|
65
66
|
self.webm_cover_spec.animated = True
|
66
67
|
|
67
68
|
self.opt_comp_cover_merged = copy.deepcopy(self.opt_comp)
|
68
|
-
self.opt_comp_cover_merged.merge(base_spec)
|
69
|
+
self.opt_comp_cover_merged.merge(self.base_spec)
|
69
70
|
|
70
71
|
async def upload_pack(
|
71
|
-
self, pack_title: str, stickers:
|
72
|
+
self, pack_title: str, stickers: List[Path], emoji_dict: Dict[str, str]
|
72
73
|
) -> str:
|
73
74
|
assert self.opt_cred.telegram_token
|
74
75
|
bot = Bot(self.opt_cred.telegram_token.strip())
|
@@ -208,6 +209,7 @@ class UploadTelegram(UploadBase):
|
|
208
209
|
Path(f"bytes{ext}"), # type: ignore
|
209
210
|
self.opt_comp_cover_merged,
|
210
211
|
self.cb,
|
212
|
+
self.cb_return,
|
211
213
|
)
|
212
214
|
|
213
215
|
try:
|
@@ -227,8 +229,8 @@ class UploadTelegram(UploadBase):
|
|
227
229
|
result = f"https://t.me/addstickers/{pack_short_name}"
|
228
230
|
return result
|
229
231
|
|
230
|
-
def upload_stickers_telegram(self) ->
|
231
|
-
urls:
|
232
|
+
def upload_stickers_telegram(self) -> List[str]:
|
233
|
+
urls: List[str] = []
|
232
234
|
|
233
235
|
if not (self.opt_cred.telegram_token and self.opt_cred.telegram_userid):
|
234
236
|
self.cb.put("Token and userid required for uploading to telegram")
|
@@ -247,7 +249,7 @@ class UploadTelegram(UploadBase):
|
|
247
249
|
msg_block += f"Default emoji is set to {self.opt_comp.default_emoji}.\n"
|
248
250
|
msg_block += "Please edit emoji.txt now, then continue"
|
249
251
|
MetadataHandler.generate_emoji_file(
|
250
|
-
|
252
|
+
directory=self.opt_output.dir, default_emoji=self.opt_comp.default_emoji
|
251
253
|
)
|
252
254
|
|
253
255
|
self.cb.put(("msg_block", (msg_block,), None))
|
@@ -281,18 +283,9 @@ class UploadTelegram(UploadBase):
|
|
281
283
|
opt_output: OutputOption,
|
282
284
|
opt_comp: CompOption,
|
283
285
|
opt_cred: CredOption,
|
284
|
-
cb: Union[
|
285
|
-
Queue[
|
286
|
-
Union[
|
287
|
-
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
|
288
|
-
str,
|
289
|
-
None,
|
290
|
-
]
|
291
|
-
],
|
292
|
-
Callback,
|
293
|
-
],
|
286
|
+
cb: "Union[Queue[CbQueueItemType], Callback]",
|
294
287
|
cb_return: CallbackReturn,
|
295
|
-
) ->
|
288
|
+
) -> List[str]:
|
296
289
|
exporter = UploadTelegram(
|
297
290
|
opt_output,
|
298
291
|
opt_comp,
|
@@ -7,93 +7,37 @@ import shutil
|
|
7
7
|
import zipfile
|
8
8
|
from pathlib import Path
|
9
9
|
from queue import Queue
|
10
|
-
from typing import Any,
|
10
|
+
from typing import Any, Dict, List, Union
|
11
11
|
|
12
12
|
from sticker_convert.converter import StickerConvert
|
13
13
|
from sticker_convert.definitions import ROOT_DIR
|
14
14
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
15
15
|
from sticker_convert.uploaders.upload_base import UploadBase
|
16
|
-
from sticker_convert.utils.callback import Callback, CallbackReturn
|
17
|
-
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
16
|
+
from sticker_convert.utils.callback import Callback, CallbackReturn, CbQueueItemType
|
17
|
+
from sticker_convert.utils.files.metadata_handler import XCODE_IMESSAGE_ICONSET, MetadataHandler
|
18
18
|
from sticker_convert.utils.files.sanitize_filename import sanitize_filename
|
19
19
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
20
20
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
21
21
|
|
22
22
|
|
23
|
-
class XcodeImessageIconset:
|
24
|
-
iconset: dict[str, tuple[int, int]] = {}
|
25
|
-
|
26
|
-
def __init__(self):
|
27
|
-
if self.iconset != {}:
|
28
|
-
return
|
29
|
-
|
30
|
-
if (ROOT_DIR / "ios-message-stickers-template").is_dir():
|
31
|
-
with open(
|
32
|
-
ROOT_DIR
|
33
|
-
/ "ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json"
|
34
|
-
) as f:
|
35
|
-
dict = json.load(f)
|
36
|
-
elif (ROOT_DIR / "ios-message-stickers-template.zip").is_file():
|
37
|
-
with zipfile.ZipFile(
|
38
|
-
(ROOT_DIR / "ios-message-stickers-template.zip"), "r"
|
39
|
-
) as f:
|
40
|
-
dict = json.loads(
|
41
|
-
f.read(
|
42
|
-
"stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json"
|
43
|
-
).decode()
|
44
|
-
)
|
45
|
-
else:
|
46
|
-
raise FileNotFoundError("ios-message-stickers-template not found")
|
47
|
-
|
48
|
-
for i in dict["images"]:
|
49
|
-
filename = i["filename"]
|
50
|
-
size = i["size"]
|
51
|
-
size_w = int(size.split("x")[0])
|
52
|
-
size_h = int(size.split("x")[1])
|
53
|
-
scale = int(i["scale"].replace("x", ""))
|
54
|
-
size_w_scaled = size_w * scale
|
55
|
-
size_h_scaled = size_h * scale
|
56
|
-
|
57
|
-
self.iconset[filename] = (size_w_scaled, size_h_scaled)
|
58
|
-
|
59
|
-
# self.iconset = {
|
60
|
-
# 'App-Store-1024x1024pt.png': (1024, 1024),
|
61
|
-
# 'iPad-Settings-29pt@2x.png': (58, 58),
|
62
|
-
# 'iPhone-settings-29pt@2x.png': (58, 58),
|
63
|
-
# 'iPhone-settings-29pt@3x.png': (87, 87),
|
64
|
-
# 'Messages27x20pt@2x.png': (54, 40),
|
65
|
-
# 'Messages27x20pt@3x.png': (81, 60),
|
66
|
-
# 'Messages32x24pt@2x.png': (64, 48),
|
67
|
-
# 'Messages32x24pt@3x.png': (96, 72),
|
68
|
-
# 'Messages-App-Store-1024x768pt.png': (1024, 768),
|
69
|
-
# 'Messages-iPad-67x50pt@2x.png': (134, 100),
|
70
|
-
# 'Messages-iPad-Pro-74x55pt@2x.png': (148, 110),
|
71
|
-
# 'Messages-iPhone-60x45pt@2x.png': (120, 90),
|
72
|
-
# 'Messages-iPhone-60x45pt@3x.png': (180, 135)
|
73
|
-
# }
|
74
|
-
|
75
|
-
|
76
23
|
class XcodeImessage(UploadBase):
|
77
|
-
def __init__(self, *args: Any, **kwargs: Any):
|
78
|
-
super(
|
79
|
-
self.
|
80
|
-
|
81
|
-
base_spec
|
82
|
-
base_spec.
|
83
|
-
base_spec.set_res(300)
|
84
|
-
base_spec.set_format(("png", ".apng", ".gif", ".jpeg", "jpg"))
|
85
|
-
base_spec.square = True
|
24
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
25
|
+
super().__init__(*args, **kwargs)
|
26
|
+
self.base_spec.set_size_max(500000)
|
27
|
+
self.base_spec.set_res(300)
|
28
|
+
self.base_spec.set_format(("png", ".apng", ".gif", ".jpeg", "jpg"))
|
29
|
+
self.base_spec.square = True
|
86
30
|
|
87
|
-
self.small_spec = copy.deepcopy(base_spec)
|
31
|
+
self.small_spec = copy.deepcopy(self.base_spec)
|
88
32
|
|
89
|
-
self.medium_spec = copy.deepcopy(base_spec)
|
33
|
+
self.medium_spec = copy.deepcopy(self.base_spec)
|
90
34
|
self.medium_spec.set_res(408)
|
91
35
|
|
92
|
-
self.large_spec = copy.deepcopy(base_spec)
|
36
|
+
self.large_spec = copy.deepcopy(self.base_spec)
|
93
37
|
self.large_spec.set_res(618)
|
94
38
|
|
95
|
-
def create_imessage_xcode(self) ->
|
96
|
-
urls:
|
39
|
+
def create_imessage_xcode(self) -> List[str]:
|
40
|
+
urls: List[str] = []
|
97
41
|
title, author, _ = MetadataHandler.get_metadata(
|
98
42
|
self.opt_output.dir,
|
99
43
|
title=self.opt_output.title,
|
@@ -155,7 +99,7 @@ class XcodeImessage(UploadBase):
|
|
155
99
|
|
156
100
|
return urls
|
157
101
|
|
158
|
-
def add_metadata(self, author: str, title: str):
|
102
|
+
def add_metadata(self, author: str, title: str) -> None:
|
159
103
|
first_image_path = Path(
|
160
104
|
self.opt_output.dir,
|
161
105
|
[
|
@@ -170,16 +114,16 @@ class XcodeImessage(UploadBase):
|
|
170
114
|
else:
|
171
115
|
icon_source = first_image_path
|
172
116
|
|
173
|
-
for icon, res in
|
117
|
+
for icon, res in XCODE_IMESSAGE_ICONSET.items():
|
174
118
|
spec_cover = CompOption()
|
175
119
|
spec_cover.set_res_w(res[0])
|
176
120
|
spec_cover.set_res_h(res[1])
|
177
121
|
spec_cover.set_fps(0)
|
178
122
|
|
179
123
|
icon_path = self.opt_output.dir / icon
|
180
|
-
if Path(icon) in
|
181
|
-
|
182
|
-
|
124
|
+
if Path(icon) in list(
|
125
|
+
self.opt_output.dir.iterdir()
|
126
|
+
) and not FormatVerify.check_file(icon_path, spec=spec_cover):
|
183
127
|
StickerConvert.convert(
|
184
128
|
icon_path, icon_path, spec_cover, self.cb, self.cb_return
|
185
129
|
)
|
@@ -190,7 +134,7 @@ class XcodeImessage(UploadBase):
|
|
190
134
|
|
191
135
|
MetadataHandler.set_metadata(self.opt_output.dir, author=author, title=title)
|
192
136
|
|
193
|
-
def create_xcode_proj(self, author: str, title: str):
|
137
|
+
def create_xcode_proj(self, author: str, title: str) -> None:
|
194
138
|
pack_path = self.opt_output.dir / title
|
195
139
|
if (ROOT_DIR / "ios-message-stickers-template.zip").is_file():
|
196
140
|
with zipfile.ZipFile(
|
@@ -260,12 +204,12 @@ class XcodeImessage(UploadBase):
|
|
260
204
|
if i.suffix == ".sticker":
|
261
205
|
shutil.rmtree(stickers_path / i)
|
262
206
|
|
263
|
-
stickers_lst:
|
207
|
+
stickers_lst: List[str] = []
|
264
208
|
for i in sorted(self.opt_output.dir.iterdir()):
|
265
209
|
if (
|
266
210
|
CodecInfo.get_file_ext(i) == ".png"
|
267
211
|
and i.stem != "cover"
|
268
|
-
and i.name not in
|
212
|
+
and i.name not in XCODE_IMESSAGE_ICONSET
|
269
213
|
):
|
270
214
|
sticker_dir = f"{i.stem}.sticker" # 0.sticker
|
271
215
|
stickers_lst.append(sticker_dir)
|
@@ -284,18 +228,18 @@ class XcodeImessage(UploadBase):
|
|
284
228
|
}
|
285
229
|
|
286
230
|
# packname StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/0.sticker/Contents.json
|
287
|
-
with open(sticker_path / "Contents.json", "w+") as f:
|
231
|
+
with open(sticker_path / "Contents.json", "w+", encoding="utf-8") as f:
|
288
232
|
json.dump(sticker_json_content, f, indent=2)
|
289
233
|
|
290
234
|
# packname StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json
|
291
|
-
with open(stickers_path / "Contents.json") as f:
|
292
|
-
stickerpack_json_content:
|
235
|
+
with open(stickers_path / "Contents.json", encoding="utf-8") as f:
|
236
|
+
stickerpack_json_content: Dict[str, List[Dict[str, str]]] = json.load(f)
|
293
237
|
|
294
238
|
stickerpack_json_content["stickers"] = []
|
295
239
|
for sticker in stickers_lst:
|
296
240
|
stickerpack_json_content["stickers"].append({"filename": sticker})
|
297
241
|
|
298
|
-
with open(stickers_path / "Contents.json", "w+") as f:
|
242
|
+
with open(stickers_path / "Contents.json", "w+", encoding="utf-8") as f:
|
299
243
|
json.dump(stickerpack_json_content, f, indent=2)
|
300
244
|
|
301
245
|
# packname StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset
|
@@ -308,8 +252,8 @@ class XcodeImessage(UploadBase):
|
|
308
252
|
if Path(iconfile_name).suffix == ".png":
|
309
253
|
os.remove(iconset_path / iconfile_name)
|
310
254
|
|
311
|
-
icons_lst:
|
312
|
-
for icon in
|
255
|
+
icons_lst: List[str] = []
|
256
|
+
for icon in XCODE_IMESSAGE_ICONSET:
|
313
257
|
shutil.copy(self.opt_output.dir / icon, iconset_path / icon)
|
314
258
|
icons_lst.append(icon)
|
315
259
|
|
@@ -335,17 +279,8 @@ class XcodeImessage(UploadBase):
|
|
335
279
|
opt_output: OutputOption,
|
336
280
|
opt_comp: CompOption,
|
337
281
|
opt_cred: CredOption,
|
338
|
-
cb: Union[
|
339
|
-
Queue[
|
340
|
-
Union[
|
341
|
-
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
|
342
|
-
str,
|
343
|
-
None,
|
344
|
-
]
|
345
|
-
],
|
346
|
-
Callback,
|
347
|
-
],
|
282
|
+
cb: "Union[Queue[CbQueueItemType], Callback]",
|
348
283
|
cb_return: CallbackReturn,
|
349
|
-
) ->
|
284
|
+
) -> List[str]:
|
350
285
|
exporter = XcodeImessage(opt_output, opt_comp, opt_cred, cb, cb_return)
|
351
286
|
return exporter.create_imessage_xcode()
|
@@ -2,7 +2,7 @@
|
|
2
2
|
import json
|
3
3
|
import secrets
|
4
4
|
import uuid
|
5
|
-
from typing import Any, Callable, Optional
|
5
|
+
from typing import Any, Callable, Dict, Optional
|
6
6
|
from urllib.parse import parse_qs, urlparse
|
7
7
|
|
8
8
|
import requests
|
@@ -17,7 +17,7 @@ class GetKakaoAuth:
|
|
17
17
|
cb_msg: Callable[..., None] = print,
|
18
18
|
cb_msg_block: Callable[..., Any] = input,
|
19
19
|
cb_ask_str: Callable[..., str] = input,
|
20
|
-
):
|
20
|
+
) -> None:
|
21
21
|
self.username = opt_cred.kakao_username
|
22
22
|
self.password = opt_cred.kakao_password
|
23
23
|
self.country_code = opt_cred.kakao_country_code
|
@@ -92,7 +92,7 @@ class GetKakaoAuth:
|
|
92
92
|
def enter_phone(self) -> bool:
|
93
93
|
self.cb_msg("Submitting phone number")
|
94
94
|
|
95
|
-
json_data:
|
95
|
+
json_data: Dict[str, Any] = {
|
96
96
|
"countryCode": self.country_code,
|
97
97
|
"countryIso": self.country_iso,
|
98
98
|
"phoneNumber": self.phone_number,
|
@@ -117,13 +117,12 @@ class GetKakaoAuth:
|
|
117
117
|
|
118
118
|
if self.verify_method == "passcode":
|
119
119
|
return self.verify_receive_sms()
|
120
|
-
|
120
|
+
if self.verify_method == "mo-send":
|
121
121
|
dest_number = response_json["viewData"]["moNumber"]
|
122
122
|
msg = response_json["viewData"]["moMessage"]
|
123
123
|
return self.verify_send_sms(dest_number, msg)
|
124
|
-
|
125
|
-
|
126
|
-
return False
|
124
|
+
self.cb_msg_block(f"Unknown verification method: {response.text}")
|
125
|
+
return False
|
127
126
|
|
128
127
|
def verify_send_sms(self, dest_number: str, msg: str) -> bool:
|
129
128
|
self.cb_msg("Verification by sending SMS")
|
@@ -210,7 +209,7 @@ class GetKakaoAuth:
|
|
210
209
|
"Connection": "close",
|
211
210
|
}
|
212
211
|
|
213
|
-
json_data:
|
212
|
+
json_data: Dict[str, str] = {
|
214
213
|
"decision": "continue",
|
215
214
|
"lang": self.app_language,
|
216
215
|
"sessionToken": session_token,
|
@@ -2,15 +2,15 @@
|
|
2
2
|
import json
|
3
3
|
import platform
|
4
4
|
from http.cookiejar import CookieJar
|
5
|
-
from typing import Any, Callable, Optional, Union
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
6
6
|
|
7
7
|
import requests
|
8
|
-
import rookiepy
|
8
|
+
import rookiepy # type: ignore
|
9
9
|
|
10
10
|
|
11
11
|
class GetLineAuth:
|
12
12
|
def get_cred(self) -> Optional[str]:
|
13
|
-
browsers:
|
13
|
+
browsers: List[Callable[..., Any]] = [
|
14
14
|
rookiepy.load, # type: ignore # Supposed to load from any browser, but may fail
|
15
15
|
rookiepy.firefox, # type: ignore
|
16
16
|
rookiepy.libre_wolf, # type: ignore
|
@@ -59,7 +59,7 @@ class GetLineAuth:
|
|
59
59
|
return cookies
|
60
60
|
|
61
61
|
@staticmethod
|
62
|
-
def validate_cookies(cookies: Union[CookieJar,
|
62
|
+
def validate_cookies(cookies: Union[CookieJar, Dict[str, str]]) -> bool:
|
63
63
|
headers = {
|
64
64
|
"x-requested-with": "XMLHttpRequest",
|
65
65
|
}
|
@@ -77,5 +77,4 @@ class GetLineAuth:
|
|
77
77
|
|
78
78
|
if response_dict["errorMessage"]:
|
79
79
|
return False
|
80
|
-
|
81
|
-
return True
|
80
|
+
return True
|
@@ -4,13 +4,13 @@ import os
|
|
4
4
|
import platform
|
5
5
|
import shutil
|
6
6
|
from pathlib import Path
|
7
|
-
from typing import Optional
|
7
|
+
from typing import Optional, Tuple
|
8
8
|
|
9
9
|
from sqlcipher3 import dbapi2 as sqlite3
|
10
10
|
|
11
11
|
|
12
12
|
class GetSignalAuth:
|
13
|
-
def get_signal_desktop(self) ->
|
13
|
+
def get_signal_desktop(self) -> Tuple[Optional[str], Optional[str]]:
|
14
14
|
if platform.system() == "Windows":
|
15
15
|
signal_bin_path_prod = os.path.expandvars(
|
16
16
|
"%localappdata%/Programs/signal-desktop/Signal.exe"
|
@@ -45,16 +45,16 @@ class GetSignalAuth:
|
|
45
45
|
|
46
46
|
if Path(signal_bin_path_prod).is_file():
|
47
47
|
return signal_bin_path_prod, signal_user_data_dir_prod
|
48
|
-
|
48
|
+
if Path(signal_bin_path_beta).is_file():
|
49
49
|
return signal_bin_path_beta, signal_user_data_dir_beta
|
50
|
-
|
51
|
-
|
50
|
+
|
51
|
+
return None, None
|
52
52
|
|
53
53
|
def get_cred(
|
54
54
|
self,
|
55
55
|
signal_bin_path: Optional[str] = None,
|
56
56
|
signal_user_data_dir: Optional[str] = None,
|
57
|
-
) ->
|
57
|
+
) -> Tuple[Optional[str], Optional[str], str]:
|
58
58
|
if not (signal_bin_path and signal_user_data_dir):
|
59
59
|
signal_bin_path, signal_user_data_dir = self.get_signal_desktop()
|
60
60
|
|
@@ -76,7 +76,7 @@ class GetSignalAuth:
|
|
76
76
|
msg += f"{signal_user_data_dir=}\n"
|
77
77
|
return None, None, msg
|
78
78
|
|
79
|
-
with open(signal_config) as f:
|
79
|
+
with open(signal_config, encoding="utf-8") as f:
|
80
80
|
config = json.load(f)
|
81
81
|
key = config.get("key")
|
82
82
|
db_key = f"x'{key}'"
|