ezKit 1.12.0__py3-none-any.whl → 1.12.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  """Bottle Extensions"""
2
+
2
3
  from types import FunctionType
3
4
  from typing import Any
4
5
 
@@ -7,20 +8,23 @@ from . import bottle, utils
7
8
 
8
9
  def enable_cors(fn: FunctionType) -> Any | None:
9
10
  """Bottle CORS"""
11
+
10
12
  # 参考文档:
11
13
  # - https://stackoverflow.com/a/17262900
12
14
  # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
13
15
  # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
14
16
  # - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
15
17
  def cors(*args, **kwargs):
16
- bottle.response.headers['Access-Control-Allow-Headers'] = '*'
17
- bottle.response.headers['Access-Control-Allow-Methods'] = '*'
18
- bottle.response.headers['Access-Control-Allow-Origin'] = '*'
19
- if bottle.request.method != 'OPTIONS':
18
+ bottle.response.headers["Access-Control-Allow-Headers"] = "*"
19
+ bottle.response.headers["Access-Control-Allow-Methods"] = "*"
20
+ bottle.response.headers["Access-Control-Allow-Origin"] = "*"
21
+ if bottle.request.method != "OPTIONS":
20
22
  return fn(*args, **kwargs)
21
23
  return None
24
+
22
25
  return cors
23
26
 
27
+
24
28
  def request_json() -> bottle.DictProperty | None:
25
29
  """Bottle Request JSON"""
26
30
  try:
ezKit/cipher.py CHANGED
@@ -1,4 +1,5 @@
1
- """Cipher"""
1
+ """Cipher Library"""
2
+
2
3
  # https://docs.python.org/3.10/library/hashlib.html
3
4
  # https://www.pycrypto.org/
4
5
  # https://stackoverflow.com/a/21928790
@@ -14,31 +15,31 @@ from loguru import logger
14
15
  class AESCipher:
15
16
  """AESCipher"""
16
17
 
17
- def __init__(self, key: str = 'vB7DoRm9C2Kd', algorithm: str = 'sha256'):
18
+ def __init__(self, key: str = "vB7DoRm9C2Kd", algorithm: str = "sha256"):
18
19
 
19
20
  self.bs = AES.block_size
20
21
 
21
22
  # dir(hashlib)
22
23
  match True:
23
- case True if algorithm == 'md5':
24
+ case True if algorithm == "md5":
24
25
  self.key = hashlib.md5(key.encode()).digest()
25
- case True if algorithm == 'sha1':
26
+ case True if algorithm == "sha1":
26
27
  self.key = hashlib.sha1(key.encode()).digest()
27
- case True if algorithm == 'sha224':
28
+ case True if algorithm == "sha224":
28
29
  self.key = hashlib.sha224(key.encode()).digest()
29
- case True if algorithm == 'sha256':
30
+ case True if algorithm == "sha256":
30
31
  self.key = hashlib.sha256(key.encode()).digest()
31
- case True if algorithm == 'sha384':
32
+ case True if algorithm == "sha384":
32
33
  self.key = hashlib.sha384(key.encode()).digest()
33
- case True if algorithm == 'sha512':
34
+ case True if algorithm == "sha512":
34
35
  self.key = hashlib.sha512(key.encode()).digest()
35
- case True if algorithm == 'sha3_224':
36
+ case True if algorithm == "sha3_224":
36
37
  self.key = hashlib.sha3_224(key.encode()).digest()
37
- case True if algorithm == 'sha3_256':
38
+ case True if algorithm == "sha3_256":
38
39
  self.key = hashlib.sha3_256(key.encode()).digest()
39
- case True if algorithm == 'sha3_384':
40
+ case True if algorithm == "sha3_384":
40
41
  self.key = hashlib.sha3_384(key.encode()).digest()
41
- case True if algorithm == 'sha3_512':
42
+ case True if algorithm == "sha3_512":
42
43
  self.key = hashlib.sha3_512(key.encode()).digest()
43
44
  # case True if algorithm == 'shake_128':
44
45
  # self.key = hashlib.shake_128(key.encode()).digest()
@@ -52,7 +53,7 @@ class AESCipher:
52
53
  raw = self._pad(raw)
