pytbox 0.0.7__py3-none-any.whl → 0.3.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.

Potentially problematic release.


This version of pytbox might be problematic. Click here for more details.

Files changed (55) hide show
  1. pytbox/alert/alert_handler.py +27 -7
  2. pytbox/alert/ping.py +0 -1
  3. pytbox/alicloud/sls.py +9 -6
  4. pytbox/base.py +74 -1
  5. pytbox/categraf/build_config.py +95 -32
  6. pytbox/categraf/instances.toml +39 -0
  7. pytbox/categraf/jinja2/__init__.py +6 -0
  8. pytbox/categraf/jinja2/input.cpu/cpu.toml.j2 +5 -0
  9. pytbox/categraf/jinja2/input.disk/disk.toml.j2 +11 -0
  10. pytbox/categraf/jinja2/input.diskio/diskio.toml.j2 +6 -0
  11. pytbox/categraf/jinja2/input.dns_query/dns_query.toml.j2 +12 -0
  12. pytbox/categraf/jinja2/input.http_response/http_response.toml.j2 +9 -0
  13. pytbox/categraf/jinja2/input.mem/mem.toml.j2 +5 -0
  14. pytbox/categraf/jinja2/input.net/net.toml.j2 +11 -0
  15. pytbox/categraf/jinja2/input.net_response/net_response.toml.j2 +9 -0
  16. pytbox/categraf/jinja2/input.ping/ping.toml.j2 +11 -0
  17. pytbox/categraf/jinja2/input.prometheus/prometheus.toml.j2 +12 -0
  18. pytbox/categraf/jinja2/input.snmp/cisco_interface.toml.j2 +96 -0
  19. pytbox/categraf/jinja2/input.snmp/cisco_system.toml.j2 +41 -0
  20. pytbox/categraf/jinja2/input.snmp/h3c_interface.toml.j2 +96 -0
  21. pytbox/categraf/jinja2/input.snmp/h3c_system.toml.j2 +41 -0
  22. pytbox/categraf/jinja2/input.snmp/huawei_interface.toml.j2 +96 -0
  23. pytbox/categraf/jinja2/input.snmp/huawei_system.toml.j2 +41 -0
  24. pytbox/categraf/jinja2/input.snmp/ruijie_interface.toml.j2 +96 -0
  25. pytbox/categraf/jinja2/input.snmp/ruijie_system.toml.j2 +41 -0
  26. pytbox/categraf/jinja2/input.vsphere/vsphere.toml.j2 +211 -0
  27. pytbox/cli/commands/vm.py +22 -0
  28. pytbox/cli/main.py +2 -0
  29. pytbox/database/mongo.py +1 -1
  30. pytbox/database/victoriametrics.py +331 -40
  31. pytbox/excel.py +64 -0
  32. pytbox/feishu/endpoints.py +6 -6
  33. pytbox/log/logger.py +29 -12
  34. pytbox/mail/alimail.py +142 -0
  35. pytbox/mail/client.py +171 -0
  36. pytbox/mail/mail_detail.py +30 -0
  37. pytbox/mingdao.py +164 -0
  38. pytbox/network/meraki.py +537 -0
  39. pytbox/notion.py +731 -0
  40. pytbox/pyjira.py +612 -0
  41. pytbox/utils/cronjob.py +79 -0
  42. pytbox/utils/env.py +2 -2
  43. pytbox/utils/load_config.py +67 -21
  44. pytbox/utils/load_vm_devfile.py +45 -0
  45. pytbox/utils/richutils.py +11 -1
  46. pytbox/utils/timeutils.py +15 -57
  47. pytbox/vmware.py +120 -0
  48. pytbox/win/ad.py +30 -0
  49. {pytbox-0.0.7.dist-info → pytbox-0.3.1.dist-info}/METADATA +7 -4
  50. pytbox-0.3.1.dist-info/RECORD +72 -0
  51. pytbox/utils/ping_checker.py +0 -1
  52. pytbox-0.0.7.dist-info/RECORD +0 -39
  53. {pytbox-0.0.7.dist-info → pytbox-0.3.1.dist-info}/WHEEL +0 -0
  54. {pytbox-0.0.7.dist-info → pytbox-0.3.1.dist-info}/entry_points.txt +0 -0
  55. {pytbox-0.0.7.dist-info → pytbox-0.3.1.dist-info}/top_level.txt +0 -0
pytbox/utils/env.py CHANGED
@@ -17,14 +17,14 @@ def get_env_by_file_exist(file_path: str) -> Literal['prod', 'dev']:
17
17
  return 'dev'
18
18
 
19
19
 
20
- def get_env_by_os_environment() -> Literal['dev', 'prod']:
20
+ def get_env_by_os_environment(check_key: str='ENV') -> Literal['dev', 'prod']:
21
21
  '''
22
22
  根据环境变量获取环境
23
23
 
24
24
  Returns:
25
25
  Literal['dev', 'prod']: 环境,dev 表示开发环境,prod 表示生产环境
26
26
  '''
27
- if os.getenv('ENV') == 'dev':
27
+ if os.getenv(check_key) == 'dev':
28
28
  return 'dev'
29
29
  else:
30
30
  return 'prod'
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
+ import os
4
+ import json
3
5
 
4
6
  try:
5
7
  import toml
@@ -8,13 +10,14 @@ except ImportError:
8
10
  from pytbox.onepassword_connect import OnePasswordConnect
9
11
 
10
12
 
