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
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import platform
4
+ import shutil
5
+ import subprocess
6
+ import time
7
+ from getpass import getpass
8
+ from io import BytesIO
9
+ from typing import Callable, Optional, Union
10
+ from zipfile import ZipFile
11
+
12
+ import psutil
13
+ import requests
14
+
15
+ from sticker_convert.definitions import CONFIG_DIR, ROOT_DIR
16
+
17
+
18
+ def killall(name: str) -> bool:
19
+ result = False
20
+
21
+ for proc in psutil.process_iter(): # type: ignore
22
+ if name in proc.name().lower():
23
+ proc.kill()
24
+ result = True
25
+
26
+ return result
27
+
28
+
29
+ def find_pid_by_name(name: str) -> Optional[int]:
30
+ for proc in psutil.process_iter(): # type: ignore
31
+ if name in proc.name().lower():
32
+ return proc.pid
33
+
34
+ return None
35
+
36
+
37
+ def check_admin() -> bool:
38
+ return True
39
+
40
+
41
+ if platform.system() == "Windows":
42
+
43
+ def check_admin() -> bool:
44
+ username = os.getenv("username")
45
+ if username is None:
46
+ return False
47
+
48
+ s = subprocess.run(
49
+ ["net", "user", username],
50
+ capture_output=True,
51
+ text=True,
52
+ ).stdout
53
+
54
+ return True if "*Administrators" in s else False
55
+
56
+ elif platform.system() == "Linux":
57
+
58
+ def check_admin() -> bool:
59
+ if shutil.which("sudo") is None:
60
+ return True
61
+
62
+ s = subprocess.run(
63
+ ["sudo", "-l"],
64
+ capture_output=True,
65
+ text=True,
66
+ ).stdout
67
+
68
+ return True if "may run the following commands" in s else False
69
+
70
+
71
+ def _get_mem_win_procdump(
72
+ pid: Union[str, int],
73
+ pw_func: Optional[Callable[..., str]] = None,
74
+ is_wine: bool = False,
75
+ ) -> Optional[bytes]:
76
+ procdump_dir = CONFIG_DIR / "ProcDump"
77
+ procdump_bin = procdump_dir / "procdump.exe"
78
+ if procdump_bin.is_file() is False:
79
+ r = requests.get("https://download.sysinternals.com/files/Procdump.zip")
80
+ if r.ok is False:
81
+ return None
82
+ with ZipFile(BytesIO(r.content)) as zf:
83
+ zf.extractall(procdump_dir)
84
+
85
+ if procdump_bin.is_file() is False:
86
+ return None
87
+
88
+ if is_wine:
89
+ cmd = ["wine"]
90
+ dump_fpath = f"/tmp/memdump.{pid}.dmp"
91
+ else:
92
+ cmd = []
93
+ dump_fpath = os.path.expandvars(f"%temp%/memdump.{pid}.dmp")
94
+ cmd += [str(procdump_bin), "-accepteula", "-ma", str(pid), dump_fpath]
95
+
96
+ subprocess.run(cmd)
97
+
98
+ with open(dump_fpath, "rb") as f:
99
+ s = f.read()
100
+ os.remove(dump_fpath)
101
+
102
+ return s
103
+
104
+
105
+ def _get_mem_win_builtin(
106
+ pid: Union[str, int], pw_func: Optional[Callable[..., str]] = None
107
+ ) -> Optional[bytes]:
108
+ from pathlib import WindowsPath
109
+
110
+ memdump_ps_path = str(WindowsPath(ROOT_DIR / "resources/memdump_windows.ps1"))
111
+ arglist = f'-NoProfile -ExecutionPolicy Bypass -File "{memdump_ps_path}" {pid}'
112
+ dump_fpath = os.path.expandvars(f"%temp%/memdump.{pid}.dmp")
113
+
114
+ cmd = [
115
+ "powershell",
116
+ "-NoProfile",
117
+ "-ExecutionPolicy",
118
+ "Bypass",
119
+ "-Command",
120
+ f"Start-Process -Verb RunAs powershell -ArgumentList '{arglist}'",
121
+ ]
122
+
123
+ subprocess.run(cmd, capture_output=True, text=True)
124
+
125
+ while True:
126
+ try:
127
+ with open(dump_fpath, "rb") as f:
128
+ s = f.read()
129
+ if len(s) != 0:
130
+ break
131
+ time.sleep(1)
132
+ except (FileNotFoundError, PermissionError):
133
+ pass
134
+
135
+ while True:
136
+ try:
137
+ os.remove(dump_fpath)
138
+ break
139
+ except PermissionError:
140
+ pass
141
+
142
+ return s
143
+
144
+
145
+ def _get_mem_darwin(
146
+ pid: Union[str, int], pw_func: Optional[Callable[..., str]] = None
147
+ ) -> Optional[bytes]:
148
+ subprocess.run(
149
+ [
150
+ "lldb",
151
+ "--attach-pid",
152
+ str(pid),
153
+ "-o",
154
+ f"process save-core /tmp/memdump.{pid}.dmp",
155
+ "-o",
156
+ "quit",
157
+ ],
158
+ stdout=subprocess.DEVNULL,
159
+ stderr=subprocess.DEVNULL,
160
+ )
161
+
162
+ with open(f"/tmp/memdump.{pid}.dmp", "rb") as f:
163
+ s = f.read()
164
+
165
+ os.remove(f"/tmp/memdump.{pid}.dmp")
166
+
167
+ return s
168
+
169
+
170
+ def _get_mem_linux(
171
+ pid: Union[str, int], pw_func: Optional[Callable[..., str]] = None
172
+ ) -> Optional[bytes]:
173
+ memdump_sh_path = (ROOT_DIR / "resources/memdump_linux.sh").as_posix()
174
+
175
+ s = subprocess.run(
176
+ [
177
+ memdump_sh_path,
178
+ str(pid),
179
+ ],
180
+ capture_output=True,
181
+ ).stdout
182
+
183
+ if len(s) > 1000:
184
+ pass
185
+ elif shutil.which("pkexec") and os.getenv("DISPLAY"):
186
+ s = subprocess.run(
187
+ [
188
+ "pkexec",
189
+ memdump_sh_path,
190
+ str(pid),
191
+ ],
192
+ capture_output=True,
193
+ ).stdout
194
+ else:
195
+ prompt = "Enter sudo password: "
196
+ if pw_func:
197
+ sudo_password = pw_func(prompt)
198
+ else:
199
+ sudo_password = getpass(prompt)
200
+ sudo_password_pipe = subprocess.Popen(
201
+ ("echo", sudo_password), stdout=subprocess.PIPE
202
+ )
203
+ s = subprocess.run(
204
+ [
205
+ "sudo",
206
+ "-S",
207
+ memdump_sh_path,
208
+ str(pid),
209
+ ],
210
+ capture_output=True,
211
+ stdin=sudo_password_pipe.stdout,
212
+ ).stdout
213
+
214
+ return s
215
+
216
+
217
+ def get_mem(
218
+ pid: Union[str, int],
219
+ pw_func: Optional[Callable[..., str]] = None,
220
+ is_wine: bool = False,
221
+ ) -> Optional[bytes]:
222
+ if is_wine or platform.system() == "Windows":
223
+ dump = _get_mem_win_procdump(pid, pw_func, is_wine)
224
+ if dump is not None or is_wine:
225
+ return dump
226
+ else:
227
+ return _get_mem_win_builtin(pid, pw_func)
228
+ elif platform.system() == "Darwin":
229
+ return _get_mem_darwin(pid, pw_func)
230
+ else:
231
+ return _get_mem_linux(pid, pw_func)
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ import gettext
3
+ import locale
4
+ import platform
5
+ import sys
6
+ from json import JSONDecodeError
7
+ from multiprocessing import current_process
8
+ from typing import Any, Callable, Dict, cast
9
+
10
+ from sticker_convert.definitions import CONFIG_DIR, ROOT_DIR, RUNTIME_STATE
11
+ from sticker_convert.utils.files.json_manager import JsonManager
12
+
13
+ LANG_DICT = {
14
+ "en_US": ("en_US",),
15
+ "ja_JP": ("ja_jp",),
16
+ "zh_CN": ("zh_chs", "zh_cn", "zh_sg"),
17
+ "zh_TW": ("zh_tw", "zh_hk", "zh_mo", "zh_cht"),
18
+ }
19
+
20
+
21
+ def get_default_lang() -> str:
22
+ lang = locale.getlocale()[0]
23
+ winlang = ""
24
+ if platform.system() == "Windows":
25
+ import ctypes
26
+
27
+ windll = ctypes.windll.kernel32 # type: ignore
28
+ winlang_id = cast(int, windll.GetUserDefaultUILanguage()) # type: ignore
29
+ winlang = cast(str, locale.windows_locale[winlang_id]) # type: ignore
30
+
31
+ for k, v in LANG_DICT.items():
32
+ for i in v:
33
+ if (
34
+ lang is not None and lang.lower().startswith(i)
35
+ ) or winlang.lower().startswith(i):
36
+ return k
37
+
38
+ return "en_US"
39
+
40
+
41
+ def get_lang() -> str:
42
+ # Priority 1: From --lang CLI flag
43
+ is_lang = False
44
+ lang = None
45
+ for i in sys.argv:
46
+ if is_lang:
47
+ return i
48
+ if i == "--lang":
49
+ is_lang = True
50
+
51
+ # Priority 2: From config
52
+ settings_path = CONFIG_DIR / "config.json"
53
+ if settings_path.is_file():
54
+ try:
55
+ settings: Dict[Any, Any] = JsonManager.load_json(settings_path)
56
+ lang = settings.get("lang")
57
+ if lang:
58
+ if lang in LANG_DICT:
59
+ return lang
60
+ elif lang != "auto":
61
+ return "en_US"
62
+ except JSONDecodeError:
63
+ pass
64
+
65
+ # Priority 3: Default locale
66
+ lang = get_default_lang()
67
+ return lang
68
+
69
+
70
+ LANG = RUNTIME_STATE.get("LANG", get_lang())
71
+ RUNTIME_STATE["LANG"] = LANG
72
+
73
+
74
+ def gettext_dummy(x: str) -> str:
75
+ return x
76
+
77
+
78
+ def get_translator() -> Callable[[str], str]:
79
+ if RUNTIME_STATE.get("TRANS") is not None:
80
+ return RUNTIME_STATE["TRANS"]
81
+
82
+ try:
83
+ trans: Callable[[str], str] = gettext.translation(
84
+ "base", ROOT_DIR / "locales", languages=[RUNTIME_STATE["LANG"]]
85
+ ).gettext
86
+ except FileNotFoundError:
87
+ if current_process().name == "MainProcess":
88
+ print(f"Warning: Cannot find locales/{LANG}/LC_MESSAGES/base.mo")
89
+ print(
90
+ "Please generate by running scripts/update-locales.sh in root of repo"
91
+ )
92
+ print("Fallback to using English...")
93
+ trans = gettext_dummy
94
+ RUNTIME_STATE["TRANS"] = trans
95
+ return trans
96
+
97
+
98
+ def I(x: str) -> str: # noqa: E743
99
+ return get_translator()(x)
100
+
101
+
102
+ SUPPORTED_LANG = {
103
+ I("Auto"): "auto",
104
+ "English": "en_US",
105
+ "繁體中文": "zh_TW",
106
+ "简体中文": "zh_CN",
107
+ "日本語": "ja_JP",
108
+ }
@@ -1,33 +1,40 @@
1
- #!/usr/bin/env python3
2
- import string
3
- from typing import Optional
4
- from urllib.parse import urlparse
5
-
6
-
7
- class UrlDetect:
8
- @staticmethod
9
- def detect(url: str) -> Optional[str]:
10
- domain = urlparse(url).netloc
11
-
12
- if domain == "signal.art":
13
- return "signal"
14
-
15
- if domain in ("telegram.me", "t.me"):
16
- return "telegram"
17
-
18
- if (
19
- domain in ("store.line.me", "line.me")
20
- or url.startswith("line://shop/detail/")
21
- or (len(url) == 24 and all(c in string.hexdigits for c in url))
22
- ):
23
- return "line"
24
-
25
- if domain in ("e.kakao.com", "emoticon.kakao.com") or url.startswith(
26
- "kakaotalk://store/emoticon/"
27
- ):
28
- return "kakao"
29
-
30
- if domain == "stickers.viber.com":
31
- return "viber"
32
-
33
- return None
1
+ #!/usr/bin/env python3
2
+ import string
3
+ from typing import Optional
4
+ from urllib.parse import urlparse
5
+
6
+
7
+ class UrlDetect:
8
+ @staticmethod
9
+ def detect(url: str) -> Optional[str]:
10
+ domain = urlparse(url).netloc
11
+
12
+ if domain == "signal.art" or url.startswith("sgnl://addstickers/"):
13
+ return "signal"
14
+
15
+ if domain in ("telegram.me", "t.me"):
16
+ return "telegram"
17
+
18
+ if (
19
+ domain in ("store.line.me", "line.me")
20
+ or url.startswith("line://shop/detail/")
21
+ or (len(url) == 24 and all(c in string.hexdigits for c in url))
22
+ ):
23
+ return "line"
24
+
25
+ if domain in ("e.kakao.com", "emoticon.kakao.com"):
26
+ return "kakao"
27
+
28
+ if domain == "www.band.us":
29
+ return "band"
30
+
31
+ if domain == "ogqmarket.naver.com":
32
+ return "ogq"
33
+
34
+ if domain == "stickers.viber.com":
35
+ return "viber"
36
+
37
+ if domain == "discord.com":
38
+ return "discord"
39
+
40
+ return None
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.12"
3
+ __version__ = "2.17.0.0"