sticker-convert 2.6.5__tar.gz → 2.7.0__tar.gz

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 (111) hide show
  1. {sticker-convert-2.6.5/src/sticker_convert.egg-info → sticker-convert-2.7.0}/PKG-INFO +2 -2
  2. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/requirements.txt +1 -1
  3. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/cli.py +6 -13
  4. sticker-convert-2.7.0/src/sticker_convert/gui_components/windows/signal_get_auth_window.py +83 -0
  5. sticker-convert-2.7.0/src/sticker_convert/utils/auth/get_signal_auth.py +115 -0
  6. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/callback.py +0 -1
  7. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/version.py +1 -1
  8. {sticker-convert-2.6.5 → sticker-convert-2.7.0/src/sticker_convert.egg-info}/PKG-INFO +2 -2
  9. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert.egg-info/requires.txt +1 -1
  10. sticker-convert-2.6.5/src/sticker_convert/gui_components/windows/signal_get_auth_window.py +0 -94
  11. sticker-convert-2.6.5/src/sticker_convert/utils/auth/get_signal_auth.py +0 -343
  12. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/LICENSE +0 -0
  13. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/MANIFEST.in +0 -0
  14. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/README.md +0 -0
  15. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/pyproject.toml +0 -0
  16. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/setup.cfg +0 -0
  17. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/__init__.py +0 -0
  18. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/__main__.py +0 -0
  19. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/converter.py +0 -0
  20. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/definitions.py +0 -0
  21. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/__init__.py +0 -0
  22. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/download_base.py +0 -0
  23. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/download_kakao.py +0 -0
  24. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/download_line.py +0 -0
  25. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/download_signal.py +0 -0
  26. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/downloaders/download_telegram.py +0 -0
  27. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui.py +0 -0
  28. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/__init__.py +0 -0
  29. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/__init__.py +0 -0
  30. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/comp_frame.py +0 -0
  31. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/config_frame.py +0 -0
  32. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/control_frame.py +0 -0
  33. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/cred_frame.py +0 -0
  34. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/input_frame.py +0 -0
  35. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/output_frame.py +0 -0
  36. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/progress_frame.py +0 -0
  37. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/frames/right_clicker.py +0 -0
  38. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/gui_utils.py +0 -0
  39. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/windows/__init__.py +0 -0
  40. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/windows/advanced_compression_window.py +0 -0
  41. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/windows/base_window.py +0 -0
  42. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/windows/kakao_get_auth_window.py +0 -0
  43. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/gui_components/windows/line_get_auth_window.py +0 -0
  44. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +0 -0
  45. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/.gitignore +0 -0
  46. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/README.md +0 -0
  47. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers/Info.plist +0 -0
  48. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +0 -0
  49. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +0 -0
  50. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +0 -0
  51. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +0 -0
  52. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
  53. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +0 -0
  54. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
  55. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +0 -0
  56. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
  57. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
  58. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +0 -0
  59. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
  60. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
  61. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
  62. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
  63. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
  64. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
  65. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
  66. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
  67. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
  68. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
  69. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
  70. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
  71. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +0 -0
  72. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  73. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  74. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  75. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  76. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/job.py +0 -0
  77. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/job_option.py +0 -0
  78. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  79. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/appicon.icns +0 -0
  80. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/appicon.ico +0 -0
  81. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/appicon.png +0 -0
  82. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/compression.json +0 -0
  83. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/emoji.json +0 -0
  84. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/help.json +0 -0
  85. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/input.json +0 -0
  86. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/resources/output.json +0 -0
  87. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/__init__.py +0 -0
  88. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/compress_wastickers.py +0 -0
  89. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/upload_base.py +0 -0
  90. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/upload_signal.py +0 -0
  91. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/upload_telegram.py +0 -0
  92. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/uploaders/xcode_imessage.py +0 -0
  93. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/auth/get_kakao_auth.py +0 -0
  94. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/auth/get_line_auth.py +0 -0
  95. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/files/cache_store.py +0 -0
  96. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/files/json_manager.py +0 -0
  97. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/files/metadata_handler.py +0 -0
  98. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/files/run_bin.py +0 -0
  99. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/files/sanitize_filename.py +0 -0
  100. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/media/apple_png_normalize.py +0 -0
  101. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/media/codec_info.py +0 -0
  102. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/media/decrypt_kakao.py +0 -0
  103. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/media/format_verify.py +0 -0
  104. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert/utils/url_detect.py +0 -0
  105. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert.egg-info/SOURCES.txt +0 -0
  106. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert.egg-info/dependency_links.txt +0 -0
  107. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert.egg-info/entry_points.txt +0 -0
  108. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/src/sticker_convert.egg-info/top_level.txt +0 -0
  109. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/tests/test_compression.py +0 -0
  110. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/tests/test_download.py +0 -0
  111. {sticker-convert-2.6.5 → sticker-convert-2.7.0}/tests/test_export.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.6.5
