1
- """
2
- This module contains classes and methods
3
- for assembling and sending telegram messages to the bot.
4
- """
1
+ """This module contains classes and methods for assembling and sending telegram messages to the bot."""
5
2
import os
6
3
import json
7
4
import math
8
5
import re
9
- from typing import Union
10
6
import emoji
7
+ from .exceptions import ConfigurationIsNotValid , TemplateNotFound , TemplatesIsNotValid
11
8
12
9
13
10
class Messages :
14
11
"""
15
- This class contains methods
16
- for assembling and sending telegram messages to the bot.
12
+ This class contains methods for assembling and sending telegram messages to the bot.
13
+
14
+ Attributes:
15
+ configuration (dict): the contents of the configuration file.
16
+
17
+ Exceptions:
18
+ ConfigurationIsNotValid: raised when the configuration file is not valid JSON.
19
+ TemplateNotFound: raised when the template is not found in the configuration file.
20
+ TemplatesIsNotValid: raised when the templates is not valid.
21
+
22
+ Examples:
23
+ >>> from messages import Messages
24
+ >>> messages = Messages('configs/messages.json')
25
+ >>> messages.render_template('test_message', username='pytest')
17
26
"""
18
27
19
- def __init__ (
20
- self ,
21
- config_path : str = None
22
- ) -> None :
28
+ def __init__ (self , config_path : str = 'configs/messages.json' ) -> None :
23
29
"""
24
30
Method for create a new messages instance.
25
31
26
32
Args:
27
33
config (str): the path as a file containing a dictionary with message templates.
34
+ """
35
+ env_variable = os .environ .get ("MESSAGES_CONFIG" , None )
28
36
29
- Returns:
30
- None
37
+ if env_variable :
38
+ config_file = env_variable
39
+ else :
40
+ config_file = config_path
31
41
32
- Examples:
33
- >>> from messages import Messages
34
- >>> messages = Messages('configs/messages.json')
42
+ self .configuration = self ._read_configuration (config_file = config_file )
43
+
44
+ if not self ._templates_is_valid ():
45
+ raise TemplatesIsNotValid (
46
+ "Templates have invalid elements. Please check your configuration file. "
47
+ "Otherwise, check examples: https://github.com/obervinov/messages-package?tab=readme-ov-file#-usage-examples"
48
+ )
49
+
50
+ def _read_configuration (self , config_file : str = None ) -> dict :
35
51
"""
36
- if os .environ .get ("MESSAGES_CONFIG" , None ) is not None :
37
- self .config_path = os .environ .get ("MESSAGES_CONFIG" , None )
38
- elif config_path :
39
- self .config_path = config_path
40
- else :
41
- self .config_path = 'configs/messages.json'
52
+ Method for checking the validity of the configuration file and reading its contents.
53
+
54
+ Args:
55
+ config_file (str): the path as a file containing a dictionary with message templates.
42
56
43
- if os .path .exists (self .config_path ):
44
- with open (self .config_path , 'r' , encoding = 'UTF-8' ) as config_json :
57
+ Returns:
58
+ dict: the contents of the configuration file.
59
+ """
60
+ if os .path .exists (config_file ):
61
+ with open (config_file , 'r' , encoding = 'UTF-8' ) as config_json :
45
62
try :
46
- self .data = json .load (config_json )
47
- config_json .close ()
63
+ return json .load (config_json )
48
64
except json .JSONDecodeError as json_error :
49
- # pylint: disable=no-value-for-parameter
50
- raise json .JSONDecodeError (
51
- f"Configuration file { self .config_path } is not valid JSON: { json_error } \n "
65
+ raise ConfigurationIsNotValid (
66
+ "Configuration file structure is not valid JSON. Please check examples: "
52
67
"https://github.com/obervinov/messages-package?tab=readme-ov-file#-usage-examples"
53
- )
68
+ ) from json_error
54
69
else :
55
- raise FileNotFoundError (f"Configuration file not found: { self .config_path } " )
70
+ raise FileNotFoundError (f"Configuration file not found: { config_file } " )
71
+
72
+ def _templates_is_valid (self ) -> bool :
73
+ """
74
+ Method for checking the validity of the templates in the configuration file.
75
+
76
+ Returns:
77
+ bool: True if the templates are valid, False otherwise.
78
+ """
79
+ if 'templates' in self .configuration :
80
+ for template in self .configuration ['templates' ].values ():
81
+ if 'text' not in template or 'args' not in template :
82
+ print (f"[Messages]: there are no text or args in template { template } " )
83
+ return False
84
+ if not isinstance (template ['text' ], str ) or not isinstance (template ['args' ], list ):
85
+ print (f"[Messages]: text or args in template { template } has an invalid data type" )
86
+ return False
87
+ args_provided = len (template ['args' ])
88
+ args_expected = len (re .findall (r"{.*?}" , template ['text' ]))
89
+ if args_provided != args_expected :
90
+ print (f"[Messages]: the number of arguments in the template { template } does nots match" )
91
+ return False
92
+ return True
56
93
57
94
def render_template (
58
95
self ,
59
96
template_alias : str = None ,
60
97
** kwargs
61
- ) -> Union [ str , None ] :
98
+ ) -> str | None :
62
99
"""
63
100
Method for reading the text from the configuration file.
64
101
65
102
Args:
66
- template_alias (str): the name of the template key for extracting text from conifg .
103
+ template_alias (str): the name of the template key for extracting text from config .
67
104
68
105
Keyword Args:
69
106
**kwargs: passing additional parameters for message assembly.
@@ -78,7 +115,7 @@ def render_template(
78
115
>>> messages.render_template('test_message', username='pytest')
79
116
"""
80
117
try :
81
- template = self .data ['templates' ][template_alias ]
118
+ template = self .configuration ['templates' ][template_alias ]
82
119
arguments = []
83
120
for arg in template ['args' ]:
84
121
if re .match (r":.*:" , arg ):
@@ -89,15 +126,17 @@ def render_template(
89
126
arguments .append (kwargs .get (arg ))
90
127
# Building full message
91
128
return template ['text' ].format (* arguments )
92
- except KeyError :
129
+ except KeyError as error :
93
130
print (f"[Messages]: template not found: { template_alias } " )
94
- return None
131
+ raise TemplateNotFound (
132
+ "Template not found in the configuration file. Please check your configuration file."
133
+ ) from error
95
134
96
135
def render_progressbar (
97
136
self ,
98
137
total_count : int = 0 ,
99
138
current_count : int = 0
100
- ) -> Union [ str , None ] :
139
+ ) -> str | None :
101
140
"""
102
141
A Method for generating string with a progress bar based
103
142
on the transmitted statistics data.
0 commit comments