53
54
  iv = Random.new().read(AES.block_size)
54
55
  cipher = AES.new(self.key, AES.MODE_CBC, iv)
55
- return base64.b64encode(iv + cipher.encrypt(raw.encode())).decode('utf-8')
56
+ return base64.b64encode(iv + cipher.encrypt(raw.encode())).decode("utf-8")
56
57
  except Exception as e:
57
58
  logger.exception(e)
58
59
  return None
@@ -60,9 +61,11 @@ class AESCipher:
60
61
  def decrypt(self, enc: str) -> str | None:
61
62
  try:
62
63
  enc_bytes = base64.b64decode(enc)
63
- iv = enc_bytes[:AES.block_size]
64
+ iv = enc_bytes[: AES.block_size]
64
65
  cipher = AES.new(self.key, AES.MODE_CBC, iv)
65
- return self._unpad(cipher.decrypt(enc_bytes[AES.block_size:])).decode('utf-8')
66
+ return self._unpad(cipher.decrypt(enc_bytes[AES.block_size :])).decode(
67
+ "utf-8"
68
+ )
66
69
  except Exception as e:
67
70
  logger.exception(e)
68
71
  return None
@@ -72,4 +75,4 @@ class AESCipher:
72
75
 
73
76
  @staticmethod
74
77
  def _unpad(s: bytes) -> bytes:
75
- return s[:-ord(s[len(s) - 1:])]
78
+ return s[: -ord(s[len(s) - 1 :])]
ezKit/database.py CHANGED
@@ -1,4 +1,5 @@
1
- """Database"""
1
+ """Database Library"""
2
+
2
3
  # Column, Table, MetaData API
3
4
  # https://docs.sqlalchemy.org/en/14/core/metadata.html#column-table-metadata-api
4
5
  # CursorResult
@@ -17,10 +18,10 @@ from sqlalchemy.orm import DeclarativeBase
17
18
  from . import utils
18
19
 
19
20
 
20
- class Database():
21
+ class Database:
21
22
  """Database"""
22
23
 
23
- engine = create_engine('sqlite://')
24
+ engine = create_engine("sqlite://")
24
25
 
25
26
  def __init__(self, target: str | None = None, **options):
26
27
  """Initiation"""
@@ -85,10 +86,10 @@ class Database():
85
86
  except Exception as e:
86
87
  logger.exception(e)
87
88
  idx.create(bind=self.engine)
88
- logger.success(f'{info} [success]')
89
+ logger.success(f"{info} [success]")
89
90
  return True
90
91
  except Exception as e:
91
- logger.error(f'{info} [failed]')
92
+ logger.error(f"{info} [failed]")
92
93
  logger.error(e)
93
94
  return False
94
95
 
@@ -227,10 +228,10 @@ class Database():
227
228
  self,
228
229
  sql: str | None = None,
229
230
  read_sql_file: dict | None = None,
230
- save_to_csv: dict | None = None
231
+ save_to_csv: dict | None = None,
231
232
  ) -> CursorResult[Any] | bool | None:
232
233
 
233
- info: str = 'Database connect execute'
234
+ info: str = "Database connect execute"
234
235
 
235
236
  logger.info(f"{info} ......")
236
237
 
@@ -245,12 +246,14 @@ class Database():
245
246
  read_sql_file_kwargs: dict = {
246
247
  "mode": "r",
247
248
  "encoding": "utf-8",
248
- **read_sql_file
249
+ **read_sql_file,
249
250
  }
250
251
  with open(encoding="utf-8", **read_sql_file_kwargs) as _file:
251
252
  sql_statement = _file.read()
252
253
  else:
253
- if not (isinstance(sql, str) and utils.check_arguments([(sql, str, "sql")])):
254
+ if not (
255
+ isinstance(sql, str) and utils.check_arguments([(sql, str, "sql")])
256
+ ):
254
257
  return None
255
258
  sql_statement = sql
256
259
  except Exception as e:
@@ -274,11 +277,13 @@ class Database():
274
277
  logger.success(f"{info} [success]")
275
278
 
276
279
  # 返回查询结果