11
- def _replace_1password_values(data, oc):
13
+ def _replace_values(data, oc=None, jsonfile_path=None):
12
14
  """
13
- 递归处理配置数据,替换 1password 和 password 开头的值
15
+ 递归处理配置数据,替换 1password、passwordjsonfile 开头的值
14
16
 
15
17
  Args:
16
18
  data: 配置数据(dict, list, str 等)
17
19
  oc: OnePasswordConnect 实例
20
+ jsonfile_path: JSON 文件路径
18
21
 
19
22
  Returns:
20
23
  处理后的数据
@@ -22,41 +25,81 @@ def _replace_1password_values(data, oc):
22
25
  if isinstance(data, dict):
23
26
  result = {}
24
27
  for k, v in data.items():
25
- result[k] = _replace_1password_values(v, oc)
28
+ result[k] = _replace_values(v, oc, jsonfile_path)
26
29
  return result
27
30
  elif isinstance(data, list):
28
- return [_replace_1password_values(item, oc) for item in data]
31
+ return [_replace_values(item, oc, jsonfile_path) for item in data]
29
32
  elif isinstance(data, str):
30
33
  # 处理 1password,item_id,field_name 格式
31
- if data.startswith("1password,"):
34
+ if data.startswith("1password,") and oc:
32
35
  parts = data.split(",")
33
36
  if len(parts) >= 3:
34
37
  item_id = parts[1]
35
38
  field_name = parts[2]
36
- # 通过 item_id 获取项目,然后从字段中提取对应值
37
- item = oc.get_item(item_id)
38
- for field in item.fields:
39
- if field.label == field_name:
40
- return field.value
39
+ try:
40
+ # 通过 item_id 获取项目,然后从字段中提取对应值
41
+ item = oc.get_item(item_id)
42
+ for field in item.fields:
43
+ if field.label == field_name:
44
+ return field.value
45
+ except (AttributeError, KeyError, ValueError):
46
+ pass
41
47
  return data # 如果找不到字段,返回原始值
42
48
  # 处理 password,item_id,field_name 格式
43
- elif data.startswith("password,"):
49
+ elif data.startswith("password,") and oc:
44
50
  parts = data.split(",")
45
51
  if len(parts) >= 3:
46
52
  item_id = parts[1]
47
53
  field_name = parts[2]
48
- # 通过 item_id 获取项目,然后从字段中提取对应值
49
- item = oc.get_item(item_id)
50
- for field in item.fields:
51
- if field.label == field_name:
52
- return field.value
54
+ try:
55
+ # 通过 item_id 获取项目,然后从字段中提取对应值
56
+ item = oc.get_item(item_id)
57
+ for field in item.fields:
58
+ if field.label == field_name:
59
+ return field.value
60
+ except (AttributeError, KeyError, ValueError):
61
+ pass
53
62
  return data # 如果找不到字段,返回原始值
63
+ # 处理 jsonfile,key 格式
64
+ elif data.startswith("jsonfile,"):
65
+ parts = data.split(",", 1) # 只分割一次,防止 key 中包含逗号
66
+ if len(parts) >= 2:
67
+ key = parts[1]
68
+
69
+ # 尝试从 JSON 文件获取值
70
+ if jsonfile_path and os.path.exists(jsonfile_path):
71
+ try:
72
+ with open(jsonfile_path, 'r', encoding='utf-8') as f:
73
+ json_data = json.load(f)
74
+ # 支持嵌套键,如 "db.password"
75
+ value = json_data
76
+ for k in key.split('.'):
77
+ if isinstance(value, dict) and k in value:
78
+ value = value[k]
79
+ else:
80
+ value = None
81
+ break
82
+ if value is not None:
83
+ return value
84
+ except (json.JSONDecodeError, FileNotFoundError, KeyError):
85
+ pass
86
+
87
+ # 如果从 JSON 文件获取失败,尝试从环境变量获取
88
+ env_value = os.getenv(key)
89
+ if env_value is not None:
90
+ return env_value
91
+
92
+ return data # 如果都获取不到,返回原始值
54
93
  return data
55
94
  else:
56
95
  return data
57
96
 
58
97
 
59
- def load_config_by_file(path: str='/workspaces/pytbox/src/pytbox/alert/config/config.toml', oc_vault_id: str=None) -> dict:
98
+ def load_config_by_file(
99
+ path: str='/workspaces/pytbox/src/pytbox/alert/config/config.toml',
100
+ oc_vault_id: str=None,
101
+ jsonfile: str="/data/jsonfile.json",
102
+ ) -> dict:
60
103
  '''
61
104
  从文件加载配置,支持 1password 集成
62
105
 
@@ -68,17 +111,20 @@ def load_config_by_file(path: str='/workspaces/pytbox/src/pytbox/alert/config/co
68
111
  dict: 配置字典
69
112
  '''
70
113
  with open(path, 'r', encoding='utf-8') as f:
71
- if path.endswith('.toml'):
114
+ if path.endswith('.toml'):
72
115
  config = toml.load(f)
73
116
  else:
74
117
  # 如果不是 toml 文件,假设是其他格式,这里可以扩展
75
- import json
76
118
  config = json.load(f)
77
119
 
120
+ # 处理配置值替换
121
+ oc = None
78
122
  if oc_vault_id:
79
123
  oc = OnePasswordConnect(vault_id=oc_vault_id)
80
- config = _replace_1password_values(config, oc)
81
-
124
+
125
+ # 替换配置中的特殊值(1password, password, jsonfile)
126
+ config = _replace_values(config, oc, jsonfile)
127
+
82
128
  return config
83
129
 
84
130
 
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import json
4
+ from pytbox.utils.response import ReturnResponse
5
+
6
+
7
+ def load_dev_file(file_path: str) -> ReturnResponse:
8
+ """从开发环境文件加载数据并返回 ReturnResponse 对象
9
+
10
+ Args:
11
+ file_path: JSON 文件路径
12
+
13
+ Returns:
14
+ ReturnResponse: 包装后的响应对象
15
+ """
16
+ try:
17
+ with open(file_path, 'r', encoding='utf-8') as f:
18
+ data = json.load(f)
19
+
20
+ # 如果已经是 ReturnResponse 格式的字典,直接转换
21
+ if isinstance(data, dict) and 'code' in data and 'msg' in data:
22
+ return ReturnResponse(
23
+ code=data.get('code', 0),
24
+ msg=data.get('msg', ''),
25
+ data=data.get('data', None)
26
+ )
27
+ else:
28
+ # 如果是其他格式,包装成成功响应
29
+ return ReturnResponse(
30
+ code=0,
31
+ msg='开发文件加载成功',
32
+ data=data
33
+ )
34
+ except FileNotFoundError:
35
+ return ReturnResponse(
36
+ code=4,
37
+ msg=f'开发文件未找到: {file_path}',
38
+ data=None
39
+ )
40
+ except json.JSONDecodeError as e:
41
+ return ReturnResponse(
42
+ code=1,
43
+ msg=f'JSON 解析错误: {str(e)}',
44
+ data=None
45
+ )
pytbox/utils/richutils.py CHANGED
@@ -4,6 +4,7 @@
4
4
  from typing import Literal
5
5
  from rich.console import Console
6
6
  from rich.theme import Theme
7
+ from rich.prompt import Prompt
7
8
 
8
9
 
9
10
  class RichUtils:
@@ -18,4 +19,13 @@ class RichUtils:
18
19
 
19
20
 
20
21
  def print(self, msg: str, style: Literal['info', 'warning', 'danger']='info'):
21
- self.console.print(msg, style=style)
22
+ self.console.print(msg, style=style)
23
+
24
+ def ask(self, msg: str="是否继续操作?", choices: list[str]=["Y", "N", "CANCEL"], default: str='N', show_choices: bool=True):
25
+ choice = Prompt.ask(
26
+ f"[bold cyan]{msg}[/bold cyan]",
27
+ choices=choices,
28
+ default=default,
29
+ show_choices=show_choices,
30
+ )
31
+ return choice
pytbox/utils/timeutils.py CHANGED
@@ -120,24 +120,6 @@ class TimeUtils:
120
120
  dt = datetime.datetime.strptime(timestr_fixed, "%Y-%m-%dT%H:%M:%S%z")
121
121
  # 返回秒级时间戳
122
122
  return int(dt.timestamp()) * 1000
123
-
124
- @staticmethod
125
- def convert_str_to_datetime_lg_backup(time_str: str):
126
- """
127
- 将 '7/10/2025 3:52:43 PM' 这种格式的时间字符串转换为时间戳(秒级)。
128
-
129
- Args:
130
- time_str (str): 时间字符串,格式如 '7/10/2025 3:52:43 PM'
131
-
132
- Returns:
133
- int: 时间戳(秒级)
134
- """
135
- if time_str is None:
136
- return None
137
- # 先将字符串转换为 datetime 对象
138
- dt = datetime.datetime.strptime(time_str, "%m/%d/%Y %I:%M:%S %p")
139
- # 返回秒级时间戳
140
- return int(dt.timestamp()) * 1000
141
123
 
142
124
  @staticmethod
143
125
  def convert_timestamp_to_str(timestamp: int, time_format: Literal['%Y-%m-%d %H:%M:%S', '%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M:%S.000Z']='%Y-%m-%d %H:%M:%S', timezone_offset: int=8):
@@ -286,29 +268,6 @@ class TimeUtils:
286
268
  def get_today_timestamp() -> int:
287
269
  return int(time.time()) * 1000
288
270
 
289
- @staticmethod
290
- def convert_str_to_datetime(time_str: str, app: Literal['lg_alert_trigger', 'lg_alert_resolved', 'mongo']='lg_alert_trigger') -> datetime.datetime:
291
- """
292
- 将字符串转换为datetime对象
293
-
294
- Args:
295
- time_str (str): 时间字符串
296
- app (Literal['lg_alert_trigger', 'lg_alert_resolved', 'mongo'], optional): 应用类型. Defaults to 'lg_alert_trigger'.
297
-
298
- Returns:
299
- datetime.datetime: 带时区信息的datetime对象
300
- """
301
- if app == 'lg_alert_trigger':
302
- time_obj = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
303
- elif app == 'lg_alert_resolved':
304
- time_obj = datetime.datetime.strptime(time_str, "%Y年%m月%d日 %H:%M:%S")
305
- elif app == 'mongo':
306
- time_obj = datetime.datetime.fromisoformat(time_str.replace('Z', '+00:00'))
307
- return time_obj # 已经包含时区信息,直接返回
308
-
309
- # 对于没有时区信息的时间对象,设置为Asia/Shanghai时区
310
- time_with_tz = time_obj.replace(tzinfo=ZoneInfo("Asia/Shanghai"))
311
- return time_with_tz
312
271
 
313
272
  @staticmethod
314
273
  def convert_timeobj_to_str(timeobj: str=None, timezone_offset: int=8, time_format: Literal['%Y-%m-%d %H:%M:%S', '%Y-%m-%dT%H:%M:%SZ']='%Y-%m-%d %H:%M:%S'):
@@ -511,21 +470,6 @@ class TimeUtils:
511
470
  # weekday()方法返回0-6的数字,0表示周一,6表示周日
512
471
  return now.weekday() + 1 + offset
513
472
 
514
- @staticmethod
515
- def get_week_of_year(customer: Literal['lululemon', 'other']='other') -> tuple[int, int]:
516
- '''
517
- 获取今天是哪一年的第几周
518
-
519
- Returns:
520
- tuple[int, int]: 返回一个元组,包含(年份, 周数)
521
- '''
522
- now = datetime.datetime.now()
523
- # isocalendar()方法返回一个元组,包含年份、周数和周几
524
- _year, week, _ = now.isocalendar()
525
- if customer == 'lululemon':
526
- week = week - 5
527
- return _year, week
528
-
529
473
  @staticmethod
530
474
  def get_last_month_start_and_end_time() -> tuple[datetime.datetime, datetime.datetime]:
531
475
  '''
@@ -544,4 +488,18 @@ class TimeUtils:
544
488
  # 获取上个月的最后一天
545
489
  end_time = first_day_of_current_month - datetime.timedelta(days=1)
546
490
  end_time = end_time.replace(hour=23, minute=59, second=59, microsecond=0)
547
- return start_time.strftime("%Y-%m-%dT%H:%M:%SZ"), end_time.strftime("%Y-%m-%dT%H:%M:%SZ")
491
+ return start_time.strftime("%Y-%m-%dT%H:%M:%SZ"), end_time.strftime("%Y-%m-%dT%H:%M:%SZ")
492
+
493
+ @staticmethod
494
+ def convert_rfc3339_to_unix_ms(ts_str: str) -> int:
495
+ """
496
+ 将 RFC3339 格式的时间字符串转换为毫秒级时间戳
497
+
498
+ Args:
499
+ ts_str (str): RFC3339 格式的时间字符串
500
+
501
+ Returns:
502
+ int: 毫秒级时间戳
503
+ """
504
+ dt = datetime.datetime.fromisoformat(ts_str.replace("Z", "+00:00"))
505
+ return int(dt.timestamp() * 1000)
pytbox/vmware.py ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ from typing import Any, Dict, Optional, Union, Literal
5
+ import urllib3
6
+ urllib3.disable_warnings()
7
+ import requests
8
+ from requests.auth import HTTPBasicAuth
9
+
10
+ from .utils.response import ReturnResponse
11
+
12
+
13
+ class VMwareClient:
14
+ """VMware vSphere Automation API 客户端。
15
+
16
+ 支持多种认证方式:
17
+ 1. Basic Auth - HTTP 基础认证
18
+ 2. API Key Auth - 使用会话 ID 认证
19
+ 3. Federated Identity Auth - 联合身份认证(Bearer Token)
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ host: str=None,
25
+ username: str=None,
26
+ password: str=None,
27
+ version: Literal['6.7', '7.0']='6.7',
28
+ proxies: dict=None,
29
+ verify_ssl: bool = False,
30
+ timeout: int = 30,
31
+ ) -> None:
32
+ """初始化 VMware 客户端。
33
+
34
+ Args:
35
+ host: vCenter Server 主机地址(例如:https://vcenter.example.com)
36
+ verify_ssl: 是否验证 SSL 证书
37
+ timeout: 请求超时时间(秒)
38
+ proxy_host: 代理服务器主机地址
39
+ proxy_port: 代理服务器端口
40
+ proxy_username: 代理认证用户名(可选)
41
+ proxy_password: 代理认证密码(可选)
42
+ """
43
+ self.host = host
44
+ self.username = username
45
+ self.password = password
46
+ self.version = version
47
+ self.proxies = proxies
48
+ self.verify_ssl = verify_ssl
49
+ self.timeout = timeout
50
+ self.session_id: Optional[str] = None
51
+
52
+ self.headers = {
53
+ "vmware-api-session-id": self.get_session()
54
+ }
55
+
56
+ def get_session(self) -> str:
57
+ """获取 VMware vSphere API 会话 ID。
58
+
59
+ Returns:
60
+ 会话 ID 字符串
61
+ """
62
+ if self.version == '6.7':
63
+ url = f"{self.host}/rest/com/vmware/cis/session"
64
+ else:
65
+ url = f"{self.host}/api/session"
66
+
67
+ response = requests.post(
68
+ url,
69
+ auth=HTTPBasicAuth(self.username, self.password),
70
+ timeout=self.timeout,
71
+ verify=self.verify_ssl,
72
+ proxies=self.proxies
73
+ )
74
+
75
+ if response.status_code == 200 or response.status_code == 201:
76
+ # vSphere API 通常直接返回 session ID 字符串
77
+ session_id = response.json()
78
+ try:
79
+ return session_id['value']
80
+ except Exception:
81
+ return session_id
82
+ else:
83
+ return f"认证失败: {response.status_code} - {response.text}"
84
+
85
+ def get_vm_list(self) -> ReturnResponse:
86
+ '''
87
+ _summary_
88
+
89
+ Returns:
90
+ ReturnResponse: _description_
91
+ '''
92
+ if self.version == '6.7':
93
+ url = f"{self.host}/rest/vcenter/vm"
94
+ else:
95
+ url = f"{self.host}/api/vcenter/vm"
96
+ response = requests.get(url, headers=self.headers, timeout=self.timeout, verify=False, proxies=self.proxies)
97
+ if response.status_code == 200:
98
+ if self.version == '6.7':
99
+ data = response.json().get('value')
100
+ else:
101
+ data = response.json()
102
+ return ReturnResponse(code=0, msg=f'成功获取到 {len(data)} 台虚拟机', data=data)
103
+ else:
104
+ return ReturnResponse(code=1, msg='error', data=response.json())
105
+
106
+ def get_vm(self, vm_id):
107
+ if self.version == '6.7':
108
+ url = f"{self.host}/rest/vcenter/vm/{vm_id}"
109
+ else:
110
+ url = f"{self.host}/api/vcenter/vm/{vm_id}"
111
+ response = requests.get(url, headers=self.headers, timeout=self.timeout, verify=False, proxies=self.proxies)
112
+ if response.status_code == 200:
113
+ return ReturnResponse(code=0, msg='成功获取到虚拟机', data=response.json())
114
+ else:
115
+ return ReturnResponse(code=1, msg=f"{response.status_code}, {response.text}", data=response.json())
116
+
117
+ # 使用示例
118
+ if __name__ == "__main__":
119
+ pass
120
+
pytbox/win/ad.py ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ from ldap3 import Server, Connection, ALL, SUBTREE, MODIFY_REPLACE, SUBTREE, MODIFY_ADD, MODIFY_DELETE
5
+
6
+
7
+ class ADClient:
8
+ '''
9
+ _summary_
10
+ '''
11
+ def __init__(self, server, base_dn, username, password):
12
+ self.server = Server(server, get_info=ALL)
13
+ self.conn = Connection(self.server, user=username, password=password, auto_bind=True)
14
+ self.base_dn = base_dn
15
+
16
+ def list_user(self):
17
+ '''
18
+ 查询所有用户
19
+
20
+ Yields:
21
+ dict: 返回的是生成器, 字典类型
22
+ '''
23
+ # 搜索过滤条件
24
+ secarch_filter = '(objectCategory=person)' # 过滤所有用户
25
+ # SEARCH_ATTRIBUTES = ['cn', 'sAMAccountName', 'mail', 'userPrincipalName'] # 需要的用户属性
26
+ search_attributes = ["*"] # 需要的用户属性
27
+ # 搜索用户
28
+ if self.conn.search(search_base=self.base_dn, search_filter=secarch_filter, search_scope=SUBTREE, attributes=search_attributes):
29
+ for entry in self.conn.entries:
30
+ yield {k: v[0] if isinstance(v, list) else v for k, v in entry.entry_attributes_as_dict.items()}
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytbox
3
- Version: 0.0.7
3
+ Version: 0.3.1
4
4
  Summary: A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)
