sticker-convert 2.13.3.0__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 (93) hide show
  1. sticker_convert/__main__.py +24 -27
  2. sticker_convert/auth/__init__.py +0 -0
  3. sticker_convert/auth/auth_base.py +19 -0
  4. sticker_convert/{utils/auth/get_discord_auth.py → auth/auth_discord.py} +149 -118
  5. sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -330
  6. sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
  7. sticker_convert/{utils/auth/get_kakao_desktop_auth.py → auth/auth_kakao_desktop_memdump.py} +281 -263
  8. sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
  9. sticker_convert/{utils/auth/get_signal_auth.py → auth/auth_signal.py} +139 -135
  10. sticker_convert/auth/auth_telethon.py +161 -0
  11. sticker_convert/{utils/auth/get_viber_auth.py → auth/auth_viber.py} +250 -235
  12. sticker_convert/{utils/auth → auth}/telegram_api.py +736 -675
  13. sticker_convert/cli.py +623 -608
  14. sticker_convert/converter.py +1093 -1084
  15. sticker_convert/definitions.py +4 -0
  16. sticker_convert/downloaders/download_band.py +111 -110
  17. sticker_convert/downloaders/download_base.py +171 -166
  18. sticker_convert/downloaders/download_discord.py +92 -91
  19. sticker_convert/downloaders/download_kakao.py +417 -404
  20. sticker_convert/downloaders/download_line.py +484 -475
  21. sticker_convert/downloaders/download_ogq.py +80 -79
  22. sticker_convert/downloaders/download_signal.py +108 -105
  23. sticker_convert/downloaders/download_telegram.py +56 -55
  24. sticker_convert/downloaders/download_viber.py +121 -120
  25. sticker_convert/gui.py +788 -873
  26. sticker_convert/gui_components/frames/comp_frame.py +180 -166
  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 -233
  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 -757
  34. sticker_convert/gui_components/windows/base_window.py +7 -2
  35. sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -82
  36. sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -321
  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 -89
  39. sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -168
  40. sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
  41. sticker_convert/ios-message-stickers-template/README.md +10 -10
  42. sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
  43. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
  44. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
  45. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
  46. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
  47. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
  48. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
  49. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
  50. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
  51. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
  52. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
  53. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
  54. sticker_convert/job.py +166 -130
  55. sticker_convert/job_option.py +1 -0
  56. sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
  57. sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
  58. sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
  59. sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
  60. sticker_convert/py.typed +0 -0
  61. sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  62. sticker_convert/resources/help.ja_JP.json +88 -0
  63. sticker_convert/resources/help.json +10 -7
  64. sticker_convert/resources/help.zh_CN.json +88 -0
  65. sticker_convert/resources/help.zh_TW.json +88 -0
  66. sticker_convert/resources/input.ja_JP.json +74 -0
  67. sticker_convert/resources/input.json +121 -121
  68. sticker_convert/resources/input.zh_CN.json +74 -0
  69. sticker_convert/resources/input.zh_TW.json +74 -0
  70. sticker_convert/resources/output.ja_JP.json +38 -0
  71. sticker_convert/resources/output.zh_CN.json +38 -0
  72. sticker_convert/resources/output.zh_TW.json +38 -0
  73. sticker_convert/uploaders/compress_wastickers.py +186 -177
  74. sticker_convert/uploaders/upload_base.py +44 -35
  75. sticker_convert/uploaders/upload_signal.py +218 -203
  76. sticker_convert/uploaders/upload_telegram.py +353 -338
  77. sticker_convert/uploaders/upload_viber.py +178 -169
  78. sticker_convert/uploaders/xcode_imessage.py +295 -286
  79. sticker_convert/utils/callback.py +238 -6
  80. sticker_convert/utils/emoji.py +16 -4
  81. sticker_convert/utils/files/json_resources_loader.py +24 -19
  82. sticker_convert/utils/files/metadata_handler.py +3 -3
  83. sticker_convert/utils/translate.py +108 -0
  84. sticker_convert/utils/url_detect.py +40 -37
  85. sticker_convert/version.py +1 -1
  86. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +89 -74
  87. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/RECORD +91 -74
  88. sticker_convert/utils/auth/telethon_setup.py +0 -97
  89. sticker_convert/utils/singletons.py +0 -18
  90. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +0 -0
  91. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
  92. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/licenses/LICENSE +0 -0
  93. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
