-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon_functions.py
More file actions
executable file
·161 lines (129 loc) · 4.66 KB
/
common_functions.py
File metadata and controls
executable file
·161 lines (129 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import json
import secrets
from asyncio import sleep
from json import JSONDecodeError
from pathlib import Path
from typing import Any, Callable, Literal, TypedDict
import fs.path
import rtoml
from fs import open_fs
from fs.appfs import UserConfigFS
from rich.console import group
from rich.panel import Panel
from typing_extensions import TypeVar
from constants import APP_NAME, CONFIG_FILE_PATH, DEFAULT_CONFIG
class Config(TypedDict):
CHROME_BINARY_PATH: str
POSTS_FOLDER_PATH: str
HEADLESS: bool
class StyledPanel(Panel):
"""
A styled panel with a message and an optional title.
:param msg: Message inside the panel.
:param title: Optional panel title.
:param msg_type: info, error, warning or success.
If error, the application will exit.
"""
def __init__(
self,
msg: Any,
title=None,
msg_type: Literal["info", "error", "warning", "success"] = "info",
):
super().__init__(msg, title=title, expand=False)
self.msg_type = msg_type
self.title = title
self.msg_type = msg_type
if msg_type == "error":
self.style = "red"
elif msg_type == "warning":
self.style = "yellow"
elif msg_type == "success":
self.style = "green"
T = TypeVar("T")
# def print_panels_group[T]( -> doesn't work in executable file
def panels_group(
iterable: list[T],
extract_msg: Callable[[T], str],
title: str = None,
children_msg_type: Literal["info", "error", "warning", "success"] = "info",
) -> Panel:
"""
Print a group of panels.
:param iterable: The list of items to iterate.
:param extract_msg: A callable that extracts the message from the item.
:param title: The title of the main panel.
:param children_msg_type: The type of the children panels. Default is info.
"""
@group()
def get_panels():
for i in iterable:
msg = extract_msg(i)
yield StyledPanel(str(msg), msg_type=children_msg_type)
return Panel(get_panels(), title=title)
async def wait_random_seconds(start: int, end: int = None) -> None:
"""
Wait a random time between start and end seconds.
:param start: The start time in seconds
:param end: The end time in seconds, if None, the end time will be equal to start time
and the function will wait exactly the start time.
"""
if end is None:
end = start
await sleep(secrets.randbelow(end - start + 1) + start)
def validate_conf_file() -> None:
"""
Create if the configuration file does not exists and write with the default
configuration. If the configuration file exists but it does not have valid keys,
it will be overwritten with the default configuration.
"""
with UserConfigFS(APP_NAME) as user_config_fs:
# Create if it does not exist
if not (user_config_fs.exists(CONFIG_FILE_PATH)):
write_conf_file(DEFAULT_CONFIG)
else:
# Check if the configuration file has valid keys
try:
with user_config_fs.open(CONFIG_FILE_PATH) as config_file:
config = json.load(config_file)
except JSONDecodeError:
write_conf_file(DEFAULT_CONFIG)
else:
keys = DEFAULT_CONFIG.keys()
if not all(key in config for key in keys):
write_conf_file(DEFAULT_CONFIG)
def load_configuration() -> Config:
"""
Load a configuration file.
:return: The configuration dictionary.
"""
validate_conf_file()
with UserConfigFS(APP_NAME) as user_config_fs:
with user_config_fs.open(CONFIG_FILE_PATH) as config_file:
config = json.load(config_file)
return config
def write_conf_file(config: Config) -> None:
"""
Write a configuration file.
:param config: The configuration dictionary.
"""
with UserConfigFS(APP_NAME) as user_config_fs:
with user_config_fs.open(CONFIG_FILE_PATH, "w") as config_file:
json.dump(config, config_file, indent=4) # type: ignore
def get_locales_fb_strings(lang: str) -> dict[str, dict[str, str] | str]:
"""
Get the Facebook strings for a specific language.
:param lang: The language code.
:return: The Facebook strings depending on the language.
"""
with open_fs(
fs.path.join(get_executable_dir_location(), "locales_fb")
) as locales_fb:
with locales_fb.open(f"{lang}.toml") as locale_file:
return rtoml.load(locale_file)
def get_executable_dir_location() -> str:
"""
Get the executable location.
:return: The executable location.
"""
return str(Path(__file__).resolve().parent)