sticker-convert 2.13.3.0__py3-none-any.whl → 2.15.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 (41) hide show
  1. sticker_convert/auth/__init__.py +0 -0
  2. sticker_convert/auth/auth_base.py +19 -0
  3. sticker_convert/{utils/auth/get_discord_auth.py → auth/auth_discord.py} +40 -13
  4. sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +80 -84
  5. sticker_convert/auth/auth_kakao_desktop_login.py +323 -0
  6. sticker_convert/{utils/auth/get_kakao_desktop_auth.py → auth/auth_kakao_desktop_memdump.py} +21 -12
  7. sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +21 -6
  8. sticker_convert/{utils/auth/get_signal_auth.py → auth/auth_signal.py} +18 -20
  9. sticker_convert/auth/auth_telethon.py +151 -0
  10. sticker_convert/{utils/auth/get_viber_auth.py → auth/auth_viber.py} +19 -11
  11. sticker_convert/{utils/auth → auth}/telegram_api.py +10 -18
  12. sticker_convert/cli.py +57 -67
  13. sticker_convert/converter.py +4 -4
  14. sticker_convert/downloaders/download_line.py +2 -2
  15. sticker_convert/downloaders/download_telegram.py +1 -1
  16. sticker_convert/gui.py +20 -100
  17. sticker_convert/gui_components/frames/comp_frame.py +12 -4
  18. sticker_convert/gui_components/frames/config_frame.py +14 -6
  19. sticker_convert/gui_components/frames/control_frame.py +1 -1
  20. sticker_convert/gui_components/frames/cred_frame.py +6 -8
  21. sticker_convert/gui_components/windows/advanced_compression_window.py +3 -4
  22. sticker_convert/gui_components/windows/base_window.py +7 -2
  23. sticker_convert/gui_components/windows/discord_get_auth_window.py +3 -7
  24. sticker_convert/gui_components/windows/kakao_get_auth_window.py +272 -97
  25. sticker_convert/gui_components/windows/line_get_auth_window.py +5 -14
  26. sticker_convert/gui_components/windows/signal_get_auth_window.py +4 -12
  27. sticker_convert/gui_components/windows/viber_get_auth_window.py +8 -11
  28. sticker_convert/job.py +16 -32
  29. sticker_convert/job_option.py +1 -0
  30. sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  31. sticker_convert/resources/help.json +8 -6
  32. sticker_convert/uploaders/upload_telegram.py +1 -1
  33. sticker_convert/utils/callback.py +238 -6
  34. sticker_convert/version.py +1 -1
  35. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/METADATA +41 -42
  36. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/RECORD +40 -37
  37. sticker_convert/utils/auth/telethon_setup.py +0 -97
  38. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/WHEEL +0 -0
  39. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/entry_points.txt +0 -0
  40. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/licenses/LICENSE +0 -0
  41. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.15.0.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python3
2
2
  import platform
3
- from functools import partial
4
3
  from pathlib import Path
5
4
  from subprocess import Popen
6
5
  from threading import Thread
@@ -9,9 +8,9 @@ from typing import Any
9
8
 
10
9
  from ttkbootstrap import Button, Entry, Frame, Label # type: ignore
11
10
 
11
+ from sticker_convert.auth.auth_viber import AuthViber
12
12
  from sticker_convert.gui_components.gui_utils import GUIUtils
13
13
  from sticker_convert.gui_components.windows.base_window import BaseWindow
14
- from sticker_convert.utils.auth.get_viber_auth import GetViberAuth
15
14
 
16
15
 
17
16
  class ViberGetAuthWindow(BaseWindow):
@@ -20,9 +19,6 @@ class ViberGetAuthWindow(BaseWindow):
20
19
 
21
20
  self.title("Get Viber auth data")
22
21
 
23
- self.cb_msg_block_viber = partial(self.gui.cb_msg_block, parent=self)
24
- self.cb_ask_str_viber = partial(self.gui.cb_ask_str, parent=self)
25
-
26
22
  self.frame_info = Frame(self.scrollable_frame)
27
23
  self.frame_btns = Frame(self.scrollable_frame)
28
24
  self.frame_config = Frame(self.scrollable_frame)
@@ -128,7 +124,7 @@ class ViberGetAuthWindow(BaseWindow):
128
124
  Thread(target=self.cb_get_cred_thread, daemon=True).start()
129
125
 
130
126
  def cb_get_cred_thread(self) -> None:
131
- m = GetViberAuth(self.cb_ask_str_viber)
127
+ m = AuthViber(self.gui.get_opt_cred(), self.gui.cb)
132
128
 
133
129
  viber_bin_path = None
134
130
  if self.gui.viber_bin_path_var.get():
@@ -145,19 +141,20 @@ class ViberGetAuthWindow(BaseWindow):
145
141
  self.gui.save_creds()
146
142
  self.gui.highlight_fields()
147
143
 
