sticker-convert 2.9.4__py3-none-any.whl → 2.10.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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}"
|