3
+ Version: 2.7.0
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -376,8 +376,8 @@ Requires-Dist: pyoxipng~=9.0.0
376
376
  Requires-Dist: python-telegram-bot~=20.5
377
377
  Requires-Dist: requests~=2.31.0
378
378
  Requires-Dist: rlottie_python~=1.2.1
379
- Requires-Dist: selenium~=4.17.2
380
379
  Requires-Dist: signalstickers-client~=3.3.0
380
+ Requires-Dist: sqlcipher3-wheels~=0.5.2.post0
381
381
  Requires-Dist: tqdm~=4.66.2
382
382
  Requires-Dist: ttkbootstrap-fork-laggykiller~=1.5.1
383
383
  Requires-Dist: webp~=0.3.0
@@ -10,8 +10,8 @@ pyoxipng~=9.0.0
10
10
  python-telegram-bot~=20.5
11
11
  requests~=2.31.0
12
12
  rlottie_python~=1.2.1
13
- selenium~=4.17.2
14
13
  signalstickers-client~=3.3.0
14
+ sqlcipher3-wheels~=0.5.2.post0
15
15
  tqdm~=4.66.2
16
16
  ttkbootstrap-fork-laggykiller~=1.5.1
17
17
  webp~=0.3.0
@@ -435,22 +435,15 @@ class CLI:
435
435
  self.cb.msg(f"Got auth_token successfully: {auth_token}")
436
436
 
437
437
  if args.signal_get_auth:
438
- m = GetSignalAuth(cb_msg=self.cb.msg, cb_ask_str=self.cb.ask_str)
439
- m.launch_signal_desktop()
438
+ m = GetSignalAuth()
440
439
 
441
- uuid, password = None, None
442
- while True:
443
- uuid, password = m.get_cred()
440
+ uuid, password, msg = m.get_cred()
444
441
 
445
- if uuid and password:
446
- opt_cred.signal_uuid = uuid
447
- opt_cred.signal_password = password
442
+ if uuid and password:
443
+ opt_cred.signal_uuid = uuid
444
+ opt_cred.signal_password = password
448
445
 
449
- self.cb.msg(
450
- f"Got uuid and password successfully: {uuid}, {password}"
451
- )
452
- m.close()
453
- break
446
+ self.cb.msg(msg)
454
447
 
455
448
  if args.line_get_auth:
456
449
  m = GetLineAuth()
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env python3
2
+ from functools import partial
3
+ from subprocess import Popen
4
+ from typing import Any
5
+
6
+ from ttkbootstrap import Button, Frame, Label # type: ignore
7
+
8
+ from sticker_convert.gui_components.gui_utils import GUIUtils
9
+ from sticker_convert.gui_components.windows.base_window import BaseWindow
10
+ from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
11
+
12
+
13
+ class SignalGetAuthWindow(BaseWindow):
14
+ def __init__(self, *args: Any, **kwargs: Any):
15
+ super(SignalGetAuthWindow, self).__init__(*args, **kwargs)
16
+
17
+ self.title("Get Signal uuid and password")
18
+
19
+ self.cb_msg_block_signal = partial(self.gui.cb_msg_block, parent=self)
20
+ self.cb_ask_str_signal = partial(self.gui.cb_ask_str, parent=self)
21
+
22
+ self.frame_info = Frame(self.scrollable_frame)
23
+ self.frame_btns = Frame(self.scrollable_frame)
24
+
25
+ self.frame_info.grid(column=0, row=0, sticky="news", padx=3, pady=3)
26
+ self.frame_btns.grid(column=0, row=1, sticky="news", padx=3, pady=3)
27
+
28
+ # Info frame
29
+ self.explanation_lbl = Label(
30
+ self.frame_info,
31
+ text="Please install Signal Desktop and login first.",
32
+ justify="left",
33
+ anchor="w",
34
+ )
35
+
36
+ self.explanation_lbl.grid(
37
+ column=0, row=0, columnspan=3, sticky="w", padx=3, pady=3
38
+ )
39
+
40
+ # Start button frame
41
+ self.launch_btn = Button(
42
+ self.frame_btns, text="Launch Signal Desktop", command=self.cb_launch_signal
43
+ )
44
+
45
+ self.login_btn = Button(
46
+ self.frame_btns, text="Get uuid and password", command=self.cb_login
47
+ )
48
+
49
+ self.launch_btn.pack()
50
+ self.login_btn.pack()
51
+
52
+ GUIUtils.finalize_window(self)
53
+
54
+ def cb_login(self):
55
+ m = GetSignalAuth()
56
+ uuid, password, msg = m.get_cred()
57
+
58
+ if uuid and password:
59
+ if not self.gui.creds.get("signal"):
60
+ self.gui.creds["signal"] = {}
61
+ self.gui.creds["signal"]["uuid"] = uuid
62
+ self.gui.creds["signal"]["password"] = password
63
+ self.gui.signal_uuid_var.set(uuid)
64
+ self.gui.signal_password_var.set(password)
65
+
66
+ self.gui.save_creds()
67
+ self.gui.highlight_fields()
68
+
69
+ self.cb_msg_block_signal(msg)
70
+
71
+ def cb_launch_signal(self):
72
+ m = GetSignalAuth()
73
+ signal_bin_path, signal_user_data_dir = m.get_signal_desktop()
74
+ if signal_bin_path:
75
+ Popen(
76
+ [
77
+ signal_bin_path,
78
+ "--no-sandbox",
79
+ f"--user-data-dir={signal_user_data_dir}",
80
+ ]
81
+ )
82
+ else:
83
+ self.cb_msg_block_signal("Error: Signal Desktop not installed.")
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import json
4
+ import platform
5
+ import shutil
6
+ from sqlcipher3 import dbapi2 as sqlite3
7
+ from pathlib import Path
8
+ from typing import Optional
9
+
10
+
11
+ class GetSignalAuth:
12
+ def get_signal_desktop(self) -> tuple[Optional[str], Optional[str]]:
13
+ if platform.system() == "Windows":
14
+ signal_bin_path_prod = os.path.expandvars(
15
+ "%localappdata%/Programs/signal-desktop/Signal.exe"
16
+ )
17
+ signal_bin_path_beta = os.path.expandvars(
18
+ "%localappdata%/Programs/signal-desktop-beta/Signal Beta.exe"
19
+ )
20
+ signal_user_data_dir_prod = os.path.abspath(
21
+ os.path.expandvars("%appdata%/Signal")
22
+ )
23
+ signal_user_data_dir_beta = os.path.abspath(
24
+ os.path.expandvars("%appdata%/Signal Beta")
25
+ )
26
+ elif platform.system() == "Darwin":
27
+ signal_bin_path_prod = "/Applications/Signal.app/Contents/MacOS/Signal"
28
+ signal_bin_path_beta = (
29
+ "/Applications/Signal Beta.app/Contents/MacOS/Signal Beta"
30
+ )
31
+ signal_user_data_dir_prod = os.path.expanduser(
32
+ "~/Library/Application Support/Signal"
33
+ )
34
+ signal_user_data_dir_beta = os.path.expanduser(
35
+ "~/Library/Application Support/Signal Beta"
36
+ )
37
+ else:
38
+ if not (signal_bin_path_prod := shutil.which("signal-desktop")): # type: ignore
39
+ signal_bin_path_prod = "signal-desktop"
40
+ if not (signal_bin_path_beta := shutil.which("signal-desktop-beta")): # type: ignore
41
+ signal_bin_path_beta = "signal-desktop-beta"
42
+ signal_user_data_dir_prod = os.path.expanduser("~/.config/Signal")
43
+ signal_user_data_dir_beta = os.path.expanduser("~/.config/Signal Beta")
44
+
45
+ if Path(signal_bin_path_prod).is_file():
46
+ return signal_bin_path_prod, signal_user_data_dir_prod
47
+ elif Path(signal_bin_path_beta).is_file():
48
+ return signal_bin_path_beta, signal_user_data_dir_beta
49
+ else:
50
+ return None, None
51
+
52
+ def get_cred(self) -> tuple[Optional[str], Optional[str], str]:
53
+ signal_bin_path, signal_user_data_dir = self.get_signal_desktop()
54
+
55
+ if not (signal_bin_path and signal_user_data_dir):
56
+ msg = "Signal Desktop not detected.\n"
57
+ msg += "Download and install Signal Desktop,\n"
58
+ msg += "then login to Signal Desktop and try again."
59
+
60
+ return None, None, msg
61
+
62
+ signal_config = Path(signal_user_data_dir, "config.json")
63
+
64
+ if not signal_config.is_file():
65
+ msg = "Signal Desktop installed,\n"
66
+ msg += "but it's config file not found.\n"
67
+ msg += "Please login to Signal Desktop and try again.\n"
68
+ msg += "\n"
69
+ msg += f"{signal_bin_path=}\n"
70
+ msg += f"{signal_user_data_dir=}\n"
71
+ return None, None, msg
72
+
73
+ with open(signal_config) as f:
74
+ config = json.load(f)
75
+ key = config.get("key")
76
+ db_key = f"x'{key}'"
77
+
78
+ signal_database = Path(signal_user_data_dir, "sql/db.sqlite")
79
+
80
+ if not signal_database.is_file():
81
+ msg = "Signal Desktop installed,\n"
82
+ msg += "but database file not found.\n"
83
+ msg += "Please login to Signal Desktop and try again.\n"
84
+ msg += "\n"
85
+ msg += f"{signal_bin_path=}\n"
86
+ msg += f"{signal_user_data_dir=}\n"
87
+ return None, None, msg
88
+
89
+ db_conn = sqlite3.connect(signal_database.as_posix()) # type: ignore
90
+ db_cursor = db_conn.cursor()
91
+ db_cursor.execute(f'PRAGMA key="{db_key}"')
92
+ db_cursor.execute("SELECT * FROM items")
93
+ result = db_cursor.fetchall()
94
+ db_conn.close()
95
+
96
+ uuid_id = None
97
+ password = None
98
+ for r in result:
99
+ if "uuid_id" in r:
100
+ uuid_id = json.loads(r[1])["value"]
101
+ if "password" in r:
102
+ password = json.loads(r[1])["value"]
103
+ if uuid_id and password:
104
+ msg = "Got uuid and password successfully:\n"
105
+ msg += f"{uuid_id=}\n"
106
+ msg += f"{password=}"
107
+ return uuid_id, password, msg
108
+
109
+ msg = "Signal Desktop installed and Database found,\n"
110
+ msg += "but uuid and password not found.\n"
111
+ msg += "Please login to Signal Desktop and try again.\n"
112
+ msg += "\n"
113
+ msg += f"{signal_bin_path=}\n"
114
+ msg += f"{signal_user_data_dir=}\n"
115
+ return None, None, msg
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env python3
2
- from queue import Queue
3
2
  from multiprocessing import Queue, Event