148
- self.cb_msg_block_viber(msg)
144
+ self.gui.cb.put(("msg_block", None, {"message": msg, "parent": self}))
149
145
 
150
146
  def cb_launch_viber(self) -> None:
151
- m = GetViberAuth(self.cb_ask_str_viber)
147
+ m = AuthViber(self.gui.get_opt_cred(), self.gui.cb)
152
148
  viber_bin_path = m.get_viber_desktop()
153
149
 
154
- if self.gui.viber_auth_var.get():
155
- viber_bin_path = self.gui.viber_auth_var.get()
150
+ if self.gui.viber_bin_path_var.get():
151
+ viber_bin_path = self.gui.viber_bin_path_var.get()
156
152
 
157
153
  if viber_bin_path:
158
154
  Popen([viber_bin_path])
159
155
  else:
160
- self.cb_msg_block_viber("Error: Viber Desktop not installed.")
156
+ msg = "Error: Viber Desktop not installed."
157
+ self.gui.cb.put(("msg_block", None, {"message": msg, "parent": self}))
161
158
 
162
159
  def cb_setdir(self) -> None:
163
160
  orig_input_dir = self.gui.viber_bin_path_var.get()
sticker_convert/job.py CHANGED
@@ -8,7 +8,7 @@ from datetime import datetime
8
8
  from multiprocessing import Manager, Process, Value
9
9
  from pathlib import Path
10
10
  from threading import Thread
11
- from typing import Any, Callable, Dict, List, Optional, Tuple
11
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
12
12
  from urllib.parse import urlparse
13
13
 
14
14
  from sticker_convert.converter import StickerConvert
@@ -32,21 +32,18 @@ from sticker_convert.utils.files.metadata_handler import MetadataHandler
32
32
  from sticker_convert.utils.media.codec_info import CodecInfo
33
33
  from sticker_convert.utils.singletons import singletons
34
34
 
35
+ if TYPE_CHECKING:
36
+ from sticker_convert.utils.callback import CallbackCli, CallbackGui
37
+
35
38
 
36
39
  class Executor:
37
- def __init__(
38
- self,
39
- cb_msg: Callable[..., None],
40
- cb_msg_block: Callable[..., None],
41
- cb_bar: Callable[..., None],
42
- cb_ask_bool: Callable[..., bool],
43
- cb_ask_str: Callable[..., str],
44
- ) -> None:
45
- self.cb_msg = cb_msg
46
- self.cb_msg_block = cb_msg_block
47
- self.cb_bar = cb_bar
48
- self.cb_ask_bool = cb_ask_bool
49
- self.cb_ask_str = cb_ask_str
40
+ def __init__(self, cb: Union[CallbackGui, CallbackCli]) -> None:
41
+ self.cb_msg = cb.cb_msg
42
+ self.cb_msg_block = cb.cb_msg_block
43
+ self.cb_msg_dynamic = cb.cb_msg_dynamic
44
+ self.cb_bar = cb.cb_bar
45
+ self.cb_ask_bool = cb.cb_ask_bool
46
+ self.cb_ask_str = cb.cb_ask_str
50
47
 
51
48
  self.manager = Manager()
52
49
  self.work_queue: WorkQueueType = self.manager.Queue()
@@ -90,7 +87,7 @@ class Executor:
90
87
  def cb(
91
88
  self,
92
89
  action: Optional[str],
93
- args: Optional[Tuple[str, ...]] = None,
90
+ args: Optional[Tuple[Any, ...]] = None,
94
91
  kwargs: Optional[Dict[str, Any]] = None,
95
92
  ) -> None:
96
93
  if args is None:
@@ -105,6 +102,8 @@ class Executor:
105
102
  self.cb_bar(update_bar=1)
106
103
  elif action == "msg_block":
107
104
  self.cb_return.set_response(self.cb_msg_block(*args, **kwargs))
105
+ elif action == "msg_dynamic":
106
+ self.cb_msg_dynamic(*args, **kwargs)
108
107
  elif action == "ask_bool":
109
108
  self.cb_return.set_response(self.cb_ask_bool(*args, **kwargs))
110
109
  elif action == "ask_str":
@@ -208,31 +207,16 @@ class Job:
208
207
  opt_comp: CompOption,
209
208
  opt_output: OutputOption,
210
209
  opt_cred: CredOption,
211
- cb_msg: Callable[..., None],
212
- cb_msg_block: Callable[..., None],
213
- cb_bar: Callable[..., None],
214
- cb_ask_bool: Callable[..., bool],
215
- cb_ask_str: Callable[..., str],
210
+ cb: Union[CallbackCli, CallbackGui],
216
211
  ) -> None:
217
212
  self.opt_input = opt_input
218
213
  self.opt_comp = opt_comp
219
214
  self.opt_output = opt_output
220
215
  self.opt_cred = opt_cred
221
- self.cb_msg = cb_msg
222
- self.cb_msg_block = cb_msg_block
223
- self.cb_bar = cb_bar
224
- self.cb_ask_bool = cb_ask_bool
225
- self.cb_ask_str = cb_ask_str
226
216
 
