sticker-convert 2.8.12__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 (124) hide show
  1. sticker_convert/__main__.py +24 -24
  2. sticker_convert/auth/__init__.py +0 -0
  3. sticker_convert/auth/auth_base.py +19 -0
  4. sticker_convert/auth/auth_discord.py +149 -0
  5. sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -300
  6. sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
  7. sticker_convert/auth/auth_kakao_desktop_memdump.py +281 -0
  8. sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
  9. sticker_convert/auth/auth_signal.py +139 -0
  10. sticker_convert/auth/auth_telethon.py +161 -0
  11. sticker_convert/auth/auth_viber.py +250 -0
  12. sticker_convert/auth/telegram_api.py +736 -0
  13. sticker_convert/cli.py +623 -509
  14. sticker_convert/converter.py +1093 -962
  15. sticker_convert/definitions.py +11 -0
  16. sticker_convert/downloaders/download_band.py +111 -0
  17. sticker_convert/downloaders/download_base.py +171 -130
  18. sticker_convert/downloaders/download_discord.py +92 -0
  19. sticker_convert/downloaders/download_kakao.py +417 -255
  20. sticker_convert/downloaders/download_line.py +484 -472
  21. sticker_convert/downloaders/download_ogq.py +80 -0
  22. sticker_convert/downloaders/download_signal.py +108 -92
  23. sticker_convert/downloaders/download_telegram.py +56 -130
  24. sticker_convert/downloaders/download_viber.py +121 -95
  25. sticker_convert/gui.py +788 -795
  26. sticker_convert/gui_components/frames/comp_frame.py +180 -165
  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 -162
  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 -715
  34. sticker_convert/gui_components/windows/base_window.py +7 -2
  35. sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -0
  36. sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -186
  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 -135
  39. sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -0
  40. sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
  41. sticker_convert/ios-message-stickers-template/.gitignore +0 -0
  42. sticker_convert/ios-message-stickers-template/README.md +10 -10
  43. sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
  44. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
  45. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
  46. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
  47. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
  48. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
  49. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
  50. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
  51. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
  52. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
  53. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
  54. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
  55. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
  56. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
  57. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
  58. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
  59. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
  60. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
  61. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
  62. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
  63. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
  64. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
  65. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
  66. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
  67. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
  68. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
  69. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
  70. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  71. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
  72. sticker_convert/job.py +279 -179
  73. sticker_convert/job_option.py +15 -2
  74. sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
  75. sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
  76. sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
  77. sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
  78. sticker_convert/py.typed +0 -0
  79. sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  80. sticker_convert/resources/compression.json +220 -16
  81. sticker_convert/resources/emoji.json +527 -77
  82. sticker_convert/resources/help.ja_JP.json +88 -0
  83. sticker_convert/resources/help.json +24 -10
  84. sticker_convert/resources/help.zh_CN.json +88 -0
  85. sticker_convert/resources/help.zh_TW.json +88 -0
  86. sticker_convert/resources/input.ja_JP.json +74 -0
  87. sticker_convert/resources/input.json +121 -71
  88. sticker_convert/resources/input.zh_CN.json +74 -0
  89. sticker_convert/resources/input.zh_TW.json +74 -0
  90. sticker_convert/resources/memdump_linux.sh +25 -0
  91. sticker_convert/resources/memdump_windows.ps1 +8 -0
  92. sticker_convert/resources/output.ja_JP.json +38 -0
  93. sticker_convert/resources/output.json +24 -0
  94. sticker_convert/resources/output.zh_CN.json +38 -0
  95. sticker_convert/resources/output.zh_TW.json +38 -0
  96. sticker_convert/uploaders/compress_wastickers.py +186 -156
  97. sticker_convert/uploaders/upload_base.py +44 -35
  98. sticker_convert/uploaders/upload_signal.py +218 -173
  99. sticker_convert/uploaders/upload_telegram.py +353 -388
  100. sticker_convert/uploaders/upload_viber.py +178 -0
  101. sticker_convert/uploaders/xcode_imessage.py +295 -285
  102. sticker_convert/utils/callback.py +238 -6
  103. sticker_convert/utils/chrome_remotedebug.py +219 -0
  104. sticker_convert/utils/chromiums/linux.py +52 -0
  105. sticker_convert/utils/chromiums/osx.py +68 -0
  106. sticker_convert/utils/chromiums/windows.py +45 -0
  107. sticker_convert/utils/emoji.py +28 -0
  108. sticker_convert/utils/files/json_resources_loader.py +24 -19
  109. sticker_convert/utils/files/metadata_handler.py +8 -7
  110. sticker_convert/utils/files/run_bin.py +1 -1
  111. sticker_convert/utils/media/codec_info.py +99 -67
  112. sticker_convert/utils/media/format_verify.py +33 -20
  113. sticker_convert/utils/process.py +231 -0
  114. sticker_convert/utils/translate.py +108 -0
  115. sticker_convert/utils/url_detect.py +40 -33
  116. sticker_convert/version.py +1 -1
  117. {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +189 -96
  118. sticker_convert-2.17.0.0.dist-info/RECORD +138 -0
  119. {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +1 -1
  120. sticker_convert/utils/auth/get_signal_auth.py +0 -129
  121. sticker_convert-2.8.12.dist-info/RECORD +0 -101
  122. {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
  123. {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info/licenses}/LICENSE +0 -0
  124. {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
sticker_convert/cli.py CHANGED
@@ -1,509 +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_kakao_auth import GetKakaoAuth
18
- from sticker_convert.utils.auth.get_line_auth import GetLineAuth
19
- from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
20
- from sticker_convert.utils.callback import Callback
21
- from sticker_convert.utils.files.json_manager import JsonManager
22
- from sticker_convert.utils.url_detect import UrlDetect
23
- from sticker_convert.version import __version__
24
-
25
-
26
- class CLI:
27
- def __init__(self) -> None:
28
- self.cb = Callback()
29
-
30
- def cli(self) -> None:
31
- try:
32
- from sticker_convert.utils.files.json_resources_loader import COMPRESSION_JSON, EMOJI_JSON, HELP_JSON, INPUT_JSON, OUTPUT_JSON
33
- except RuntimeError as e:
34
- self.cb.msg(str(e))
35
- return
36
-
37
- self.help = HELP_JSON
38
- self.input_presets = INPUT_JSON
39
- self.compression_presets = COMPRESSION_JSON
40
- self.output_presets = OUTPUT_JSON
41
- self.emoji_list = EMOJI_JSON
42
-
43
- parser = argparse.ArgumentParser(
44
- description="CLI for stickers-convert",
45
- formatter_class=argparse.RawTextHelpFormatter,
46
- )
47
-
48
- parser.add_argument("--version", action="version", version=__version__)
49
- parser.add_argument(
50
- "--no-confirm",
51
- dest="no_confirm",
52
- action="store_true",
53
- help=self.help["global"]["no_confirm"],
54
- )
55
- parser.add_argument(
56
- "--no-progress",
57
- dest="no_progress",
58
- action="store_true",
59
- help=self.help["global"]["no_progress"],
60
- )
61
- parser.add_argument(
62
- "--custom-presets",
63
- dest="custom_presets",
64
- default=None,
65
- help=self.help["global"]["custom_presets"],
66
- )
67
-
68
- parser_input = parser.add_argument_group("Input options")
69
- for k, v_str in self.help["input"].items():
70
- parser_input.add_argument(f'--{k.replace("_", "-")}', dest=k, help=v_str)
71
- parser_input_src = parser_input.add_mutually_exclusive_group()
72
- for k, v_dict in self.input_presets.items():
73
- if k == "local":
74
- continue
75
- parser_input_src.add_argument(
76
- f'--download-{k.replace("_", "-")}',
77
- dest=f"download_{k}",
78
- help=f'{v_dict["help"]}\n({v_dict["example"]})',
79
- )
80
-
81
- parser_output = parser.add_argument_group("Output options")
82
- for k, v_str in self.help["output"].items():
83
- parser_output.add_argument(f'--{k.replace("_", "-")}', dest=k, help=v_str)
84
- parser_output_dst = parser_output.add_mutually_exclusive_group()
85
- for k, v_dict in self.output_presets.items():
86
- if k == "local":
87
- continue
88
- parser_output_dst.add_argument(
89
- f'--export-{k.replace("_", "-")}',
90
- dest=f"export_{k}",
91
- action="store_true",
92
- help=v_dict["help"],
93
- )
94
-
95
- parser_comp = parser.add_argument_group("Compression options")
96
- parser_comp.add_argument(
97
- "--no-compress",
98
- dest="no_compress",
99
- action="store_true",
100
- help=self.help["comp"]["no_compress"],
101
- )
102
- parser_comp.add_argument(
103
- "--preset",
104
- dest="preset",
105
- default="auto",
106
- choices=self.compression_presets.keys(),
107
- help=self.help["comp"]["preset"],
108
- )
109
- flags_comp_int = (
110
- "steps",
111
- "processes",
112
- "fps_min",
113
- "fps_max",
114
- "res_min",
115
- "res_max",
116
- "res_w_min",
117
- "res_w_max",
118
- "res_h_min",
119
- "res_h_max",
120
- "quality_min",
121
- "quality_max",
122
- "color_min",
123
- "color_max",
124
- "duration_min",
125
- "duration_max",
126
- "vid_size_max",
127
- "img_size_max",
128
- "padding_percent",
129
- )
130
- flags_comp_float = ("fps_power", "res_power", "quality_power", "color_power")
131
- flags_comp_str = (
132
- "bg_color",
133
- "vid_format",
134
- "img_format",
135
- "cache_dir",
136
- "scale_filter",
137
- "quantize_method",
138
- )
139
- flags_comp_bool = ("fake_vid",)
140
- keyword_args: Dict[str, Any]
141
- for k, v in self.help["comp"].items():
142
- if k in flags_comp_int:
143
- keyword_args = {"type": int, "default": None}
144
- elif k in flags_comp_float:
145
- keyword_args = {"type": float, "default": None}
146
- elif k in flags_comp_str:
147
- keyword_args = {"default": None}
148
- elif k in flags_comp_bool:
149
- keyword_args = {"action": "store_true", "default": None}
150
- else:
151
- continue
152
- parser_comp.add_argument(
153
- f'--{k.replace("_", "-")}',
154
- **keyword_args,
155
- dest=k,
156
- help=v,
157
- )
158
- parser_comp.add_argument(
159
- "--default-emoji",
160
- dest="default_emoji",
161
- default=self.compression_presets["custom"]["default_emoji"],
162
- help=self.help["comp"]["default_emoji"],
163
- )
164
-
165
- parser_cred = parser.add_argument_group("Credentials options")
166
- flags_cred_bool = ("signal_get_auth", "kakao_get_auth", "line_get_auth")
167
- for k, v in self.help["cred"].items():
168
- keyword_args = {}
169
- if k in flags_cred_bool:
170
- keyword_args = {"action": "store_true"}
171
- parser_cred.add_argument(
172
- f'--{k.replace("_", "-")}',
173
- **keyword_args,
174
- dest=k,
175
- help=v,
176
- )
177
-
178
- args = parser.parse_args()
179
-
180
- if args.custom_presets:
181
- try:
182
- custom_presets = JsonManager.load_json(Path(args.custom_presets))
183
- self.compression_presets: Dict[Any, Any] = merge( # type: ignore
184
- self.compression_presets, # type: ignore
185
- custom_presets,
186
- )
187
- except RuntimeError:
188
- print(f"Error: Cannot load custom presets from {args.custom_presets}")
189
-
190
- self.cb.no_confirm = args.no_confirm
191
- self.cb.no_progress = args.no_progress
192
-
193
- self.opt_input = self.get_opt_input(args)
194
- self.opt_output = self.get_opt_output(args)
195
- self.opt_comp = self.get_opt_comp(args)
196
- self.opt_cred = self.get_opt_cred(args)
197
-
198
- job = Job(
199
- self.opt_input,
200
- self.opt_comp,
201
- self.opt_output,
202
- self.opt_cred,
203
- self.cb.msg,
204
- self.cb.msg_block,
205
- self.cb.bar,
206
- self.cb.ask_bool,
207
- self.cb.ask_str,
208
- )
209
-
210
- signal.signal(signal.SIGINT, job.cancel)
211
- status = job.start()
212
- sys.exit(status)
213
-
214
- def get_opt_input(self, args: Namespace) -> InputOption:
215
- download_options = {
216
- "auto": args.download_auto,
217
- "signal": args.download_signal,
218
- "line": args.download_line,
219
- "telegram": args.download_telegram,
220
- "kakao": args.download_kakao,
221
- "viber": args.download_viber,
222
- }
223
-
224
- download_option = "local"
225
- url = ""
226
- for k, v in download_options.items():
227
- if v:
228
- download_option = k
229
- url = v
230
- break
231
-
232
- if download_option == "auto":
233
- detected_download_option = UrlDetect.detect(url)
234
- if detected_download_option:
235
- download_option = detected_download_option
236
- self.cb.msg(f"Detected URL input source: {download_option}")
237
- else:
238
- self.cb.msg(f"Error: Unrecognied URL input source for url: {url}")
239
- sys.exit()
240
-
241
- opt_input = InputOption(
242
- option=download_option,
243
- url=url,
244
- dir=Path(args.input_dir).resolve()
245
- if args.input_dir
246
- else DEFAULT_DIR / "stickers_input",
247
- )
248
-
249
- return opt_input
250
-
251
- def get_opt_output(self, args: Namespace) -> OutputOption:
252
- if args.export_whatsapp:
253
- export_option = "whatsapp"
254
- elif args.export_signal:
255
- export_option = "signal"
256
- elif args.export_telegram:
257
- export_option = "telegram"
258
- elif args.export_imessage:
259
- export_option = "imessage"
260
- else:
261
- export_option = "local"
262
-
263
- opt_output = OutputOption(
264
- option=export_option,
265
- dir=Path(args.output_dir).resolve()
266
- if args.output_dir
267
- else DEFAULT_DIR / "stickers_output",
268
- title=args.title,
269
- author=args.author,
270
- )
271
-
272
- return opt_output
273
-
274
- def get_opt_comp(self, args: Namespace) -> CompOption:
275
- preset: str = args.preset if args.preset else "auto"
276
- if args.preset == "custom":
277
- if (
278
- sum(
279
- (
280
- args.export_whatsapp,
281
- args.export_signal,
282
- args.export_telegram,
283
- args.export_imessage,
284
- )
285
- )
286
- > 1
287
- ):
288
- # Let the verify functions in export do the compression
289
- args.no_compress = True
290
- elif args.export_whatsapp:
291
- preset = "whatsapp"
292
- elif args.export_signal:
293
- preset = "signal"
294
- elif args.export_telegram:
295
- preset = "telegram"
296
- elif args.export_imessage:
297
- preset = "imessage_small"
298
- elif args.preset == "auto":
299
- output_option = (
300
- self.opt_output.option if self.opt_output.option else "local"
301
- )
302
- if output_option == "local":
303
- preset = "custom"
304
- args.no_compress = True
305
- self.cb.msg(
306
- "Auto compression option set to no_compress (Reason: Export to local directory only)"
307
- )
308
- elif output_option == "imessage":
309
- preset = "imessage_small"
310
- self.cb.msg(f"Auto compression option set to {preset}")
311
- else:
312
- preset = output_option
313
- self.cb.msg(f"Auto compression option set to {preset}")
314
-
315
- opt_comp = CompOption(
316
- preset=preset,
317
- size_max_img=self.compression_presets[preset]["size_max"]["img"]
318
- if args.img_size_max is None
319
- else args.img_size_max,
320
- size_max_vid=self.compression_presets[preset]["size_max"]["vid"]
321
- if args.vid_size_max is None
322
- else args.vid_size_max,
323
- format_img=(
324
- self.compression_presets[preset]["format"]["img"]
325
- if args.img_format is None
326
- else args.img_format,
327
- ),
328
- format_vid=(
329
- self.compression_presets[preset]["format"]["vid"]
330
- if args.vid_format is None
331
- else args.vid_format,
332
- ),
333
- fps_min=self.compression_presets[preset]["fps"]["min"]
334
- if args.fps_min is None
335
- else args.fps_min,
336
- fps_max=self.compression_presets[preset]["fps"]["max"]
337
- if args.fps_max is None
338
- else args.fps_max,
339
- fps_power=self.compression_presets[preset]["fps"]["power"]
340
- if args.fps_power is None
341
- else args.fps_power,
342
- res_w_min=self.compression_presets[preset]["res"]["w"]["min"]
343
- if args.res_w_min is None
344
- else args.res_w_min,
345
- res_w_max=self.compression_presets[preset]["res"]["w"]["max"]
346
- if args.res_w_max is None
347
- else args.res_w_max,
348
- res_h_min=self.compression_presets[preset]["res"]["h"]["min"]
349
- if args.res_h_min is None
350
- else args.res_h_min,
351
- res_h_max=self.compression_presets[preset]["res"]["h"]["max"]
352
- if args.res_h_max is None
353
- else args.res_h_max,
354
- res_power=self.compression_presets[preset]["res"]["power"]
355
- if args.res_power is None
356
- else args.res_power,
357
- quality_min=self.compression_presets[preset]["quality"]["min"]
358
- if args.quality_min is None
359
- else args.quality_min,
360
- quality_max=self.compression_presets[preset]["quality"]["max"]
361
- if args.quality_max is None
362
- else args.quality_max,
363
- quality_power=self.compression_presets[preset]["quality"]["power"]
364
- if args.quality_power is None
365
- else args.quality_power,
366
- color_min=self.compression_presets[preset]["color"]["min"]
367
- if args.color_min is None
368
- else args.color_min,
369
- color_max=self.compression_presets[preset]["color"]["max"]
370
- if args.color_max is None
371
- else args.color_max,
372
- color_power=self.compression_presets[preset]["color"]["power"]
373
- if args.color_power is None
374
- else args.color_power,
375
- duration_min=self.compression_presets[preset]["duration"]["min"]
376
- if args.duration_min is None
377
- else args.duration_min,
378
- duration_max=self.compression_presets[preset]["duration"]["max"]
379
- if args.duration_max is None
380
- else args.duration_max,
381
- bg_color=self.compression_presets[preset]["bg_color"]
382
- if args.bg_color is None
383
- else args.bg_color,
384
- padding_percent=self.compression_presets[preset]["padding_percent"]
385
- if args.padding_percent is None
386
- else args.padding_percent,
387
- steps=self.compression_presets[preset]["steps"]
388
- if args.steps is None
389
- else args.steps,
390
- fake_vid=self.compression_presets[preset]["fake_vid"]
391
- if args.fake_vid is None
392
- else args.fake_vid,
393
- cache_dir=args.cache_dir,
394
- scale_filter=self.compression_presets[preset]["scale_filter"]
395
- if args.scale_filter is None
396
- else args.scale_filter,
397
- quantize_method=self.compression_presets[preset]["quantize_method"]
398
- if args.quantize_method is None
399
- else args.quantize_method,
400
- default_emoji=self.compression_presets[preset]["default_emoji"]
401
- if args.default_emoji is None
402
- else args.default_emoji,
403
- no_compress=args.no_compress,
404
- processes=args.processes if args.processes else ceil(cpu_count() / 2),
405
- )
406
-
407
- return opt_comp
408
-
409
- def get_opt_cred(self, args: Namespace) -> CredOption:
410
- creds_path = CONFIG_DIR / "creds.json"
411
- creds = {}
412
- if creds_path.is_file():
413
- try:
414
- creds = JsonManager.load_json(creds_path)
415
- except JSONDecodeError:
416
- self.cb.msg("Warning: creds.json content is corrupted")
417
- creds = {}
418
- else:
419
- creds = {}
420
-
421
- if creds:
422
- self.cb.msg("Loaded credentials from creds.json")
423
-
424
- opt_cred = CredOption(
425
- signal_uuid=args.signal_uuid
426
- if args.signal_uuid
427
- else creds.get("signal", {}).get("uuid"),
428
- signal_password=args.signal_password
429
- if args.signal_password
430
- else creds.get("signal", {}).get("password"),
431
- telegram_token=args.telegram_token
432
- if args.telegram_token
433
- else creds.get("telegram", {}).get("token"),
434
- telegram_userid=args.telegram_userid
435
- if args.telegram_userid
436
- else creds.get("telegram", {}).get("userid"),
437
- kakao_auth_token=args.kakao_auth_token
438
- if args.kakao_auth_token
439
- else creds.get("kakao", {}).get("auth_token"),
440
- kakao_username=args.kakao_username
441
- if args.kakao_username
442
- else creds.get("kakao", {}).get("username"),
443
- kakao_password=args.kakao_password
444
- if args.kakao_password
445
- else creds.get("kakao", {}).get("password"),
446
- kakao_country_code=args.kakao_country_code
447
- if args.kakao_country_code
448
- else creds.get("kakao", {}).get("country_code"),
449
- kakao_phone_number=args.kakao_phone_number
450
- if args.kakao_phone_number
451
- else creds.get("kakao", {}).get("phone_number"),
452
- line_cookies=args.line_cookies
453
- if args.line_cookies
454
- else creds.get("line", {}).get("cookies"),
455
- )
456
-
457
- if args.kakao_get_auth:
458
- get_kakao_auth = GetKakaoAuth(
459
- opt_cred=opt_cred,
460
- cb_msg=self.cb.msg,
461
- cb_msg_block=self.cb.msg_block,
462
- cb_ask_str=self.cb.ask_str,
463
- )
464
- auth_token = get_kakao_auth.get_cred()
465
-
466
- if auth_token:
467
- opt_cred.kakao_auth_token = auth_token
468
-
469
- self.cb.msg(f"Got auth_token successfully: {auth_token}")
470
-
471
- if args.signal_get_auth:
472
- get_signal_auth = GetSignalAuth()
473
-
474
- signal_bin_path = None
475
- signal_user_data_dir = None
476
- if args.signal_data_dir:
477
- signal_bin_path = "(User specified)"
478
- signal_user_data_dir = args.signal_data_dir
479
-
480
- uuid, password, msg = get_signal_auth.get_cred(
481
- signal_bin_path, signal_user_data_dir
482
- )
483
-
484
- if uuid and password:
485
- opt_cred.signal_uuid = uuid
486
- opt_cred.signal_password = password
487
-
488
- self.cb.msg(msg)
489
-
490
- if args.line_get_auth:
491
- get_line_auth = GetLineAuth()
492
-
493
- line_cookies = get_line_auth.get_cred()
494
-
495
- if line_cookies:
496
- opt_cred.line_cookies = line_cookies
497
-
498
- self.cb.msg("Got Line cookies successfully")
499
- else:
500
- self.cb.msg(
501
- "Failed to get Line cookies. Have you logged in the web browser?"
502
- )
503
-
504
- if args.save_cred:
505
- creds_path = CONFIG_DIR / "creds.json"
506
- JsonManager.save_json(creds_path, opt_cred.to_dict())
507
- self.cb.msg("Saved credentials to creds.json")
508
-
509
- 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