Skip to content

Commit acd68c9

Browse files
committed
im too lazy to write a comment, but believe me, i tried to write good code
1 parent ee75b88 commit acd68c9

19 files changed

+449
-183
lines changed

budget_graph/bot.py

Lines changed: 138 additions & 66 deletions
Large diffs are not rendered by default.

budget_graph/db_manager.py

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020

2121
logger_database = setup_logger('logs/DatabaseLog.log', 'db_logger')
2222

23+
feature_ids: dict[str, int] = {
24+
'del_msg_after_transaction': 1,
25+
'skip_input_date': 2,
26+
'skip_input_category': 3,
27+
'skip_input_description': 4,
28+
}
29+
2330

2431
@timeit
2532
def connect_db():
@@ -86,7 +93,7 @@ def close_db_flask_g(error): # DO NOT REMOVE the parameter # noqa
8693

8794
def read_sql_file(request_name):
8895
filename: str = path.join(path.dirname(__file__), f'sql/{request_name}.sql')
89-
logger_database.info(f'[DB_QUERY] request to *.sql file: {filename}')
96+
logger_database.info(f'[REQUEST *.SQL] File: {filename}')
9097
with open(filename, 'r', encoding='utf-8') as sql_file:
9198
return sql_file.read()
9299

@@ -97,6 +104,8 @@ class DatabaseQueries:
97104
The class is used to query the database.
98105
All details of the structure of functions are indicated in the comments to the first function
99106
"""
107+
__slots__ = ('__conn',)
108+
100109
def __init__(self, connection):
101110
self.__conn = connection
102111

@@ -363,12 +372,27 @@ def check_user_is_group_owner_by_telegram_id(self, telegram_id: int, group_id: i
363372
read_sql_file('check_user_is_group_owner_by_telegram_id'),
364373
{'owner': telegram_id, 'group_id': group_id}
365374
)
366-
return bool(cur.fetchone()[0])
375+
return res[0] if (res := cur.fetchone()) else False
367376

368377
except (DatabaseError, TypeError) as err:
369-
logger_database.error(f"[DB_QUERY] {str(err)}, "
370-
f"telegram_id: {logging_hash(telegram_id)}"
371-
f"group id: {group_id}")
378+
logger_database.error(f'[DB_QUERY] {str(err)}, '
379+
f'telegram_id: {logging_hash(telegram_id)}'
380+
f'group id: {group_id}')
381+
return False
382+
383+
def check_user_is_premium_by_telegram_id(self, telegram_id: int) -> bool:
384+
try:
385+
with self.__conn as conn:
386+
with conn.cursor() as cur:
387+
cur.execute(
388+
read_sql_file('check_user_is_premium_by_telegram_id'),
389+
{'telegram_id': telegram_id}
390+
)
391+
return res[0] if (res := cur.fetchone()) else False
392+
393+
except (DatabaseError, TypeError) as err:
394+
logger_database.error(f'[DB_QUERY] {str(err)}, '
395+
f'telegram_id: {logging_hash(telegram_id)}')
372396
return False
373397

374398
def get_group_owner_username_by_group_id(self, group_id: int) -> str:
@@ -422,7 +446,7 @@ def get_user_timezone_by_telegram_id(self, telegram_id: int) -> int | None:
422446
with self.__conn as conn:
423447
with conn.cursor() as cur:
424448
cur.execute(read_sql_file('get_user_timezone_by_telegram_id'), {'telegram_id': telegram_id})
425-
return cur.fetchone()[0]
449+
return res[0] if (res := cur.fetchone()) else None
426450

427451
except (DatabaseError, TypeError) as err:
428452
logger_database.error(f"[DB_QUERY] {str(err)}, "
@@ -435,7 +459,7 @@ def check_record_id_is_exist(self, group_id: int, transaction_id: int) -> bool:
435459
with conn.cursor() as cur:
436460
cur.execute(read_sql_file('check_record_id_is_exist'),
437461
{'group_id': group_id, 'transaction_id': transaction_id})
438-
return bool(cur.fetchone()[0])
462+
return bool(res[0]) if (res := cur.fetchone()) else False
439463

440464
except (DatabaseError, TypeError) as err:
441465
logger_database.error(f"[DB_QUERY] {str(err)}, "
@@ -451,7 +475,7 @@ def check_username_is_exist(self, username: str) -> bool:
451475
with self.__conn as conn:
452476
with conn.cursor() as cur:
453477
cur.execute(read_sql_file('check_username_is_exist'), {'username': username})
454-
return bool(cur.fetchone()[0])
478+
return bool(res[0]) if (res := cur.fetchone()) else False
455479

456480
except (DatabaseError, TypeError) as err:
457481
logger_database.error(f"[DB_QUERY] {str(err)}, "
@@ -463,7 +487,7 @@ def check_telegram_id_is_exist(self, telegram_id: int) -> bool:
463487
with self.__conn as conn:
464488
with conn.cursor() as cur:
465489
cur.execute(read_sql_file('check_telegram_id_is_exist'), {'telegram_id': telegram_id})
466-
return bool(cur.fetchone()[0])
490+
return bool(res[0]) if (res := cur.fetchone()) else False
467491

468492
except (DatabaseError, TypeError) as err:
469493
logger_database.error(f"[DB_QUERY] {str(err)}, "
@@ -478,7 +502,7 @@ def check_token_is_unique(self, token: str) -> bool:
478502
with self.__conn as conn:
479503
with conn.cursor() as cur:
480504
cur.execute(read_sql_file('check_token_is_unique'), {'token': token})
481-
return not bool(cur.fetchone()[0])
505+
return not bool(res[0]) if (res := cur.fetchone()) else False
482506

483507
except (DatabaseError, TypeError) as err:
484508
logger_database.error(f"[DB_QUERY] {str(err)}, "
@@ -496,42 +520,50 @@ def check_limit_users_in_group(self, group_id: int) -> bool:
496520
with self.__conn as conn:
497521
with conn.cursor() as cur:
498522
cur.execute(read_sql_file('check_limit_users_in_group'), {'group_id': group_id})
499-
return bool(cur.fetchone()[0])
523+
return bool(res[0]) if (res := cur.fetchone()) else False
500524

501525
except (DatabaseError, TypeError) as err:
502526
logger_database.error(f"[DB_QUERY] {str(err)}, "
503527
f"group id: {group_id}")
504528
return False # to prevent a user from being written to a non-existent group
505529

506-
def get_feature_status_del_msg_after_transaction(self, telegram_id: int) -> bool:
507-
"""
508-
Checks the status whether the function is enabled
509-
for the operation of the StorageMsgIdForDeleteAfterOperation class
510-
"""
530+
def get_skip_operations_status(self, telegram_id: int) -> tuple:
531+
try:
532+
with self.__conn as conn:
533+
with conn.cursor() as cur:
534+
cur.execute(read_sql_file('get_skip_operations_status'), {'telegram_id': telegram_id})
535+
return tuple(bool(status) for status in res[0]) if (res := cur.fetchone()) else tuple([False]*3)
536+
537+
except (DatabaseError, TypeError) as err:
538+
logger_database.error(f"[DB_QUERY] {str(err)}, "
539+
f"telegram_id: {telegram_id}")
540+
return tuple([False]*3) # default value - (False, False, False)
541+
542+
def get_feature_status(self, telegram_id: int, feature: str):
511543
try:
512544
with self.__conn as conn:
513545
with conn.cursor() as cur:
514546
cur.execute(
515-
read_sql_file('get_feature_status_del_msg_after_transaction'),
516-
{'telegram_id': telegram_id}
547+
read_sql_file('get_feature_status'),
548+
{'telegram_id': telegram_id, 'feature': feature_ids.get(feature)}
517549
)
518-
return bool(cur.fetchone()[0])
550+
return bool(res[0]) if (res := cur.fetchone()) else False
519551

520552
except (DatabaseError, TypeError) as err:
521553
logger_database.error(f"[DB_QUERY] {str(err)}, "
522554
f"telegram_id: {telegram_id}")
523555
return False # default value - False
524556

525-
def change_feature_status_del_msg_after_transaction(self, telegram_id: int) -> bool:
557+
def change_feature_status(self, telegram_id: int, feature: str):
526558
try:
527559
with self.__conn as conn:
528560
with conn.cursor() as cur:
529561
cur.execute(
530-
read_sql_file('change_feature_status_del_msg_after_transaction'),
531-
{'telegram_id': telegram_id}
562+
read_sql_file('change_feature_status'),
563+
{'telegram_id': telegram_id, 'feature': feature_ids.get(feature)}
532564
)
533565
conn.commit()
534-
logger_database.info(f"[del_msg_transaction] successfully changed for {logging_hash(telegram_id)}")
566+
logger_database.info(f"[{feature}] successfully changed for {logging_hash(telegram_id)}")
535567
return True
536568

537569
except (DatabaseError, TypeError) as err:
@@ -817,7 +849,7 @@ def delete_group_with_users(self, group_id: int) -> bool: # TODO REFERENCES IN
817849
DELETE FROM
818850
"budget_graph"."users"
819851
WHERE
820-
"telegram_id" = ANY(ARRAY(SELECT "telegram_id" FROM telegram_id_users));
852+
"telegram_id" IS NOT NULL AND "telegram_id" = ANY(ARRAY(SELECT "telegram_id" FROM telegram_id_users));
821853
822854
-- groups
823855
DELETE FROM

budget_graph/helpers.py

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, feature_is_active=None):
1919
self.msg_id_to_delete: list = []
2020

2121
def append(self, msg_id: int):
22-
if self.feature_is_active:
22+
if self.feature_is_active and msg_id not in self.msg_id_to_delete:
2323
self.msg_id_to_delete.append(msg_id)
2424

2525
def delete_messages(self, bot, chat_id: int) -> None:
@@ -74,25 +74,63 @@ def get_language_buttons() -> tuple:
7474

7575

7676
@cache
77-
def get_diagram_buttons(user_language: str, user_is_owner: bool) -> tuple:
77+
def get_diagram_buttons(user_language: str, user_is_owner: bool, user_is_premium: bool) -> tuple:
78+
return_buttons: list = []
7879
buttons: tuple = (
7980
[
8081
InlineKeyboardButton(
8182
receive_translation(user_language, 'my_budget_diagram'), callback_data='get_diagram_0'
82-
)
83+
) # premium
8384
],
8485
[
8586
InlineKeyboardButton(
8687
receive_translation(user_language, 'budget_diagram_for_group'), callback_data='get_diagram_1'
87-
)
88+
) # group_owner
8889
],
8990
[
9091
InlineKeyboardButton(
9192
receive_translation(user_language, 'specific_user_budget_diagram'), callback_data='get_diagram_2'
93+
) # group_owner + premium
94+
],
95+
[
96+
InlineKeyboardButton(
97+
receive_translation(user_language, 'get_diagram_info'), callback_data='get_diagram_info'
98+
) # for any user
99+
]
100+
)
101+
# It is important that the buttons are in their original order.
102+
if user_is_premium:
103+
return_buttons.append(buttons[0])
104+
if user_is_owner:
105+
return_buttons.append(buttons[1])
106+
if user_is_premium:
107+
return_buttons.append(buttons[2])
108+
return_buttons.append(buttons[-1])
109+
return tuple(return_buttons)
110+
111+
112+
@cache
113+
def get_premium_buttons(user_language: str, premium_status: bool) -> tuple:
114+
premium_buttons: tuple = (
115+
[
116+
InlineKeyboardButton(
117+
receive_translation(user_language, 'get_premium'), callback_data='premium_get'
92118
)
93119
],
120+
[
121+
InlineKeyboardButton(
122+
receive_translation(user_language, 'check_premium_status'), callback_data='premium_status'
123+
)
124+
],
125+
[
126+
InlineKeyboardButton(
127+
receive_translation(user_language, 'about_premium'), callback_data='premium_info'
128+
)
129+
]
94130
)
95-
return buttons if user_is_owner else buttons[0]
131+
if premium_status:
132+
return tuple(premium_buttons[1:])
133+
return tuple(premium_buttons[0:3:2])
96134

97135

98136
@cache
@@ -154,12 +192,15 @@ def get_category_translate(user_language: str) -> tuple:
154192
def get_bot_commands() -> list:
155193
commands: list = [
156194
BotCommand('start', 'Start'),
195+
BotCommand('help', 'Help'),
196+
BotCommand('premium', 'Premium'),
157197
BotCommand('change_language', 'Change Language'),
158-
BotCommand('del_msg_transaction', '[ON/OFF] Delete messages after successful transaction'),
198+
BotCommand('del_msg_after_transaction', '[ON/OFF] Delete messages after successful transaction'),
199+
BotCommand('skip_input_date', '[ON/OFF] Skip setting transaction date (current will be used)'),
200+
BotCommand('skip_input_category', '[ON/OFF] Skip transaction category selection'),
201+
BotCommand('skip_input_description', '[ON/OFF] Skip adding description to transaction'),
159202
BotCommand('change_timezone', 'Change Time zone'),
160203
BotCommand('get_my_id', 'Get my Telegram ID'),
161-
BotCommand('premium', 'Premium'),
162-
BotCommand('help', 'Help'),
163204
BotCommand('project_github', 'GitHub')
164205
]
165206

budget_graph/localization/de.json

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"jewelry": "Schmuck",
5656
"salary": "Gehalt",
5757
"other": "Andere",
58-
"select_category": "Wählen Sie eine Kategorie",
58+
"select_category": "Wählen Sie eine Kategorie:",
5959
"add_description": "Beschreibung hinzufügen (nicht mehr als 50 Zeichen)",
6060
"no_description": "Keine Beschreibung",
6161
"entry_add_success": "Eintrag erfolgreich hinzugefügt",
@@ -84,7 +84,7 @@
8484
"datetime": "Terminzeit",
8585
"description": "Beschreibung",
8686
"table_is_empty": "Ihre Datensatztabelle ist leer",
87-
"csv_not_found_error": "Fehler. Versuchen Sie es später erneut oder melden Sie das Problem dem technischen Support.",
87+
"error_connect_support": "Fehler. Versuchen Sie es später erneut oder melden Sie das Problem dem technischen Support.",
8888
"owner": "Eigentümer",
8989
"small_group_exception": "Es gibt nur 1 Mitglied in dieser Gruppe.",
9090
"username_new_owner": "Schreiben Sie unten den Namen des Benutzers (aus der Liste), den Sie als Eigentümer der Gruppe zuweisen möchten",
@@ -131,14 +131,27 @@
131131
"select_timezone": "Wählen Sie Ihre Zeitzone aus",
132132
"error_select_timezone": "Fehler beim Festlegen des Zeitzonenwerts",
133133
"timezone_changed": "Die Zeitzone für Ihr Konto wurde erfolgreich eingestellt",
134-
"del_msg_transaction_on": "Funktion zum Löschen von Nachrichten nach der Transaktion aktiviert",
135-
"del_msg_transaction_of": "Die Funktion zum Löschen von Nachrichten nach einer Transaktion ist deaktiviert",
136-
"del_msg_transaction_err": "Beim Aktivieren/Deaktivieren der Funktionalität ist ein Fehler aufgetreten",
134+
"del_msg_after_transaction_on": "Funktion zum Löschen von Nachrichten nach der Transaktion aktiviert",
135+
"del_msg_after_transaction_off": "Die Funktion zum Löschen von Nachrichten nach einer Transaktion ist deaktiviert",
136+
"feature_err": "Beim Aktivieren/Deaktivieren der Funktionalität ist ein Fehler aufgetreten",
137137
"get_diagram": "Diagramm erstellen",
138138
"my_budget_diagram": "Mein Diagramm",
139139
"budget_diagram_for_group": "Graph gruppieren",
140140
"specific_user_budget_diagram": "Diagramm nach bestimmtem Benutzer",
141141
"choose_diagram_type": "Wählen Sie einen verfügbaren Diagrammtyp aus:",
142142
"wait_diagram": "Wir erstellen bereits ein Diagramm. Bitte warten...",
143-
"feature_uuid_filename": "Anwendungs-ID (Name der zukünftigen Datei)"
143+
"feature_uuid_filename": "Anwendungs-ID (Name der zukünftigen Datei)",
144+
"get_diagram_info": "Mehr zu Diagrammen",
145+
"diagram_info": "Das Diagramm ist eine HTML-Datei, die Sie auf jedem Gerät öffnen können. Es enthält in Form eines Diagramms Informationen zu Ihren Ausgaben, den Ausgaben einer Gruppe oder bestimmter Benutzer (je nach ausgewählter Kategorie).\n\nNur der Gruppenbesitzer kann Informationen zu den Gruppenausgaben anfordern. Um Ihre Ausgaben anzuzeigen, müssen Sie über ein Premium-Abonnement verfügen. Wenn Sie die Ausgaben bestimmter Benutzer sehen möchten, muss der Eigentümer der Gruppe ebenfalls über ein Premium-Abonnement verfügen und nur er selbst kann ein solches Diagramm anfordern.\n\nSobald Sie die Datei erhalten haben, können Sie sie an jeden senden.\n\nWenn Sie den Zeitplan auswählen, der Sie interessiert, wird eine Anfrage gesendet. Die durchschnittliche Wartezeit zum Empfangen eines Diagramms beträgt ungefähr 1 Sekunde",
146+
"get_premium": "Holen Sie sich den Premium-Status",
147+
"check_premium_status": "Aktuelle Abonnementinformationen",
148+
"about_premium": "Mehr zum Premium-Status",
149+
"choose_menu": "Wählen Sie den Artikel, der Sie interessiert, aus dem Menü",
150+
"premium_info": "Der Premium-Status bietet Zugriff auf erweiterte Funktionen wie exklusive Funktionen und vorrangigen technischen Support.\n\nNicht-Premium-Benutzer haben weiterhin Zugriff auf alle Kernfunktionen unseres Dienstes und können die Vorteile genauso nutzen wie andere Benutzer.\n\nDer Kauf eines Premium-Status durch Benutzer trägt zur Unterstützung und Entwicklung des Produkts bei",
151+
"skip_input_date_on": "Funktion zum Überspringen der Eingabe des Transaktionsdatums aktiviert",
152+
"skip_input_date_off": "Funktion zum Überspringen der Eingabe des Transaktionsdatums deaktiviert",
153+
"skip_input_category_on": "Funktion zur Auswahl der Transaktionskategorie aktiviert",
154+
"skip_input_category_off": "Die Funktion zur Auswahl der Transaktionskategorie ist deaktiviert",
155+
"skip_input_description_on": "Die Funktion zum Hinzufügen einer Beschreibung für eine Transaktion ist aktiviert",
156+
"skip_input_description_off": "Die Funktion zum Hinzufügen einer Beschreibung für eine Transaktion ist deaktiviert"
144157
}

0 commit comments

Comments
 (0)