227
217
  self.out_urls: List[str] = []
228
218
 
229
- self.executor = Executor(
230
- self.cb_msg,
231
- self.cb_msg_block,
232
- self.cb_bar,
233
- self.cb_ask_bool,
234
- self.cb_ask_str,
235
- )
219
+ self.executor = Executor(cb)
236
220
 
237
221
  def start(self) -> int:
238
222
  if Path(self.opt_input.dir).is_dir() is False:
@@ -223,6 +223,7 @@ class CredOption(BaseOption):
223
223
  kakao_auth_token: str = ""
224
224
  kakao_username: str = ""
225
225
  kakao_password: str = ""
226
+ kakao_device_uuid: str = ""
226
227
  kakao_country_code: str = ""
227
228
  kakao_phone_number: str = ""
228
229
  line_cookies: str = ""
@@ -66,13 +66,15 @@
66
66
  "telegram_userid": "Set Telegram user_id (From real account, not bot account). Required for uploading Telegram stickers.",
67
67
  "telethon_setup": "Setup Telethon",
68
68
  "kakao_auth_token": "Set Kakao auth_token. Required for downloading animated stickers from https://e.kakao.com/t/xxxxx",
69
- "kakao_get_auth": "Generate Kakao auth_token by simulating login. Kakao username, password, country code and phone number are also required.",
70
- "kakao_get_auth_desktop": "Get Kakao auth_token from Kakao Desktop application.",
69
+ "kakao_get_auth_android_login": "Get Kakao auth_token by simulating login from Android. Kakao username, password, country code and phone number required.",
70
+ "kakao_get_auth_desktop_memdump": "Get Kakao auth_token from installed Kakao Desktop application with memdump.",
71
+ "kakao_get_auth_desktop_login": "Get Kakao auth_token by simulating login from Desktop application. Kakao username and password required.",
71
72
  "kakao_bin_path": "Set Kakao Desktop application path for launching and getting auth_token.\nUseful for portable installation.",
72
- "kakao_username": "Set Kakao username, which is email or phone number used for signing up Kakao account\nExample: +447700900142\nRequired for generating Kakao auth_token.",
73
- "kakao_password": "Set Kakao password (Password of Kakao account).\nRequired for generating Kakao auth_token.",
74
- "kakao_country_code": "Set Kakao country code of phone.\nExample: 82 (For korea), 44 (For UK), 1 (For USA).\nRequired for generating Kakao auth_token.",
75
- "kakao_phone_number": "Set Kakao phone number (Phone number associated with your Kakao account)\nDo NOT enter country code\nExample: 7700900142\nUsed for send / receive verification code via SMS.\nRequired for generating Kakao auth_token.",
73
+ "kakao_username": "Set Kakao username, which is email or phone number used for signing up Kakao account\nExample: +447700900142\nRequired for getting Kakao auth_token by simulating android/desktop login.",
74
+ "kakao_password": "Set Kakao password (Password of Kakao account).\nRequired for getting Kakao auth_token by simulating android/desktop login.",
75
+ "kakao_country_code": "Set Kakao country code of phone.\nExample: 82 (For korea), 44 (For UK), 1 (For USA).\nRequired for getting Kakao auth_token by simulating android login.",
76
+ "kakao_phone_number": "Set Kakao phone number (Phone number associated with your Kakao account)\nDo NOT enter country code\nExample: 7700900142\nUsed for send / receive verification code via SMS.\nRequired for getting Kakao auth_token by simulating android login.",
77
+ "kakao_device_uuid": "Set Kakao device uuid for desktop login. Defaults to real device uuid.\nOptional for getting Kakao auth_token by simulating desktop login",
76
78
  "line_get_auth": "Get Line cookies from browser, which is required to create custom message stickers.",
77
79
  "line_cookies": "Set Line cookies, which is required to create custom message stickers.",
78
80
  "viber_auth": "Set Viber authentication data.\nRequired for uploading Viber stickers.",
@@ -6,10 +6,10 @@ from typing import Any, Dict, List, Optional, Tuple, Union, cast
6
6
  import anyio
7
7
  from telegram import Sticker
8
8
 
9
+ from sticker_convert.auth.telegram_api import BotAPI, TelegramAPI, TelegramSticker, TelethonAPI
9
10
  from sticker_convert.converter import StickerConvert
10
11
  from sticker_convert.job_option import CompOption, CredOption, OutputOption
11
12
  from sticker_convert.uploaders.upload_base import UploadBase
12
- from sticker_convert.utils.auth.telegram_api import BotAPI, TelegramAPI, TelegramSticker, TelethonAPI
13
13
  from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
14
14
  from sticker_convert.utils.emoji import extract_emojis
15
15
  from sticker_convert.utils.files.metadata_handler import MetadataHandler
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env python3
2
+ from functools import partial
3
+ from getpass import getpass
2
4
  from multiprocessing import Event, Manager
