sticker-convert 2.9.4__py3-none-any.whl → 2.10.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.
- sticker_convert/cli.py +26 -13
- sticker_convert/downloaders/download_base.py +20 -23
- sticker_convert/downloaders/download_discord.py +91 -0
- sticker_convert/downloaders/download_kakao.py +3 -4
- sticker_convert/downloaders/download_line.py +3 -4
- sticker_convert/downloaders/download_signal.py +3 -4
- sticker_convert/downloaders/download_telegram.py +3 -4
- sticker_convert/downloaders/download_viber.py +3 -4
- sticker_convert/gui.py +15 -3
- sticker_convert/gui_components/frames/cred_frame.py +22 -1
- sticker_convert/gui_components/windows/discord_get_auth_window.py +82 -0
- sticker_convert/gui_components/windows/signal_get_auth_window.py +39 -85
- sticker_convert/job.py +11 -1
- sticker_convert/job_option.py +2 -0
- sticker_convert/resources/compression.json +94 -0
- sticker_convert/resources/help.json +2 -1
- sticker_convert/resources/input.json +20 -0
- sticker_convert/uploaders/upload_signal.py +5 -4
- sticker_convert/uploaders/upload_telegram.py +11 -10
- sticker_convert/utils/auth/get_discord_auth.py +115 -0
- sticker_convert/utils/auth/get_signal_auth.py +115 -114
- sticker_convert/utils/auth/get_viber_auth.py +10 -214
- sticker_convert/utils/chrome_remotedebug.py +152 -0
- sticker_convert/utils/emoji.py +16 -0
- sticker_convert/utils/files/run_bin.py +1 -1
- sticker_convert/utils/media/codec_info.py +45 -60
- sticker_convert/utils/process.py +187 -0
- sticker_convert/utils/url_detect.py +3 -0
- sticker_convert/version.py +1 -1
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/METADATA +40 -42
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/RECORD +35 -29
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/LICENSE +0 -0
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/WHEEL +0 -0
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.9.4.dist-info → sticker_convert-2.10.0.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,9 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
from functools import partial
|
3
|
-
from
|
4
|
-
from subprocess import Popen
|
5
|
-
from tkinter import filedialog
|
3
|
+
from threading import Thread
|
6
4
|
from typing import Any
|
7
5
|
|
8
|
-
from ttkbootstrap import Button,
|
6
|
+
from ttkbootstrap import Button, Frame, Label # type: ignore
|
9
7
|
|
10
8
|
from sticker_convert.gui_components.gui_utils import GUIUtils
|
11
9
|
from sticker_convert.gui_components.windows.base_window import BaseWindow
|
@@ -13,8 +11,8 @@ from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
|
|
13
11
|
|
14
12
|
|
15
13
|
class SignalGetAuthWindow(BaseWindow):
|
16
|
-
def __init__(self, *args: Any, **kwargs: Any)
|
17
|
-
super().__init__(*args, **kwargs)
|
14
|
+
def __init__(self, *args: Any, **kwargs: Any):
|
15
|
+
super(SignalGetAuthWindow, self).__init__(*args, **kwargs)
|
18
16
|
|
19
17
|
self.title("Get Signal uuid and password")
|
20
18
|
|
@@ -22,79 +20,57 @@ class SignalGetAuthWindow(BaseWindow):
|
|
22
20
|
self.cb_ask_str_signal = partial(self.gui.cb_ask_str, parent=self)
|
23
21
|
|
24
22
|
self.frame_info = Frame(self.scrollable_frame)
|
25
|
-
self.
|
26
|
-
self.frame_config = Frame(self.scrollable_frame)
|
23
|
+
self.frame_start_btn = Frame(self.scrollable_frame)
|
27
24
|
|
28
25
|
self.frame_info.grid(column=0, row=0, sticky="news", padx=3, pady=3)
|
29
|
-
self.
|
30
|
-
self.frame_config.grid(column=0, row=2, sticky="news", padx=3, pady=3)
|
26
|
+
self.frame_start_btn.grid(column=0, row=1, sticky="news", padx=3, pady=3)
|
31
27
|
|
32
28
|
# Info frame
|
33
|
-
self.
|
29
|
+
self.explanation1_lbl = Label(
|
34
30
|
self.frame_info,
|
35
|
-
text="Please install Signal Desktop
|
31
|
+
text="Please install Signal Desktop",
|
36
32
|
justify="left",
|
37
33
|
anchor="w",
|
38
34
|
)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
self.frame_btns,
|
45
|
-
text="Launch Signal Desktop",
|
46
|
-
command=self.cb_launch_signal,
|
47
|
-
bootstyle="secondary", # type: ignore
|
48
|
-
)
|
49
|
-
|
50
|
-
self.get_cred_btn = Button(
|
51
|
-
self.frame_btns,
|
52
|
-
text="Get uuid and password",
|
53
|
-
command=self.cb_get_cred,
|
54
|
-
bootstyle="default", # type: ignore
|
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",
|
55
40
|
)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# Config frame
|
61
|
-
self.setdir_lbl = Label(
|
62
|
-
self.frame_config,
|
63
|
-
text=self.gui.help["cred"]["signal_data_dir"],
|
41
|
+
self.explanation3_lbl = Label(
|
42
|
+
self.frame_info,
|
43
|
+
text="uuid and password will be automatically fetched",
|
64
44
|
justify="left",
|
65
45
|
anchor="w",
|
66
46
|
)
|
67
47
|
|
68
|
-
self.
|
69
|
-
|
70
|
-
textvariable=self.gui.signal_data_dir_var,
|
71
|
-
width=32,
|
48
|
+
self.explanation1_lbl.grid(
|
49
|
+
column=0, row=0, columnspan=3, sticky="w", padx=3, pady=3
|
72
50
|
)
|
73
|
-
self.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
bootstyle="secondary", # type: ignore
|
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
|
79
56
|
)
|
80
57
|
|
81
|
-
|
82
|
-
self.
|
83
|
-
|
58
|
+
# Start button frame
|
59
|
+
self.login_btn = Button(
|
60
|
+
self.frame_start_btn, text="Get uuid and password", command=self.cb_login
|
61
|
+
)
|
84
62
|
|
85
|
-
|
63
|
+
self.login_btn.pack()
|
86
64
|
|
87
|
-
|
88
|
-
m = GetSignalAuth()
|
65
|
+
GUIUtils.finalize_window(self)
|
89
66
|
|
90
|
-
|
91
|
-
|
92
|
-
if self.gui.signal_data_dir_var.get():
|
93
|
-
signal_bin_path = "(User specified)"
|
94
|
-
signal_user_data_dir = self.gui.signal_data_dir_var.get()
|
67
|
+
def cb_login(self):
|
68
|
+
Thread(target=self.cb_login_thread, daemon=True).start()
|
95
69
|
|
96
|
-
|
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)
|
97
72
|
|
73
|
+
uuid, password = m.get_cred()
|
98
74
|
if uuid and password:
|
99
75
|
if not self.gui.creds.get("signal"):
|
100
76
|
self.gui.creds["signal"] = {}
|
@@ -103,33 +79,11 @@ class SignalGetAuthWindow(BaseWindow):
|
|
103
79
|
self.gui.signal_uuid_var.set(uuid)
|
104
80
|
self.gui.signal_password_var.set(password)
|
105
81
|
|
82
|
+
self.cb_msg_block_signal(
|
83
|
+
f"Got uuid and password successfully:\nuuid={uuid}\npassword={password}"
|
84
|
+
)
|
106
85
|
self.gui.save_creds()
|
107
86
|
self.gui.highlight_fields()
|
87
|
+
return
|
108
88
|
|
109
|
-
self.cb_msg_block_signal(
|
110
|
-
|
111
|
-
def cb_launch_signal(self) -> None:
|
112
|
-
m = GetSignalAuth()
|
113
|
-
signal_bin_path, signal_user_data_dir = m.get_signal_desktop()
|
114
|
-
|
115
|
-
if self.gui.signal_data_dir_var.get():
|
116
|
-
signal_user_data_dir = self.gui.signal_data_dir_var.get()
|
117
|
-
|
118
|
-
if signal_bin_path:
|
119
|
-
Popen(
|
120
|
-
[
|
121
|
-
signal_bin_path,
|
122
|
-
"--no-sandbox",
|
123
|
-
f"--user-data-dir={signal_user_data_dir}",
|
124
|
-
]
|
125
|
-
)
|
126
|
-
else:
|
127
|
-
self.cb_msg_block_signal("Error: Signal Desktop not installed.")
|
128
|
-
|
129
|
-
def cb_setdir(self) -> None:
|
130
|
-
orig_input_dir = self.gui.signal_data_dir_var.get()
|
131
|
-
if not Path(orig_input_dir).is_dir():
|
132
|
-
orig_input_dir = ""
|
133
|
-
input_dir = filedialog.askdirectory(initialdir=orig_input_dir)
|
134
|
-
if input_dir:
|
135
|
-
self.gui.signal_data_dir_var.set(input_dir)
|
89
|
+
self.cb_msg_block_signal("Failed to get uuid and password")
|
sticker_convert/job.py
CHANGED
@@ -12,6 +12,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
12
12
|
from urllib.parse import urlparse
|
13
13
|
|
14
14
|
from sticker_convert.converter import StickerConvert
|
15
|
+
from sticker_convert.downloaders.download_discord import DownloadDiscord
|
15
16
|
from sticker_convert.downloaders.download_kakao import DownloadKakao
|
16
17
|
from sticker_convert.downloaders.download_line import DownloadLine
|
17
18
|
from sticker_convert.downloaders.download_signal import DownloadSignal
|
@@ -295,6 +296,12 @@ class Job:
|
|
295
296
|
)
|
296
297
|
error_msg += save_to_local_tip
|
297
298
|
|
299
|
+
if (
|
300
|
+
self.opt_input.option.startswith("discord")
|
301
|
+
and not self.opt_cred.discord_token
|
302
|
+
):
|
303
|
+
error_msg += "[X] Downloading from Discord requires token.\n"
|
304
|
+
|
298
305
|
if self.opt_output.option == "telegram" and not self.opt_cred.telegram_userid:
|
299
306
|
error_msg += "[X] Uploading to telegram requires user_id \n"
|
300
307
|
error_msg += " (From real account, not bot account).\n"
|
@@ -536,6 +543,9 @@ class Job:
|
|
536
543
|
if self.opt_input.option == "viber":
|
537
544
|
downloaders.append(DownloadViber.start)
|
538
545
|
|
546
|
+
if self.opt_input.option.startswith("discord"):
|
547
|
+
downloaders.append(DownloadDiscord.start)
|
548
|
+
|
539
549
|
if len(downloaders) > 0:
|
540
550
|
self.executor.cb("Downloading...")
|
541
551
|
else:
|
@@ -547,7 +557,7 @@ class Job:
|
|
547
557
|
for downloader in downloaders:
|
548
558
|
self.executor.add_work(
|
549
559
|
work_func=downloader,
|
550
|
-
work_args=(self.opt_input
|
560
|
+
work_args=(self.opt_input, self.opt_cred),
|
551
561
|
)
|
552
562
|
|
553
563
|
self.executor.join_workers()
|
sticker_convert/job_option.py
CHANGED
@@ -223,6 +223,7 @@ class CredOption(BaseOption):
|
|
223
223
|
kakao_phone_number: str = ""
|
224
224
|
line_cookies: str = ""
|
225
225
|
viber_auth: str = ""
|
226
|
+
discord_token: str = ""
|
226
227
|
|
227
228
|
def to_dict(self) -> Dict[Any, Any]:
|
228
229
|
return {
|
@@ -237,4 +238,5 @@ class CredOption(BaseOption):
|
|
237
238
|
},
|
238
239
|
"line": {"cookies": self.line_cookies},
|
239
240
|
"viber": {"auth": self.viber_auth},
|
241
|
+
"discord": {"token": self.discord_token},
|
240
242
|
}
|
@@ -375,6 +375,100 @@
|
|
375
375
|
"quantize_method": "imagequant",
|
376
376
|
"default_emoji": "😀"
|
377
377
|
},
|
378
|
+
"discord": {
|
379
|
+
"size_max": {
|
380
|
+
"img": 512000,
|
381
|
+
"vid": 512000
|
382
|
+
},
|
383
|
+
"format": {
|
384
|
+
"img": ".png",
|
385
|
+
"vid": ".png"
|
386
|
+
},
|
387
|
+
"fps": {
|
388
|
+
"min": 1,
|
389
|
+
"max": 60,
|
390
|
+
"power": -0.3
|
391
|
+
},
|
392
|
+
"res": {
|
393
|
+
"w": {
|
394
|
+
"min": 320,
|
395
|
+
"max": 320
|
396
|
+
},
|
397
|
+
"h": {
|
398
|
+
"min": 320,
|
399
|
+
"max": 320
|
400
|
+
},
|
401
|
+
"power": 1
|
402
|
+
},
|
403
|
+
"quality": {
|
404
|
+
"min": 10,
|
405
|
+
"max": 95,
|
406
|
+
"power": 5
|
407
|
+
},
|
408
|
+
"color": {
|
409
|
+
"min": 32,
|
410
|
+
"max": 257,
|
411
|
+
"power": 3
|
412
|
+
},
|
413
|
+
"duration": {
|
414
|
+
"min": 0,
|
415
|
+
"max": 5000
|
416
|
+
},
|
417
|
+
"padding_percent": 0,
|
418
|
+
"bg_color": "",
|
419
|
+
"steps": 16,
|
420
|
+
"fake_vid": false,
|
421
|
+
"scale_filter": "bicubic",
|
422
|
+
"quantize_method": "imagequant",
|
423
|
+
"default_emoji": "😀"
|
424
|
+
},
|
425
|
+
"discord_emoji": {
|
426
|
+
"size_max": {
|
427
|
+
"img": 256000,
|
428
|
+
"vid": 256000
|
429
|
+
},
|
430
|
+
"format": {
|
431
|
+
"img": ".png",
|
432
|
+
"vid": ".gif"
|
433
|
+
},
|
434
|
+
"fps": {
|
435
|
+
"min": 1,
|
436
|
+
"max": 60,
|
437
|
+
"power": -0.3
|
438
|
+
},
|
439
|
+
"res": {
|
440
|
+
"w": {
|
441
|
+
"min": 32,
|
442
|
+
"max": 128
|
443
|
+
},
|
444
|
+
"h": {
|
445
|
+
"min": 32,
|
446
|
+
"max": 128
|
447
|
+
},
|
448
|
+
"power": 1
|
449
|
+
},
|
450
|
+
"quality": {
|
451
|
+
"min": 10,
|
452
|
+
"max": 95,
|
453
|
+
"power": 5
|
454
|
+
},
|
455
|
+
"color": {
|
456
|
+
"min": 32,
|
457
|
+
"max": 257,
|
458
|
+
"power": 3
|
459
|
+
},
|
460
|
+
"duration": {
|
461
|
+
"min": 0,
|
462
|
+
"max": 5000
|
463
|
+
},
|
464
|
+
"padding_percent": 0,
|
465
|
+
"bg_color": "",
|
466
|
+
"steps": 16,
|
467
|
+
"fake_vid": false,
|
468
|
+
"scale_filter": "bicubic",
|
469
|
+
"quantize_method": "imagequant",
|
470
|
+
"default_emoji": "😀"
|
471
|
+
},
|
378
472
|
"imessage_small": {
|
379
473
|
"size_max": {
|
380
474
|
"img": 500000,
|
@@ -58,7 +58,6 @@
|
|
58
58
|
"signal_uuid": "Set Signal uuid. Required for uploading Signal stickers.",
|
59
59
|
"signal_password": "Set Signal password. Required for uploading Signal stickers.",
|
60
60
|
"signal_get_auth": "Generate Signal uuid and password.",
|
61
|
-
"signal_data_dir": "Optionally specify Signal data directory\nfor getting uuid and password. Useful for portable Signal.",
|
62
61
|
"telegram_token": "Set Telegram token. Required for uploading and downloading Telegram stickers.",
|
63
62
|
"telegram_userid": "Set telegram user_id (From real account, not bot account). Required for uploading Telegram stickers.",
|
64
63
|
"kakao_auth_token": "Set Kakao auth_token. Required for downloading animated stickers from https://e.kakao.com/t/xxxxx",
|
@@ -72,6 +71,8 @@
|
|
72
71
|
"viber_auth": "Set Viber authentication data.\nRequired for uploading Viber stickers.",
|
73
72
|
"viber_get_auth": "Generate Viber authentication data.",
|
74
73
|
"viber_bin_path": "Specify location of Viber Desktop application.\nUseful for portable installation.",
|
74
|
+
"discord_get_auth": "Get Discord token.",
|
75
|
+
"discord_token": "Set Discord token. Required for downloading Discord stickers and emojis.",
|
75
76
|
"save_cred": "Save Signal and Telegram credentials."
|
76
77
|
}
|
77
78
|
}
|
@@ -59,6 +59,26 @@
|
|
59
59
|
"author": false
|
60
60
|
}
|
61
61
|
},
|
62
|
+
"discord": {
|
63
|
+
"full_name": "Download from Discord",
|
64
|
+
"help": "Download discord stickers from a channel URL / ID as input",
|
65
|
+
"example": "Example: https://discord.com/channels/169256939211980800/@home\nOR 169256939211980800",
|
66
|
+
"address_lbls": "URL address / ID",
|
67
|
+
"metadata_provides": {
|
68
|
+
"title": true,
|
69
|
+
"author": true
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"discord_emoji": {
|
73
|
+
"full_name": "Download from Discord (emoji)",
|
74
|
+
"help": "Download discord emojis from a channel URL / ID as input",
|
75
|
+
"example": "Example: https://discord.com/channels/169256939211980800/@home\nOR 169256939211980800",
|
76
|
+
"address_lbls": "URL address / ID",
|
77
|
+
"metadata_provides": {
|
78
|
+
"title": true,
|
79
|
+
"author": true
|
80
|
+
}
|
81
|
+
},
|
62
82
|
"local": {
|
63
83
|
"full_name": "From local directory",
|
64
84
|
"help": "Load files from local directory on computer",
|
@@ -12,6 +12,7 @@ from sticker_convert.converter import StickerConvert
|
|
12
12
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
13
13
|
from sticker_convert.uploaders.upload_base import UploadBase
|
14
14
|
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
15
|
+
from sticker_convert.utils.emoji import extract_emojis
|
15
16
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
16
17
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
17
18
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
@@ -55,12 +56,12 @@ class UploadSignal(UploadBase):
|
|
55
56
|
sticker = Sticker()
|
56
57
|
sticker.id = pack.nb_stickers
|
57
58
|
|
58
|
-
emoji = emoji_dict.get(Path(src).stem,
|
59
|
-
if
|
59
|
+
emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
|
60
|
+
if emoji == "":
|
60
61
|
self.cb.put(
|
61
|
-
f"Warning: Cannot find emoji for file {Path(src).name},
|
62
|
+
f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
|
62
63
|
)
|
63
|
-
|
64
|
+
emoji = self.opt_comp.default_emoji
|
64
65
|
sticker.emoji = emoji[:1]
|
65
66
|
|
66
67
|
if Path(src).suffix == ".webp":
|
@@ -13,6 +13,7 @@ from sticker_convert.converter import StickerConvert
|
|
13
13
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
14
14
|
from sticker_convert.uploaders.upload_base import UploadBase
|
15
15
|
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
16
|
+
from sticker_convert.utils.emoji import extract_emojis
|
16
17
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
17
18
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
18
19
|
|
@@ -158,18 +159,18 @@ class UploadTelegram(UploadBase):
|
|
158
159
|
for count, src in enumerate(stickers):
|
159
160
|
self.cb.put(f"Verifying {src} for uploading to telegram")
|
160
161
|
|
161
|
-
emoji = emoji_dict.get(Path(src).stem,
|
162
|
-
if emoji:
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
162
|
+
emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
|
163
|
+
if emoji == "":
|
164
|
+
self.cb.put(
|
165
|
+
f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
|
166
|
+
)
|
167
|
+
emoji_list = [self.opt_comp.default_emoji]
|
168
|
+
|
169
|
+
if len(emoji) > 20:
|
169
170
|
self.cb.put(
|
170
|
-
f"Warning:
|
171
|
+
f"Warning: {len(emoji)} emoji for file {Path(src).name}, exceeding limit of 20, keep first 20 only..."
|
171
172
|
)
|
172
|
-
|
173
|
+
emoji_list = [*emoji][:20]
|
173
174
|
|
174
175
|
ext = Path(src).suffix
|
175
176
|
if ext == ".tgs":
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import platform
|
5
|
+
import shutil
|
6
|
+
import time
|
7
|
+
from typing import Callable, Optional, Tuple
|
8
|
+
from urllib.parse import urlparse
|
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 GetDiscordAuth:
|
16
|
+
def __init__(self, cb_msg: Callable[..., None] = print):
|
17
|
+
chromedriver_download_dir = CONFIG_DIR / "bin"
|
18
|
+
os.makedirs(chromedriver_download_dir, exist_ok=True)
|
19
|
+
|
20
|
+
self.chromedriver_download_dir = chromedriver_download_dir
|
21
|
+
|
22
|
+
self.cb_msg = cb_msg
|
23
|
+
|
24
|
+
def get_discord_bin_path(self) -> Optional[str]:
|
25
|
+
discord_bin: Optional[str]
|
26
|
+
if platform.system() == "Windows":
|
27
|
+
discord_win_dirs: Tuple[Tuple[str, str], ...]
|
28
|
+
discord_win_dirs = (
|
29
|
+
(
|
30
|
+
os.path.expandvars("%localappdata%/Discord"),
|
31
|
+
"Discord.exe",
|
32
|
+
),
|
33
|
+
(
|
34
|
+
os.path.expandvars("%localappdata%/DiscordCanary"),
|
35
|
+
"DiscordCanary.exe",
|
36
|
+
),
|
37
|
+
(
|
38
|
+
os.path.expandvars("%localappdata%/DiscordPTB"),
|
39
|
+
"DiscordPTB.exe",
|
40
|
+
),
|
41
|
+
)
|
42
|
+
for discord_dir, discord_bin in discord_win_dirs:
|
43
|
+
app_dir: Optional[str] = None
|
44
|
+
chrome_path: Optional[str] = None
|
45
|
+
for i in [j for j in os.listdir(discord_dir) if j.startswith("app-")]:
|
46
|
+
app_dir = os.path.join(discord_dir, i)
|
47
|
+
chrome_path = os.path.join(app_dir, discord_bin)
|
48
|
+
if os.path.isfile(chrome_path):
|
49
|
+
return chrome_path
|
50
|
+
else:
|
51
|
+
discord_dirs: Tuple[Optional[str], ...]
|
52
|
+
if platform.system() == "Darwin":
|
53
|
+
discord_dirs = (
|
54
|
+
"/Applications/Discord.app/Contents/MacOS/Discord",
|
55
|
+
"/Applications/Discord Canary.app/Contents/MacOS/Discord Canary",
|
56
|
+
"/Applications/Discord PTB.app/Contents/MacOS/Discord PTB",
|
57
|
+
)
|
58
|
+
else:
|
59
|
+
discord_dirs = (
|
60
|
+
shutil.which("discord"),
|
61
|
+
shutil.which("discord-canary"),
|
62
|
+
shutil.which("discord-ptb"),
|
63
|
+
)
|
64
|
+
for discord_bin in discord_dirs:
|
65
|
+
if discord_bin is not None and os.path.isfile(discord_bin):
|
66
|
+
return discord_bin
|
67
|
+
return None
|
68
|
+
|
69
|
+
def get_cred(self) -> Tuple[Optional[str], str]:
|
70
|
+
using_discord_app = False
|
71
|
+
chrome_path = self.get_discord_bin_path()
|
72
|
+
if chrome_path is not None:
|
73
|
+
using_discord_app = True
|
74
|
+
else:
|
75
|
+
chrome_path = CRD.get_chrome_path()
|
76
|
+
if chrome_path is None:
|
77
|
+
return None, "Please install Discord Desktop or Chrome and try again"
|
78
|
+
|
79
|
+
token = None
|
80
|
+
if using_discord_app:
|
81
|
+
killall("discord")
|
82
|
+
|
83
|
+
crd = CRD(chrome_path)
|
84
|
+
while True:
|
85
|
+
crd.connect()
|
86
|
+
if using_discord_app is False:
|
87
|
+
crd.navigate("https://discord.com/channels/@me")
|
88
|
+
break
|
89
|
+
else:
|
90
|
+
curr_url = crd.get_curr_url()
|
91
|
+
netloc = urlparse(curr_url).netloc
|
92
|
+
if netloc in ("discordapp.com", "discord.com"):
|
93
|
+
break
|
94
|
+
time.sleep(1)
|
95
|
+
|
96
|
+
while True:
|
97
|
+
try:
|
98
|
+
r = crd.exec_js(
|
99
|
+
"(webpackChunkdiscord_app.push([[''],{},e=>{m=[];for(let c in e.c)m.push(e.c[c])}]),m).find(m=>m?.exports?.default?.getToken!==void 0).exports.default.getToken();"
|
100
|
+
)
|
101
|
+
except RuntimeError:
|
102
|
+
break
|
103
|
+
if (
|
104
|
+
json.loads(r).get("result", {}).get("result", {}).get("type", "")
|
105
|
+
== "string"
|
106
|
+
):
|
107
|
+
token = json.loads(r)["result"]["result"]["value"]
|
108
|
+
break
|
109
|
+
time.sleep(1)
|
110
|
+
crd.close()
|
111
|
+
|
112
|
+
if token is None:
|
113
|
+
return None, "Failed to get token"
|
114
|
+
|
115
|
+
return token, f"Got token successfully:\ntoken={token}"
|