Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
anasty17
GitHub Repository: anasty17/mirror-leech-telegram-bot
Path: blob/master/bot/core/config_manager.py
1630 views
1
from importlib import import_module
2
from ast import literal_eval
3
from os import getenv
4
5
from bot import LOGGER
6
7
8
class Config:
9
AS_DOCUMENT = False
10
AUTHORIZED_CHATS = ""
11
BASE_URL = ""
12
BASE_URL_PORT = 80
13
BOT_TOKEN = ""
14
CMD_SUFFIX = ""
15
CLONE_DUMP_CHATS = ""
16
DATABASE_URL = ""
17
DATABASE_NAME = "mltb"
18
DEFAULT_UPLOAD = "rc"
19
EQUAL_SPLITS = False
20
EXCLUDED_EXTENSIONS = ""
21
INCLUDED_EXTENSIONS = ""
22
FFMPEG_CMDS = {}
23
FILELION_API = ""
24
FILES_LINKS = False
25
GDRIVE_ID = ""
26
INCOMPLETE_TASK_NOTIFIER = False
27
INDEX_URL = ""
28
IS_TEAM_DRIVE = False
29
JD_EMAIL = ""
30
JD_PASS = ""
31
LEECH_DUMP_CHAT = ""
32
LEECH_FILENAME_PREFIX = ""
33
LEECH_SPLIT_SIZE = 2097152000
34
MEDIA_GROUP = False
35
HYBRID_LEECH = False
36
HYDRA_IP = ""
37
HYDRA_API_KEY = ""
38
NAME_SUBSTITUTE = r""
39
OWNER_ID = 0
40
QUEUE_ALL = 0
41
QUEUE_DOWNLOAD = 0
42
QUEUE_UPLOAD = 0
43
RCLONE_FLAGS = ""
44
RCLONE_PATH = ""
45
RCLONE_SERVE_URL = ""
46
RCLONE_SERVE_USER = ""
47
RCLONE_SERVE_PASS = ""
48
RCLONE_SERVE_PORT = 8080
49
RSS_CHAT = ""
50
RSS_DELAY = 600
51
RSS_SIZE_LIMIT = 0
52
SEARCH_API_LINK = ""
53
SEARCH_LIMIT = 0
54
SEARCH_PLUGINS = []
55
STATUS_LIMIT = 4
56
STATUS_UPDATE_INTERVAL = 15
57
STOP_DUPLICATE = False
58
STREAMWISH_API = ""
59
SUDO_USERS = ""
60
TELEGRAM_API = 0
61
TELEGRAM_HASH = ""
62
TG_PROXY = {}
63
THUMBNAIL_LAYOUT = ""
64
TORRENT_TIMEOUT = 0
65
UPLOAD_PATHS = {}
66
UPSTREAM_REPO = ""
67
UPSTREAM_BRANCH = "master"
68
USENET_SERVERS = []
69
USER_SESSION_STRING = ""
70
USER_TRANSMISSION = False
71
USE_SERVICE_ACCOUNTS = False
72
WEB_PINCODE = False
73
YT_DLP_OPTIONS = {}
74
75
@classmethod
76
def _convert(cls, key: str, value):
77
if not hasattr(cls, key):
78
raise KeyError(f"{key} is not a valid configuration key.")
79
80
expected_type = type(getattr(cls, key))
81
82
if value is None:
83
return None
84
85
if isinstance(value, expected_type):
86
return value
87
88
if expected_type is bool:
89
return str(value).strip().lower() in {"true", "1", "yes"}
90
91
if expected_type in [list, dict]:
92
if not isinstance(value, str):
93
raise TypeError(
94
f"{key} should be {expected_type.__name__}, got {type(value).__name__}"
95
)
96
97
if not value:
98
return expected_type()
99
100
try:
101
evaluated = literal_eval(value)
102
if not isinstance(evaluated, expected_type):
103
raise TypeError(
104
f"Expected {expected_type.__name__}, got {type(evaluated).__name__}"
105
)
106
return evaluated
107
except (ValueError, SyntaxError, TypeError) as e:
108
raise TypeError(
109
f"{key} should be {expected_type.__name__}, got invalid string: {value}"
110
) from e
111
112
try:
113
return expected_type(value)
114
except (ValueError, TypeError) as exc:
115
raise TypeError(
116
f"Invalid type for {key}: expected {expected_type}, got {type(value)}"
117
) from exc
118
119
@classmethod
120
def get(cls, key: str):
121
return getattr(cls, key, None)
122
123
@classmethod
124
def set(cls, key: str, value) -> None:
125
if not hasattr(cls, key):
126
raise KeyError(f"{key} is not a valid configuration key.")
127
128
converted_value = cls._convert(key, value)
129
setattr(cls, key, converted_value)
130
131
@classmethod
132
def get_all(cls):
133
return {
134
key: getattr(cls, key)
135
for key in cls.__dict__.keys()
136
if not key.startswith("__") and not callable(getattr(cls, key))
137
}
138
139
@classmethod
140
def _is_valid_config_attr(cls, attr: str) -> bool:
141
if attr.startswith("__") or callable(getattr(cls, attr, None)):
142
return False
143
return hasattr(cls, attr)
144
145
@classmethod
146
def _process_config_value(cls, attr: str, value):
147
if not value:
148
return None
149
150
converted_value = cls._convert(attr, value)
151
152
if isinstance(converted_value, str):
153
converted_value = converted_value.strip()
154
155
if attr == "DEFAULT_UPLOAD" and converted_value != "gd":
156
return "rc"
157
158
if attr in {
159
"BASE_URL",
160
"RCLONE_SERVE_URL",
161
"SEARCH_API_LINK",
162
}:
163
return converted_value.strip("/") if converted_value else ""
164
165
if attr == "USENET_SERVERS" and (
166
not converted_value or not converted_value[0].get("host")
167
):
168
return None
169
170
return converted_value
171
172
@classmethod
173
def _load_from_module(cls) -> bool:
174
try:
175
settings = import_module("config")
176
except ModuleNotFoundError:
177
return False
178
179
for attr in dir(settings):
180
if not cls._is_valid_config_attr(attr):
181
continue
182
183
raw_value = getattr(settings, attr)
184
processed_value = cls._process_config_value(attr, raw_value)
185
186
if processed_value is not None:
187
setattr(cls, attr, processed_value)
188
189
return True
190
191
@classmethod
192
def _load_from_env(cls) -> None:
193
for attr in dir(cls):
194
if not cls._is_valid_config_attr(attr):
195
continue
196
197
env_value = getenv(attr)
198
if env_value is None:
199
continue
200
201
processed_value = cls._process_config_value(attr, env_value)
202
if processed_value is not None:
203
setattr(cls, attr, processed_value)
204
205
@classmethod
206
def _validate_required_config(cls) -> None:
207
required_keys = ["BOT_TOKEN", "OWNER_ID", "TELEGRAM_API", "TELEGRAM_HASH"]
208
209
for key in required_keys:
210
value = getattr(cls, key)
211
if isinstance(value, str):
212
value = value.strip()
213
if not value:
214
raise ValueError(f"{key} variable is missing!")
215
216
@classmethod
217
def load(cls) -> None:
218
if not cls._load_from_module():
219
LOGGER.info(
220
"Config module not found, loading from environment variables..."
221
)
222
cls._load_from_env()
223
224
cls._validate_required_config()
225
226
@classmethod
227
def load_dict(cls, config_dict) -> None:
228
for key, value in config_dict.items():
229
if not hasattr(cls, key):
230
continue
231
232
processed_value = cls._process_config_value(key, value)
233
234
if key == "USENET_SERVERS" and processed_value is None:
235
processed_value = []
236
237
if processed_value is not None:
238
setattr(cls, key, processed_value)
239
240
cls._validate_required_config()
241
242