4
3
  from typing import Callable, Optional, Union, Any
5
4
 
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env python3
2
- __version__ = "2.6.5"
2
+ __version__ = "2.7.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.6.5
3
+ Version: 2.7.0
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -376,8 +376,8 @@ Requires-Dist: pyoxipng~=9.0.0
376
376
  Requires-Dist: python-telegram-bot~=20.5
377
377
  Requires-Dist: requests~=2.31.0
378
378
  Requires-Dist: rlottie_python~=1.2.1
379
- Requires-Dist: selenium~=4.17.2
380
379
  Requires-Dist: signalstickers-client~=3.3.0
380
+ Requires-Dist: sqlcipher3-wheels~=0.5.2.post0
381
381
  Requires-Dist: tqdm~=4.66.2
382
382
  Requires-Dist: ttkbootstrap-fork-laggykiller~=1.5.1
383
383
  Requires-Dist: webp~=0.3.0
@@ -10,8 +10,8 @@ pyoxipng~=9.0.0
10
10
  python-telegram-bot~=20.5
11
11
  requests~=2.31.0
12
12
  rlottie_python~=1.2.1
13
- selenium~=4.17.2
14
13
  signalstickers-client~=3.3.0
14
+ sqlcipher3-wheels~=0.5.2.post0
15
15
  tqdm~=4.66.2
16
16
  ttkbootstrap-fork-laggykiller~=1.5.1
17
17
  webp~=0.3.0