277
- if isinstance(save_to_csv, dict) and utils.isTrue(save_to_csv, dict):
280
+ if isinstance(save_to_csv, dict) and utils.isTrue(
281
+ save_to_csv, dict
282
+ ):
278
283
  save_to_csv_kwargs: dict = {
279
284
  "mode": "w",
280
285
  "encoding": "utf-8",
281
- **save_to_csv
286
+ **save_to_csv,
282
287
  }
283
288
  with open(encoding="utf-8", **save_to_csv_kwargs) as _file:
284
289
  return self._result_save(_file, result)
@@ -294,10 +299,7 @@ class Database():
294
299
  # ----------------------------------------------------------------------------------------------
295
300
 
296
301
  def read_with_pandas(
297
- self,
298
- method: str = "read_sql",
299
- result_type: str = "df",
300
- **kwargs
302
+ self, method: str = "read_sql", result_type: str = "df", **kwargs
301
303
  ) -> pd.DataFrame | list | dict:
302
304
  """读取数据"""
303
305
 
@@ -322,7 +324,7 @@ class Database():
322
324
  logger.info(f"{info} ......")
323
325
 
324
326
  # 从 kwargs 中删除 con 键
325
- kwargs.pop('con', None)
327
+ kwargs.pop("con", None)
326
328
 
327
329
  match method:
328
330
  case "read_sql":
@@ -343,12 +345,12 @@ class Database():
343
345
 
344
346
  match result_type:
345
347
  case "json":
346
- return json.loads(data.to_json(orient='records'))
348
+ return json.loads(data.to_json(orient="records"))
347
349
  case "dict":
348
350
  return data.to_dict()
349
351
  case "list":
350
352
  # https://stackoverflow.com/a/26716774
351
- return data.to_dict('list')
353
+ return data.to_dict("list")
352
354
  case _:
353
355
  return data
354
356
 
ezKit/dockerhub.py CHANGED
@@ -1,9 +1,12 @@
1
- """Docker Hub"""
1
+ """Docker Hub Library"""
2
+
2
3
  import requests
3
4
  from loguru import logger
4
5
 
5
6
 
6
- def get_latest_tags(url: str, limit: int = 20, proxies: dict | None = None) -> list | None:
7
+ def get_latest_tags(
8
+ url: str, limit: int = 20, proxies: dict | None = None
9
+ ) -> list | None:
7
10
 
8
11
  info: str = "获取最新标签"
9
12
 
@@ -20,7 +23,9 @@ def get_latest_tags(url: str, limit: int = 20, proxies: dict | None = None) -> l
20
23
  # }
21
24
 
22
25
  # 请求接口
23
- response = requests.get(url, params={"page": 1, "page_size": limit}, proxies=proxies, timeout=10)
26
+ response = requests.get(
27
+ url, params={"page": 1, "page_size": limit}, proxies=proxies, timeout=10
28
+ )
24
29
 
25
30
  # 检查请求状态码
26
31
  if response.status_code != 200:
@@ -47,6 +52,7 @@ def get_latest_tags(url: str, limit: int = 20, proxies: dict | None = None) -> l
47
52
  logger.exception(e)
48
53
  return None
49
54
 
55
+
50
56
  # def get_all_tags():
51
57
  # url = "https://hub.docker.com/v2/repositories/library/postgres/tags"
52
58
  # tags = []
ezKit/http.py CHANGED
@@ -1,4 +1,5 @@
1
- """HTTP"""
1
+ """HTTP Library"""
2
+
2
3
  import json
3
4
  from typing import Any
4
5
 
@@ -13,7 +14,7 @@ def download(
13
14
  file: dict,
14
15
  chunks: bool = False,
15
16
  iter_content: dict | None = None,
16
- info: str | None = None
17
+ info: str | None = None,
17
18
  ) -> bool:
18
19
  """下载文件"""
19
20
 
