sticker-convert 2.7.2__py3-none-any.whl → 2.7.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. sticker_convert/__init__.py +1 -0
  2. sticker_convert/__main__.py +3 -1
  3. sticker_convert/cli.py +20 -24
  4. sticker_convert/converter.py +108 -119
  5. sticker_convert/definitions.py +8 -12
  6. sticker_convert/downloaders/download_base.py +14 -31
  7. sticker_convert/downloaders/download_kakao.py +25 -39
  8. sticker_convert/downloaders/download_line.py +24 -33
  9. sticker_convert/downloaders/download_signal.py +7 -16
  10. sticker_convert/downloaders/download_telegram.py +6 -15
  11. sticker_convert/gui.py +53 -61
  12. sticker_convert/gui_components/frames/comp_frame.py +11 -20
  13. sticker_convert/gui_components/frames/config_frame.py +9 -9
  14. sticker_convert/gui_components/frames/control_frame.py +3 -3
  15. sticker_convert/gui_components/frames/cred_frame.py +12 -18
  16. sticker_convert/gui_components/frames/input_frame.py +9 -15
  17. sticker_convert/gui_components/frames/output_frame.py +9 -15
  18. sticker_convert/gui_components/frames/progress_frame.py +8 -8
  19. sticker_convert/gui_components/frames/right_clicker.py +2 -2
  20. sticker_convert/gui_components/gui_utils.py +6 -8
  21. sticker_convert/gui_components/windows/advanced_compression_window.py +23 -32
  22. sticker_convert/gui_components/windows/base_window.py +6 -6
  23. sticker_convert/gui_components/windows/kakao_get_auth_window.py +5 -11
  24. sticker_convert/gui_components/windows/line_get_auth_window.py +5 -5
  25. sticker_convert/gui_components/windows/signal_get_auth_window.py +6 -6
  26. sticker_convert/job.py +84 -90
  27. sticker_convert/job_option.py +36 -32
  28. sticker_convert/resources/emoji.json +334 -70
  29. sticker_convert/resources/help.json +1 -1
  30. sticker_convert/uploaders/compress_wastickers.py +19 -30
  31. sticker_convert/uploaders/upload_base.py +19 -13
  32. sticker_convert/uploaders/upload_signal.py +20 -33
  33. sticker_convert/uploaders/upload_telegram.py +21 -28
  34. sticker_convert/uploaders/xcode_imessage.py +30 -95
  35. sticker_convert/utils/auth/get_kakao_auth.py +7 -8
  36. sticker_convert/utils/auth/get_line_auth.py +5 -6
  37. sticker_convert/utils/auth/get_signal_auth.py +7 -7
  38. sticker_convert/utils/callback.py +31 -23
  39. sticker_convert/utils/files/cache_store.py +6 -8
  40. sticker_convert/utils/files/json_manager.py +6 -7
  41. sticker_convert/utils/files/json_resources_loader.py +12 -0
  42. sticker_convert/utils/files/metadata_handler.py +93 -84
  43. sticker_convert/utils/files/run_bin.py +11 -10
  44. sticker_convert/utils/files/sanitize_filename.py +30 -28
  45. sticker_convert/utils/media/apple_png_normalize.py +3 -2
  46. sticker_convert/utils/media/codec_info.py +41 -44
  47. sticker_convert/utils/media/decrypt_kakao.py +7 -7
  48. sticker_convert/utils/media/format_verify.py +14 -14
  49. sticker_convert/utils/url_detect.py +4 -5
  50. sticker_convert/version.py +2 -1
  51. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/METADATA +19 -17
  52. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/RECORD +56 -55
  53. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/WHEEL +1 -1
  54. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/LICENSE +0 -0
  55. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/entry_points.txt +0 -0
  56. {sticker_convert-2.7.2.dist-info → sticker_convert-2.7.4.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@ from ttkbootstrap import Menu # type: ignore
6
6
 
7
7
  # Reference: https://stackoverflow.com/a/57704013
8
8
  class RightClicker:
9
- def __init__(self, event: Any):
9
+ def __init__(self, event: Any) -> None:
10
10
  right_click_menu = Menu(None, tearoff=0, takefocus=0)
11
11
 
12
12
  for txt in ["Cut", "Copy", "Paste"]:
@@ -19,5 +19,5 @@ class RightClicker:
19
19
 
20
20
  right_click_menu.tk_popup(event.x_root, event.y_root, entry="0")
21
21
 
22
- def right_click_command(self, event: Any, cmd: str):
22
+ def right_click_command(self, event: Any, cmd: str) -> None:
23
23
  event.widget.event_generate(f"<<{cmd}>>")
@@ -2,7 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import platform
5
- from typing import TYPE_CHECKING, Union
5
+ from typing import TYPE_CHECKING, Tuple, Union
6
6
 
7
7
  from ttkbootstrap import Canvas, Frame, PhotoImage, Scrollbar # type: ignore
8
8
 
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
15
15
 
16
16
  class GUIUtils:
17
17
  @staticmethod
18
- def set_icon(window: Union["BaseWindow", "GUI"]):
18
+ def set_icon(window: Union["BaseWindow", "GUI"]) -> None:
19
19
  window.icon = PhotoImage(file=ROOT_DIR / "resources/appicon.png") # type: ignore
20
20
  window.iconphoto(1, window.icon) # type: ignore
21
21
  if platform.system() == "Darwin":
@@ -27,7 +27,7 @@ class GUIUtils:
27
27
  @staticmethod
28
28
  def create_scrollable_frame(
29
29
  window: Union["BaseWindow", "GUI"],
30
- ) -> tuple[Frame, Frame, Canvas, Scrollbar, Scrollbar, Frame]:
30
+ ) -> Tuple[Frame, Frame, Canvas, Scrollbar, Scrollbar, Frame]:
31
31
  main_frame = Frame(window)