5
5
  Author-email: mingming hou <houm01@foxmail.com>
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Requires-Python: >=3.8
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: requests>=2.0
@@ -13,15 +13,18 @@ Requires-Dist: loguru>=0.7.3
13
13
  Requires-Dist: chinese_calendar>=1.10.0
14
14
  Requires-Dist: click>=8.0.0
15
15
  Requires-Dist: rich>=12.0.0
16
+ Requires-Dist: jinja2>=3.0.0
17
+ Requires-Dist: toml>=0.10.0
18
+ Requires-Dist: ldap3>=2.9.1
19
+ Requires-Dist: imap-tools>=1.11.0
20
+ Requires-Dist: yagmail>=0.15.293
16
21
  Provides-Extra: dev
17
22
  Requires-Dist: pytest; extra == "dev"
18
23
  Requires-Dist: black; extra == "dev"
19
24
  Requires-Dist: ruff; extra == "dev"
20
25
  Requires-Dist: python-dotenv; extra == "dev"
21
26
  Provides-Extra: cli
22
- Requires-Dist: jinja2>=3.0.0; extra == "cli"
23
27
  Requires-Dist: pyyaml>=6.0; extra == "cli"
24
- Requires-Dist: toml>=0.10.0; extra == "cli"
25
28
 
26
29
  # PytBox