@@ -38,7 +39,7 @@ def download(
38
39
 
39
40
  try:
40
41
 
41
- logger.info(f'{info_prefix} ......')
42
+ logger.info(f"{info_prefix} ......")
42
43
 
43
44
  response = requests.request(**request_arguments)
44
45
 
@@ -51,13 +52,13 @@ def download(
51
52
  else:
52
53
  _file.write(response.content)
53
54
 
54
- logger.success(f'{info_prefix} [success]')
55
+ logger.success(f"{info_prefix} [success]")
55
56
 
56
57
  return True
57
58
 
58
59
  except Exception as e:
59
60
 
60
- logger.error(f'{info_prefix} [failed]')
61
+ logger.error(f"{info_prefix} [failed]")
61
62
  logger.exception(e)
62
63
  return False
63
64
 
@@ -65,7 +66,9 @@ def download(
65
66
  def response_json(data: Any = None, **kwargs) -> str | None:
66
67
  """解决字符编码问题: ensure_ascii=False"""
67
68
  try:
68
- return json.dumps(data, default=str, ensure_ascii=False, sort_keys=True, **kwargs)
69
+ return json.dumps(
70
+ data, default=str, ensure_ascii=False, sort_keys=True, **kwargs
71
+ )
69
72
  except Exception as e:
70
73
  logger.exception(e)
71
74
  return None
ezKit/mongo.py CHANGED
@@ -1,4 +1,5 @@
1
- """MongoDB"""
1
+ """MongoDB Library"""
2
+
2
3
  from loguru import logger
3
4
  from pymongo import MongoClient
4
5
  from pymongo.collection import Collection
@@ -6,7 +7,7 @@ from pymongo.collection import Collection
6
7
  from . import utils
7
8
 
8
9
 
9
- class Mongo():
10
+ class Mongo:
10
11
  """MongoDB"""
11
12
 
12
13
  client = MongoClient()
ezKit/qywx.py CHANGED
@@ -1,4 +1,5 @@
1
- """企业微信"""
1
+ """腾讯企业微信"""
2
+
2
3
  #
3
4
  # 企业微信开发者中心
4
5
  # https://developer.work.weixin.qq.com/
@@ -60,7 +61,13 @@ class QYWX:
60
61
  # Token: https://developer.work.weixin.qq.com/document/path/90665#access-token
61
62
  access_token: str = ""
62
63
 
63
- def __init__(self, work_id: str, agent_id: str, agent_secret: str, api_prefix: str = "https://qyapi.weixin.qq.com"):
64
+ def __init__(
65
+ self,
66
+ work_id: str,
67
+ agent_id: str,
68
+ agent_secret: str,
69
+ api_prefix: str = "https://qyapi.weixin.qq.com",
70
+ ):
64
71
  """Initiation"""
65
72
  self.api_prefix = api_prefix
66
73
  self.work_id = work_id
@@ -79,7 +86,10 @@ class QYWX:
79
86
 
80
87
  logger.info(f"{info} ......")
81
88
 
82
- response = requests.get(f"{self.api_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}", timeout=10)
89
+ response = requests.get(
90
+ f"{self.api_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}",
91
+ timeout=10,
92
+ )
83
93
 
84
94
  if response.status_code != 200:
85
95
  logger.error(f"{info} [状态码错误]")
@@ -170,9 +180,13 @@ class QYWX:
170
180
  if not utils.isTrue(self.access_token, str):
171
181
  self.get_access_token()
172
182
 
173
- json_string = json.dumps({'mobile': mobile})
183
+ json_string = json.dumps({"mobile": mobile})
174
184
 
175
- response = requests.post(f"{self.api_prefix}/cgi-bin/user/getuserid?access_token={self.access_token}", data=json_string, timeout=10)
185
+ response = requests.post(
186
+ f"{self.api_prefix}/cgi-bin/user/getuserid?access_token={self.access_token}",
187
+ data=json_string,
188
+ timeout=10,
189
+ )
176
190
 
177
191
  if response.status_code != 200:
178
192
  logger.error(f"{info} [接口请求错误]")
@@ -180,7 +194,7 @@ class QYWX:
180
194
 
181
195
  response_data: dict = response.json()
182
196
 
183
- if response_data.get('errcode') == 42001:
197
+ if response_data.get("errcode") == 42001:
184
198
  self.get_access_token()
185
199
  time.sleep(1)
186
200
  self.get_user_id_by_mobile(mobile)
@@ -222,7 +236,9 @@ class QYWX:
222
236
 
223
237
  info: str = "发送消息"
224
238
 
225
- if not utils.check_arguments([(mobile, (str, list), "mobile"), (message, str, "message")]):
239
+ if not utils.check_arguments(
240
+ [(mobile, (str, list), "mobile"), (message, str, "message")]
241
+ ):
226
242
  logger.error(f"{info} [失败]")
227
243
  return False
228
244
 
@@ -251,28 +267,39 @@ class QYWX:
251
267
 
252
268
  user_object = self.get_user_id_by_mobile(user)
253
269
 
254
- if not (isinstance(user_object, dict) and utils.isTrue(user_object, dict)):
270
+ if not (
271
+ isinstance(user_object, dict) and utils.isTrue(user_object, dict)
272
+ ):
255
273
  logger.error(f"{info} [获取用户ID错误: {user}]")
256
274
  continue
257
275
 
258
- if user_object.get("errcode", -1) != 0 or user_object.get("errmsg", "") != "ok":
259
- logger.error(f"{user_object.get('errcode')}: {user_object.get('errmsg')}")
276
+ if (
277
+ user_object.get("errcode", -1) != 0
278
+ or user_object.get("errmsg", "") != "ok"
279
+ ):
280
+ logger.error(
281
+ f"{user_object.get('errcode')}: {user_object.get('errmsg')}"
282
+ )
260
283
  continue
261
284
 
262
285
  json_dict = {
263
- 'touser': user_object.get('userid'),
264
- 'msgtype': 'text',
265
- 'agentid': self.agent_id,
266
- 'text': {'content': message},
267
- 'safe': 0,
268
- 'enable_id_trans': 0,
269
- 'enable_duplicate_check': 0,
270
- 'duplicate_check_interval': 1800
286
+ "touser": user_object.get("userid"),
287
+ "msgtype": "text",
288
+ "agentid": self.agent_id,
289
+ "text": {"content": message},
290
+ "safe": 0,
291
+ "enable_id_trans": 0,
292
+ "enable_duplicate_check": 0,
293
+ "duplicate_check_interval": 1800,
271
294
  }
272
295
 
273
296
  json_string = json.dumps(json_dict)
274
297
 
275
- response = requests.post(f"{self.api_prefix}/cgi-bin/message/send?access_token={self.access_token}", data=json_string, timeout=10)
298
+ response = requests.post(
299
+ f"{self.api_prefix}/cgi-bin/message/send?access_token={self.access_token}",
300
+ data=json_string,
301
+ timeout=10,
302
+ )
276
303
 
277
304
  if response.status_code != 200:
278
305
  logger.error(f"{info} [发送消息失败: {user}]")
@@ -280,7 +307,7 @@ class QYWX:
280
307
 
281
308
  response_data: dict = response.json()
282
309
 
283
- if response_data.get('errcode') == 42001:
310
+ if response_data.get("errcode") == 42001:
284
311
  self.get_access_token()
285
312
  time.sleep(1)
286
313
  self.send_message_by_mobile(mobile, message)
ezKit/redis.py CHANGED
@@ -1,4 +1,5 @@
1
- """Redis"""
1
+ """Redis Library"""
2
+
2
3
  import redis as RedisClient
3
4
  from loguru import logger
4
5
 
ezKit/sendemail.py CHANGED
@@ -1,4 +1,5 @@
1
- """发送邮件"""
1
+ """Send eMail Library"""
2
+
2
3
  # https://stackoverflow.com/questions/882712/sending-html-email-using-python
3
4
  import smtplib
4
5
  from email.header import Header
@@ -15,33 +16,40 @@ from . import utils
15
16
 
16
17
  class TypedSMTP(TypedDict):
17
18
  """smtp type"""
19
+
18
20
  server: str
19
21
  port: int
20
22
  tls: bool
21
23
 
24
+
22
25
  class TypedSender(TypedDict):
23
26
  """sender type"""
27
+
24
28
  name: str
25
29
  address: str
26
30
  password: str
27
31
 
32
+
28
33
  class TypedBody(TypedDict, total=False):
29
34
  """body type"""
35
+
30
36
  content: str
31
37
  type: str | None # "plain", "html", or "file"
32
38
 
39
+
33
40
  def format_parse(s):
34
41
  """格式化邮件地址"""
35
42
  _name, _addr = parseaddr(s)
36
43
  return formataddr((Header(_name, "utf-8").encode(), _addr))
37
44
 
45
+
38
46
  def sendemail(
39
47
  smtp: TypedSMTP,
40
48
  sender: TypedSender,
41
49
  recipients: str | list,
42
50
  subject: str,
43
51
  body: TypedBody,
44
- images: None | list = None
52
+ images: None | list = None,
45
53
  ) -> bool:
46
54
  """发送邮件"""
47
55
 
@@ -233,10 +241,10 @@ def sendemail(
233
241
  except Exception as e:
234
242
 
235
243
  # 忽略腾讯邮箱返回的异常
236
- if e.args == (-1, b'\x00\x00\x00'):
244
+ if e.args == (-1, b"\x00\x00\x00"):
237
245
  # pass
238
246
  return True
239
247
 
240
- logger.error('sendemail error')
248
+ logger.error("sendemail error")
241
249
  logger.exception(e)
242
250
  return False
ezKit/token.py CHANGED
@@ -1,4 +1,5 @@
1
- """Token"""
1
+ """Token Library"""
2
+
2
3
  import json
3
4
  from typing import Any
4
5
 
@@ -7,7 +8,9 @@ from loguru import logger
7
8
  from . import cipher, utils
8
9
 
9
10
 
10
- def generate_token(key: str = 'Fc0zXCmGKd7tPu6W', timeout: int = 3600, data: Any = None) -> (str | None):
11
+ def generate_token(
12
+ key: str = "Fc0zXCmGKd7tPu6W", timeout: int = 3600, data: Any = None
13
+ ) -> str | None:
11
14
  try:
12
15
  now = utils.datetime_now()
13
16
 
@@ -20,14 +23,11 @@ def generate_token(key: str = 'Fc0zXCmGKd7tPu6W', timeout: int = 3600, data: Any
20
23
  return None
21
24
 
22
25
  source = json.dumps(
23
- obj={
24
- "datetime": utils.datetime_to_string(offset),
25
- "data": data
26
- },
27
- default=str
26
+ obj={"datetime": utils.datetime_to_string(offset), "data": data},
27
+ default=str,
28
28
  )
29
29
 
30
- aes_cipher = cipher.AESCipher(key=key, algorithm='sha256')
30
+ aes_cipher = cipher.AESCipher(key=key, algorithm="sha256")
31
31
 
32
32
  return aes_cipher.encrypt(source)
33
33
 
@@ -36,12 +36,12 @@ def generate_token(key: str = 'Fc0zXCmGKd7tPu6W', timeout: int = 3600, data: Any
36
36
  return None
37
37
 
38
38
 
39
- def parsing_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> (dict | None):
39
+ def parsing_token(token_string: str, key: str = "Fc0zXCmGKd7tPu6W") -> dict | None:
40
40
  try:
41
41
  if not utils.isTrue(token_string, str):
42
42
  return None
43
43
 
44
- aes_cipher = cipher.AESCipher(key=key, algorithm='sha256')
44
+ aes_cipher = cipher.AESCipher(key=key, algorithm="sha256")
45
45
 
46
46
  target = aes_cipher.decrypt(token_string)
47
47
 
@@ -50,7 +50,7 @@ def parsing_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> (dict | N
50
50
 
51
51
  source: dict = json.loads(target)
52
52
 
53
- source['datetime'] = utils.datetime_string_to_datetime(source['datetime'])
53
+ source["datetime"] = utils.datetime_string_to_datetime(source["datetime"])
54
54
 
55
55
  return source
56
56
 
@@ -59,7 +59,7 @@ def parsing_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> (dict | N
59
59
  return None
60
60
 
61
61
 
62
- def certify_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> bool:
62
+ def certify_token(token_string: str, key: str = "Fc0zXCmGKd7tPu6W") -> bool:
63
63
  try:
64
64
 
65
65
  result = parsing_token(token_string, key)
@@ -67,7 +67,7 @@ def certify_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> bool:
67
67
  if result is None:
68
68
  return False
69
69
 
70
- if result.get('datetime') < utils.datetime_now(): # type: ignore
70
+ if result.get("datetime") < utils.datetime_now(): # type: ignore
71
71
  return False
72
72
 
73
73
  return True