32
32
  main_frame.pack(fill="both", expand=1)
33
33
 
@@ -66,7 +66,7 @@ class GUIUtils:
66
66
  )
67
67
 
68
68
  @staticmethod
69
- def finalize_window(window: Union["GUI", "BaseWindow"]):
69
+ def finalize_window(window: Union["GUI", "BaseWindow"]) -> None:
70
70
  window.attributes("-alpha", 0) # type: ignore
71
71
 
72
72
  screen_width = window.winfo_screenwidth()
@@ -80,10 +80,8 @@ class GUIUtils:
80
80
  window_width = frame_width + window.y_scrollbar.winfo_width()
81
81
  window_height = frame_height + window.x_scrollbar.winfo_height()
82
82
 
83
- if window_width > screen_width:
84
- window_width = screen_width
85
- if window_height > screen_height:
86
- window_height = screen_height
83
+ window_width = min(window_width, screen_width)
84
+ window_height = min(window_height, screen_height)
87
85
 
88
86
  frame_width = window_width - window.y_scrollbar.winfo_width()
89
87
  frame_height = window_height - window.x_scrollbar.winfo_height()
@@ -2,21 +2,10 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  from functools import partial
5
- from typing import Any
5
+ from typing import Any, List, Tuple
6
6
 
7
7
  from PIL import Image, ImageDraw, ImageTk
8
- from ttkbootstrap import ( # type: ignore
9
- Button,
10
- Canvas,
11
- Checkbutton,
12
- Entry,
13
- Frame,
14
- Label,
15
- LabelFrame,
16
- OptionMenu,
17
- Scrollbar,
18
- StringVar,
19
- )
8
+ from ttkbootstrap import Button, Canvas, Checkbutton, Entry, Frame, Label, LabelFrame, OptionMenu, Scrollbar, StringVar # type: ignore
20
9
 
21
10
  from sticker_convert.gui_components.frames.right_clicker import RightClicker
22
11
  from sticker_convert.gui_components.gui_utils import GUIUtils
@@ -26,10 +15,10 @@ from sticker_convert.gui_components.windows.base_window import BaseWindow
26
15
  class AdvancedCompressionWindow(BaseWindow):
27
16
  emoji_column_per_row = 10
28
17
  emoji_visible_rows = 5
29
- emoji_btns: list[tuple[Button, ImageTk.PhotoImage]] = []
18
+ emoji_btns: List[Tuple[Button, ImageTk.PhotoImage]] = []
30
19
 
31
- def __init__(self, *args: Any, **kwargs: Any):
32
- super(AdvancedCompressionWindow, self).__init__(*args, **kwargs)
20
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
21
+ super().__init__(*args, **kwargs)
33
22
  self.categories = list({entry["category"] for entry in self.gui.emoji_list})
34
23
 
35
24
  self.title("Advanced compression options")
@@ -340,7 +329,9 @@ class AdvancedCompressionWindow(BaseWindow):
340
329
  self.gui.scale_filter_var,
341
330
  self.gui.scale_filter_var.get(),
342
331
  "nearest",
332
+ "box",
343
333
  "bilinear",
334
+ "hamming",
344
335
  "bicubic",
345
336
  "lanczos",