27
30
 
@@ -0,0 +1,72 @@
1
+ pytbox/base.py,sha256=WC_p_PYMMpNq-5JRLyZoD74k-d2EQVmO4VjTvnI7VqE,4541
2
+ pytbox/cli.py,sha256=N775a0GK80IT2lQC2KRYtkZpIiu9UjavZmaxgNUgJhQ,160
3
+ pytbox/dida365.py,sha256=pUMPB9AyLZpTTbaz2LbtzdEpyjvuGf4YlRrCvM5sbJo,10545
4
+ pytbox/excel.py,sha256=f5XBLCeJbGgxytoSwVhbk03WLTzz8Q3IJ_RZ2-r_w6A,2334
5
+ pytbox/mingdao.py,sha256=afEFJ9NKPdsmAZ4trBEJKl66fMj3Z8TWfaOcomNGhzw,6042
6
+ pytbox/notion.py,sha256=GRPdZAtyG2I6M6pCFbdrTWDACaPsp1RAXrY_RpWYKus,26572
7
+ pytbox/onepassword_connect.py,sha256=nD3xTl1ykQ4ct_dCRRF138gXCtk-phPfKYXuOn-P7Z8,3064
8
+ pytbox/onepassword_sa.py,sha256=08iUcYud3aEHuQcUsem9bWNxdXKgaxFbMy9yvtr-DZQ,6995
9
+ pytbox/pyjira.py,sha256=Str9f7qTeBuy8XtJq2bXBI9ib79aQYCHBlJP1QKtZeo,24605
10
+ pytbox/vmware.py,sha256=WiH67_3-VCBjXJuh3UueOc31BdZDItiZhkeuPzoRhw4,3975
11
+ pytbox/alert/alert_handler.py,sha256=WCn4cKahv5G5BFGgmc7dX7BQ38h2kxTgxfRVTwc1O2M,6579
12
+ pytbox/alert/ping.py,sha256=KEnnXdIRJHvR_rEHPWLBt0wz4cGwmA29Lenlak3Z_1Y,778
13
+ pytbox/alicloud/sls.py,sha256=-r6rbCwDUQ4jwAgSVSNu7B2h1MNg20CrRIKnlXVeY9w,4159
14
+ pytbox/categraf/build_config.py,sha256=9G85rLqkz3lchpH7ef0LbvckYHl0nRA6mHVLeUfs9Mw,6308
15
+ pytbox/categraf/instances.toml,sha256=jcJyEaqhohUcECczWArxUK4t0-rdk4vmrX21kxZlSLA,1254
16
+ pytbox/categraf/jinja2/__init__.py,sha256=Epm01j8Oujeg4Sk5GgHMvgKIZ6h3BTx-MGmuMgIjUMo,150
17
+ pytbox/categraf/jinja2/input.cpu/cpu.toml.j2,sha256=wxpyLDNvz2ViZK-0a4EgH35Zsg82CwMwijOtT0nBfTI,92
18
+ pytbox/categraf/jinja2/input.disk/disk.toml.j2,sha256=kOWwVF6u7x2huLVa4eBIOhC8R13DXmw0PD9o3HXwEZo,420
19
+ pytbox/categraf/jinja2/input.diskio/diskio.toml.j2,sha256=33E4L1mkUkJOocUsSgpW5zoFCzvx5ogfbnm2jkwzLx8,227
20
+ pytbox/categraf/jinja2/input.dns_query/dns_query.toml.j2,sha256=-oMkIMtCg4zq_oGENrm9aUzUzVkWmgxPSrGlwo2k2Pc,461
21
+ pytbox/categraf/jinja2/input.http_response/http_response.toml.j2,sha256=Qp1EOxx7TC7_cH69KqMVwbfCKrD5xbbVO2drVdkvo6s,317
22
+ pytbox/categraf/jinja2/input.mem/mem.toml.j2,sha256=_-qJyE0K_76IMehbN1xq1hi9vY1Y1Jp4TuITzaLjCg4,116
23
+ pytbox/categraf/jinja2/input.net/net.toml.j2,sha256=yodVoT1f7bcuNMFFmAvc7WhORUsTnM92IhpWQHXfY_U,279
24
+ pytbox/categraf/jinja2/input.net_response/net_response.toml.j2,sha256=Qp1EOxx7TC7_cH69KqMVwbfCKrD5xbbVO2drVdkvo6s,317
25
+ pytbox/categraf/jinja2/input.ping/ping.toml.j2,sha256=UCRy_IVoI_FDQxfsDpGS-aZJasFG1sf67ScN9U8YVIo,344
26
+ pytbox/categraf/jinja2/input.prometheus/prometheus.toml.j2,sha256=6ax30L1sAUreojlzf0v26GzOAiheCP0Lj7n5IIjgco0,384
27
+ pytbox/categraf/jinja2/input.snmp/cisco_interface.toml.j2,sha256=0u7eEoi4Q_NB8nnujq8a424r7GNB1eR8J3DToOhwWeQ,1941
28
+ pytbox/categraf/jinja2/input.snmp/cisco_system.toml.j2,sha256=DMJSEouhyGu54BIxehzsHQnnMgPHjnTweuVG0Y5iIw4,925
29
+ pytbox/categraf/jinja2/input.snmp/h3c_interface.toml.j2,sha256=0u7eEoi4Q_NB8nnujq8a424r7GNB1eR8J3DToOhwWeQ,1941
30
+ pytbox/categraf/jinja2/input.snmp/h3c_system.toml.j2,sha256=DMJSEouhyGu54BIxehzsHQnnMgPHjnTweuVG0Y5iIw4,925
31
+ pytbox/categraf/jinja2/input.snmp/huawei_interface.toml.j2,sha256=0u7eEoi4Q_NB8nnujq8a424r7GNB1eR8J3DToOhwWeQ,1941
32
+ pytbox/categraf/jinja2/input.snmp/huawei_system.toml.j2,sha256=DMJSEouhyGu54BIxehzsHQnnMgPHjnTweuVG0Y5iIw4,925
33
+ pytbox/categraf/jinja2/input.snmp/ruijie_interface.toml.j2,sha256=0u7eEoi4Q_NB8nnujq8a424r7GNB1eR8J3DToOhwWeQ,1941
34
+ pytbox/categraf/jinja2/input.snmp/ruijie_system.toml.j2,sha256=DMJSEouhyGu54BIxehzsHQnnMgPHjnTweuVG0Y5iIw4,925
35
+ pytbox/categraf/jinja2/input.vsphere/vsphere.toml.j2,sha256=7SCo8DSh5Uuy-7MeWw-soy6sqblK54k6K2WWSlimELk,8396
36
+ pytbox/cli/__init__.py,sha256=5ID4-oXrMsHFcfDsQeXDYeThPOuQ1Fl2x2kHWfgfOEw,67
37
+ pytbox/cli/main.py,sha256=CywsgiwQepM-mTGTnmDLcr9LHLhC2EYluCDU5NONFZI,394
38
+ pytbox/cli/categraf/__init__.py,sha256=HfhDhWiWEuT5e6fXb6fs7UgoZPwn9WQ1wdFoza2muaI,96
39
+ pytbox/cli/categraf/commands.py,sha256=M-coJaHhb5I9fMW7OMWe9SMrs_RmSm4hSIJ1CPS0Ipc,1874
40
+ pytbox/cli/commands/vm.py,sha256=K3Jf7dFI493raB5v4-SUmnUisVpfX1aQqOZkE5hDE60,559
41
+ pytbox/cli/common/__init__.py,sha256=1_OE4q6OIUQkpwXBWqiKHr7SXxEu925hRgmd2hulIy4,70
42
+ pytbox/cli/common/options.py,sha256=Xv1wXja-fdaQVY6_FzvYRrXDozeTOJV6BL8zYIKJE9k,773
43
+ pytbox/cli/common/utils.py,sha256=0uQ5L1l5cySFheixB91B9ptq0p6tGsBhqvvm3ouRGbI,9050
44
+ pytbox/cli/formatters/__init__.py,sha256=4o85w4j-A-O1oBLvuE9q8AFiJ2C9rvB3MIKsy5VvdfQ,101
45
+ pytbox/cli/formatters/output.py,sha256=h5WhZlQk1rjmxEj88Jy5ODLcv6L5zfGUhks_3AWIkKU,5455
46
+ pytbox/common/__init__.py,sha256=3JWfgCQZKZuSH5NCE7OCzKwq82pkyop9l7sH5YSNyfU,122
47
+ pytbox/database/mongo.py,sha256=AhJ9nCAQHKrrcL-ujeonOwEf3x2QkmT2VhoCdglqJmU,3478
48
+ pytbox/database/victoriametrics.py,sha256=iSgYLcINpWK3ry1fWoL32k65j91Ag49kNBWXYxW3NKA,15750
49
+ pytbox/feishu/client.py,sha256=kwGLseGT_iQUFmSqpuS2_77WmxtHstD64nXvktuQ3B4,5865
50
+ pytbox/feishu/endpoints.py,sha256=z3nPOZPC2JGDJlO7SusWBpRA33hZZ4Z-GBhI6F8L_u4,40240
51
+ pytbox/feishu/errors.py,sha256=79qFAHZw7jDj3gnWAjI1-W4tB0q1_aSfdjee4xzXeuI,1179
52
+ pytbox/feishu/helpers.py,sha256=jhSkHiUw4822QBXx2Jw8AksogZdakZ-3QqvC3lB3qEI,201
53
+ pytbox/feishu/typing.py,sha256=3hWkJgOi-v2bt9viMxkyvNHsPgrbAa0aZOxsZYg2vdM,122
54
+ pytbox/log/logger.py,sha256=t5LEvuYTDixh67JOyX0ke1ukb9kT5PEaUSsQnDDck90,8921
55
+ pytbox/log/victorialog.py,sha256=gffEiq38adv9sC5oZeMcyKghd3SGfRuqtZOFuqHQF6E,4139
56
+ pytbox/mail/alimail.py,sha256=njKA3PUbIaiKFaxKvUObmklmEEHg2YA-O5rpgsgT5_w,5147
57
+ pytbox/mail/client.py,sha256=RNgWhhTXFTpD43U4p7hbmnfRdmltuZmbm890gaZTzhI,6278
58
+ pytbox/mail/mail_detail.py,sha256=6u8DK-7WzYPSuX6TdicSCh2Os_9Ou6Rn9xc6WRvv85M,699
59
+ pytbox/network/meraki.py,sha256=OdT5PWNYiPcJfsQ4tMkjKSE22EH1xBHHG-vuv0L4jM8,20064
60
+ pytbox/utils/cronjob.py,sha256=b17CY1fmaFTdQojicXAXHliov_JZdmT7cZhtO4v5sCo,3080
61
+ pytbox/utils/env.py,sha256=gD2-NyL3K3Vg1B1eGeD1hRtlSHPGgF8Oi9mchuQL6_o,646
62
+ pytbox/utils/load_config.py,sha256=R4pGerBinbewsym41hQ8Z-I5I7gepuEKODjIrli4C08,5043
63
+ pytbox/utils/load_vm_devfile.py,sha256=GVbB-FvGb0l586SDaraz__ZaXyDWd1WxcXVw5xGfXWw,1328
64
+ pytbox/utils/response.py,sha256=kXjlwt0WVmLRam2eu1shzX2cQ7ux4cCQryaPGYwle5g,1247
65
+ pytbox/utils/richutils.py,sha256=Qy7DB8dowt2lINp07RfDCyd8EXpbdvlKslVnjiMn-5o,863
66
+ pytbox/utils/timeutils.py,sha256=YqPZC3DVm0RjIxesBZQfKkT6LlJcuJy1a1r3rHMveng,18366
67
+ pytbox/win/ad.py,sha256=-3pWfL3dElz-XoO4j4M9lrgu3KJtlhrS9gCWJBpafAU,1147
68
+ pytbox-0.3.1.dist-info/METADATA,sha256=2JNJeSTV8TvbLWDcbgalpqYnhBsbXzHspe-ORSksCyI,6319
69
+ pytbox-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
+ pytbox-0.3.1.dist-info/entry_points.txt,sha256=YaTOJ2oPjOiv2SZwY0UC-UA9QS2phRH1oMvxGnxO0Js,43
71
+ pytbox-0.3.1.dist-info/top_level.txt,sha256=YADgWue-Oe128ptN3J2hS3GB0Ncc5uZaSUM3e1rwswE,7
72
+ pytbox-0.3.1.dist-info/RECORD,,
@@ -1 +0,0 @@
1
-
@@ -1,39 +0,0 @@
1
- pytbox/base.py,sha256=_SpfeIiJE4xbQMsYghnMehcNzHP-mBfrKONX43b0OQk,1490
2
- pytbox/cli.py,sha256=N775a0GK80IT2lQC2KRYtkZpIiu9UjavZmaxgNUgJhQ,160
3
- pytbox/dida365.py,sha256=pUMPB9AyLZpTTbaz2LbtzdEpyjvuGf4YlRrCvM5sbJo,10545
4
- pytbox/onepassword_connect.py,sha256=nD3xTl1ykQ4ct_dCRRF138gXCtk-phPfKYXuOn-P7Z8,3064
5
- pytbox/onepassword_sa.py,sha256=08iUcYud3aEHuQcUsem9bWNxdXKgaxFbMy9yvtr-DZQ,6995
6
- pytbox/alert/alert_handler.py,sha256=FePPQS4LyGphSJ0QMv0_pLWaXxEqsRlcTKMfUjtsNfk,5048
7
- pytbox/alert/ping.py,sha256=g36X0U3U8ndZqfpVIcuoxJJ0X5gST3I_IwjTQC1roHA,779
8
- pytbox/alicloud/sls.py,sha256=UR4GdI86dCKAFI2xt_1DELu7q743dpd3xrYtuNpfC5A,4065
9
- pytbox/categraf/build_config.py,sha256=DBBKjqCJZ3a6BbVuJbN_C573Z-K3p43iDbB9Ahaw3Tw,2944
10
- pytbox/cli/__init__.py,sha256=5ID4-oXrMsHFcfDsQeXDYeThPOuQ1Fl2x2kHWfgfOEw,67
11
- pytbox/cli/main.py,sha256=S-DBp-1d0BCpvZ7jRE3bYmhKSiPpCJHFGsbdVF485BY,322
12
- pytbox/cli/categraf/__init__.py,sha256=HfhDhWiWEuT5e6fXb6fs7UgoZPwn9WQ1wdFoza2muaI,96
13
- pytbox/cli/categraf/commands.py,sha256=M-coJaHhb5I9fMW7OMWe9SMrs_RmSm4hSIJ1CPS0Ipc,1874
14
- pytbox/cli/common/__init__.py,sha256=1_OE4q6OIUQkpwXBWqiKHr7SXxEu925hRgmd2hulIy4,70
15
- pytbox/cli/common/options.py,sha256=Xv1wXja-fdaQVY6_FzvYRrXDozeTOJV6BL8zYIKJE9k,773
16
- pytbox/cli/common/utils.py,sha256=0uQ5L1l5cySFheixB91B9ptq0p6tGsBhqvvm3ouRGbI,9050
17
- pytbox/cli/formatters/__init__.py,sha256=4o85w4j-A-O1oBLvuE9q8AFiJ2C9rvB3MIKsy5VvdfQ,101
18
- pytbox/cli/formatters/output.py,sha256=h5WhZlQk1rjmxEj88Jy5ODLcv6L5zfGUhks_3AWIkKU,5455
19
- pytbox/common/__init__.py,sha256=3JWfgCQZKZuSH5NCE7OCzKwq82pkyop9l7sH5YSNyfU,122
20
- pytbox/database/mongo.py,sha256=CSpHC7iR-M0BaVxXz5j6iXjMKPgXJX_G7MrjCj5Gm8Q,3478
21
- pytbox/database/victoriametrics.py,sha256=PfeshtlgZNfbiq7Fo4ibJruWYeAKryBXu8ckl8YC1jM,4389
22
- pytbox/feishu/client.py,sha256=kwGLseGT_iQUFmSqpuS2_77WmxtHstD64nXvktuQ3B4,5865
23
- pytbox/feishu/endpoints.py,sha256=KmLB7yq0mpJgkWsTgGCufrejrPGV6JP0_p1GE6Pp4yI,40264
24
- pytbox/feishu/errors.py,sha256=79qFAHZw7jDj3gnWAjI1-W4tB0q1_aSfdjee4xzXeuI,1179
25
- pytbox/feishu/helpers.py,sha256=jhSkHiUw4822QBXx2Jw8AksogZdakZ-3QqvC3lB3qEI,201
26
- pytbox/feishu/typing.py,sha256=3hWkJgOi-v2bt9viMxkyvNHsPgrbAa0aZOxsZYg2vdM,122
27
- pytbox/log/logger.py,sha256=7ZisXRxLb_MVbIqlYHWoTbj1EA0Z4G5SZvITlt1IKW8,7416
28
- pytbox/log/victorialog.py,sha256=gffEiq38adv9sC5oZeMcyKghd3SGfRuqtZOFuqHQF6E,4139
29
- pytbox/utils/env.py,sha256=jO_-BKbGuDU7lIL9KYkcxGCzQwTXfxD4mIYtSAjREmI,622
30
- pytbox/utils/load_config.py,sha256=wNCDPLH7xet5b9pUlTz6VsBejRsJZ7LP85wWMaITBYg,3042
31
- pytbox/utils/ping_checker.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
32
- pytbox/utils/response.py,sha256=kXjlwt0WVmLRam2eu1shzX2cQ7ux4cCQryaPGYwle5g,1247
33
- pytbox/utils/richutils.py,sha256=OT9_q2Q1bthzB0g1GlhZVvM4ZAepJRKL6a_Vsr6vEqo,487
34
- pytbox/utils/timeutils.py,sha256=XbK2KB-SVi7agNqoQN7i40wysrZvrGuwebViv1Cw-Ok,20226
35
- pytbox-0.0.7.dist-info/METADATA,sha256=veBpwrGnlKlCI5E9XVzVYmW2dVsLQXqSgeMXe0F2cXU,6245
36
- pytbox-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- pytbox-0.0.7.dist-info/entry_points.txt,sha256=YaTOJ2oPjOiv2SZwY0UC-UA9QS2phRH1oMvxGnxO0Js,43
38
- pytbox-0.0.7.dist-info/top_level.txt,sha256=YADgWue-Oe128ptN3J2hS3GB0Ncc5uZaSUM3e1rwswE,7
39
- pytbox-0.0.7.dist-info/RECORD,,
File without changes