3
5
  from multiprocessing.managers import ListProxy, SyncManager
4
6
  from queue import Queue
@@ -19,6 +21,9 @@ if TYPE_CHECKING:
19
21
  ResponseListType = ListProxy[ResponseItemType] # type: ignore
20
22
  CbQueueType = Queue[CbQueueItemType] # type: ignore
21
23
  WorkQueueType = Queue[WorkQueueItemType] # type: ignore
24
+ from ttkbootstrap import Toplevel # type: ignore
25
+
26
+ from sticker_convert.gui import GUI # type: ignore
22
27
  else:
23
28
  ResultsListType = List[Any]
24
29
  ResponseListType = List[ResponseItemType]
@@ -51,12 +56,13 @@ class CallbackProtocol(Protocol):
51
56
  def put(self, i: Union[CbQueueItemType, str]) -> Any: ...
52
57
 
53
58
 
54
- class Callback(CallbackProtocol):
59
+ class CallbackCli(CallbackProtocol):
55
60
  def __init__(
56
61
  self,
57
62
  msg: Optional[Callable[..., None]] = None,
58
63
  bar: Optional[Callable[..., None]] = None,
59
64
  msg_block: Optional[Callable[..., None]] = None,
65
+ msg_dynamic: Optional[Callable[..., bool]] = None,
60
66
  ask_bool: Optional[Callable[..., bool]] = None,
61
67
  ask_str: Optional[Callable[..., str]] = None,
62
68
  silent: bool = False,
@@ -80,6 +86,11 @@ class Callback(CallbackProtocol):
80
86
  else:
81
87
  self.msg_block = self.cb_msg_block
82
88
 
89
+ if msg_dynamic:
90
+ self.msg_dynamic = msg_dynamic
91
+ else:
92
+ self.msg_dynamic = self.cb_msg_dynamic
93
+
83
94
  if ask_bool:
84
95
  self.ask_bool = ask_bool
85
96
  else:
@@ -136,6 +147,16 @@ class Callback(CallbackProtocol):
136
147
  if not self.no_confirm:
137
148
  input("Press Enter to continue...")
138
149
 
150
+ def cb_msg_dynamic(self, *args: Any) -> bool:
151
+ message = args[0]
152
+
153
+ if message is None:
154
+ print()
155
+ else:
156
+ print(message, end="\r", flush=True)
157
+
158
+ return True
159
+
139
160
  def cb_ask_bool(self, *args: Any, **kwargs: Any) -> bool:
140
161
  question = args[0]
141
162
 
@@ -158,17 +179,23 @@ class Callback(CallbackProtocol):
158
179
 
159
180
  def cb_ask_str(
160
181
  self,
161
- msg: Optional[str] = None,
182
+ question: Optional[str] = None,
162
183
  initialvalue: Optional[str] = None,
163
184
  cli_show_initialvalue: bool = True,
185
+ password: bool = False,
164
186
  ) -> str:
165
- self.msg(msg)
187
+ self.msg(question)
166
188
 
167
189
  hint = ""
168
190
  if cli_show_initialvalue and initialvalue:
169
191
  hint = f" [Default: {initialvalue}]"
170
192
 
171
- response = input(f"Enter your response and press enter{hint} > ")
193
+ if password is True:
194
+ if question is None:
195
+ question = "Password: "
196
+ response = getpass(question)
197
+ else:
198
+ response = input(f"Enter your response and press enter{hint} > ")
172
199
 
173
200
  if initialvalue and not response:
174
201
  response = initialvalue
@@ -179,7 +206,210 @@ class Callback(CallbackProtocol):
179
206
  if isinstance(i, tuple):
180
207
  action = i[0]
181
208
  if len(i) >= 2:
182
- args: Tuple[str, ...] = i[1] if i[1] else tuple()
209
+ args: Tuple[Any, ...] = i[1] if i[1] else tuple()
210
+ else:
211
+ args = tuple()
212
+ if len(i) >= 3:
213
+ kwargs: Dict[str, Any] = i[2] if i[2] else {}
214
+ else:
215
+ kwargs = {}
216
+ else:
217
+ action = i
218
+ args = tuple()
219
+ kwargs = {}
220
+
221
+ # Fake implementation for Queue.put()
222
+ if action is None:
223
+ return None
224
+ if action == "msg":
225
+ self.msg(*args, **kwargs)
226
+ elif action == "bar":
227
+ self.bar(**kwargs)
228
+ elif action == "update_bar":
229
+ self.bar(update_bar=1)
230
+ elif action == "msg_block":
231
+ return self.msg_block(*args, **kwargs)
232
+ elif action == "msg_dynamic":
233
+ return self.msg_dynamic(*args, **kwargs)
234
+ elif action == "ask_bool":
235
+ return self.ask_bool(*args, **kwargs)
236
+ elif action == "ask_str":
237
+ return self.ask_str(*args, **kwargs)
238
+ else:
239
+ self.msg(action)
240
+ return None
241
+
242
+
243
+ class CallbackGui(CallbackProtocol):
244
+ def __init__(self, gui: "GUI"):
245
+ from ttkbootstrap import Label, Progressbar, StringVar # type: ignore
246
+
247
+ from sticker_convert.gui_components.windows.base_window import BaseWindow
248
+ from sticker_convert.job import Job
249
+
250
+ self.gui = gui
251
+ self.job: Optional[Job] = None
252
+ self.msg_dynamic_window: Optional[BaseWindow] = None
253
+ self.message_var = StringVar(self.gui)
254
+ self.msg_dynamic_label: Optional[Label] = None
255
+ self.msg_dynamic_bar: Optional[Progressbar] = None
256
+
257
+ self.ask_str = self.cb_ask_str
258
+ self.ask_bool = self.cb_ask_bool
259
+ self.msg = self.cb_msg
260
+ self.msg_block = self.cb_msg_block
261
+ self.msg_dynamic = self.cb_msg_dynamic
262
+ self.bar = self.cb_bar
263
+
264
+ def cb_ask_str(
265
+ self,
266
+ question: str,
267
+ initialvalue: Optional[str] = None,
268
+ cli_show_initialvalue: bool = True,
269
+ password: bool = False,
270
+ parent: Optional[object] = None,
271
+ ) -> str:
272
+ from ttkbootstrap import Querybox # type: ignore
273
+
274
+ self.gui.action = partial(
275
+ Querybox.get_string, # type: ignore
276
+ question,
277
+ title="sticker-convert",
278
+ initialvalue=initialvalue,
279
+ parent=parent,
280
+ )
281
+ self.gui.event_generate("<<exec_in_main>>")
282
+ self.gui.response_event.wait()
283
+ self.gui.response_event.clear()
284
+
285
+ if self.gui.response is None:
286
+ return ""
287
+ elif isinstance(self.gui.response, str):
288
+ return self.gui.response
289
+ else:
290
+ raise RuntimeError(f"Invalid response in cb_ask_str: {self.gui.response}")
291
+
292
+ def cb_ask_bool(self, question: str, parent: Optional["Toplevel"] = None) -> bool:
293
+ from ttkbootstrap.dialogs import Messagebox # type: ignore
294
+
295
+ self.gui.action = partial(
296
+ Messagebox.yesno, # type: ignore
297
+ question,
298
+ title="sticker-convert",
299
+ parent=parent,
300
+ )
301
+ self.gui.event_generate("<<exec_in_main>>")
302
+ self.gui.response_event.wait()
303
+ self.gui.response_event.clear()
304
+
305
+ if self.gui.response == "Yes":
306
+ return True
307
+ return False
308
+
309
+ def cb_msg(self, *args: Any, **kwargs: Any) -> None:
310
+ self.gui.progress_frame.update_message_box(*args, **kwargs)
311
+
312
+ def cb_msg_block(
313
+ self,
314
+ message: Optional[str] = None,
315
+ parent: Optional[object] = None,
316
+ **_kwargs: Any,
317
+ ) -> Any:
318
+ from ttkbootstrap.dialogs import Messagebox # type: ignore
319
+
320
+ self.gui.action = partial(
321
+ Messagebox.show_info, # type: ignore
322
+ message,
323
+ title="sticker-convert",
324
+ parent=parent,
325
+ )
326
+ self.gui.event_generate("<<exec_in_main>>")
327
+ self.gui.response_event.wait()
328
+ self.gui.response_event.clear()
329
+
330
+ return self.gui.response
331
+
332
+ def cb_msg_dynamic(
333
+ self,
334
+ message: Optional[str] = None,
335
+ parent: Optional["Toplevel"] = None,
336
+ **_kwargs: Any,
337
+ ) -> bool:
338
+ from ttkbootstrap import Label, Progressbar # type: ignore
339
+
340
+ from sticker_convert.gui_components.gui_utils import GUIUtils
341
+ from sticker_convert.gui_components.windows.base_window import BaseWindow
342
+
343
+ self.gui.action = None
344
+ if self.msg_dynamic_window is None:
345
+ if message is not None:
346
+ self.msg_dynamic_window = BaseWindow(self.gui, parent)
347
+ self.msg_dynamic_window.wm_title("sticker-convert")
348
+ self.message_var.set(message)
349
+ self.msg_dynamic_label = Label(
350
+ self.msg_dynamic_window.scrollable_frame,
351
+ textvariable=self.message_var,
352
+ )
353
+ self.msg_dynamic_bar = Progressbar(
354
+ self.msg_dynamic_window.scrollable_frame,
355
+ orient="horizontal",
356
+ mode="indeterminate",
357
+ )
358
+ self.msg_dynamic_bar.start(50)
359
+ self.msg_dynamic_label.pack()
360
+ self.msg_dynamic_bar.pack(fill="x")
361
+ self.gui.action = partial(
362
+ GUIUtils.finalize_window, self.msg_dynamic_window
363
+ )
364
+ print(message, end="\r", flush=True)
365
+ ret = True
366
+ else:
367
+ print()
368
+ ret = False
369
+ elif self.msg_dynamic_window.winfo_exists() == 0:
370
+ self.msg_dynamic_window = None
371
+ print()
372
+ ret = False
373
+ else:
374
+ if message is None:
375
+
376
+ def _action():
377
+ assert self.msg_dynamic_window is not None
378
+ self.msg_dynamic_window.destroy()
379
+ self.msg_dynamic_window = None
380
+
381
+ self.gui.action = _action
382
+ print()
383
+ ret = False
384
+ else:
385
+ self.gui.action = partial(self.message_var.set, message)
386
+ print(message, end="\r", flush=True)
387
+ ret = True
388
+
389
+ if self.gui.action is not None:
390
+ self.gui.event_generate("<<exec_in_main>>")
391
+ self.gui.response_event.wait()
392
+ self.gui.response_event.clear()
393
+
394
+ return ret
395
+
396
+ def cb_bar(
397
+ self,
398
+ set_progress_mode: Optional[str] = None,
399
+ steps: int = 0,
400
+ update_bar: int = 0,
401
+ *args: Any,
402
+ **kwargs: Any,
403
+ ) -> None:
404
+ self.gui.progress_frame.update_progress_bar(
405
+ set_progress_mode, steps, update_bar, *args, **kwargs
406
+ )
407
+
408
+ def put(self, i: Union[CbQueueItemType, str]) -> Union[str, bool, None]:
409
+ if isinstance(i, tuple):
410
+ action = i[0]
411
+ if len(i) >= 2:
412
+ args: Tuple[Any, ...] = i[1] if i[1] else tuple()
183
413
  else:
184
414
  args = tuple()
185
415
  if len(i) >= 3:
@@ -202,10 +432,12 @@ class Callback(CallbackProtocol):
202
432
  self.bar(update_bar=1)
203
433
  elif action == "msg_block":
204
434
  return self.msg_block(*args, **kwargs)
435
+ elif action == "msg_dynamic":
436
+ return self.msg_dynamic(*args, **kwargs)
205
437
  elif action == "ask_bool":
206
438
  return self.ask_bool(*args, **kwargs)
207
439
  elif action == "ask_str":
208
- return self.ask_str(**kwargs)
440
+ return self.ask_str(*args, **kwargs)
209
441
  else:
210
442
  self.msg(action)
211
443
  return None
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.13.3.0"
3
+ __version__ = "2.15.0.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sticker-convert
3
- Version: 2.13.3.0
3
+ Version: 2.15.0.0
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, Viber, Discord, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -364,11 +364,12 @@ Requires-Python: >=3.9
364
364
  Description-Content-Type: text/markdown
365
365
  License-File: LICENSE
366
366
  Requires-Dist: aiolimiter~=1.2.1
367
- Requires-Dist: anyio~=4.10.0
367
+ Requires-Dist: anyio~=4.11.0
368
368
  Requires-Dist: apngasm_python~=1.3.2
369
- Requires-Dist: av>=13.1.0
370
- Requires-Dist: beautifulsoup4~=4.13.4
369
+ Requires-Dist: av<15,>=13.1.0
370
+ Requires-Dist: beautifulsoup4~=4.14.2
371
371
  Requires-Dist: cryptg~=0.5.1
372
+ Requires-Dist: cryptography~=46.0.1
372
373
  Requires-Dist: rookiepy~=0.5.6
373
374
  Requires-Dist: httpx~=0.28.1
374
375
  Requires-Dist: imagequant~=1.1.4
@@ -376,15 +377,15 @@ Requires-Dist: memory-tempfile~=2.2.3
376
377
  Requires-Dist: mergedeep~=1.3.4
377
378
  Requires-Dist: numpy>=1.22.4
378
379
  Requires-Dist: Pillow~=11.3.0
379
- Requires-Dist: pyoxipng~=9.1.0
380
- Requires-Dist: python-telegram-bot~=22.3
381
- Requires-Dist: psutil~=7.0.0
380
+ Requires-Dist: pyoxipng~=9.1.1
381
+ Requires-Dist: python-telegram-bot~=22.5
382
+ Requires-Dist: psutil~=7.1.0
382
383
  Requires-Dist: PyMemoryEditor~=1.5.24
383
384
  Requires-Dist: requests~=2.32.4
384
- Requires-Dist: rlottie_python~=1.3.7
385
+ Requires-Dist: rlottie_python~=1.3.8
385
386
  Requires-Dist: signalstickers-client-fork-laggykiller~=3.3.0.post2
386
387
  Requires-Dist: socksio~=1.0.0
387
- Requires-Dist: telethon~=1.40.0
388
+ Requires-Dist: telethon~=1.41.2
388
389
  Requires-Dist: tqdm~=4.67.1
389
390
  Requires-Dist: ttkbootstrap-fork-laggykiller~=1.5.1
390
391
  Requires-Dist: websocket_client~=1.8.0
@@ -497,37 +498,29 @@ Dynamic: license-file
497
498
  To run in CLI mode, pass on any arguments
498
499
 
499
500
  ```
500
- usage: sticker-convert.py [-h] [--version] [--no-confirm] [--no-progress]
501
- [--custom-presets CUSTOM_PRESETS] [--input-dir INPUT_DIR]
501
+ usage: sticker-convert.py [-h] [--version] [--no-confirm] [--no-progress] [--custom-presets CUSTOM_PRESETS] [--input-dir INPUT_DIR]
502
502
  [--download-auto DOWNLOAD_AUTO | --download-signal DOWNLOAD_SIGNAL | --download-telegram DOWNLOAD_TELEGRAM | --download-telegram-telethon DOWNLOAD_TELEGRAM_TELETHON | --download-line DOWNLOAD_LINE | --download-kakao DOWNLOAD_KAKAO | --download-band DOWNLOAD_BAND | --download-ogq DOWNLOAD_OGQ | --download-viber DOWNLOAD_VIBER | --download-discord DOWNLOAD_DISCORD | --download-discord-emoji DOWNLOAD_DISCORD_EMOJI]
503
503
  [--output-dir OUTPUT_DIR] [--author AUTHOR] [--title TITLE]
504
504
  [--export-signal | --export-telegram | --export-telegram-emoji | --export-telegram-telethon | --export-telegram-emoji-telethon | --export-viber | --export-whatsapp | --export-imessage]
505
505
  [--no-compress]
506
506
  [--preset {auto,signal,telegram,telegram_emoji,whatsapp,line,kakao,band,ogq,viber,discord,discord_emoji,imessage_small,imessage_medium,imessage_large,custom}]
507
- [--steps STEPS] [--processes PROCESSES] [--fps-min FPS_MIN] [--fps-max FPS_MAX]
508
- [--fps-power FPS_POWER] [--res-min RES_MIN] [--res-max RES_MAX]
509
- [--res-w-min RES_W_MIN] [--res-w-max RES_W_MAX] [--res-h-min RES_H_MIN]
510
- [--res-h-max RES_H_MAX] [--res-power RES_POWER] [--res-snap-pow2]
511
- [--no-res-snap-pow2] [--quality-min QUALITY_MIN] [--quality-max QUALITY_MAX]
512
- [--quality-power QUALITY_POWER] [--color-min COLOR_MIN] [--color-max COLOR_MAX]
513
- [--color-power COLOR_POWER] [--duration-min DURATION_MIN]
514
- [--duration-max DURATION_MAX] [--padding-percent PADDING_PERCENT]
515
- [--bg-color BG_COLOR] [--vid-size-max VID_SIZE_MAX]
516
- [--img-size-max IMG_SIZE_MAX] [--vid-format VID_FORMAT]
517
- [--img-format IMG_FORMAT] [--fake-vid] [--no-fake-vid]
518
- [--scale-filter SCALE_FILTER] [--quantize-method QUANTIZE_METHOD]
519
- [--cache-dir CACHE_DIR] [--chromium-path CHROMIUM_PATH]
520
- [--default-emoji DEFAULT_EMOJI] [--signal-uuid SIGNAL_UUID]
521
- [--signal-password SIGNAL_PASSWORD] [--signal-get-auth]
522
- [--telegram-token TELEGRAM_TOKEN] [--telegram-userid TELEGRAM_USERID]
523
- [--telethon-setup] [--kakao-auth-token KAKAO_AUTH_TOKEN] [--kakao-get-auth]
524
- [--kakao-get-auth-desktop] [--kakao-bin-path KAKAO_BIN_PATH]
525
- [--kakao-username KAKAO_USERNAME] [--kakao-password KAKAO_PASSWORD]
526
- [--kakao-country-code KAKAO_COUNTRY_CODE]
527
- [--kakao-phone-number KAKAO_PHONE_NUMBER] [--line-get-auth]
528
- [--line-cookies LINE_COOKIES] [--viber-auth VIBER_AUTH]
529
- [--viber-get-auth VIBER_GET_AUTH] [--viber-bin-path VIBER_BIN_PATH]
530
- [--discord-get-auth] [--discord-token DISCORD_TOKEN] [--save-cred]
507
+ [--steps STEPS] [--processes PROCESSES] [--fps-min FPS_MIN] [--fps-max FPS_MAX] [--fps-power FPS_POWER]
508
+ [--res-min RES_MIN] [--res-max RES_MAX] [--res-w-min RES_W_MIN] [--res-w-max RES_W_MAX]
509
+ [--res-h-min RES_H_MIN] [--res-h-max RES_H_MAX] [--res-power RES_POWER] [--res-snap-pow2]
510
+ [--no-res-snap-pow2] [--quality-min QUALITY_MIN] [--quality-max QUALITY_MAX] [--quality-power QUALITY_POWER]
511
+ [--color-min COLOR_MIN] [--color-max COLOR_MAX] [--color-power COLOR_POWER] [--duration-min DURATION_MIN]
512
+ [--duration-max DURATION_MAX] [--padding-percent PADDING_PERCENT] [--bg-color BG_COLOR]
513
+ [--vid-size-max VID_SIZE_MAX] [--img-size-max IMG_SIZE_MAX] [--vid-format VID_FORMAT]
514
+ [--img-format IMG_FORMAT] [--fake-vid] [--no-fake-vid] [--scale-filter SCALE_FILTER]
515
+ [--quantize-method QUANTIZE_METHOD] [--cache-dir CACHE_DIR] [--chromium-path CHROMIUM_PATH]
516
+ [--default-emoji DEFAULT_EMOJI] [--signal-uuid SIGNAL_UUID] [--signal-password SIGNAL_PASSWORD]
517
+ [--signal-get-auth] [--telegram-token TELEGRAM_TOKEN] [--telegram-userid TELEGRAM_USERID] [--telethon-setup]
518
+ [--kakao-auth-token KAKAO_AUTH_TOKEN] [--kakao-get-auth-android-login] [--kakao-get-auth-desktop-memdump]
519
+ [--kakao-get-auth-desktop-login] [--kakao-bin-path KAKAO_BIN_PATH] [--kakao-username KAKAO_USERNAME]
520
+ [--kakao-password KAKAO_PASSWORD] [--kakao-country-code KAKAO_COUNTRY_CODE]
521
+ [--kakao-phone-number KAKAO_PHONE_NUMBER] [--kakao-device-uuid KAKAO_DEVICE_UUID] [--line-get-auth]
522
+ [--line-cookies LINE_COOKIES] [--viber-auth VIBER_AUTH] [--viber-get-auth VIBER_GET_AUTH]
523
+ [--viber-bin-path VIBER_BIN_PATH] [--discord-get-auth] [--discord-token DISCORD_TOKEN] [--save-cred]
531
524
 
532
525
  CLI for stickers-convert
533
526
 
@@ -706,29 +699,35 @@ Credentials options:
706
699
  --telethon-setup Setup Telethon
707
700
  --kakao-auth-token KAKAO_AUTH_TOKEN
708
701
  Set Kakao auth_token. Required for downloading animated stickers from https://e.kakao.com/t/xxxxx
709
- --kakao-get-auth Generate Kakao auth_token by simulating login. Kakao username, password, country code and phone number are also required.
710
- --kakao-get-auth-desktop
711
- Get Kakao auth_token from Kakao Desktop application.
702
+ --kakao-get-auth-android-login
703
+ Get Kakao auth_token by simulating login from Android. Kakao username, password, country code and phone number required.
704
+ --kakao-get-auth-desktop-memdump
705
+ Get Kakao auth_token from installed Kakao Desktop application with memdump.
706
+ --kakao-get-auth-desktop-login
707
+ Get Kakao auth_token by simulating login from Desktop application. Kakao username and password required.
712
708
  --kakao-bin-path KAKAO_BIN_PATH
713
709
  Set Kakao Desktop application path for launching and getting auth_token.
714
710
  Useful for portable installation.
715
711
  --kakao-username KAKAO_USERNAME
716
712
  Set Kakao username, which is email or phone number used for signing up Kakao account
717
713
  Example: +447700900142
718
- Required for generating Kakao auth_token.
714
+ Required for getting Kakao auth_token by simulating android/desktop login.
719
715
  --kakao-password KAKAO_PASSWORD
720
716
  Set Kakao password (Password of Kakao account).
721
- Required for generating Kakao auth_token.
717
+ Required for getting Kakao auth_token by simulating android/desktop login.
722
718
  --kakao-country-code KAKAO_COUNTRY_CODE
723
719
  Set Kakao country code of phone.
724
720
  Example: 82 (For korea), 44 (For UK), 1 (For USA).
725
- Required for generating Kakao auth_token.
721
+ Required for getting Kakao auth_token by simulating android login.
726
722
  --kakao-phone-number KAKAO_PHONE_NUMBER
727
723
  Set Kakao phone number (Phone number associated with your Kakao account)
728
724
  Do NOT enter country code
729
725
  Example: 7700900142
730
726
  Used for send / receive verification code via SMS.
731
- Required for generating Kakao auth_token.
727
+ Required for getting Kakao auth_token by simulating android login.
728
+ --kakao-device-uuid KAKAO_DEVICE_UUID
729
+ Set Kakao device uuid for desktop login. Defaults to real device uuid.
730
+ Optional for getting Kakao auth_token by simulating desktop login
732
731
  --line-get-auth Get Line cookies from browser, which is required to create custom message stickers.
733
732
  --line-cookies LINE_COOKIES
734
733
  Set Line cookies, which is required to create custom message stickers.