346
337
  bootstyle="secondary", # type: ignore
@@ -391,7 +382,7 @@ class AdvancedCompressionWindow(BaseWindow):
391
382
  bootstyle="secondary", # type: ignore
392
383
  )
393
384
  self.default_emoji_lbl = Label(self.frame_advcomp, text="Default emoji")
394
- self.im = Image.new("RGBA", (32, 32), (255, 255, 255, 0))
385
+ self.im: Image.Image = Image.new("RGBA", (32, 32), (255, 255, 255, 0))
395
386
  self.ph_im = ImageTk.PhotoImage(self.im)
396
387
  self.default_emoji_dsp = Label(self.frame_advcomp, image=self.ph_im)
397
388
 
@@ -570,7 +561,7 @@ class AdvancedCompressionWindow(BaseWindow):
570
561
 
571
562
  GUIUtils.finalize_window(self)
572
563
 
573
- def cb_disable_fps(self, *args: Any):
564
+ def cb_disable_fps(self, *_: Any) -> None:
574
565
  if self.gui.fps_disable_var.get() is True:
575
566
  state = "disabled"
576
567
  else:
@@ -579,7 +570,7 @@ class AdvancedCompressionWindow(BaseWindow):
579
570
  self.fps_min_entry.config(state=state)
580
571
  self.fps_max_entry.config(state=state)
581
572
 
582
- def cb_disable_res_w(self, *args: Any):
573
+ def cb_disable_res_w(self, *_: Any) -> None:
583
574
  if self.gui.res_w_disable_var.get() is True:
584
575
  state = "disabled"
585
576
  else:
@@ -588,7 +579,7 @@ class AdvancedCompressionWindow(BaseWindow):
588
579
  self.res_w_min_entry.config(state=state)
589
580
  self.res_w_max_entry.config(state=state)
590
581
 
591
- def cb_disable_res_h(self, *args: Any):
582
+ def cb_disable_res_h(self, *_: Any) -> None:
592
583
  if self.gui.res_h_disable_var.get() is True:
593
584
  state = "disabled"
594
585
  else:
@@ -597,7 +588,7 @@ class AdvancedCompressionWindow(BaseWindow):
597
588
  self.res_h_min_entry.config(state=state)
598
589
  self.res_h_max_entry.config(state=state)
599
590
 
600
- def cb_disable_quality(self, *args: Any):
591
+ def cb_disable_quality(self, *_: Any) -> None:
601
592
  if self.gui.quality_disable_var.get() is True:
602
593
  state = "disabled"
603
594
  else:
@@ -606,7 +597,7 @@ class AdvancedCompressionWindow(BaseWindow):
606
597
  self.quality_min_entry.config(state=state)
607
598
  self.quality_max_entry.config(state=state)
608
599
 
609
- def cb_disable_color(self, *args: Any):
600
+ def cb_disable_color(self, *_: Any) -> None:
610
601
  if self.gui.color_disable_var.get() is True:
611
602
  state = "disabled"
612
603
  else:
@@ -615,7 +606,7 @@ class AdvancedCompressionWindow(BaseWindow):
615
606
  self.color_min_entry.config(state=state)
616
607
  self.color_max_entry.config(state=state)
617
608
 