@@ -1,94 +0,0 @@
1
- #!/usr/bin/env python3
2
- from functools import partial
3
- from threading import Thread
4
- from typing import Any
5
-
6
- from ttkbootstrap import Button, Frame, Label, Toplevel # type: ignore
7
-
8
- from sticker_convert.gui_components.gui_utils import GUIUtils
9
- from sticker_convert.gui_components.windows.base_window import BaseWindow
10
- from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
11
-
12
-
13
- class SignalGetAuthWindow(BaseWindow):
14
- def __init__(self, *args: Any, **kwargs: Any):
15
- super(SignalGetAuthWindow, self).__init__(*args, **kwargs)
16
-
17
- self.title("Get Signal uuid and password")
18
-
19
- self.cb_msg_block_signal = partial(self.gui.cb_msg_block, parent=self)
20
- self.cb_ask_str_signal = partial(self.gui.cb_ask_str, parent=self)
21
-
22
- self.frame_info = Frame(self.scrollable_frame)
23
- self.frame_start_btn = Frame(self.scrollable_frame)
24
-
25
- self.frame_info.grid(column=0, row=0, sticky="news", padx=3, pady=3)
26
- self.frame_start_btn.grid(column=0, row=1, sticky="news", padx=3, pady=3)
27
-
28
- # Info frame
29
- self.explanation1_lbl = Label(
30
- self.frame_info,
31
- text="Please install Signal Desktop BETA VERSION",
32
- justify="left",
33
- anchor="w",
34
- )
35
- self.explanation2_lbl = Label(
36
- self.frame_info,
37
- text="After installation, you need to login to Signal Desktop",
38
- justify="left",
39
- anchor="w",
40
- )
41
- self.explanation3_lbl = Label(
42
- self.frame_info,
43
- text="uuid and password will be automatically fetched",
44
- justify="left",
45
- anchor="w",
46
- )
47
-
48
- self.explanation1_lbl.grid(
49
- column=0, row=0, columnspan=3, sticky="w", padx=3, pady=3
50
- )
51
- self.explanation2_lbl.grid(
52
- column=0, row=1, columnspan=3, sticky="w", padx=3, pady=3
53
- )
54
- self.explanation3_lbl.grid(
55
- column=0, row=2, columnspan=3, sticky="w", padx=3, pady=3
56
- )
57
-
58
- # Start button frame
59
- self.login_btn = Button(
60
- self.frame_start_btn, text="Get uuid and password", command=self.cb_login
61
- )
62
-
63
- self.login_btn.pack()
64
-
65
- GUIUtils.finalize_window(self)
66
-
67
- def cb_login(self):
68
- Thread(target=self.cb_login_thread, daemon=True).start()
69
-
70
- def cb_login_thread(self, *args: Any):
71
- m = GetSignalAuth(cb_msg=self.gui.cb_msg, cb_ask_str=self.cb_ask_str_signal)
72
- m.launch_signal_desktop()
73
-
74
- uuid, password = None, None
75
- while Toplevel.winfo_exists(self):
76
- uuid, password = m.get_cred()
77
-
78
- if uuid and password:
79
- if not self.gui.creds.get("signal"):
80
- self.gui.creds["signal"] = {}
81
- self.gui.creds["signal"]["uuid"] = uuid
82
- self.gui.creds["signal"]["password"] = password
83
- self.gui.signal_uuid_var.set(uuid)
84
- self.gui.signal_password_var.set(password)
85
- m.close()
86
-
87
- self.cb_msg_block_signal(
88
- f"Got uuid and password successfully:\nuuid={uuid}\npassword={password}"
89
- )
90
- self.gui.save_creds()
91
- self.gui.highlight_fields()
92
- return
93
-
94
- self.cb_msg_block_signal("Failed to get uuid and password")
@@ -1,343 +0,0 @@
1
- #!/usr/bin/env python3
2
- import io
3
- import json
4
- import os
5
- import platform
6
- import shutil
7
- import stat
8
- import string
9
- import webbrowser
10
- import zipfile
11
- from pathlib import Path
12
- from typing import Generator, Optional, Callable
13
-
14
- import requests
15
- from selenium import webdriver
16
- from selenium.common.exceptions import JavascriptException
17
- from selenium.webdriver.chrome.service import Service
18
-
19
- from sticker_convert.definitions import CONFIG_DIR
20
- from sticker_convert.utils.files.run_bin import RunBin
21
-
22
-
23
- # https://stackoverflow.com/a/17197027
24
- def strings(filename: str, min: int = 4) -> Generator[str, None, None]:
25
- with open(filename, "r", errors="ignore") as f:
26
- result = ""
27
- for c in f.read():
28
- if c in string.printable:
29
- result += c
30
- continue
31
- if len(result) >= min:
32
- yield result
33
- result = ""
34
- if len(result) >= min: # catch result at EOF
35
- yield result
36
-
37
-
38
- class GetSignalAuth:
39
- def __init__(
40
- self,
41
- signal_bin_version: str = "beta",
42
- cb_msg: Callable[..., None] = print,
43
- cb_ask_str: Callable[..., str] = input,
44
- ):
45
- chromedriver_download_dir = CONFIG_DIR / "bin"
46
- os.makedirs(chromedriver_download_dir, exist_ok=True)
47
-
48
- self.signal_bin_version = signal_bin_version
49
- self.chromedriver_download_dir = chromedriver_download_dir
50
-
51
- self.cb_ask_str = cb_ask_str
52
- self.cb_msg = cb_msg
53
-
54
- def download_signal_desktop(self, download_url: str, signal_bin_path: str):
55
- webbrowser.open(download_url)
56
-
57
- self.cb_msg(download_url)
58
-
59
- prompt = "Signal Desktop not detected.\n"
60
- prompt += "Download and install Signal Desktop BETA version\n"
61
- prompt += "After installation, quit Signal Desktop before continuing"
62
- while not (Path(signal_bin_path).is_file() or shutil.which(signal_bin_path)):
63
- if self.cb_ask_str != input:
64
- self.cb_ask_str(
65
- prompt, initialvalue=download_url, cli_show_initialvalue=False
66
- )
67
- else:
68
- input(prompt)
69
-
70
- def get_signal_chromedriver_version(self, electron_bin_path: str) -> Optional[str]:
71
- if RunBin.get_bin("strings", silent=True):
72
- status, output_str = RunBin.run_cmd(
73
- cmd_list=["strings", electron_bin_path], silence=True
74
- )
75
- if status is False:
76
- return None
77
- ss = output_str.split("\n")
78
- else:
79
- ss = strings(electron_bin_path)
80
-
81
- for s in ss:
82
- if "Chrome/" in s and " Electron/" in s:
83
- major_version = s.replace("Chrome/", "").split(".", 1)[0]
84
- if major_version.isnumeric():
85
- return major_version
86
-
87
- return None
88
-
89
- def get_local_chromedriver(
90
- self, chromedriver_download_dir: Path
91
- ) -> tuple[Optional[Path], Optional[str]]:
92
- local_chromedriver_version = None
93
- if platform.system() == "Windows":
94
- chromedriver_name = "chromedriver.exe"
95
- else:
96
- chromedriver_name = "chromedriver"
97
- chromedriver_path = Path(chromedriver_download_dir, chromedriver_name).resolve()
98
- if not chromedriver_path.is_file():
99
- chromedriver_which = shutil.which("chromedriver")
100
- if chromedriver_which:
101
- chromedriver_path = Path(chromedriver_which)
102
- else:
103
- chromedriver_path = None
104
-
105
- if chromedriver_path:
106
- status, output_str = RunBin.run_cmd(
107
- cmd_list=[str(chromedriver_path), "-v"], silence=True
108
- )
109
- if status is False:
110
- local_chromedriver_version = None
111
- local_chromedriver_version = output_str.split(" ")[1].split(".", 1)[0]
112
- else:
113
- local_chromedriver_version = None
114
-
115
- return chromedriver_path, local_chromedriver_version
116
-
117
- def download_chromedriver(
118
- self, major_version: str, chromedriver_download_dir: Path
119
- ) -> Optional[Path]:
120
- if platform.system() == "Windows":
121
- chromedriver_platform = "win32"
122
- if "64" in platform.architecture()[0]:
123
- chromedriver_platform_new = "win64"
124
- else:
125
- chromedriver_platform_new = "win32"
126
- elif platform.system() == "Darwin":
127
- if platform.processor().lower() == "arm64":
128
- chromedriver_platform = "mac_arm64"
129
- chromedriver_platform_new = "mac-arm64"
130
- else:
131
- chromedriver_platform = "mac64"
132
- chromedriver_platform_new = "mac-x64"
133
- else:
134
- chromedriver_platform = "linux64"
135
- chromedriver_platform_new = "linux64"
136
-
137
- chromedriver_url = None
138
- chromedriver_version_url = f"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_{major_version}"
139
- r = requests.get(chromedriver_version_url)
140
- if r.ok:
141
- new_chrome = False
142
- chromedriver_version = r.text
143
- chromedriver_url = f"https://chromedriver.storage.googleapis.com/{chromedriver_version}/chromedriver_{chromedriver_platform}.zip"
144
- else:
145
- new_chrome = True
146
- r = requests.get(
147
- "https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone-with-downloads.json"
148
- )
149
- versions_dict = json.loads(r.text)
150
- chromedriver_list = (
151
- versions_dict.get("milestones", {})
152
- .get(major_version, {})
153
- .get("downloads", {})
154
- .get("chromedriver", {})
155
- )
156
-
157
- chromedriver_url = None
158
- for i in chromedriver_list:
159
- if i.get("platform") == chromedriver_platform_new:
160
- chromedriver_url = i.get("url")
161
-
162
- if not chromedriver_url:
163
- return None
164
-
165
- if platform.system() == "Windows":
166
- chromedriver_name = "chromedriver.exe"
167
- else:
168
- chromedriver_name = "chromedriver"
169
-
170
- if new_chrome:
171
- chromedriver_zip_path = (
172
- f"chromedriver-{chromedriver_platform_new}/{chromedriver_name}"
173
- )
174
- else:
175
- chromedriver_zip_path = chromedriver_name
176
-
177
- chromedriver_path = Path(chromedriver_download_dir, chromedriver_name).resolve()
178
-
179
- with io.BytesIO() as f:
180
- f.write(requests.get(chromedriver_url).content) # type: ignore
181
- with zipfile.ZipFile(f, "r") as z, open(chromedriver_path, "wb+") as g:
182
- g.write(z.read(chromedriver_zip_path))
183
-
184
- if platform.system() != "Windows":
185
- st = os.stat(chromedriver_path)
186
- os.chmod(chromedriver_path, st.st_mode | stat.S_IEXEC)
187
-
188
- return chromedriver_path
189
-
190
- def killall_signal(self):
191
- if platform.system() == "Windows":
192
- os.system('taskkill /F /im "Signal.exe"')
193
- os.system('taskkill /F /im "Signal Beta.exe"')
194
- else:
195
- RunBin.run_cmd(cmd_list=["killall", "signal-desktop"], silence=True)
196
- RunBin.run_cmd(cmd_list=["killall", "signal-desktop-beta"], silence=True)
197
-
198
- def launch_signal(
199
- self, signal_bin_path: str, signal_user_data_dir: str, chromedriver_path: str
200
- ):
201
- options = webdriver.ChromeOptions()
202
- options.binary_location = signal_bin_path
203
- options.add_argument(f"user-data-dir={signal_user_data_dir}") # type: ignore
204
- options.add_argument("no-sandbox") # type: ignore
205
- service = Service(executable_path=chromedriver_path)
206
-
207
- self.driver = webdriver.Chrome(options=options, service=service)
208
-
209
- def get_cred(self) -> tuple[Optional[str], Optional[str]]:
210
- # https://stackoverflow.com/a/73456344
211
- uuid: Optional[str] = None
212
- password: Optional[str] = None
213
- try:
214
- if self.signal_bin_version == "prod":
215
- uuid = self.driver.execute_script( # type: ignore
216
- "return window.reduxStore.getState().items.uuid_id"
217
- )
218
- password = self.driver.execute_script( # type: ignore
219
- "return window.reduxStore.getState().items.password"
220
- )
221
- else:
222
- uuid = self.driver.execute_script( # type: ignore
223
- "return window.SignalDebug.getReduxState().items.uuid_id"
224
- )
225
- password = self.driver.execute_script( # type: ignore
226
- "return window.SignalDebug.getReduxState().items.password"
227
- )
228
- except JavascriptException:
229
- pass
230
-
231
- assert uuid is None or isinstance(uuid, str)
232
- assert password is None or isinstance(password, str)
233
- return uuid, password
234
-
235
- def close(self):
236
- self.cb_msg("Closing Signal Desktop")
237
- self.driver.quit()
238
-
239
- def launch_signal_desktop(self) -> bool:
240
- if platform.system() == "Windows":
241
- signal_bin_path_prod = os.path.expandvars(
242
- "%localappdata%/Programs/signal-desktop/Signal.exe"
243
- )
244
- signal_bin_path_beta = os.path.expandvars(
245
- "%localappdata%/Programs/signal-desktop-beta/Signal Beta.exe"
246
- )
247
- signal_user_data_dir_prod = os.path.abspath(
248
- os.path.expandvars("%appdata%/Signal")
249
- )
250
- signal_user_data_dir_beta = os.path.abspath(
251
- os.path.expandvars("%appdata%/Signal Beta")
252
- )
253
- electron_bin_path_prod = signal_bin_path_prod
254
- electron_bin_path_beta = signal_bin_path_beta
255
- elif platform.system() == "Darwin":
256
- signal_bin_path_prod = "/Applications/Signal.app/Contents/MacOS/Signal"
257
- signal_bin_path_beta = (
258
- "/Applications/Signal Beta.app/Contents/MacOS/Signal Beta"
259
- )
260
- signal_user_data_dir_prod = os.path.expanduser(
261
- "~/Library/Application Support/Signal"
262
- )
263
- signal_user_data_dir_beta = os.path.expanduser(
264
- "~/Library/Application Support/Signal Beta"
265
- )
266
- electron_bin_path_prod = "/Applications/Signal.app/Contents/Frameworks/Electron Framework.framework/Electron Framework"
267
- electron_bin_path_beta = "/Applications/Signal Beta.app/Contents/Frameworks/Electron Framework.framework/Electron Framework"
268
- else:
269
- signal_bin_path_prod = "signal-desktop"
270
- signal_bin_path_beta = "signal-desktop-beta"
271
- signal_user_data_dir_prod = os.path.expanduser("~/.config/Signal")
272
- signal_user_data_dir_beta = os.path.expanduser("~/.config/Signal Beta")
273
- electron_bin_path_prod = signal_bin_path_prod
274
- electron_bin_path_beta = signal_bin_path_beta
275
-
276
- if self.signal_bin_version == "prod":
277
- signal_bin_path = signal_bin_path_prod
278
- signal_user_data_dir = signal_user_data_dir_prod
279
- electron_bin_path = electron_bin_path_prod
280
- signal_download_url = "https://signal.org/en/download/"
281
- else:
282
- signal_bin_path = signal_bin_path_beta
283
- signal_user_data_dir = signal_user_data_dir_beta
284
- electron_bin_path = electron_bin_path_beta
285
- signal_download_url = (
286
- "https://support.signal.org/hc/en-us/articles/360007318471-Signal-Beta"
287
- )
288
-
289
- if not (Path(signal_bin_path).is_file() or shutil.which(signal_bin_path)):
290
- success = self.download_signal_desktop(signal_download_url, signal_bin_path)
291
-
292
- if not success:
293
- return False
294
-
295
- electron_bin_path = (
296
- shutil.which(electron_bin_path)
297
- if not Path(electron_bin_path).is_file()
298
- else electron_bin_path
299
- )
300
- if not electron_bin_path:
301
- self.cb_msg("Cannot find Electron Framework inside Signal installation")
302
- return False
303
-
304
- signal_bin_path = (
305
- signal_bin_path
306
- if not shutil.which(signal_bin_path)
307
- else shutil.which(signal_bin_path)
308
- )
309
- if not signal_bin_path:
310
- self.cb_msg("Cannot find Signal installation")
311
- return False
312
-
313
- major_version = self.get_signal_chromedriver_version(electron_bin_path)
314
- if major_version:
315
- self.cb_msg(f"Signal Desktop is using chrome version {major_version}")
316
- else:
317
- self.cb_msg("Unable to determine Signal Desktop chrome version")
318
- return False
319
-
320
- chromedriver_path, local_chromedriver_version = self.get_local_chromedriver(
321
- chromedriver_download_dir=self.chromedriver_download_dir
322
- )
323
- if chromedriver_path and local_chromedriver_version == major_version:
324
- self.cb_msg(
325
- f"Found chromedriver version {local_chromedriver_version}, skip downloading"
326
- )
327
- else:
328
- chromedriver_path = self.download_chromedriver(
329
- major_version, chromedriver_download_dir=self.chromedriver_download_dir
330
- )
331
- if not chromedriver_path:
332
- self.cb_msg("Unable to download suitable chromedriver")
333
- return False
334
-
335
- self.cb_msg("Killing all Signal Desktop processes")
336
- self.killall_signal()
337
-
338
- self.cb_msg("Starting Signal Desktop with Selenium")
339
- self.launch_signal(
340
- signal_bin_path, signal_user_data_dir, str(chromedriver_path)
341
- )
342
-
343
- return True
File without changes