sticker-convert 2.13.3.0__py3-none-any.whl → 2.17.0.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/__main__.py +24 -27
- sticker_convert/auth/__init__.py +0 -0
- sticker_convert/auth/auth_base.py +19 -0
- sticker_convert/{utils/auth/get_discord_auth.py → auth/auth_discord.py} +149 -118
- sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -330
- sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
- sticker_convert/{utils/auth/get_kakao_desktop_auth.py → auth/auth_kakao_desktop_memdump.py} +281 -263
- sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
- sticker_convert/{utils/auth/get_signal_auth.py → auth/auth_signal.py} +139 -135
- sticker_convert/auth/auth_telethon.py +161 -0
- sticker_convert/{utils/auth/get_viber_auth.py → auth/auth_viber.py} +250 -235
- sticker_convert/{utils/auth → auth}/telegram_api.py +736 -675
- sticker_convert/cli.py +623 -608
- sticker_convert/converter.py +1093 -1084
- sticker_convert/definitions.py +4 -0
- sticker_convert/downloaders/download_band.py +111 -110
- sticker_convert/downloaders/download_base.py +171 -166
- sticker_convert/downloaders/download_discord.py +92 -91
- sticker_convert/downloaders/download_kakao.py +417 -404
- sticker_convert/downloaders/download_line.py +484 -475
- sticker_convert/downloaders/download_ogq.py +80 -79
- sticker_convert/downloaders/download_signal.py +108 -105
- sticker_convert/downloaders/download_telegram.py +56 -55
- sticker_convert/downloaders/download_viber.py +121 -120
- sticker_convert/gui.py +788 -873
- sticker_convert/gui_components/frames/comp_frame.py +180 -166
- sticker_convert/gui_components/frames/config_frame.py +156 -113
- sticker_convert/gui_components/frames/control_frame.py +32 -30
- sticker_convert/gui_components/frames/cred_frame.py +232 -233
- sticker_convert/gui_components/frames/input_frame.py +139 -137
- sticker_convert/gui_components/frames/output_frame.py +112 -110
- sticker_convert/gui_components/frames/right_clicker.py +25 -23
- sticker_convert/gui_components/windows/advanced_compression_window.py +757 -757
- sticker_convert/gui_components/windows/base_window.py +7 -2
- sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -82
- sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -321
- sticker_convert/gui_components/windows/line_get_auth_window.py +94 -102
- sticker_convert/gui_components/windows/signal_get_auth_window.py +84 -89
- sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -168
- sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
- sticker_convert/ios-message-stickers-template/README.md +10 -10
- sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
- sticker_convert/job.py +166 -130
- sticker_convert/job_option.py +1 -0
- sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
- sticker_convert/py.typed +0 -0
- sticker_convert/resources/NotoColorEmoji.ttf +0 -0
- sticker_convert/resources/help.ja_JP.json +88 -0
- sticker_convert/resources/help.json +10 -7
- sticker_convert/resources/help.zh_CN.json +88 -0
- sticker_convert/resources/help.zh_TW.json +88 -0
- sticker_convert/resources/input.ja_JP.json +74 -0
- sticker_convert/resources/input.json +121 -121
- sticker_convert/resources/input.zh_CN.json +74 -0
- sticker_convert/resources/input.zh_TW.json +74 -0
- sticker_convert/resources/output.ja_JP.json +38 -0
- sticker_convert/resources/output.zh_CN.json +38 -0
- sticker_convert/resources/output.zh_TW.json +38 -0
- sticker_convert/uploaders/compress_wastickers.py +186 -177
- sticker_convert/uploaders/upload_base.py +44 -35
- sticker_convert/uploaders/upload_signal.py +218 -203
- sticker_convert/uploaders/upload_telegram.py +353 -338
- sticker_convert/uploaders/upload_viber.py +178 -169
- sticker_convert/uploaders/xcode_imessage.py +295 -286
- sticker_convert/utils/callback.py +238 -6
- sticker_convert/utils/emoji.py +16 -4
- sticker_convert/utils/files/json_resources_loader.py +24 -19
- sticker_convert/utils/files/metadata_handler.py +3 -3
- sticker_convert/utils/translate.py +108 -0
- sticker_convert/utils/url_detect.py +40 -37
- sticker_convert/version.py +1 -1
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +89 -74
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/RECORD +91 -74
- sticker_convert/utils/auth/telethon_setup.py +0 -97
- sticker_convert/utils/singletons.py +0 -18
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +0 -0
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/licenses/LICENSE +0 -0
- {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<Workspace
|
|
3
|
-
version = "1.0">
|
|
4
|
-
<FileRef
|
|
5
|
-
location = "self:">
|
|
6
|
-
</FileRef>
|
|
7
|
-
</Workspace>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<Workspace
|
|
3
|
+
version = "1.0">
|
|
4
|
+
<FileRef
|
|
5
|
+
location = "self:">
|
|
6
|
+
</FileRef>
|
|
7
|
+
</Workspace>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>IDEDidComputeMac32BitWarning</key>
|
|
6
|
-
<true/>
|
|
7
|
-
</dict>
|
|
8
|
-
</plist>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>IDEDidComputeMac32BitWarning</key>
|
|
6
|
+
<true/>
|
|
7
|
+
</dict>
|
|
8
|
+
</plist>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>SchemeUserState</key>
|
|
6
|
-
<dict>
|
|
7
|
-
<key>stickers StickerPackExtension.xcscheme_^#shared#^_</key>
|
|
8
|
-
<dict>
|
|
9
|
-
<key>orderHint</key>
|
|
10
|
-
<integer>0</integer>
|
|
11
|
-
</dict>
|
|
12
|
-
</dict>
|
|
13
|
-
</dict>
|
|
14
|
-
</plist>
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>stickers StickerPackExtension.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
</dict>
|
|
14
|
+
</plist>
|
sticker_convert/job.py
CHANGED
|
@@ -8,10 +8,11 @@ from datetime import datetime
|
|
|
8
8
|
from multiprocessing import Manager, Process, Value
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from threading import Thread
|
|
11
|
-
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union, cast
|
|
12
12
|
from urllib.parse import urlparse
|
|
13
13
|
|
|
14
14
|
from sticker_convert.converter import StickerConvert
|
|
15
|
+
from sticker_convert.definitions import RUNTIME_STATE
|
|
15
16
|
from sticker_convert.downloaders.download_band import DownloadBand
|
|
16
17
|
from sticker_convert.downloaders.download_discord import DownloadDiscord
|
|
17
18
|
from sticker_convert.downloaders.download_kakao import DownloadKakao
|
|
@@ -27,26 +28,24 @@ from sticker_convert.uploaders.upload_telegram import UploadTelegram
|
|
|
27
28
|
from sticker_convert.uploaders.upload_viber import UploadViber
|
|
28
29
|
from sticker_convert.uploaders.xcode_imessage import XcodeImessage
|
|
29
30
|
from sticker_convert.utils.callback import CallbackReturn, CbQueueType, ResultsListType, WorkQueueType
|
|
30
|
-
from sticker_convert.utils.
|
|
31
|
+
from sticker_convert.utils.chrome_remotedebug import CRD
|
|
32
|
+
from sticker_convert.utils.files.json_resources_loader import load_resource_json
|
|
31
33
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
|
32
34
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
|
33
|
-
from sticker_convert.utils.
|
|
35
|
+
from sticker_convert.utils.translate import I
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from sticker_convert.utils.callback import CallbackCli, CallbackGui
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
class Executor:
|
|
37
|
-
def __init__(
|
|
38
|
-
self
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
cb_bar
|
|
42
|
-
cb_ask_bool
|
|
43
|
-
cb_ask_str
|
|
44
|
-
) -> None:
|
|
45
|
-
self.cb_msg = cb_msg
|
|
46
|
-
self.cb_msg_block = cb_msg_block
|
|
47
|
-
self.cb_bar = cb_bar
|
|
48
|
-
self.cb_ask_bool = cb_ask_bool
|
|
49
|
-
self.cb_ask_str = cb_ask_str
|
|
42
|
+
def __init__(self, cb: Union[CallbackGui, CallbackCli]) -> None:
|
|
43
|
+
self.cb_msg = cb.cb_msg
|
|
44
|
+
self.cb_msg_block = cb.cb_msg_block
|
|
45
|
+
self.cb_msg_dynamic = cb.cb_msg_dynamic
|
|
46
|
+
self.cb_bar = cb.cb_bar
|
|
47
|
+
self.cb_ask_bool = cb.cb_ask_bool
|
|
48
|
+
self.cb_ask_str = cb.cb_ask_str
|
|
50
49
|
|
|
51
50
|
self.manager = Manager()
|
|
52
51
|
self.work_queue: WorkQueueType = self.manager.Queue()
|
|
@@ -90,7 +89,7 @@ class Executor:
|
|
|
90
89
|
def cb(
|
|
91
90
|
self,
|
|
92
91
|
action: Optional[str],
|
|
93
|
-
args: Optional[Tuple[
|
|
92
|
+
args: Optional[Tuple[Any, ...]] = None,
|
|
94
93
|
kwargs: Optional[Dict[str, Any]] = None,
|
|
95
94
|
) -> None:
|
|
96
95
|
if args is None:
|
|
@@ -105,6 +104,8 @@ class Executor:
|
|
|
105
104
|
self.cb_bar(update_bar=1)
|
|
106
105
|
elif action == "msg_block":
|
|
107
106
|
self.cb_return.set_response(self.cb_msg_block(*args, **kwargs))
|
|
107
|
+
elif action == "msg_dynamic":
|
|
108
|
+
self.cb_msg_dynamic(*args, **kwargs)
|
|
108
109
|
elif action == "ask_bool":
|
|
109
110
|
self.cb_return.set_response(self.cb_ask_bool(*args, **kwargs))
|
|
110
111
|
elif action == "ask_str":
|
|
@@ -130,16 +131,24 @@ class Executor:
|
|
|
130
131
|
arg_dump.append("CredOption(REDACTED)")
|
|
131
132
|
else:
|
|
132
133
|
arg_dump.append(i)
|
|
133
|
-
e =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
e = I(
|
|
135
|
+
"##### EXCEPTION #####\n"
|
|
136
|
+
"Function: {function}\n"
|
|
137
|
+
"Arguments: {args}\n"
|
|
138
|
+
"{tb}\n"
|
|
139
|
+
"#####################"
|
|
140
|
+
).format(
|
|
141
|
+
function=repr(work_func),
|
|
142
|
+
args=repr(arg_dump),
|
|
143
|
+
tb=traceback.format_exc(),
|
|
144
|
+
)
|
|
138
145
|
cb_queue.put(e)
|
|
139
146
|
|
|
140
147
|
work_queue.put(None)
|
|
141
148
|
cb_queue.put("__PROCESS_DONE__")
|
|
142
|
-
|
|
149
|
+
crd = cast(CRD, RUNTIME_STATE.get("crd"))
|
|
150
|
+
if crd:
|
|
151
|
+
crd.close()
|
|
143
152
|
|
|
144
153
|
def start_workers(self, processes: int = 1) -> None:
|
|
145
154
|
self.cb_thread_instance = Thread(
|
|
@@ -178,7 +187,9 @@ class Executor:
|
|
|
178
187
|
process.join()
|
|
179
188
|
if process.exitcode != 0 and self.is_cancel_job.value == 0:
|
|
180
189
|
self.cb_msg(
|
|
181
|
-
|
|
190
|
+
I("Warning: A process exited with error (code {})").format(
|
|
191
|
+
process.exitcode
|
|
192
|
+
)
|
|
182
193
|
)
|
|
183
194
|
except KeyboardInterrupt:
|
|
184
195
|
pass
|
|
@@ -208,31 +219,16 @@ class Job:
|
|
|
208
219
|
opt_comp: CompOption,
|
|
209
220
|
opt_output: OutputOption,
|
|
210
221
|
opt_cred: CredOption,
|
|
211
|
-
|
|
212
|
-
cb_msg_block: Callable[..., None],
|
|
213
|
-
cb_bar: Callable[..., None],
|
|
214
|
-
cb_ask_bool: Callable[..., bool],
|
|
215
|
-
cb_ask_str: Callable[..., str],
|
|
222
|
+
cb: Union[CallbackCli, CallbackGui],
|
|
216
223
|
) -> None:
|
|
217
224
|
self.opt_input = opt_input
|
|
218
225
|
self.opt_comp = opt_comp
|
|
219
226
|
self.opt_output = opt_output
|
|
220
227
|
self.opt_cred = opt_cred
|
|
221
|
-
self.cb_msg = cb_msg
|
|
222
|
-
self.cb_msg_block = cb_msg_block
|
|
223
|
-
self.cb_bar = cb_bar
|
|
224
|
-
self.cb_ask_bool = cb_ask_bool
|
|
225
|
-
self.cb_ask_str = cb_ask_str
|
|
226
228
|
|
|
227
229
|
self.out_urls: List[str] = []
|
|
228
230
|
|
|
229
|
-
self.executor = Executor(
|
|
230
|
-
self.cb_msg,
|
|
231
|
-
self.cb_msg_block,
|
|
232
|
-
self.cb_bar,
|
|
233
|
-
self.cb_ask_bool,
|
|
234
|
-
self.cb_ask_str,
|
|
235
|
-
)
|
|
231
|
+
self.executor = Executor(cb)
|
|
236
232
|
|
|
237
233
|
def start(self) -> int:
|
|
238
234
|
if Path(self.opt_input.dir).is_dir() is False:
|
|
@@ -264,22 +260,20 @@ class Job:
|
|
|
264
260
|
break
|
|
265
261
|
if not success:
|
|
266
262
|
code = 1
|
|
267
|
-
self.executor.cb("An error occured during this run.")
|
|
263
|
+
self.executor.cb(I("An error occured during this run."))
|
|
268
264
|
break
|
|
269
265
|
|
|
270
|
-
msg = "##########\n"
|
|
271
|
-
msg += "Summary:\n"
|
|
272
|
-
msg += "##########\n"
|
|
266
|
+
msg = I("##########\nSummary:\n##########\n")
|
|
273
267
|
|
|
274
268
|
msg += "\n"
|
|
275
269
|
msg += "\n".join(summaries)
|
|
276
270
|
msg += "\n"
|
|
277
271
|
|
|
278
272
|
if self.out_urls:
|
|
279
|
-
msg += "Export results:\n"
|
|
273
|
+
msg += I("Export results:\n")
|
|
280
274
|
msg += "\n".join(self.out_urls)
|
|
281
275
|
else:
|
|
282
|
-
msg += "Export result: None"
|
|
276
|
+
msg += I("Export result: None")
|
|
283
277
|
|
|
284
278
|
self.executor.cb(msg)
|
|
285
279
|
|
|
@@ -294,29 +288,31 @@ class Job:
|
|
|
294
288
|
info_msg = ""
|
|
295
289
|
error_msg = ""
|
|
296
290
|
|
|
297
|
-
save_to_local_tip =
|
|
298
|
-
|
|
299
|
-
|
|
291
|
+
save_to_local_tip = I(
|
|
292
|
+
"\n"
|
|
293
|
+
" If you want to upload the results by yourself,\n"
|
|
294
|
+
' select "Save to local directory only" for output\n'
|
|
295
|
+
)
|
|
300
296
|
|
|
301
297
|
if Path(self.opt_input.dir).resolve() == Path(self.opt_output.dir).resolve():
|
|
302
|
-
error_msg += "\n"
|
|
303
|
-
error_msg += "[X] Input and output directories cannot be the same\n"
|
|
298
|
+
error_msg += I("\n[X] Input and output directories cannot be the same\n")
|
|
304
299
|
|
|
305
300
|
if self.opt_input.option == "auto":
|
|
306
|
-
error_msg += "\n"
|
|
307
|
-
error_msg += "[X] Unrecognized URL input source\n"
|
|
301
|
+
error_msg += I("\n[X] Unrecognized URL input source\n")
|
|
308
302
|
|
|
309
303
|
if self.opt_input.option != "local" and not self.opt_input.url:
|
|
310
|
-
error_msg +=
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
304
|
+
error_msg += I(
|
|
305
|
+
"\n"
|
|
306
|
+
"[X] URL address cannot be empty.\n"
|
|
307
|
+
" If you only want to use local files,\n"
|
|
308
|
+
' choose "Save to local directory only"\n'
|
|
309
|
+
' in "Input source"\n'
|
|
310
|
+
)
|
|
315
311
|
|
|
316
312
|
if (
|
|
317
313
|
self.opt_input.option == "telegram" or self.opt_output.option == "telegram"
|
|
318
314
|
) and not self.opt_cred.telegram_token:
|
|
319
|
-
error_msg += (
|
|
315
|
+
error_msg += I(
|
|
320
316
|
"[X] Downloading from and uploading to telegram requires bot token.\n"
|
|
321
317
|
)
|
|
322
318
|
error_msg += save_to_local_tip
|
|
@@ -325,24 +321,26 @@ class Job:
|
|
|
325
321
|
self.opt_input.option.startswith("discord")
|
|
326
322
|
and not self.opt_cred.discord_token
|
|
327
323
|
):
|
|
328
|
-
error_msg += "[X] Downloading from Discord requires token.\n"
|
|
324
|
+
error_msg += I("[X] Downloading from Discord requires token.\n")
|
|
329
325
|
|
|
330
326
|
if self.opt_output.option == "telegram" and not self.opt_cred.telegram_userid:
|
|
331
|
-
error_msg +=
|
|
332
|
-
|
|
327
|
+
error_msg += I(
|
|
328
|
+
"[X] Uploading to telegram requires user_id \n"
|
|
329
|
+
" (From real account, not bot account).\n"
|
|
330
|
+
)
|
|
333
331
|
error_msg += save_to_local_tip
|
|
334
332
|
|
|
335
333
|
if self.opt_output.option == "signal" and not (
|
|
336
334
|
self.opt_cred.signal_uuid and self.opt_cred.signal_password
|
|
337
335
|
):
|
|
338
|
-
error_msg += "[X] Uploading to signal requires uuid and password.\n"
|
|
336
|
+
error_msg += I("[X] Uploading to signal requires uuid and password.\n")
|
|
339
337
|
error_msg += save_to_local_tip
|
|
340
338
|
|
|
341
339
|
if self.opt_output.option == "viber" and not self.opt_cred.viber_auth:
|
|
342
|
-
error_msg += "[X] Uploading to Viber requires auth data.\n"
|
|
340
|
+
error_msg += I("[X] Uploading to Viber requires auth data.\n")
|
|
343
341
|
error_msg += save_to_local_tip
|
|
344
342
|
|
|
345
|
-
output_presets =
|
|
343
|
+
output_presets = load_resource_json("output")
|
|
346
344
|
|
|
347
345
|
input_option = self.opt_input.option
|
|
348
346
|
output_option = self.opt_output.option
|
|
@@ -354,23 +352,37 @@ class Job:
|
|
|
354
352
|
if not MetadataHandler.check_metadata_provided(
|
|
355
353
|
self.opt_input.dir, input_option, metadata
|
|
356
354
|
):
|
|
357
|
-
error_msg +=
|
|
355
|
+
error_msg += I("[X] {output_option} requires {metadata}\n").format(
|
|
356
|
+
output_option=output_presets[output_option]["full_name"],
|
|
357
|
+
metadata=metadata,
|
|
358
|
+
)
|
|
358
359
|
if self.opt_input.option == "local":
|
|
359
|
-
error_msg +=
|
|
360
|
+
error_msg += I(
|
|
361
|
+
" {metadata} was not supplied and {metadata}.txt is absent\n"
|
|
362
|
+
).format(metadata=metadata)
|
|
360
363
|
else:
|
|
361
|
-
error_msg +=
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
error_msg += I(
|
|
365
|
+
" {metadata} was not supplied and input source will not provide {metadata}\n"
|
|
366
|
+
).format(metadata=metadata)
|
|
367
|
+
error_msg += I(
|
|
368
|
+
" Supply the {metadata} by filling in the option, or\n"
|
|
369
|
+
" Create {metadata}.txt with the {metadata} name\n"
|
|
370
|
+
).format(metadata=metadata)
|
|
366
371
|
else:
|
|
367
|
-
info_msg +=
|
|
372
|
+
info_msg += I("[!] {output_option} requires {metadata}\n").format(
|
|
373
|
+
output_option=output_presets[output_option]["full_name"],
|
|
374
|
+
metadata=metadata,
|
|
375
|
+
)
|
|
368
376
|
if self.opt_input.option == "local":
|
|
369
|
-
info_msg +=
|
|
370
|
-
|
|
377
|
+
info_msg += I(
|
|
378
|
+
" {metadata} was not supplied but {metadata}.txt is present\n"
|
|
379
|
+
" Using {metadata} name in {metadata}.txt\n"
|
|
380
|
+
).format(metadata=metadata)
|
|
371
381
|
else:
|
|
372
|
-
info_msg +=
|
|
373
|
-
|
|
382
|
+
info_msg += I(
|
|
383
|
+
f" {metadata} was not supplied but input source will provide {metadata}\n"
|
|
384
|
+
f" Using {metadata} provided by input source\n"
|
|
385
|
+
).format(metadata=metadata)
|
|
374
386
|
|
|
375
387
|
if info_msg != "":
|
|
376
388
|
self.executor.cb(info_msg)
|
|
@@ -392,9 +404,11 @@ class Job:
|
|
|
392
404
|
and self.opt_comp.preset not in self.opt_output.option
|
|
393
405
|
)
|
|
394
406
|
):
|
|
395
|
-
msg =
|
|
396
|
-
|
|
397
|
-
|
|
407
|
+
msg = I(
|
|
408
|
+
"Compression preset does not match export option\n"
|
|
409
|
+
"You may continue, but the files will need to be compressed again before export\n"
|
|
410
|
+
"You are recommended to choose the matching option for compression and output. Continue?"
|
|
411
|
+
)
|
|
398
412
|
|
|
399
413
|
self.executor.cb("ask_bool", (msg,))
|
|
400
414
|
response = self.executor.cb_return.get_response()
|
|
@@ -409,8 +423,10 @@ class Job:
|
|
|
409
423
|
("color_power", self.opt_comp.color_power),
|
|
410
424
|
):
|
|
411
425
|
if value < -1:
|
|
412
|
-
error_msg +=
|
|
413
|
-
|
|
426
|
+
error_msg += I(
|
|
427
|
+
"\n"
|
|
428
|
+
"[X] {param} should be between -1 and positive infinity. {value} was given."
|
|
429
|
+
).format(param=param, value=value)
|
|
414
430
|
|
|
415
431
|
if self.opt_comp.scale_filter not in (
|
|
416
432
|
"nearest",
|
|
@@ -420,13 +436,11 @@ class Job:
|
|
|
420
436
|
"bicubic",
|
|
421
437
|
"lanczos",
|
|
422
438
|
):
|
|
423
|
-
error_msg +=
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
)
|
|
427
|
-
error_msg += (
|
|
439
|
+
error_msg += I(
|
|
440
|
+
"\n"
|
|
441
|
+
"[X] scale_filter {scale_filter} is not valid option\n"
|
|
428
442
|
" Valid options: nearest, box, bilinear, hamming, bicubic, lanczos"
|
|
429
|
-
)
|
|
443
|
+
).format(scale_filter=self.opt_comp.scale_filter)
|
|
430
444
|
|
|
431
445
|
if self.opt_comp.quantize_method not in (
|
|
432
446
|
"imagequant",
|
|
@@ -435,18 +449,19 @@ class Job:
|
|
|
435
449
|
"mediancut",
|
|
436
450
|
"none",
|
|
437
451
|
):
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
452
|
+
I(
|
|
453
|
+
"\n"
|
|
454
|
+
"[X] quantize_method {quantize_method} is not valid option\n"
|
|
455
|
+
" Valid options: imagequant, fastoctree, maxcoverage, mediancut, none"
|
|
456
|
+
).format(quantize_method=self.opt_comp.quantize_method)
|
|
441
457
|
|
|
442
458
|
if self.opt_comp.bg_color:
|
|
443
459
|
try:
|
|
444
460
|
_, _, _ = bytes.fromhex(self.opt_comp.bg_color)
|
|
445
461
|
except ValueError:
|
|
446
|
-
error_msg +=
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
)
|
|
462
|
+
error_msg += I(
|
|
463
|
+
"\n[X] bg_color {bg_color} is not valid color hex"
|
|
464
|
+
).format(bg_color=self.opt_comp.bg_color)
|
|
450
465
|
|
|
451
466
|
# Warn about unable to download animated Kakao stickers with such link
|
|
452
467
|
if (
|
|
@@ -454,12 +469,14 @@ class Job:
|
|
|
454
469
|
and urlparse(self.opt_input.url).netloc == "e.kakao.com"
|
|
455
470
|
and not self.opt_cred.kakao_auth_token
|
|
456
471
|
):
|
|
457
|
-
msg =
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
472
|
+
msg = I(
|
|
473
|
+
"To download ANIMATED stickers from e.kakao.com,\n"
|
|
474
|
+
"you need to generate auth_token.\n"
|
|
475
|
+
"Alternatively, you can generate share link (emoticon.kakao.com/items/xxxxx)\n"
|
|
476
|
+
"from Kakao app on phone.\n"
|
|
477
|
+
"You are adviced to read documentations.\n"
|
|
478
|
+
"If you continue, you will only download static stickers. Continue?"
|
|
479
|
+
)
|
|
463
480
|
|
|
464
481
|
self.executor.cb("ask_bool", (msg,))
|
|
465
482
|
response = self.executor.cb_return.get_response()
|
|
@@ -489,15 +506,22 @@ class Job:
|
|
|
489
506
|
|
|
490
507
|
related_files = MetadataHandler.get_files_related_to_sticker_convert(path)
|
|
491
508
|
if any(i for i in path.iterdir() if i not in related_files):
|
|
492
|
-
msg =
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
509
|
+
msg = I(
|
|
510
|
+
"WARNING: {path_type} directory is set to {path}.\n"
|
|
511
|
+
'It does not have default name of "{default_name}",\n'
|
|
512
|
+
"and It seems like it contains PERSONAL DATA.\n"
|
|
513
|
+
"During execution, contents of this directory\n"
|
|
514
|
+
'maybe MOVED to "archive_*".\n'
|
|
515
|
+
"THIS MAY CAUSE DAMAGE TO YOUR DATA. Continue?"
|
|
516
|
+
)
|
|
498
517
|
|
|
499
518
|
self.executor.cb(
|
|
500
|
-
"ask_bool",
|
|
519
|
+
"ask_bool",
|
|
520
|
+
(
|
|
521
|
+
msg.format(
|
|
522
|
+
path_type=path_type, path=path, default_name=default_name
|
|
523
|
+
),
|
|
524
|
+
),
|
|
501
525
|
)
|
|
502
526
|
response = self.executor.cb_return.get_response()
|
|
503
527
|
|
|
@@ -525,16 +549,18 @@ class Job:
|
|
|
525
549
|
|
|
526
550
|
if self.opt_input.option == "local":
|
|
527
551
|
self.executor.cb(
|
|
528
|
-
"Skip moving old files in input directory as input source is local"
|
|
552
|
+
I("Skip moving old files in input directory as input source is local")
|
|
529
553
|
)
|
|
530
554
|
elif len(in_dir_files) == 0:
|
|
531
555
|
self.executor.cb(
|
|
532
|
-
"Skip moving old files in input directory as input source is empty"
|
|
556
|
+
I("Skip moving old files in input directory as input source is empty")
|
|
533
557
|
)
|
|
534
558
|
else:
|
|
535
559
|
archive_dir = Path(self.opt_input.dir, dir_name)
|
|
536
560
|
self.executor.cb(
|
|
537
|
-
|
|
561
|
+
I(
|
|
562
|
+
"Moving old files in input directory to {archive_dir} as input source is not local"
|
|
563
|
+
).format(archive_dir=archive_dir)
|
|
538
564
|
)
|
|
539
565
|
archive_dir.mkdir(exist_ok=True)
|
|
540
566
|
for old_path in in_dir_files:
|
|
@@ -543,15 +569,19 @@ class Job:
|
|
|
543
569
|
|
|
544
570
|
if self.opt_comp.no_compress:
|
|
545
571
|
self.executor.cb(
|
|
546
|
-
"Skip moving old files in output directory as no_compress is True"
|
|
572
|
+
I("Skip moving old files in output directory as no_compress is True")
|
|
547
573
|
)
|
|
548
574
|
elif len(out_dir_files) == 0:
|
|
549
575
|
self.executor.cb(
|
|
550
|
-
"Skip moving old files in output directory as output source is empty"
|
|
576
|
+
I("Skip moving old files in output directory as output source is empty")
|
|
551
577
|
)
|
|
552
578
|
else:
|
|
553
579
|
archive_dir = Path(self.opt_output.dir, dir_name)
|
|
554
|
-
self.executor.cb(
|
|
580
|
+
self.executor.cb(
|
|
581
|
+
I("Moving old files in output directory to {archive_dir}").format(
|
|
582
|
+
archive_dir=archive_dir
|
|
583
|
+
)
|
|
584
|
+
)
|
|
555
585
|
os.makedirs(archive_dir)
|
|
556
586
|
for old_path in out_dir_files:
|
|
557
587
|
new_path = Path(archive_dir, old_path.name)
|
|
@@ -587,10 +617,10 @@ class Job:
|
|
|
587
617
|
downloaders.append(DownloadDiscord.start)
|
|
588
618
|
|
|
589
619
|
if len(downloaders) > 0:
|
|
590
|
-
self.executor.cb("Downloading...")
|
|
620
|
+
self.executor.cb(I("Downloading..."))
|
|
591
621
|
else:
|
|
592
|
-
self.executor.cb("Skipped download (No files to download)")
|
|
593
|
-
return True, "Download: Skipped (No files to download)"
|
|
622
|
+
self.executor.cb(I("Skipped download (No files to download)"))
|
|
623
|
+
return True, I("Download: Skipped (No files to download)")
|
|
594
624
|
|
|
595
625
|
self.executor.start_workers(processes=1)
|
|
596
626
|
|
|
@@ -620,7 +650,7 @@ class Job:
|
|
|
620
650
|
|
|
621
651
|
def compress(self) -> Tuple[bool, str]:
|
|
622
652
|
if self.opt_comp.no_compress is True:
|
|
623
|
-
self.executor.cb("Skipped compression (no_compress is set to True)")
|
|
653
|
+
self.executor.cb(I("Skipped compression (no_compress is set to True)"))
|
|
624
654
|
in_dir_files = [
|
|
625
655
|
i
|
|
626
656
|
for i in sorted(self.opt_input.dir.iterdir())
|
|
@@ -633,15 +663,17 @@ class Job:
|
|
|
633
663
|
]
|
|
634
664
|
if len(in_dir_files) == 0:
|
|
635
665
|
self.executor.cb(
|
|
636
|
-
"Input directory is empty, nothing to copy to output directory"
|
|
666
|
+
I("Input directory is empty, nothing to copy to output directory")
|
|
637
667
|
)
|
|
638
668
|
elif len(out_dir_files) != 0:
|
|
639
669
|
self.executor.cb(
|
|
640
|
-
|
|
670
|
+
I(
|
|
671
|
+
"Output directory is not empty, not copying files from input directory"
|
|
672
|
+
)
|
|
641
673
|
)
|
|
642
674
|
else:
|
|
643
675
|
self.executor.cb(
|
|
644
|
-
"Output directory is empty, copying files from input directory"
|
|
676
|
+
I("Output directory is empty, copying files from input directory")
|
|
645
677
|
)
|
|
646
678
|
for i in in_dir_files:
|
|
647
679
|
src_f = Path(self.opt_input.dir, i.name)
|
|
@@ -674,7 +706,7 @@ class Job:
|
|
|
674
706
|
|
|
675
707
|
in_fs_count = len(in_fs)
|
|
676
708
|
if in_fs_count == 0:
|
|
677
|
-
self.executor.cb("Skipped compression (No files to compress)")
|
|
709
|
+
self.executor.cb(I("Skipped compression (No files to compress)"))
|
|
678
710
|
return True, "Compress: Skipped (No files to compress)"
|
|
679
711
|
|
|
680
712
|
self.executor.cb(msg)
|
|
@@ -717,10 +749,10 @@ class Job:
|
|
|
717
749
|
|
|
718
750
|
def export(self) -> Tuple[bool, str]:
|
|
719
751
|
if self.opt_output.option == "local":
|
|
720
|
-
self.executor.cb("Skipped export (Saving to local directory only)")
|
|
721
|
-
return True, "Export: Skipped (Saving to local directory only)"
|
|
752
|
+
self.executor.cb(I("Skipped export (Saving to local directory only)"))
|
|
753
|
+
return True, I("Export: Skipped (Saving to local directory only)")
|
|
722
754
|
|
|
723
|
-
self.executor.cb("Exporting...")
|
|
755
|
+
self.executor.cb(I("Exporting..."))
|
|
724
756
|
|
|
725
757
|
exporters: List[Callable[..., Tuple[int, int, List[str]]]] = []
|
|
726
758
|
|
|
@@ -762,7 +794,11 @@ class Job:
|
|
|
762
794
|
) as f:
|
|
763
795
|
f.write("\n".join(self.out_urls))
|
|
764
796
|
else:
|
|
765
|
-
self.executor.cb("An error occured while exporting stickers")
|
|
766
|
-
return False,
|
|
767
|
-
|
|
768
|
-
|
|
797
|
+
self.executor.cb(I("An error occured while exporting stickers"))
|
|
798
|
+
return False, I(
|
|
799
|
+
"Export: {stickers_ok}/{stickers_total} stickers success"
|
|
800
|
+
).format(stickers_ok=stickers_ok, stickers_total=stickers_total)
|
|
801
|
+
|
|
802
|
+
return True, I(
|
|
803
|
+
"Export: {stickers_ok}/{stickers_total} stickers success"
|
|
804
|
+
).format(stickers_ok=stickers_ok, stickers_total=stickers_total)
|
sticker_convert/job_option.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
sticker_convert/py.typed
ADDED
|
File without changes
|
|
Binary file
|