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.
Files changed (93) hide show
  1. sticker_convert/__main__.py +24 -27
  2. sticker_convert/auth/__init__.py +0 -0
  3. sticker_convert/auth/auth_base.py +19 -0
  4. sticker_convert/{utils/auth/get_discord_auth.py → auth/auth_discord.py} +149 -118
  5. sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -330
  6. sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
  7. sticker_convert/{utils/auth/get_kakao_desktop_auth.py → auth/auth_kakao_desktop_memdump.py} +281 -263
  8. sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
  9. sticker_convert/{utils/auth/get_signal_auth.py → auth/auth_signal.py} +139 -135
  10. sticker_convert/auth/auth_telethon.py +161 -0
  11. sticker_convert/{utils/auth/get_viber_auth.py → auth/auth_viber.py} +250 -235
  12. sticker_convert/{utils/auth → auth}/telegram_api.py +736 -675
  13. sticker_convert/cli.py +623 -608
  14. sticker_convert/converter.py +1093 -1084
  15. sticker_convert/definitions.py +4 -0
  16. sticker_convert/downloaders/download_band.py +111 -110
  17. sticker_convert/downloaders/download_base.py +171 -166
  18. sticker_convert/downloaders/download_discord.py +92 -91
  19. sticker_convert/downloaders/download_kakao.py +417 -404
  20. sticker_convert/downloaders/download_line.py +484 -475
  21. sticker_convert/downloaders/download_ogq.py +80 -79
  22. sticker_convert/downloaders/download_signal.py +108 -105
  23. sticker_convert/downloaders/download_telegram.py +56 -55
  24. sticker_convert/downloaders/download_viber.py +121 -120
  25. sticker_convert/gui.py +788 -873
  26. sticker_convert/gui_components/frames/comp_frame.py +180 -166
  27. sticker_convert/gui_components/frames/config_frame.py +156 -113
  28. sticker_convert/gui_components/frames/control_frame.py +32 -30
  29. sticker_convert/gui_components/frames/cred_frame.py +232 -233
  30. sticker_convert/gui_components/frames/input_frame.py +139 -137
  31. sticker_convert/gui_components/frames/output_frame.py +112 -110
  32. sticker_convert/gui_components/frames/right_clicker.py +25 -23
  33. sticker_convert/gui_components/windows/advanced_compression_window.py +757 -757
  34. sticker_convert/gui_components/windows/base_window.py +7 -2
  35. sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -82
  36. sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -321
  37. sticker_convert/gui_components/windows/line_get_auth_window.py +94 -102
  38. sticker_convert/gui_components/windows/signal_get_auth_window.py +84 -89
  39. sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -168
  40. sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
  41. sticker_convert/ios-message-stickers-template/README.md +10 -10
  42. sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
  43. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
  44. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
  45. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
  46. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
  47. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
  48. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
  49. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
  50. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
  51. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
  52. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
  53. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
  54. sticker_convert/job.py +166 -130
  55. sticker_convert/job_option.py +1 -0
  56. sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
  57. sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
  58. sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
  59. sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
  60. sticker_convert/py.typed +0 -0
  61. sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  62. sticker_convert/resources/help.ja_JP.json +88 -0
  63. sticker_convert/resources/help.json +10 -7
  64. sticker_convert/resources/help.zh_CN.json +88 -0
  65. sticker_convert/resources/help.zh_TW.json +88 -0
  66. sticker_convert/resources/input.ja_JP.json +74 -0
  67. sticker_convert/resources/input.json +121 -121
  68. sticker_convert/resources/input.zh_CN.json +74 -0
  69. sticker_convert/resources/input.zh_TW.json +74 -0
  70. sticker_convert/resources/output.ja_JP.json +38 -0
  71. sticker_convert/resources/output.zh_CN.json +38 -0
  72. sticker_convert/resources/output.zh_TW.json +38 -0
  73. sticker_convert/uploaders/compress_wastickers.py +186 -177
  74. sticker_convert/uploaders/upload_base.py +44 -35
  75. sticker_convert/uploaders/upload_signal.py +218 -203
  76. sticker_convert/uploaders/upload_telegram.py +353 -338
  77. sticker_convert/uploaders/upload_viber.py +178 -169
  78. sticker_convert/uploaders/xcode_imessage.py +295 -286
  79. sticker_convert/utils/callback.py +238 -6
  80. sticker_convert/utils/emoji.py +16 -4
  81. sticker_convert/utils/files/json_resources_loader.py +24 -19
  82. sticker_convert/utils/files/metadata_handler.py +3 -3
  83. sticker_convert/utils/translate.py +108 -0
  84. sticker_convert/utils/url_detect.py +40 -37
  85. sticker_convert/version.py +1 -1
  86. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +89 -74
  87. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/RECORD +91 -74
  88. sticker_convert/utils/auth/telethon_setup.py +0 -97
  89. sticker_convert/utils/singletons.py +0 -18
  90. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +0 -0
  91. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
  92. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/licenses/LICENSE +0 -0
  93. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