@@ -1,80 +1,98 @@
1
- #!/usr/bin/env python3
2
- import json
3
- import platform
4
- from http.cookiejar import CookieJar
5
- from typing import Any, Callable, Dict, List, Optional, Union
6
-
7
- import requests
8
- import rookiepy
9
-
10
-
11
- class GetLineAuth:
12
- def get_cred(self) -> Optional[str]:
13
- browsers: List[Callable[..., Any]] = [
14
- rookiepy.load, # Supposed to load from any browser, but may fail
15
- rookiepy.firefox,
16
- rookiepy.librewolf,
17
- rookiepy.chrome,
18
- rookiepy.chromium,
19
- rookiepy.brave,
20
- rookiepy.edge,
21
- rookiepy.opera,
22
- rookiepy.vivaldi,
23
- ]
24
-
25
- if platform.system() == "Windows":
26
- browsers.extend(
27
- [
28
- rookiepy.opera_gx,
29
- rookiepy.internet_explorer,
30
- ]
31
- )
32
- elif platform.system() == "Darwin":
33
- browsers.extend(
34
- [
35
- rookiepy.opera_gx,
36
- rookiepy.safari,
37
- ]
38
- )
39
-
40
- cookies_dict = None
41
- cookies_jar = None
42
- for browser in browsers:
43
- try:
44
- cookies_dict = browser(["store.line.me"])
45
- cookies_jar = rookiepy.to_cookiejar(cookies_dict)
46
-
47
- if GetLineAuth.validate_cookies(cookies_jar):
48
- break
49
-
50
- except Exception:
51
- continue
52
-
53
- if cookies_dict is None or cookies_jar is None:
54
- return None
55
-
56
- cookies_list = ["%s=%s" % (i["name"], i["value"]) for i in cookies_dict]
57
- cookies = ";".join(cookies_list)
58
-
59
- return cookies
60
-
61
- @staticmethod
62
- def validate_cookies(cookies: Union[CookieJar, Dict[str, str]]) -> bool:
63
- headers = {
64
- "x-requested-with": "XMLHttpRequest",
65
- }
66
-
67
- params = {"text": "test"}
68
-
69
- response = requests.get(
70
- "https://store.line.me/api/custom-sticker/validate/13782/en",
71
- params=params,
72
- cookies=cookies, # type: ignore
73
- headers=headers,
74
- )
75
-
76
- response_dict = json.loads(response.text)
77
-
78
- if response_dict["errorMessage"]:
79
- return False
80
- return True
1
+ #!/usr/bin/env python3
2
+ import json
3
+ import platform
4
+ from http.cookiejar import CookieJar
5
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
6
+
7
+ import requests
8
+ import rookiepy
9
+
10
+ from sticker_convert.auth.auth_base import AuthBase
11
+ from sticker_convert.utils.translate import I
12
+
13
+
14
+ class AuthLine(AuthBase):
15
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
16
+ self.OK_MSG = I("Got Line cookies successfully")
17
+ self.FAIL_MSG = I(
18
+ "Failed to get Line cookies. Have you logged in the web browser?"
19
+ )
20
+
21
+ super().__init__(*args, **kwargs)
22
+
23
+ def get_cred(self) -> Tuple[Optional[str], str]:
24
+ msg = I("Getting Line cookies")
25
+ self.cb.put(("msg_dynamic", (msg,), None))
26
+
27
+ browsers: List[Callable[..., Any]] = [
28
+ rookiepy.load, # Supposed to load from any browser, but may fail
29
+ rookiepy.firefox,
30
+ rookiepy.librewolf,
31
+ rookiepy.chrome,
32
+ rookiepy.chromium,
33
+ rookiepy.brave,
34
+ rookiepy.edge,
35
+ rookiepy.opera,
36
+ rookiepy.vivaldi,
37
+ ]
38
+
39
+ if platform.system() == "Windows":
40
+ browsers.extend(
41
+ [
42
+ rookiepy.opera_gx,
43
+ rookiepy.internet_explorer,
44
+ ]
45
+ )
46
+ elif platform.system() == "Darwin":
47
+ browsers.extend(
48
+ [
49
+ rookiepy.opera_gx,
50
+ rookiepy.safari,
51
+ ]
52
+ )
53
+
54
+ cookies_dict = None
55
+ cookies_jar = None
56
+ for browser in browsers:
57
+ try:
58
+ cookies_dict = browser(["store.line.me"])
59
+ cookies_jar = rookiepy.to_cookiejar(cookies_dict)
60
+
61
+ if AuthLine.validate_cookies(cookies_jar):
62
+ break
63
+
64
+ except Exception:
65
+ continue
66
+
67
+ self.cb.put(("msg_dynamic", (None,), None))
68
+ if cookies_dict is None or cookies_jar is None:
69
+ return (
70
+ None,
71
+ self.FAIL_MSG,
72
+ )
73
+
74
+ cookies_list = ["%s=%s" % (i["name"], i["value"]) for i in cookies_dict]
75
+ cookies = ";".join(cookies_list)
76
+
77
+ return cookies, self.OK_MSG
78
+
79
+ @staticmethod
80
+ def validate_cookies(cookies: Union[CookieJar, Dict[str, str]]) -> bool:
81
+ headers = {
82
+ "x-requested-with": "XMLHttpRequest",
83
+ }
84
+
85
+ params = {"text": "test"}
86
+
87
+ response = requests.get(
88
+ "https://store.line.me/api/custom-sticker/validate/13782/en",
89
+ params=params,
90
+ cookies=cookies, # type: ignore
91
+ headers=headers,
92
+ )
93
+
94
+ response_dict = json.loads(response.text)
95
+
96
+ if response_dict["errorMessage"]:
97
+ return False
98
+ return True
@@ -1,135 +1,139 @@
1
- #!/usr/bin/env python3
2
- import json
3
- import os
4
- import platform
5
- import shutil
6
- import time
7
- import webbrowser
8
- from typing import Callable, Optional, Tuple, cast
9
-
10
- from sticker_convert.definitions import CONFIG_DIR
11
- from sticker_convert.utils.chrome_remotedebug import CRD
12
- from sticker_convert.utils.process import killall
13
-
14
-
15
- class GetSignalAuth:
16
- def __init__(
17
- self,
18
- cb_msg: Callable[..., None] = print,
19
- cb_ask_str: Callable[..., str] = input,
20
- ) -> None:
21
- chromedriver_download_dir = CONFIG_DIR / "bin"
22
- os.makedirs(chromedriver_download_dir, exist_ok=True)
23
-
24
- self.chromedriver_download_dir = chromedriver_download_dir
25
-
26
- self.cb_ask_str = cb_ask_str
27
- self.cb_msg = cb_msg
28
-
29
- def download_signal_desktop(self) -> None:
30
- download_url = "https://signal.org/en/download/"
31
-
32
- webbrowser.open(download_url)
33
-
34
- self.cb_msg(download_url)
35
-
36
- prompt = "Signal Desktop not detected.\n"
37
- prompt += "Download and install Signal Desktop version\n"
38
- prompt += "After installation, quit Signal Desktop before continuing"
39
- if self.cb_ask_str != input:
40
- self.cb_ask_str(
41
- prompt, initialvalue=download_url, cli_show_initialvalue=False
42
- )
43
- else:
44
- self.cb_msg(prompt)
45
-
46
- def get_signal_bin_path(self) -> Optional[str]:
47
- signal_paths: Tuple[Optional[str], ...]
48
- if platform.system() == "Windows":
49
- signal_paths = (
50
- os.path.expandvars("%localappdata%/Programs/signal-desktop/Signal.exe"),
51
- os.path.expandvars(
52
- "%localappdata%/Programs/signal-desktop-beta/Signal Beta.exe"
53
- ),
54
- )
55
- elif platform.system() == "Darwin":
56
- signal_paths = (
57
- "/Applications/Signal.app/Contents/MacOS/Signal",
58
- "/Applications/Signal Beta.app/Contents/MacOS/Signal Beta",
59
- )
60
- else:
61
- signal_paths = (
62
- shutil.which("signal-desktop"),
63
- shutil.which("signal-desktop-beta"),
64
- shutil.which("org.signal.Signal"), # Flatpak
65
- os.path.expanduser(
66
- "~/.local/share/flatpak/exports/bin/org.signal.Signal"
67
- ),
68
- "/var/lib/flatpak/exports/bin/org.signal.Signal",
69
- )
70
-
71
- for signal_path in signal_paths:
72
- if signal_path is not None and os.path.isfile(signal_path):
73
- return signal_path
74
- return None
75
-
76
- def get_cred(self) -> Tuple[Optional[str], Optional[str]]:
77
- signal_bin_path = self.get_signal_bin_path()
78
- if signal_bin_path is None:
79
- self.download_signal_desktop()
80
- return None, None
81
-
82
- if platform.system() == "Windows":
83
- killall("signal")
84
- else:
85
- killall("signal-desktop")
86
-
87
- crd = CRD(signal_bin_path)
88
- crd.connect()
89
- # crd.runtime_enable()
90
- # crd.reload()
91
- # while True:
92
- # r = crd.ws.recv()
93
- # data = json.loads(r)
94
- # if data.get("method") == "Runtime.executionContextCreated":
95
- # print(data)
96
- # if (data.get("method") == "Runtime.executionContextCreated" and
97
- # data["params"]["context"]["name"] == "Electron Isolated Context"
98
- # ):
99
- # context_id = data["params"]["context"]["id"]
100
- # break
101
- # crd.runtime_disable()
102
- context_id = 2
103
-
104
- uuid, password = None, None
105
- while True:
106
- try:
107
- r = crd.exec_js(
108
- "window.reduxStore.getState().items.uuid_id", context_id
109
- )
110
- except RuntimeError:
111
- break
112
- if (
113
- json.loads(r).get("result", {}).get("result", {}).get("type", "")
114
- == "string"
115
- ):
116
- uuid = cast(str, json.loads(r)["result"]["result"]["value"])
117
- break
118
- time.sleep(1)
119
- while True:
120
- try:
121
- r = crd.exec_js(
122
- "window.reduxStore.getState().items.password", context_id
123
- )
124
- except RuntimeError:
125
- break
126
- if (
127
- json.loads(r).get("result", {}).get("result", {}).get("type", "")
128
- == "string"
129
- ):
130
- password = cast(str, json.loads(r)["result"]["result"]["value"])
131
- break
132
- time.sleep(1)
133
-
134
- crd.close()
135
- return uuid, password
1
+ #!/usr/bin/env python3
2
+ import json
3
+ import os
4
+ import platform
5
+ import shutil
6
+ import time
7
+ import webbrowser
8
+ from typing import Any, Optional, Tuple, cast
9
+
10
+ from sticker_convert.auth.auth_base import AuthBase
11
+ from sticker_convert.definitions import CONFIG_DIR
12
+ from sticker_convert.utils.chrome_remotedebug import CRD
13
+ from sticker_convert.utils.process import killall
14
+ from sticker_convert.utils.translate import I
15
+
16
+
17
+ class AuthSignal(AuthBase):
18
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
19
+ self.MSG_NO_SIGDESK = I(
20
+ "Signal Desktop not detected.\n"
21
+ "Download and install Signal Desktop version\n"
22
+ "After installation, quit Signal Desktop before continuing"
23
+ )
24
+
25
+ super().__init__(*args, **kwargs)
26
+ chromedriver_download_dir = CONFIG_DIR / "bin"
27
+ os.makedirs(chromedriver_download_dir, exist_ok=True)
28
+
29
+ self.chromedriver_download_dir = chromedriver_download_dir
30
+
31
+ def download_signal_desktop(self) -> None:
32
+ download_url = "https://signal.org/en/download/"
33
+
34
+ webbrowser.open(download_url)
35
+
36
+ self.cb.put(download_url)
37
+
38
+ self.cb.put(("ask_str", (self.MSG_NO_SIGDESK,), None))
39
+
40
+ def get_signal_bin_path(self) -> Optional[str]:
41
+ signal_paths: Tuple[Optional[str], ...]
42
+ if platform.system() == "Windows":
43
+ signal_paths = (
44
+ os.path.expandvars("%localappdata%/Programs/signal-desktop/Signal.exe"),
45
+ os.path.expandvars(
46
+ "%localappdata%/Programs/signal-desktop-beta/Signal Beta.exe"
47
+ ),
48
+ )
49
+ elif platform.system() == "Darwin":
50
+ signal_paths = (
51
+ "/Applications/Signal.app/Contents/MacOS/Signal",
52
+ "/Applications/Signal Beta.app/Contents/MacOS/Signal Beta",
53
+ )
54
+ else:
55
+ signal_paths = (
56
+ shutil.which("signal-desktop"),
57
+ shutil.which("signal-desktop-beta"),
58
+ shutil.which("org.signal.Signal"), # Flatpak
59
+ os.path.expanduser(
60
+ "~/.local/share/flatpak/exports/bin/org.signal.Signal"
61
+ ),
62
+ "/var/lib/flatpak/exports/bin/org.signal.Signal",
63
+ )
64
+
65
+ for signal_path in signal_paths:
66
+ if signal_path is not None and os.path.isfile(signal_path):
67
+ return signal_path
68
+ return None
69
+
70
+ def get_cred(self) -> Tuple[Optional[str], Optional[str], str]:
71
+ msg = I("Getting Signal credentials...")
72
+ self.cb.put(("msg_dynamic", (msg,), None))
73
+ signal_bin_path = self.get_signal_bin_path()
74
+ if signal_bin_path is None:
75
+ self.cb.put(("msg_dynamic", (None,), None))
76
+ self.download_signal_desktop()
77
+ return None, None, I("Failed to get uuid and password")
78
+
79
+ if platform.system() == "Windows":
80
+ killall("signal")
81
+ else:
82
+ killall("signal-desktop")
83
+
84
+ crd = CRD(signal_bin_path)
85
+ crd.connect()
86
+ # crd.runtime_enable()
87
+ # crd.reload()
88
+ # while True:
89
+ # r = crd.ws.recv()
90
+ # data = json.loads(r)
91
+ # if data.get("method") == "Runtime.executionContextCreated":
92
+ # print(data)
93
+ # if (data.get("method") == "Runtime.executionContextCreated" and
94
+ # data["params"]["context"]["name"] == "Electron Isolated Context"
95
+ # ):
96
+ # context_id = data["params"]["context"]["id"]
97
+ # break
98
+ # crd.runtime_disable()
99
+ context_id = 2
100
+
101
+ uuid, password = None, None
102
+ while True:
103
+ try:
104
+ r = crd.exec_js(
105
+ "window.reduxStore.getState().items.uuid_id", context_id
106
+ )
107
+ except RuntimeError:
108
+ break
109
+ if (
110
+ json.loads(r).get("result", {}).get("result", {}).get("type", "")
111
+ == "string"
112
+ ):
113
+ uuid = cast(str, json.loads(r)["result"]["result"]["value"])
114
+ break
115
+ time.sleep(1)
116
+ while True:
117
+ try:
118
+ r = crd.exec_js(
119
+ "window.reduxStore.getState().items.password", context_id
120
+ )
121
+ except RuntimeError:
122
+ break
123
+ if (
124
+ json.loads(r).get("result", {}).get("result", {}).get("type", "")
125
+ == "string"
126
+ ):
127
+ password = cast(str, json.loads(r)["result"]["result"]["value"])
128
+ break
129
+ time.sleep(1)
130
+
131
+ crd.close()
132
+ self.cb.put(("msg_dynamic", (None,), None))
133
+ return (
134
+ uuid,
135
+ password,
136
+ I("Got uuid and password successfully:\nuuid={}\npassword={}").format(
137
+ uuid, password
138
+ ),
139
+ )
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python3
2
+ from typing import Any, Optional, Tuple
3
+
4
+ import anyio
5
+ from telethon import TelegramClient # type: ignore
6
+ from telethon.errors import RPCError, SessionPasswordNeededError # type: ignore
7
+
8
+ from sticker_convert.auth.auth_base import AuthBase
9
+ from sticker_convert.definitions import CONFIG_DIR
10
+ from sticker_convert.utils.translate import I
11
+
12
+
13
+ class AuthTelethon(AuthBase):
14
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
15
+ self.GUIDE_MSG = I(
16
+ "1. Visit {telegram_api_url}\n"
17
+ "2. Login using your phone number\n"
18
+ '3. Go to "API development tools"\n'
19
+ "4. Fill form\n"
20
+ "- App title: sticker-convert\n"
21
+ "- Short name: sticker-convert\n"
22
+ "- URL: www.telegram.org\n"
23
+ "- Platform: Desktop\n"
24
+ "- Description: sticker-convert\n"
25
+ "5. Note down api_id and api_hash\n"
26
+ "Continue when done"
27
+ )
28
+ self.TELEGRAM_API_URL = "https://my.telegram.org"
29
+ self.OK_MSG = I("Telethon setup successful")
30
+ self.FAIL_MSG = I("Telethon setup failed")
31
+
32
+ super().__init__(*args, **kwargs)
33
+
34
+ async def signin_async(
35
+ self, try_sign_in: bool = True
36
+ ) -> Tuple[bool, TelegramClient, int, str, str]:
37
+ client = TelegramClient(
38
+ CONFIG_DIR / f"telethon-{self.opt_cred.telethon_api_id}.session",
39
+ self.opt_cred.telethon_api_id,
40
+ self.opt_cred.telethon_api_hash,
41
+ )
42
+
43
+ await client.connect()
44
+ authed = await client.is_user_authorized()
45
+ if authed is False and try_sign_in is True:
46
+ error_msg = ""
47
+ while True:
48
+ msg = error_msg + I("Enter phone number: ")
49
+ phone_number = self.cb.put(("ask_str", (msg,), None))
50
+ if phone_number == "":
51
+ return False, client, 0, "", self.FAIL_MSG
52
+ try:
53
+ await client.send_code_request(phone_number)
54
+ break
55
+ except RPCError as e:
56
+ error_msg = f"Error: {e}\n"
57
+
58
+ error_msg = ""
59
+ while True:
60
+ msg = error_msg + I("Enter code: ")
61
+ code = self.cb.put(("ask_str", (msg,), None))
62
+ if code == "":
63
+ return False, client, 0, "", self.FAIL_MSG
64
+ try:
65
+ await client.sign_in(phone_number, code)
66
+ break
67
+ except SessionPasswordNeededError:
68
+ password = self.cb.put(
69
+ (
70
+ "ask_str",
71
+ None,
72
+ {"question": "Enter password: ", "password": True},
73
+ )
74
+ )
75
+ try:
76
+ await client.sign_in(password=password)
77
+ break
78
+ except RPCError as e:
79
+ error_msg = f"Error: {e}\n"
80
+ except RPCError as e:
81
+ error_msg = f"Error: {e}\n"
82
+ authed = await client.is_user_authorized()
83
+
84
+ return (
85
+ authed,
86
+ client,
87
+ self.opt_cred.telethon_api_id,
88
+ self.opt_cred.telethon_api_hash,
89
+ self.OK_MSG if authed else self.FAIL_MSG,
90
+ )
91
+
92
+ def guide(self) -> None:
93
+ self.cb.put(
94
+ (
95
+ "msg_block",
96
+ (self.GUIDE_MSG.format(telegram_api_url=self.TELEGRAM_API_URL),),
97
+ None,
98
+ )
99
+ )
100
+
101
+ def get_api_info(self) -> bool:
102
+ api_id_ask = I("Enter api_id: ")
103
+ wrong_hint = ""
104
+
105
+ while True:
106
+ telethon_api_id = self.cb.put(
107
+ (
108
+ "ask_str",
109
+ None,
110
+ {
111
+ "question": wrong_hint + api_id_ask,
112
+ "initialvalue": str(self.opt_cred.telethon_api_id),
113
+ },
114
+ )
115
+ )
116
+ if telethon_api_id == "":
117
+ return False
118
+ elif telethon_api_id.isnumeric():
119
+ self.opt_cred.telethon_api_id = int(telethon_api_id)
120
+ break
121
+ else:
122
+ wrong_hint = I("Error: api_id should be numeric\n")
123
+
124
+ msg = I("Enter api_hash: ")
125
+ self.opt_cred.telethon_api_hash = self.cb.put(
126
+ (
127
+ "ask_str",
128
+ None,
129
+ {"question": msg, "initialvalue": self.opt_cred.telethon_api_hash},
130
+ )
131
+ )
132
+ if self.opt_cred.telethon_api_hash == "":
133
+ return False
134
+ return True
135
+
136
+ async def start_async(
137
+ self, check_auth_only: bool = False
138
+ ) -> Tuple[bool, Optional[TelegramClient], int, str, str]:
139
+ if self.opt_cred.telethon_api_id != 0 and self.opt_cred.telethon_api_hash != "":
140
+ success, client, api_id, api_hash, msg = await self.signin_async(
141
+ try_sign_in=False
142
+ )
143
+ if check_auth_only:
144
+ client.disconnect()
145
+ if success is True:
146
+ return success, client, api_id, api_hash, msg
147
+
148
+ self.guide()
149
+ cred_valid = self.get_api_info()
150
+ if cred_valid:
151
+ success, client, api_id, api_hash, msg = await self.signin_async()
152
+ if check_auth_only:
153
+ client.disconnect()
154
+ return success, client, api_id, api_hash, msg
155
+ else:
156
+ return False, None, 0, "", self.FAIL_MSG
157
+
158
+ def start(
159
+ self, check_auth_only: bool = False
160
+ ) -> Tuple[bool, Optional[TelegramClient], int, str, str]:
161
+ return anyio.run(self.start_async, check_auth_only)