11import json
22import os
3+ import urllib .parse
34import xml .etree .ElementTree as ET
5+ from datetime import datetime , timedelta
6+ from enum import Enum
47from http import HTTPStatus
58from io import IOBase
69from typing import Any , Dict , List , Optional , Tuple , Union
@@ -19,6 +22,20 @@ def to_header_specific_case(string: str) -> str:
1922 return "-" .join (word .capitalize () for word in string .split ("_" ))
2023
2124
25+ def url_encoding (string_to_encode : str , safe : str = "" , encoding : str = "utf-8" ) -> str :
26+ """
27+ Special characters and user credentials are properly encoded.
28+ Use a URL encoding reference as a guide:
29+ https://www.w3schools.com/tags/ref_urlencode.asp
30+
31+ The optional safe parameter specifies additional ASCII characters
32+ that should not be quoted — its default value is '/'.
33+ """
34+ return urllib .parse .quote (
35+ string_to_encode , safe = safe , encoding = encoding , errors = None
36+ )
37+
38+
2239class Authentication (BaseModel ):
2340 base_url : AnyHttpUrl
2441 api_key : constr (min_length = 1 )
@@ -48,6 +65,71 @@ def validate_url_length(cls, value: str) -> str:
4865 return value
4966
5067
68+ class FromAndToTimeValidator :
69+ _MINIMUM_DELIVERY_WINDOW_MINUTES = 60
70+
71+ @classmethod
72+ def _validate_time_differences (cls , from_time , to_time ):
73+ from_time_in_minutes = from_time .hour * 60 + from_time .minute
74+ to_time_in_minutes = to_time .hour * 60 + to_time .minute
75+
76+ if (
77+ to_time_in_minutes - from_time_in_minutes
78+ < cls ._MINIMUM_DELIVERY_WINDOW_MINUTES
79+ ):
80+ raise ValueError (
81+ f"Minimum of { cls ._MINIMUM_DELIVERY_WINDOW_MINUTES } minutes has to pass "
82+ f"between from and to delivery window times."
83+ )
84+
85+ @classmethod
86+ def validate_from_and_to (cls , values ):
87+ if not values .get ("from_time" ) and not values .get ("to" ):
88+ return values
89+
90+ if values .get ("from_time" ) and not values .get ("to" ):
91+ raise ValueError ("If 'from_time' is set, 'to' has to be set also" )
92+
93+ if values .get ("to" ) and not values .get ("from_time" ):
94+ raise ValueError ("If 'to' is set, 'from_time' has to be set also" )
95+
96+ cls ._validate_time_differences (values ["from_time" ], values ["to" ])
97+
98+ return values
99+
100+
101+ class DateTimeValidator :
102+ _MAX_TIME_LIMIT = 180
103+ _EXPECTED_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
104+
105+ @classmethod
106+ def convert_to_date_time_format (cls , value ):
107+ if not value :
108+ return
109+ if isinstance (value , str ):
110+ value = datetime .fromisoformat (value )
111+
112+ return value
113+
114+ @classmethod
115+ def convert_time_to_correct_format (cls , value ) -> str :
116+ date_time_format = cls .convert_to_date_time_format (value )
117+
118+ return date_time_format .strftime (cls ._EXPECTED_TIME_FORMAT )
119+
120+ @classmethod
121+ def convert_time_to_correct_format_validate_limit (cls , value ):
122+
123+ date_time_format = cls .convert_to_date_time_format (value )
124+
125+ if date_time_format > datetime .now () + timedelta (days = cls ._MAX_TIME_LIMIT ):
126+ raise ValueError (
127+ "Scheduled message must be sooner than 180 days from today"
128+ )
129+
130+ return value .strftime (cls ._EXPECTED_TIME_FORMAT )
131+
132+
51133class CamelCaseModel (BaseModel ):
52134 class Config :
53135 alias_generator = to_camel_case
@@ -133,6 +215,41 @@ def validate(cls, value):
133215 return cls (value )
134216
135217
218+ class LanguageEnum (str , Enum ):
219+ TURKISH = "TR"
220+ SPANISH = "ES"
221+ PORTUGUESE = "PT"
222+ AUTODETECT = "AUTODETECT"
223+
224+
225+ class TransliterationEnum (str , Enum ):
226+ TURKISH = "TURKISH"
227+ GREEK = "GREEK"
228+ CYRILLIC = "CYRILLIC"
229+ SERBIAN_CYRILLIC = "SERBIAN_CYRILLIC"
230+ CENTRAL_EUROPEAN = "CENTRAL_EUROPEAN"
231+ BALTIC = "BALTIC"
232+ NON_UNICODE = "NON_UNICODE"
233+
234+
235+ class GeneralStatus (str , Enum ):
236+ ACCEPTED = "ACCEPTED"
237+ PENDING = "PENDING"
238+ UNDELIVERABLE = "UNDELIVERABLE"
239+ DELIVERED = "DELIVERED"
240+ REJECTED = "REJECTED"
241+ EXPIRED = "EXPIRED"
242+
243+
244+ class MessageStatus (str , Enum ):
245+ PENDING = "PENDING"
246+ PAUSED = "PAUSED"
247+ PROCESSING = "PROCESSING"
248+ CANCELED = "CANCELED"
249+ FINISHED = "FINISHED"
250+ FAILED = "FAILED"
251+
252+
136253class MultipartMixin :
137254 """Mixin used for allowing models to export their fields to a multipart/form-data
138255 format. Field types currently supported are listed in the
@@ -211,3 +328,13 @@ def _get_json_for_field(model: Union[CamelCaseModel, List[CamelCaseModel]]) -> s
211328 model_aliased = model .dict (by_alias = True )
212329
213330 return json .dumps (model_aliased )
331+
332+
333+ class DaysEnum (str , Enum ):
334+ MONDAY = "MONDAY"
335+ TUESDAY = "TUESDAY"
336+ WEDNESDAY = "WEDNESDAY"
337+ THURSDAY = "THURSDAY"
338+ FRIDAY = "FRIDAY"
339+ SATURDAY = "SATURDAY"
340+ SUNDAY = "SUNDAY"
0 commit comments