sticker_convert/cli.py CHANGED
@@ -1,608 +1,623 @@
1
- #!/usr/bin/env python3
2
- import argparse
3
- import signal
4
- import sys
5
- from argparse import Namespace
6
- from json.decoder import JSONDecodeError
7
- from math import ceil
8
- from multiprocessing import cpu_count
9
- from pathlib import Path
10
- from typing import Any, Dict
11
-
12
- from mergedeep import merge # type: ignore
13
-
14
- from sticker_convert.definitions import CONFIG_DIR, DEFAULT_DIR
15
- from sticker_convert.job import Job
16
- from sticker_convert.job_option import CompOption, CredOption, InputOption, OutputOption
17
- from sticker_convert.utils.auth.get_discord_auth import GetDiscordAuth
18
- from sticker_convert.utils.auth.get_kakao_auth import GetKakaoAuth
19
- from sticker_convert.utils.auth.get_kakao_desktop_auth import GetKakaoDesktopAuth
20
- from sticker_convert.utils.auth.get_line_auth import GetLineAuth
21
- from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
22
- from sticker_convert.utils.auth.get_viber_auth import GetViberAuth
23
- from sticker_convert.utils.auth.telethon_setup import TelethonSetup
24
- from sticker_convert.utils.callback import Callback
25
- from sticker_convert.utils.files.json_manager import JsonManager
26
- from sticker_convert.utils.url_detect import UrlDetect
27
- from sticker_convert.version import __version__
28
-
29
-
30
- class CLI:
31
- def __init__(self) -> None:
32
- self.cb = Callback()
33
-
34
- def cli(self) -> None:
35
- try:
36
- from sticker_convert.utils.files.json_resources_loader import COMPRESSION_JSON, EMOJI_JSON, HELP_JSON, INPUT_JSON, OUTPUT_JSON
37
- except RuntimeError as e:
38
- self.cb.msg(str(e))
39
- return
40
-
41
- self.help = HELP_JSON
42
- self.input_presets = INPUT_JSON
43
- self.compression_presets = COMPRESSION_JSON
44
- self.output_presets = OUTPUT_JSON
45
- self.emoji_list = EMOJI_JSON
46
-
47
- parser = argparse.ArgumentParser(
48
- description="CLI for stickers-convert",
49
- formatter_class=argparse.RawTextHelpFormatter,
50
- )
51
-
52
- parser.add_argument("--version", action="version", version=__version__)
53
- parser.add_argument(
54
- "--no-confirm",
55
- dest="no_confirm",
56
- action="store_true",
57
- help=self.help["global"]["no_confirm"],
58
- )
59
- parser.add_argument(
60
- "--no-progress",
61
- dest="no_progress",
62
- action="store_true",
63
- help=self.help["global"]["no_progress"],
64
- )
65
- parser.add_argument(
66
- "--custom-presets",
67
- dest="custom_presets",
68
- default=None,
69
- help=self.help["global"]["custom_presets"],
70
- )
71
-
72
- parser_input = parser.add_argument_group("Input options")
73
- for k, v_str in self.help["input"].items():
74
- parser_input.add_argument(f"--{k.replace('_', '-')}", dest=k, help=v_str)
75
- parser_input_src = parser_input.add_mutually_exclusive_group()
76
- for k, v_dict in self.input_presets.items():
77
- if k == "local":
78
- continue
79
- parser_input_src.add_argument(
80
- f"--download-{k.replace('_', '-')}",
81
- dest=f"download_{k}",
82
- help=f"{v_dict['help']}\n({v_dict['example']})",
83
- )
84
-
85
- parser_output = parser.add_argument_group("Output options")
86
- for k, v_str in self.help["output"].items():
87
- parser_output.add_argument(f"--{k.replace('_', '-')}", dest=k, help=v_str)
88
- parser_output_dst = parser_output.add_mutually_exclusive_group()
89
- for k, v_dict in self.output_presets.items():
90
- if k == "local":
91
- continue
92
- parser_output_dst.add_argument(
93
- f"--export-{k.replace('_', '-')}",
94
- dest=f"export_{k}",
95
- action="store_true",
96
- help=v_dict["help"],
97
- )
98
-
99
- parser_comp = parser.add_argument_group("Compression options")
100
- parser_comp.add_argument(
101
- "--no-compress",
102
- dest="no_compress",
103
- action="store_true",
104
- help=self.help["comp"]["no_compress"],
105
- )
106
- parser_comp.add_argument(
107
- "--preset",
108
- dest="preset",
109
- default="auto",
110
- choices=self.compression_presets.keys(),
111
- help=self.help["comp"]["preset"],
112
- )
113
- flags_comp_int = (
114
- "steps",
115
- "processes",
116
- "fps_min",
117
- "fps_max",
118
- "res_min",
119
- "res_max",
120
- "res_w_min",
121
- "res_w_max",
122
- "res_h_min",
123
- "res_h_max",
124
- "quality_min",
125
- "quality_max",
126
- "color_min",
127
- "color_max",
128
- "duration_min",
129
- "duration_max",
130
- "vid_size_max",
131
- "img_size_max",
132
- "padding_percent",
133
- )
134
- flags_comp_float = ("fps_power", "res_power", "quality_power", "color_power")
135
- flags_comp_str = (
136
- "bg_color",
137
- "vid_format",
138
- "img_format",
139
- "cache_dir",
140
- "scale_filter",
141
- "quantize_method",
142
- "chromium_path",
143
- )
144
- flags_comp_bool = (
145
- "fake_vid",
146
- "no_fake_vid",
147
- "res_snap_pow2",
148
- "no_res_snap_pow2",
149
- )
150
- keyword_args: Dict[str, Any]
151
- for k, v in self.help["comp"].items():
152
- if k in flags_comp_int:
153
- keyword_args = {"type": int, "default": None}
154
- elif k in flags_comp_float:
155
- keyword_args = {"type": float, "default": None}
156
- elif k in flags_comp_str:
157
- keyword_args = {"default": None}
158
- elif k in flags_comp_bool:
159
- keyword_args = {"action": "store_true", "default": None}
160
- else:
161
- continue
162
- parser_comp.add_argument(
163
- f"--{k.replace('_', '-')}",
164
- **keyword_args,
165
- dest=k,
166
- help=v,
167
- )
168
- parser_comp.add_argument(
169
- "--default-emoji",
170
- dest="default_emoji",
171
- default=self.compression_presets["custom"]["default_emoji"],
172
- help=self.help["comp"]["default_emoji"],
173
- )
174
-
175
- parser_cred = parser.add_argument_group("Credentials options")
176
- flags_cred_bool = (
177
- "signal_get_auth",
178
- "telethon_setup",
179
- "kakao_get_auth",
180
- "kakao_get_auth_desktop",
181
- "line_get_auth",
182
- "discord_get_auth",
183
- "save_cred",
184
- )
185
- for k, v in self.help["cred"].items():
186
- keyword_args = {}
187
- if k in flags_cred_bool:
188
- keyword_args = {"action": "store_true"}
189
- parser_cred.add_argument(
190
- f"--{k.replace('_', '-')}",
191
- **keyword_args,
192
- dest=k,
193
- help=v,
194
- )
195
-
196
- args = parser.parse_args()
197
-
198
- if args.custom_presets:
199
- try:
200
- custom_presets = JsonManager.load_json(Path(args.custom_presets))
201
- self.compression_presets: Dict[Any, Any] = merge( # type: ignore
202
- self.compression_presets, # type: ignore
203
- custom_presets,
204
- )
205
- except RuntimeError:
206
- print(f"Error: Cannot load custom presets from {args.custom_presets}")
207
-
208
- self.cb.no_confirm = args.no_confirm
209
- self.cb.no_progress = args.no_progress
210
-
211
- self.opt_input = self.get_opt_input(args)
212
- self.opt_output = self.get_opt_output(args)
213
- self.opt_comp = self.get_opt_comp(args)
214
- self.opt_cred = self.get_opt_cred(args)
215
-
216
- job = Job(
217
- self.opt_input,
218
- self.opt_comp,
219
- self.opt_output,
220
- self.opt_cred,
221
- self.cb.msg,
222
- self.cb.msg_block,
223
- self.cb.bar,
224
- self.cb.ask_bool,
225
- self.cb.ask_str,
226
- )
227
-
228
- signal.signal(signal.SIGINT, job.cancel)
229
- status = job.start()
230
- sys.exit(status)
231
-
232
- def get_opt_input(self, args: Namespace) -> InputOption:
233
- download_options = {
234
- "auto": args.download_auto,
235
- "signal": args.download_signal,
236
- "line": args.download_line,
237
- "telegram": args.download_telegram,
238
- "telegram_telethon": args.download_telegram_telethon,
239
- "kakao": args.download_kakao,
240
- "band": args.download_band,
241
- "ogq": args.download_ogq,
242
- "viber": args.download_viber,
243
- "discord": args.download_discord,
244
- "discord_emoji": args.download_discord_emoji,
245
- }
246
-
247
- download_option = "local"
248
- url = ""
249
- for k, v in download_options.items():
250
- if v:
251
- download_option = k
252
- url = v
253
- break
254
-
255
- if download_option == "auto":
256
- detected_download_option = UrlDetect.detect(url)
257
- if detected_download_option:
258
- download_option = detected_download_option
259
- self.cb.msg(f"Detected URL input source: {download_option}")
260
- else:
261
- self.cb.msg(f"Error: Unrecognied URL input source for url: {url}")
262
- sys.exit()
263
-
264
- opt_input = InputOption(
265
- option=download_option,
266
- url=url,
267
- dir=Path(args.input_dir).resolve()
268
- if args.input_dir
269
- else DEFAULT_DIR / "stickers_input",
270
- )
271
-
272
- return opt_input
273
-
274
- def get_opt_output(self, args: Namespace) -> OutputOption:
275
- if args.export_whatsapp:
276
- export_option = "whatsapp"
277
- elif args.export_signal:
278
- export_option = "signal"
279
- elif args.export_telegram:
280
- export_option = "telegram"
281
- elif args.export_telegram_emoji:
282
- export_option = "telegram_emoji"
283
- elif args.export_telegram_telethon:
284
- export_option = "telegram_telethon"
285
- elif args.export_telegram_emoji_telethon:
286
- export_option = "telegram_emoji_telethon"
287
- elif args.export_viber:
288
- export_option = "viber"
289
- elif args.export_imessage:
290
- export_option = "imessage"
291
- else:
292
- export_option = "local"
293
-
294
- opt_output = OutputOption(
295
- option=export_option,
296
- dir=Path(args.output_dir).resolve()
297
- if args.output_dir
298
- else DEFAULT_DIR / "stickers_output",
299
- title=args.title,
300
- author=args.author,
301
- )
302
-
303
- return opt_output
304
-
305
- def get_opt_comp(self, args: Namespace) -> CompOption:
306
- preset: str = args.preset if args.preset else "auto"
307
- if args.preset == "custom":
308
- if (
309
- sum(
310
- (
311
- args.export_whatsapp,
312
- args.export_signal,
313
- args.export_telegram,
314
- args.export_telegram_emoji,
315
- args.export_telegram_telethon,
316
- args.export_telegram_emoji_telethon,
317
- args.export_viber,
318
- args.export_imessage,
319
- )
320
- )
321
- > 1
322
- ):
323
- # Let the verify functions in export do the compression
324
- args.no_compress = True
325
- elif args.export_whatsapp:
326
- preset = "whatsapp"
327
- elif args.export_signal:
328
- preset = "signal"
329
- elif args.export_telegram or args.export_telegram_telethon:
330
- preset = "telegram"
331
- elif args.export_telegram_emoji or args.export_telegram_emoji_telethon:
332
- preset = "telegram_emoji"
333
- elif args.export_viber:
334
- preset = "viber"
335
- elif args.export_imessage:
336
- preset = "imessage_small"
337
- elif args.preset == "auto":
338
- output_option = (
339
- self.opt_output.option if self.opt_output.option else "local"
340
- )
341
- if output_option == "local":
342
- preset = "custom"
343
- args.no_compress = True
344
- self.cb.msg(
345
- "Auto compression option set to no_compress (Reason: Export to local directory only)"
346
- )
347
- elif "telegram_emoji" in output_option:
348
- preset = "telegram_emoji"
349
- self.cb.msg(f"Auto compression option set to {preset}")
350
- elif "telegram" in output_option:
351
- preset = "telegram"
352
- self.cb.msg(f"Auto compression option set to {preset}")
353
- elif output_option == "imessage":
354
- preset = "imessage_small"
355
- self.cb.msg(f"Auto compression option set to {preset}")
356
- else:
357
- preset = output_option
358
- self.cb.msg(f"Auto compression option set to {preset}")
359
-
360
- opt_comp = CompOption(
361
- preset=preset,
362
- size_max_img=self.compression_presets[preset]["size_max"]["img"]
363
- if args.img_size_max is None
364
- else args.img_size_max,
365
- size_max_vid=self.compression_presets[preset]["size_max"]["vid"]
366
- if args.vid_size_max is None
367
- else args.vid_size_max,
368
- format_img=(
369
- self.compression_presets[preset]["format"]["img"]
370
- if args.img_format is None
371
- else args.img_format,
372
- ),
373
- format_vid=(
374
- self.compression_presets[preset]["format"]["vid"]
375
- if args.vid_format is None
376
- else args.vid_format,
377
- ),
378
- fps_min=self.compression_presets[preset]["fps"]["min"]
379
- if args.fps_min is None
380
- else args.fps_min,
381
- fps_max=self.compression_presets[preset]["fps"]["max"]
382
- if args.fps_max is None
383
- else args.fps_max,
384
- fps_power=self.compression_presets[preset]["fps"]["power"]
385
- if args.fps_power is None
386
- else args.fps_power,
387
- res_w_min=self.compression_presets[preset]["res"]["w"]["min"]
388
- if args.res_w_min is None
389
- else args.res_w_min,
390
- res_w_max=self.compression_presets[preset]["res"]["w"]["max"]
391
- if args.res_w_max is None
392
- else args.res_w_max,
393
- res_h_min=self.compression_presets[preset]["res"]["h"]["min"]
394
- if args.res_h_min is None
395
- else args.res_h_min,
396
- res_h_max=self.compression_presets[preset]["res"]["h"]["max"]
397
- if args.res_h_max is None
398
- else args.res_h_max,
399
- res_power=self.compression_presets[preset]["res"]["power"]
400
- if args.res_power is None
401
- else args.res_power,
402
- res_snap_pow2=self.compression_presets[preset]["res"]["snap_pow2"]
403
- if args.res_snap_pow2 is None and args.no_res_snap_pow2 is None
404
- else args.res_snap_pow2,
405
- quality_min=self.compression_presets[preset]["quality"]["min"]
406
- if args.quality_min is None
407
- else args.quality_min,
408
- quality_max=self.compression_presets[preset]["quality"]["max"]
409
- if args.quality_max is None
410
- else args.quality_max,
411
- quality_power=self.compression_presets[preset]["quality"]["power"]
412
- if args.quality_power is None
413
- else args.quality_power,
414
- color_min=self.compression_presets[preset]["color"]["min"]
415
- if args.color_min is None
416
- else args.color_min,
417
- color_max=self.compression_presets[preset]["color"]["max"]
418
- if args.color_max is None
419
- else args.color_max,
420
- color_power=self.compression_presets[preset]["color"]["power"]
421
- if args.color_power is None
422
- else args.color_power,
423
- duration_min=self.compression_presets[preset]["duration"]["min"]
424
- if args.duration_min is None
425
- else args.duration_min,
426
- duration_max=self.compression_presets[preset]["duration"]["max"]
427
- if args.duration_max is None
428
- else args.duration_max,
429
- bg_color=self.compression_presets[preset]["bg_color"]
430
- if args.bg_color is None
431
- else args.bg_color,
432
- padding_percent=self.compression_presets[preset]["padding_percent"]
433
- if args.padding_percent is None
434
- else args.padding_percent,
435
- steps=self.compression_presets[preset]["steps"]
436
- if args.steps is None
437
- else args.steps,
438
- fake_vid=self.compression_presets[preset]["fake_vid"]
439
- if args.fake_vid is None and args.no_fake_vid is None
440
- else args.fake_vid,
441
- chromium_path=args.chromium_path,
442
- cache_dir=args.cache_dir,
443
- scale_filter=self.compression_presets[preset]["scale_filter"]
444
- if args.scale_filter is None
445
- else args.scale_filter,
446
- quantize_method=self.compression_presets[preset]["quantize_method"]
447
- if args.quantize_method is None
448
- else args.quantize_method,
449
- default_emoji=self.compression_presets[preset]["default_emoji"]
450
- if args.default_emoji is None
451
- else args.default_emoji,
452
- no_compress=args.no_compress,
453
- processes=args.processes if args.processes else ceil(cpu_count() / 2),
454
- )
455
-
456
- return opt_comp
457
-
458
- def get_opt_cred(self, args: Namespace) -> CredOption:
459
- creds_path = CONFIG_DIR / "creds.json"
460
- creds = {}
461
- if creds_path.is_file():
462
- try:
463
- creds = JsonManager.load_json(creds_path)
464
- except JSONDecodeError:
465
- self.cb.msg("Warning: creds.json content is corrupted")
466
- creds = {}
467
- else:
468
- creds = {}
469
-
470
- if creds:
471
- self.cb.msg("Loaded credentials from creds.json")
472
-
473
- opt_cred = CredOption(
474
- signal_uuid=args.signal_uuid
475
- if args.signal_uuid
476
- else creds.get("signal", {}).get("uuid"),
477
- signal_password=args.signal_password
478
- if args.signal_password
479
- else creds.get("signal", {}).get("password"),
480
- telegram_token=args.telegram_token
481
- if args.telegram_token
482
- else creds.get("telegram", {}).get("token"),
483
- telegram_userid=args.telegram_userid
484
- if args.telegram_userid
485
- else creds.get("telegram", {}).get("userid"),
486
- telethon_api_id=creds.get("telethon", {}).get("api_id"),
487
- telethon_api_hash=creds.get("telethon", {}).get("api_hash"),
488
- kakao_auth_token=args.kakao_auth_token
489
- if args.kakao_auth_token
490
- else creds.get("kakao", {}).get("auth_token"),
491
- kakao_username=args.kakao_username
492
- if args.kakao_username
493
- else creds.get("kakao", {}).get("username"),
494
- kakao_password=args.kakao_password
495
- if args.kakao_password
496
- else creds.get("kakao", {}).get("password"),
497
- kakao_country_code=args.kakao_country_code
498
- if args.kakao_country_code
499
- else creds.get("kakao", {}).get("country_code"),
500
- kakao_phone_number=args.kakao_phone_number
501
- if args.kakao_phone_number
502
- else creds.get("kakao", {}).get("phone_number"),
503
- line_cookies=args.line_cookies
504
- if args.line_cookies
505
- else creds.get("line", {}).get("cookies"),
506
- viber_auth=args.viber_auth
507
- if args.viber_auth
508
- else creds.get("viber", {}).get("auth"),
509
- discord_token=args.discord_token
510
- if args.discord_token
511
- else creds.get("discord", {}).get("token"),
512
- )
513
-
514
- if args.kakao_get_auth:
515
- get_kakao_auth = GetKakaoAuth(
516
- opt_cred=opt_cred,
517
- cb_msg=self.cb.msg,
518
- cb_msg_block=self.cb.msg_block,
519
- cb_ask_str=self.cb.ask_str,
520
- )
521
- auth_token = get_kakao_auth.get_cred()
522
-
523
- if auth_token:
524
- opt_cred.kakao_auth_token = auth_token
525
-
526
- self.cb.msg(f"Got auth_token successfully: {auth_token}")
527
-
528
- if args.kakao_get_auth_desktop:
529
- get_kakao_desktop_auth = GetKakaoDesktopAuth(
530
- cb_ask_str=self.cb.ask_str,
531
- )
532
- kakao_bin_path = None
533
- if args.kakao_bin_path:
534
- kakao_bin_path = args.kakao_bin_path
535
- auth_token, msg = get_kakao_desktop_auth.get_cred(kakao_bin_path)
536
-
537
- if auth_token:
538
- opt_cred.kakao_auth_token = auth_token
539
-
540
- self.cb.msg(msg)
541
-
542
- if args.signal_get_auth:
543
- m = GetSignalAuth(cb_msg=self.cb.msg, cb_ask_str=self.cb.ask_str)
544
-
545
- uuid, password = m.get_cred()
546
- if uuid and password:
547
- opt_cred.signal_uuid = uuid
548
- opt_cred.signal_password = password
549
-
550
- self.cb.msg(f"Got uuid and password successfully: {uuid}, {password}")
551
-
552
- self.cb.msg("Failed to get uuid and password")
553
-
554
- if args.telethon_setup:
555
- telethon_setup = TelethonSetup(opt_cred, self.cb.ask_str)
556
- success, _, telethon_api_id, telethon_api_hash = telethon_setup.start()
557
-
558
- if success:
559
- opt_cred.telethon_api_id = telethon_api_id
560
- opt_cred.telethon_api_hash = telethon_api_hash
561
-
562
- self.cb.msg("Telethon setup successful")
563
- else:
564
- self.cb.msg("Telethon setup failed")
565
-
566
- if args.line_get_auth:
567
- get_line_auth = GetLineAuth()
568
-
569
- line_cookies = get_line_auth.get_cred()
570
-
571
- if line_cookies:
572
- opt_cred.line_cookies = line_cookies
573
-
574
- self.cb.msg("Got Line cookies successfully")
575
- else:
576
- self.cb.msg(
577
- "Failed to get Line cookies. Have you logged in the web browser?"
578
- )
579
-
580
- if args.viber_get_auth:
581
- get_viber_auth = GetViberAuth(self.cb.ask_str)
582
-
583
- viber_bin_path = None
584
- if args.viber_bin_path:
585
- viber_bin_path = args.viber_bin_path
586
-
587
- viber_auth, msg = get_viber_auth.get_cred(viber_bin_path)
588
-
589
- if viber_auth:
590
- opt_cred.viber_auth = viber_auth
591
-
592
- self.cb.msg(msg)
593
-
594
- if args.discord_get_auth:
595
- get_discord_auth = GetDiscordAuth(self.cb.msg)
596
- discord_token, msg = get_discord_auth.get_cred()
597
-
598
- if discord_token:
599
- opt_cred.discord_token = discord_token
600
-
601
- self.cb.msg(msg)
602
-
603
- if args.save_cred:
604
- creds_path = CONFIG_DIR / "creds.json"
605
- JsonManager.save_json(creds_path, opt_cred.to_dict())
606
- self.cb.msg("Saved credentials to creds.json")
607
-
608
- return opt_cred
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import signal
4
+ import sys
5
+ from argparse import Namespace
6
+ from json.decoder import JSONDecodeError
7
+ from math import ceil
8
+ from multiprocessing import cpu_count
9
+ from pathlib import Path
10
+ from typing import Any, Dict
11
+
12
+ from mergedeep import merge # type: ignore
13
+
14
+ from sticker_convert.auth.auth_discord import AuthDiscord
15
+ from sticker_convert.auth.auth_kakao_android_login import AuthKakaoAndroidLogin
16
+ from sticker_convert.auth.auth_kakao_desktop_login import AuthKakaoDesktopLogin
17
+ from sticker_convert.auth.auth_kakao_desktop_memdump import AuthKakaoDesktopMemdump
18
+ from sticker_convert.auth.auth_line import AuthLine
19
+ from sticker_convert.auth.auth_signal import AuthSignal
20
+ from sticker_convert.auth.auth_telethon import AuthTelethon
21
+ from sticker_convert.auth.auth_viber import AuthViber
22
+ from sticker_convert.definitions import CONFIG_DIR, DEFAULT_DIR
23
+ from sticker_convert.job import Job
24
+ from sticker_convert.job_option import CompOption, CredOption, InputOption, OutputOption
25
+ from sticker_convert.utils.callback import CallbackCli
26
+ from sticker_convert.utils.files.json_manager import JsonManager
27
+ from sticker_convert.utils.translate import LANG_DICT, I
28
+ from sticker_convert.utils.url_detect import UrlDetect
29
+ from sticker_convert.version import __version__
30
+
31
+
32
+ class CLI:
33
+ def __init__(self) -> None:
34
+ self.MSG_MORAL = I(
35
+ "sticker-convert is Free and Opensource software by laggykiller\n"
36
+ "{project_url}\n"
37
+ "Please use the stickers with your friends only.\n"
38
+ "It is illegal and immoral to sell stickers downloaded from this program."
39
+ )
40
+ self.PROJECT_URL = "https://github.com/laggykiller/sticker-convert"
41
+ self.cb = CallbackCli()
42
+
43
+ def cli(self) -> None:
44
+ print(self.MSG_MORAL.format(project_url=self.PROJECT_URL))
45
+ print()
46
+ try:
47
+ from sticker_convert.utils.files.json_resources_loader import load_resource_json
48
+ except RuntimeError as e:
49
+ self.cb.put(str(e))
50
+ return
51
+
52
+ self.help = load_resource_json("help")
53
+ self.input_presets = load_resource_json("input")
54
+ self.compression_presets = load_resource_json("compression")
55
+ self.output_presets = load_resource_json("output")
56
+ self.emoji_list = load_resource_json("emoji")
57
+
58
+ parser = argparse.ArgumentParser(
59
+ description=I("CLI for sticker-convert"),
60
+ formatter_class=argparse.RawTextHelpFormatter,
61
+ )
62
+
63
+ parser.add_argument("--version", action="version", version=__version__)
64
+ parser.add_argument(
65
+ "--no-confirm",
66
+ dest="no_confirm",
67
+ action="store_true",
68
+ help=self.help["global"]["no_confirm"],
69
+ )
70
+ parser.add_argument(
71
+ "--no-progress",
72
+ dest="no_progress",
73
+ action="store_true",
74
+ help=self.help["global"]["no_progress"],
75
+ )
76
+ parser.add_argument(
77
+ "--custom-presets",
78
+ dest="custom_presets",
79
+ default=None,
80
+ help=self.help["global"]["custom_presets"],
81
+ )
82
+ parser.add_argument(
83
+ "--lang",
84
+ dest="lang",
85
+ default=None,
86
+ help=self.help["global"]["lang"],
87
+ choices=LANG_DICT.keys(),
88
+ )
89
+
90
+ parser_input = parser.add_argument_group(I("Input options"))
91
+ for k, v_str in self.help["input"].items():
92
+ parser_input.add_argument(f"--{k.replace('_', '-')}", dest=k, help=v_str)
93
+ parser_input_src = parser_input.add_mutually_exclusive_group()
94
+ for k, v_dict in self.input_presets.items():
95
+ if k == "local":
96
+ continue
97
+ parser_input_src.add_argument(
98
+ f"--download-{k.replace('_', '-')}",
99
+ dest=f"download_{k}",
100
+ help=f"{v_dict['help']}\n({v_dict['example']})",
101
+ )
102
+
103
+ parser_output = parser.add_argument_group(I("Output options"))
104
+ for k, v_str in self.help["output"].items():
105
+ parser_output.add_argument(f"--{k.replace('_', '-')}", dest=k, help=v_str)
106
+ parser_output_dst = parser_output.add_mutually_exclusive_group()
107
+ for k, v_dict in self.output_presets.items():
108
+ if k == "local":
109
+ continue
110
+ parser_output_dst.add_argument(
111
+ f"--export-{k.replace('_', '-')}",
112
+ dest=f"export_{k}",
113
+ action="store_true",
114
+ help=v_dict["help"],
115
+ )
116
+
117
+ parser_comp = parser.add_argument_group(I("Compression options"))
118
+ parser_comp.add_argument(
119
+ "--no-compress",
120
+ dest="no_compress",
121
+ action="store_true",
122
+ help=self.help["comp"]["no_compress"],
123
+ )
124
+ parser_comp.add_argument(
125
+ "--preset",
126
+ dest="preset",
127
+ default="auto",
128
+ choices=self.compression_presets.keys(),
129
+ help=self.help["comp"]["preset"],
130
+ )
131
+ flags_comp_int = (
132
+ "steps",
133
+ "processes",
134
+ "fps_min",
135
+ "fps_max",
136
+ "res_min",
137
+ "res_max",
138
+ "res_w_min",
139
+ "res_w_max",
140
+ "res_h_min",
141
+ "res_h_max",
142
+ "quality_min",
143
+ "quality_max",
144
+ "color_min",
145
+ "color_max",
146
+ "duration_min",
147
+ "duration_max",
148
+ "vid_size_max",
149
+ "img_size_max",
150
+ "padding_percent",
151
+ )
152
+ flags_comp_float = ("fps_power", "res_power", "quality_power", "color_power")
153
+ flags_comp_str = (
154
+ "bg_color",
155
+ "vid_format",
156
+ "img_format",
157
+ "cache_dir",
158
+ "scale_filter",
159
+ "quantize_method",
160
+ "chromium_path",
161
+ )
162
+ flags_comp_bool = (
163
+ "fake_vid",
164
+ "no_fake_vid",
165
+ "res_snap_pow2",
166
+ "no_res_snap_pow2",
167
+ )
168
+ keyword_args: Dict[str, Any]
169
+ for k, v in self.help["comp"].items():
170
+ if k in flags_comp_int:
171
+ keyword_args = {"type": int, "default": None}
172
+ elif k in flags_comp_float:
173
+ keyword_args = {"type": float, "default": None}
174
+ elif k in flags_comp_str:
175
+ keyword_args = {"default": None}
176
+ elif k in flags_comp_bool:
177
+ keyword_args = {"action": "store_true", "default": None}
178
+ else:
179
+ continue
180
+ parser_comp.add_argument(
181
+ f"--{k.replace('_', '-')}",
182
+ **keyword_args,
183
+ dest=k,
184
+ help=v,
185
+ )
186
+ parser_comp.add_argument(
187
+ "--default-emoji",
188
+ dest="default_emoji",
189
+ default=self.compression_presets["custom"]["default_emoji"],
190
+ help=self.help["comp"]["default_emoji"],
191
+ )
192
+
193
+ parser_cred = parser.add_argument_group(I("Credentials options"))
194
+ flags_cred_bool = (
195
+ "signal_get_auth",
196
+ "telethon_setup",
197
+ "kakao_get_auth_desktop_memdump",
198
+ "kakao_get_auth_desktop_login",
199
+ "kakao_get_auth_android_login",
200
+ "line_get_auth",
201
+ "discord_get_auth",
202
+ "save_cred",
203
+ )
204
+ for k, v in self.help["cred"].items():
205
+ keyword_args = {}
206
+ if k in flags_cred_bool:
207
+ keyword_args = {"action": "store_true"}
208
+ parser_cred.add_argument(
209
+ f"--{k.replace('_', '-')}",
210
+ **keyword_args,
211
+ dest=k,
212
+ help=v,
213
+ )
214
+
215
+ args = parser.parse_args()
216
+
217
+ if args.custom_presets:
218
+ try:
219
+ custom_presets = JsonManager.load_json(Path(args.custom_presets))
220
+ self.compression_presets: Dict[Any, Any] = merge( # type: ignore
221
+ self.compression_presets, # type: ignore
222
+ custom_presets,
223
+ )
224
+ except RuntimeError:
225
+ print(
226
+ I("Error: Cannot load custom presets from {}").format(
227
+ args.custom_presets
228
+ )
229
+ )
230
+
231
+ self.cb.no_confirm = args.no_confirm
232
+ self.cb.no_progress = args.no_progress
233
+
234
+ self.opt_input = self.get_opt_input(args)
235
+ self.opt_output = self.get_opt_output(args)
236
+ self.opt_comp = self.get_opt_comp(args)
237
+ self.opt_cred = self.get_opt_cred(args)
238
+
239
+ job = Job(
240
+ self.opt_input, self.opt_comp, self.opt_output, self.opt_cred, self.cb
241
+ )
242
+
243
+ signal.signal(signal.SIGINT, job.cancel)
244
+ status = job.start()
245
+ sys.exit(status)
246
+
247
+ def get_opt_input(self, args: Namespace) -> InputOption:
248
+ download_options = {
249
+ "auto": args.download_auto,
250
+ "signal": args.download_signal,
251
+ "line": args.download_line,
252
+ "telegram": args.download_telegram,
253
+ "telegram_telethon": args.download_telegram_telethon,
254
+ "kakao": args.download_kakao,
255
+ "band": args.download_band,
256
+ "ogq": args.download_ogq,
257
+ "viber": args.download_viber,
258
+ "discord": args.download_discord,
259
+ "discord_emoji": args.download_discord_emoji,
260
+ }
261
+
262
+ download_option = "local"
263
+ url = ""
264
+ for k, v in download_options.items():
265
+ if v:
266
+ download_option = k
267
+ url = v
268
+ break
269
+
270
+ if download_option == "auto":
271
+ detected_download_option = UrlDetect.detect(url)
272
+ if detected_download_option:
273
+ download_option = detected_download_option
274
+ self.cb.put(I("Detected URL input source: {}").format(download_option))
275
+ else:
276
+ self.cb.put(
277
+ I("Error: Unrecognied URL input source for url: {}").format(url)
278
+ )
279
+ sys.exit()
280
+
281
+ opt_input = InputOption(
282
+ option=download_option,
283
+ url=url,
284
+ dir=Path(args.input_dir).resolve()
285
+ if args.input_dir
286
+ else DEFAULT_DIR / "stickers_input",
287
+ )
288
+
289
+ return opt_input
290
+
291
+ def get_opt_output(self, args: Namespace) -> OutputOption:
292
+ if args.export_whatsapp:
293
+ export_option = "whatsapp"
294
+ elif args.export_signal:
295
+ export_option = "signal"
296
+ elif args.export_telegram:
297
+ export_option = "telegram"
298
+ elif args.export_telegram_emoji:
299
+ export_option = "telegram_emoji"
300
+ elif args.export_telegram_telethon:
301
+ export_option = "telegram_telethon"
302
+ elif args.export_telegram_emoji_telethon:
303
+ export_option = "telegram_emoji_telethon"
304
+ elif args.export_viber:
305
+ export_option = "viber"
306
+ elif args.export_imessage:
307
+ export_option = "imessage"
308
+ else:
309
+ export_option = "local"
310
+
311
+ opt_output = OutputOption(
312
+ option=export_option,
313
+ dir=Path(args.output_dir).resolve()
314
+ if args.output_dir
315
+ else DEFAULT_DIR / "stickers_output",
316
+ title=args.title,
317
+ author=args.author,
318
+ )
319
+
320
+ return opt_output
321
+
322
+ def get_opt_comp(self, args: Namespace) -> CompOption:
323
+ preset: str = args.preset if args.preset else "auto"
324
+ if args.preset == "custom":
325
+ if (
326
+ sum(
327
+ (
328
+ args.export_whatsapp,
329
+ args.export_signal,
330
+ args.export_telegram,
331
+ args.export_telegram_emoji,
332
+ args.export_telegram_telethon,
333
+ args.export_telegram_emoji_telethon,
334
+ args.export_viber,
335
+ args.export_imessage,
336
+ )
337
+ )
338
+ > 1
339
+ ):
340
+ # Let the verify functions in export do the compression
341
+ args.no_compress = True
342
+ elif args.export_whatsapp:
343
+ preset = "whatsapp"
344
+ elif args.export_signal:
345
+ preset = "signal"
346
+ elif args.export_telegram or args.export_telegram_telethon:
347
+ preset = "telegram"
348
+ elif args.export_telegram_emoji or args.export_telegram_emoji_telethon:
349
+ preset = "telegram_emoji"
350
+ elif args.export_viber:
351
+ preset = "viber"
352
+ elif args.export_imessage:
353
+ preset = "imessage_small"
354
+ elif args.preset == "auto":
355
+ msg_base = I("Auto compression option set to {}")
356
+ output_option = (
357
+ self.opt_output.option if self.opt_output.option else "local"
358
+ )
359
+ if output_option == "local":
360
+ preset = "custom"
361
+ args.no_compress = True
362
+ self.cb.put(
363
+ msg_base.format("no_compress")
364
+ + I(" Reason: Export to local directory only")
365
+ )
366
+ elif "telegram_emoji" in output_option:
367
+ preset = "telegram_emoji"
368
+ self.cb.put(msg_base.format(preset))
369
+ elif "telegram" in output_option:
370
+ preset = "telegram"
371
+ self.cb.put(msg_base.format(preset))
372
+ elif output_option == "imessage":
373
+ preset = "imessage_small"
374
+ self.cb.put(msg_base.format(preset))
375
+ else:
376
+ preset = output_option
377
+ self.cb.put(msg_base.format(preset))
378
+
379
+ opt_comp = CompOption(
380
+ preset=preset,
381
+ size_max_img=self.compression_presets[preset]["size_max"]["img"]
382
+ if args.img_size_max is None
383
+ else args.img_size_max,
384
+ size_max_vid=self.compression_presets[preset]["size_max"]["vid"]
385
+ if args.vid_size_max is None
386
+ else args.vid_size_max,
387
+ format_img=(
388
+ self.compression_presets[preset]["format"]["img"]
389
+ if args.img_format is None
390
+ else args.img_format,
391
+ ),
392
+ format_vid=(
393
+ self.compression_presets[preset]["format"]["vid"]
394
+ if args.vid_format is None
395
+ else args.vid_format,
396
+ ),
397
+ fps_min=self.compression_presets[preset]["fps"]["min"]
398
+ if args.fps_min is None
399
+ else args.fps_min,
400
+ fps_max=self.compression_presets[preset]["fps"]["max"]
401
+ if args.fps_max is None
402
+ else args.fps_max,
403
+ fps_power=self.compression_presets[preset]["fps"]["power"]
404
+ if args.fps_power is None
405
+ else args.fps_power,
406
+ res_w_min=self.compression_presets[preset]["res"]["w"]["min"]
407
+ if args.res_w_min is None
408
+ else args.res_w_min,
409
+ res_w_max=self.compression_presets[preset]["res"]["w"]["max"]
410
+ if args.res_w_max is None
411
+ else args.res_w_max,
412
+ res_h_min=self.compression_presets[preset]["res"]["h"]["min"]
413
+ if args.res_h_min is None
414
+ else args.res_h_min,
415
+ res_h_max=self.compression_presets[preset]["res"]["h"]["max"]
416
+ if args.res_h_max is None
417
+ else args.res_h_max,
418
+ res_power=self.compression_presets[preset]["res"]["power"]
419
+ if args.res_power is None
420
+ else args.res_power,
421
+ res_snap_pow2=self.compression_presets[preset]["res"]["snap_pow2"]
422
+ if args.res_snap_pow2 is None and args.no_res_snap_pow2 is None
423
+ else args.res_snap_pow2,
424
+ quality_min=self.compression_presets[preset]["quality"]["min"]
425
+ if args.quality_min is None
426
+ else args.quality_min,
427
+ quality_max=self.compression_presets[preset]["quality"]["max"]
428
+ if args.quality_max is None
429
+ else args.quality_max,
430
+ quality_power=self.compression_presets[preset]["quality"]["power"]
431
+ if args.quality_power is None
432
+ else args.quality_power,
433
+ color_min=self.compression_presets[preset]["color"]["min"]
434
+ if args.color_min is None
435
+ else args.color_min,
436
+ color_max=self.compression_presets[preset]["color"]["max"]
437
+ if args.color_max is None
438
+ else args.color_max,
439
+ color_power=self.compression_presets[preset]["color"]["power"]
440
+ if args.color_power is None
441
+ else args.color_power,
442
+ duration_min=self.compression_presets[preset]["duration"]["min"]
443
+ if args.duration_min is None
444
+ else args.duration_min,
445
+ duration_max=self.compression_presets[preset]["duration"]["max"]
446
+ if args.duration_max is None
447
+ else args.duration_max,
448
+ bg_color=self.compression_presets[preset]["bg_color"]
449
+ if args.bg_color is None
450
+ else args.bg_color,
451
+ padding_percent=self.compression_presets[preset]["padding_percent"]
452
+ if args.padding_percent is None
453
+ else args.padding_percent,
454
+ steps=self.compression_presets[preset]["steps"]
455
+ if args.steps is None
456
+ else args.steps,
457
+ fake_vid=self.compression_presets[preset]["fake_vid"]
458
+ if args.fake_vid is None and args.no_fake_vid is None
459
+ else args.fake_vid,
460
+ chromium_path=args.chromium_path,
461
+ cache_dir=args.cache_dir,
462
+ scale_filter=self.compression_presets[preset]["scale_filter"]
463
+ if args.scale_filter is None
464
+ else args.scale_filter,
465
+ quantize_method=self.compression_presets[preset]["quantize_method"]
466
+ if args.quantize_method is None
467
+ else args.quantize_method,
468
+ default_emoji=self.compression_presets[preset]["default_emoji"]
469
+ if args.default_emoji is None
470
+ else args.default_emoji,
471
+ no_compress=args.no_compress,
472
+ processes=args.processes if args.processes else ceil(cpu_count() / 2),
473
+ )
474
+
475
+ return opt_comp
476
+
477
+ def get_opt_cred(self, args: Namespace) -> CredOption:
478
+ creds_path = CONFIG_DIR / "creds.json"
479
+ creds = {}
480
+ if creds_path.is_file():
481
+ try:
482
+ creds = JsonManager.load_json(creds_path)
483
+ except JSONDecodeError:
484
+ self.cb.put(I("Warning: creds.json content is corrupted"))
485
+ creds = {}
486
+ else:
487
+ creds = {}
488
+
489
+ if creds:
490
+ self.cb.put(I("Loaded credentials from creds.json"))
491
+
492
+ opt_cred = CredOption(
493
+ signal_uuid=args.signal_uuid
494
+ if args.signal_uuid
495
+ else creds.get("signal", {}).get("uuid"),
496
+ signal_password=args.signal_password
497
+ if args.signal_password
498
+ else creds.get("signal", {}).get("password"),
499
+ telegram_token=args.telegram_token
500
+ if args.telegram_token
501
+ else creds.get("telegram", {}).get("token"),
502
+ telegram_userid=args.telegram_userid
503
+ if args.telegram_userid
504
+ else creds.get("telegram", {}).get("userid"),
505
+ telethon_api_id=creds.get("telethon", {}).get("api_id"),
506
+ telethon_api_hash=creds.get("telethon", {}).get("api_hash"),
507
+ kakao_auth_token=args.kakao_auth_token
508
+ if args.kakao_auth_token
509
+ else creds.get("kakao", {}).get("auth_token"),
510
+ kakao_username=args.kakao_username
511
+ if args.kakao_username
512
+ else creds.get("kakao", {}).get("username"),
513
+ kakao_password=args.kakao_password
514
+ if args.kakao_password
515
+ else creds.get("kakao", {}).get("password"),
516
+ kakao_country_code=args.kakao_country_code
517
+ if args.kakao_country_code
518
+ else creds.get("kakao", {}).get("country_code"),
519
+ kakao_phone_number=args.kakao_phone_number
520
+ if args.kakao_phone_number
521
+ else creds.get("kakao", {}).get("phone_number"),
522
+ line_cookies=args.line_cookies
523
+ if args.line_cookies
524
+ else creds.get("line", {}).get("cookies"),
525
+ viber_auth=args.viber_auth
526
+ if args.viber_auth
527
+ else creds.get("viber", {}).get("auth"),
528
+ discord_token=args.discord_token
529
+ if args.discord_token
530
+ else creds.get("discord", {}).get("token"),
531
+ )
532
+
533
+ if args.kakao_get_auth_android_login:
534
+ get_kakao_auth_android_login = AuthKakaoAndroidLogin(opt_cred, self.cb)
535
+ auth_token, msg = get_kakao_auth_android_login.get_cred()
536
+
537
+ if auth_token:
538
+ opt_cred.kakao_auth_token = auth_token
539
+
540
+ self.cb.put(msg)
541
+
542
+ if args.kakao_get_auth_desktop_memdump:
543
+ get_kakao_auth_desktop_memdump = AuthKakaoDesktopMemdump(opt_cred, self.cb)
544
+ kakao_bin_path = None
545
+ if args.kakao_bin_path:
546
+ kakao_bin_path = args.kakao_bin_path
547
+ auth_token, msg = get_kakao_auth_desktop_memdump.get_cred(kakao_bin_path)
548
+
549
+ if auth_token:
550
+ opt_cred.kakao_auth_token = auth_token
551
+
552
+ self.cb.put(msg)
553
+
554
+ if args.kakao_get_auth_desktop_login:
555
+ get_kakao_auth_desktop_login = AuthKakaoDesktopLogin(opt_cred, self.cb)
556
+ auth_token, msg = get_kakao_auth_desktop_login.get_cred()
557
+
558
+ if auth_token:
559
+ opt_cred.kakao_auth_token = auth_token
560
+
561
+ self.cb.put(msg)
562
+
563
+ if args.signal_get_auth:
564
+ m = AuthSignal(opt_cred, self.cb)
565
+
566
+ uuid, password, msg = m.get_cred()
567
+ if uuid and password:
568
+ opt_cred.signal_uuid = uuid
569
+ opt_cred.signal_password = password
570
+
571
+ self.cb.put(msg)
572
+
573
+ if args.telethon_setup:
574
+ telethon_setup = AuthTelethon(opt_cred, self.cb)
575
+ success, _, telethon_api_id, telethon_api_hash, msg = telethon_setup.start(
576
+ check_auth_only=True
577
+ )
578
+
579
+ if success:
580
+ opt_cred.telethon_api_id = telethon_api_id
581
+ opt_cred.telethon_api_hash = telethon_api_hash
582
+
583
+ self.cb.put(msg)
584
+
585
+ if args.line_get_auth:
586
+ get_line_auth = AuthLine(opt_cred, self.cb)
587
+
588
+ line_cookies, msg = get_line_auth.get_cred()
589
+
590
+ if line_cookies:
591
+ opt_cred.line_cookies = line_cookies
592
+
593
+ self.cb.put(msg)
594
+
595
+ if args.viber_get_auth:
596
+ get_viber_auth = AuthViber(opt_cred, self.cb)
597
+
598
+ viber_bin_path = None
599
+ if args.viber_bin_path:
600
+ viber_bin_path = args.viber_bin_path
601
+
602
+ viber_auth, msg = get_viber_auth.get_cred(viber_bin_path)
603
+
604
+ if viber_auth:
605
+ opt_cred.viber_auth = viber_auth
606
+
607
+ self.cb.put(msg)
608
+
609
+ if args.discord_get_auth:
610
+ get_discord_auth = AuthDiscord(opt_cred, self.cb)
611
+ discord_token, msg = get_discord_auth.get_cred()
612
+
613
+ if discord_token:
614
+ opt_cred.discord_token = discord_token
615
+
616
+ self.cb.put(msg)
617
+
618
+ if args.save_cred:
619
+ creds_path = CONFIG_DIR / "creds.json"
620
+ JsonManager.save_json(creds_path, opt_cred.to_dict())
621
+ self.cb.put(I("Saved credentials to creds.json"))
622
+
623
+ return opt_cred