618
- def cb_disable_duration(self, *args: Any):
609
+ def cb_disable_duration(self, *_: Any) -> None:
619
610
  if (
620
611
  self.gui.duration_disable_var.get() is True
621
612
  or self.gui.comp_preset_var.get() == "auto"
@@ -627,7 +618,7 @@ class AdvancedCompressionWindow(BaseWindow):
627
618
  self.duration_min_entry.config(state=state)
628
619
  self.duration_max_entry.config(state=state)
629
620
 
630
- def cb_disable_size(self, *args: Any):
621
+ def cb_disable_size(self, *_: Any) -> None:
631
622
  if (
632
623
  self.gui.size_disable_var.get() is True
633
624
  or self.gui.comp_preset_var.get() == "auto"
@@ -639,7 +630,7 @@ class AdvancedCompressionWindow(BaseWindow):
639
630
  self.img_size_max_entry.config(state=state)
640
631
  self.vid_size_max_entry.config(state=state)
641
632
 
642
- def cb_disable_format(self, *args: Any):
633
+ def cb_disable_format(self, *_: Any) -> None:
643
634
  if self.gui.comp_preset_var.get() == "auto":
644
635
  state = "disabled"
645
636
  else:
@@ -648,7 +639,7 @@ class AdvancedCompressionWindow(BaseWindow):
648
639
  self.img_format_entry.config(state=state)
649
640
  self.vid_format_entry.config(state=state)
650
641
 
651
- def cb_disable_fake_vid(self, *args: Any):
642
+ def cb_disable_fake_vid(self, *_: Any) -> None:
652
643
  if self.gui.comp_preset_var.get() == "auto":
653
644
  state = "disabled"
654
645
  else:
@@ -656,7 +647,7 @@ class AdvancedCompressionWindow(BaseWindow):
656
647
 
657
648
  self.fake_vid_cbox.config(state=state)
658
649
 
659
- def set_emoji_btn(self):
650
+ def set_emoji_btn(self) -> None:
660
651
  self.im = Image.new("RGBA", (128, 128), (255, 255, 255, 0))
661
652
  ImageDraw.Draw(self.im).text( # type: ignore
662
653
  (0, 0),
@@ -668,7 +659,7 @@ class AdvancedCompressionWindow(BaseWindow):
668
659
  self.ph_im = ImageTk.PhotoImage(self.im)
669
660
  self.default_emoji_dsp.config(image=self.ph_im)
670
661
 
671
- def render_emoji_list(self, *args: Any):
662
+ def render_emoji_list(self, *_: Any) -> None:
672
663
  category = self.categories_var.get()
673
664
 
674
665
  for emoji_btn, ph_im in self.emoji_btns:
@@ -746,19 +737,19 @@ class AdvancedCompressionWindow(BaseWindow):
746
737
  self.emoji_canvas.bind("<Enter>", self.cb_bound_to_mousewheel)
747
738
  self.emoji_canvas.bind("<Leave>", self.cb_unbound_to_mousewheel)
748
739
 
749
- def cb_bound_to_mousewheel(self, event: Any):
740
+ def cb_bound_to_mousewheel(self, event: Any) -> None:
750
741
  for i in self.mousewheel:
751
742
  self.emoji_canvas.bind_all(i, self.cb_on_mousewheel)
752
743
 
753
- def cb_unbound_to_mousewheel(self, event: Any):
744
+ def cb_unbound_to_mousewheel(self, event: Any) -> None:
754
745
  for i in self.mousewheel:
755
746
  self.emoji_canvas.unbind_all(i)
756
747
 
757
- def cb_on_mousewheel(self, event: Any):
748
+ def cb_on_mousewheel(self, event: Any) -> None:
758
749
  self.emoji_canvas.yview_scroll(
759
750
  int(-1 * (event.delta / self.delta_divide)), "units"
760
751
  ) # type: ignore
761
752
 
762
- def cb_set_emoji(self, emoji: str):
753
+ def cb_set_emoji(self, emoji: str) -> None:
763
754
  self.gui.default_emoji_var.set(emoji)
764
755
  self.set_emoji_btn()
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env python3
2
2
  import platform
3
- from typing import TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Tuple
4
4
 
5
5
  from ttkbootstrap import Toplevel # type: ignore
6
6
 
7
+ from sticker_convert.gui_components.gui_utils import GUIUtils
8
+
7
9
  if TYPE_CHECKING:
8
10
  from sticker_convert.gui import GUI # type: ignore
9
11
 
10
- from sticker_convert.gui_components.gui_utils import GUIUtils
11
-
12
12
 
13
13
  class BaseWindow(Toplevel):
14
- def __init__(self, gui: "GUI"):
15
- super(BaseWindow, self).__init__(alpha=0) # type: ignore
14
+ def __init__(self, gui: "GUI") -> None:
15
+ super().__init__(alpha=0) # type: ignore
16
16
  self.gui = gui
17
17
 
18
18
  GUIUtils.set_icon(self)
19
19
 
20
- self.mousewheel: tuple[str, ...]
20
+ self.mousewheel: Tuple[str, ...]
21
21
  if platform.system() == "Windows":
22
22
  self.mousewheel = ("<MouseWheel>",)
23
23
  self.delta_divide = 120
@@ -3,13 +3,7 @@ from functools import partial
3
3
  from threading import Thread
4
4
  from typing import Any
5
5
 
6
- from ttkbootstrap import ( # type: ignore
7
- Button,
8
- Entry,
9
- Frame,
10
- Label,
11
- LabelFrame,
12
- )
6
+ from ttkbootstrap import Button, Entry, Frame, Label, LabelFrame # type: ignore
13
7
 
14
8
  from sticker_convert.gui_components.frames.right_clicker import RightClicker
15
9
  from sticker_convert.gui_components.gui_utils import GUIUtils
@@ -18,8 +12,8 @@ from sticker_convert.utils.auth.get_kakao_auth import GetKakaoAuth
18
12
 
19
13
 
20
14
  class KakaoGetAuthWindow(BaseWindow):
21
- def __init__(self, *args: Any, **kwargs: Any):
22
- super(KakaoGetAuthWindow, self).__init__(*args, **kwargs)
15
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
16
+ super().__init__(*args, **kwargs)
23
17
 
24
18
  self.title("Get Kakao auth_token")
25
19
 
@@ -165,10 +159,10 @@ class KakaoGetAuthWindow(BaseWindow):
165
159
 
166
160
  GUIUtils.finalize_window(self)
167
161
 
168
- def cb_login(self):
162
+ def cb_login(self) -> None:
169
163
  Thread(target=self.cb_login_thread, daemon=True).start()
170
164
 
171
- def cb_login_thread(self, *args: Any):
165
+ def cb_login_thread(self, *_: Any) -> None:
172
166
  self.gui.save_creds()
173
167
  m = GetKakaoAuth(
174
168
  opt_cred=self.gui.get_opt_cred(),
@@ -12,8 +12,8 @@ from sticker_convert.utils.auth.get_line_auth import GetLineAuth
12
12
 
13
13
 
14
14
  class LineGetAuthWindow(BaseWindow):
15
- def __init__(self, *args: Any, **kwargs: Any):
16
- super(LineGetAuthWindow, self).__init__(*args, **kwargs)
15
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
16
+ super().__init__(*args, **kwargs)
17
17
 
18
18
  self.title("Get Line cookie")
19
19
 
@@ -68,7 +68,7 @@ class LineGetAuthWindow(BaseWindow):
68
68
 
69
69
  GUIUtils.finalize_window(self)
70
70
 
71
- def cb_open_browser(self):
71
+ def cb_open_browser(self) -> None:
72
72
  line_login_site = "https://store.line.me/login"
73
73
  success = webbrowser.open(line_login_site)
74
74
  if not success:
@@ -77,10 +77,10 @@ class LineGetAuthWindow(BaseWindow):
77
77
  initialvalue=line_login_site,
78
78
  )
79
79
 
80
- def cb_get_cookies(self):
80
+ def cb_get_cookies(self) -> None:
81
81
  Thread(target=self.cb_get_cookies_thread, daemon=True).start()
82
82
 
83
- def cb_get_cookies_thread(self, *args: Any):
83
+ def cb_get_cookies_thread(self, *_: Any) -> None:
84
84
  m = GetLineAuth()
85
85
 
86
86
  line_cookies = None
@@ -13,8 +13,8 @@ from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
13
13
 
14
14
 
15
15
  class SignalGetAuthWindow(BaseWindow):
16
- def __init__(self, *args: Any, **kwargs: Any):
17
- super(SignalGetAuthWindow, self).__init__(*args, **kwargs)
16
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
17
+ super().__init__(*args, **kwargs)
18
18
 
19
19
  self.title("Get Signal uuid and password")
20
20
 
@@ -78,7 +78,7 @@ class SignalGetAuthWindow(BaseWindow):
78
78
 
79
79
  GUIUtils.finalize_window(self)
80
80
 
81
- def cb_login(self):
81
+ def cb_login(self) -> None:
82
82
  m = GetSignalAuth()
83
83
 
84
84
  signal_bin_path = None
@@ -102,13 +102,13 @@ class SignalGetAuthWindow(BaseWindow):
102
102
 
103
103
  self.cb_msg_block_signal(msg)
104
104
 
105
- def cb_launch_signal(self):
105
+ def cb_launch_signal(self) -> None:
106
106
  m = GetSignalAuth()
107
107
  signal_bin_path, signal_user_data_dir = m.get_signal_desktop()
108
108
 
109
109
  if self.gui.signal_data_dir_var.get():
110
110
  signal_user_data_dir = self.gui.signal_data_dir_var.get()
111
-
111
+
112
112
  if signal_bin_path:
113
113
  Popen(
114
114
  [
@@ -120,7 +120,7 @@ class SignalGetAuthWindow(BaseWindow):
120
120
  else:
121
121
  self.cb_msg_block_signal("Error: Signal Desktop not installed.")
122
122
 
123
- def cb_setdir(self):
123
+ def cb_setdir(self) -> None:
124
124
  orig_input_dir = self.gui.signal_data_dir_var.get()
125
125
  if not Path(orig_input_dir).is_dir():
126
126
  orig_input_dir = ""