infomankit 0.3.23__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.
Files changed (143) hide show
  1. infoman/__init__.py +1 -0
  2. infoman/cli/README.md +378 -0
  3. infoman/cli/__init__.py +7 -0
  4. infoman/cli/commands/__init__.py +3 -0
  5. infoman/cli/commands/init.py +312 -0
  6. infoman/cli/scaffold.py +634 -0
  7. infoman/cli/templates/Makefile.template +132 -0
  8. infoman/cli/templates/app/__init__.py.template +3 -0
  9. infoman/cli/templates/app/app.py.template +4 -0
  10. infoman/cli/templates/app/models_base.py.template +18 -0
  11. infoman/cli/templates/app/models_entity_init.py.template +11 -0
  12. infoman/cli/templates/app/models_schemas_init.py.template +11 -0
  13. infoman/cli/templates/app/repository_init.py.template +11 -0
  14. infoman/cli/templates/app/routers_init.py.template +15 -0
  15. infoman/cli/templates/app/services_init.py.template +11 -0
  16. infoman/cli/templates/app/static_index.html.template +39 -0
  17. infoman/cli/templates/app/static_main.js.template +31 -0
  18. infoman/cli/templates/app/static_style.css.template +111 -0
  19. infoman/cli/templates/app/utils_init.py.template +11 -0
  20. infoman/cli/templates/config/.env.dev.template +43 -0
  21. infoman/cli/templates/config/.env.prod.template +43 -0
  22. infoman/cli/templates/config/README.md.template +28 -0
  23. infoman/cli/templates/docker/.dockerignore.template +60 -0
  24. infoman/cli/templates/docker/Dockerfile.template +47 -0
  25. infoman/cli/templates/docker/README.md.template +240 -0
  26. infoman/cli/templates/docker/docker-compose.yml.template +81 -0
  27. infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
  28. infoman/cli/templates/docker/mysql_init.sql.template +15 -0
  29. infoman/cli/templates/project/.env.example.template +1 -0
  30. infoman/cli/templates/project/.gitignore.template +60 -0
  31. infoman/cli/templates/project/Makefile.template +38 -0
  32. infoman/cli/templates/project/README.md.template +137 -0
  33. infoman/cli/templates/project/deploy.sh.template +97 -0
  34. infoman/cli/templates/project/main.py.template +10 -0
  35. infoman/cli/templates/project/manage.sh.template +97 -0
  36. infoman/cli/templates/project/pyproject.toml.template +47 -0
  37. infoman/cli/templates/project/service.sh.template +203 -0
  38. infoman/config/__init__.py +25 -0
  39. infoman/config/base.py +67 -0
  40. infoman/config/db_cache.py +237 -0
  41. infoman/config/db_relation.py +181 -0
  42. infoman/config/db_vector.py +39 -0
  43. infoman/config/jwt.py +16 -0
  44. infoman/config/llm.py +16 -0
  45. infoman/config/log.py +627 -0
  46. infoman/config/mq.py +26 -0
  47. infoman/config/settings.py +65 -0
  48. infoman/llm/__init__.py +0 -0
  49. infoman/llm/llm.py +297 -0
  50. infoman/logger/__init__.py +57 -0
  51. infoman/logger/context.py +191 -0
  52. infoman/logger/core.py +358 -0
  53. infoman/logger/filters.py +157 -0
  54. infoman/logger/formatters.py +138 -0
  55. infoman/logger/handlers.py +276 -0
  56. infoman/logger/metrics.py +160 -0
  57. infoman/performance/README.md +583 -0
  58. infoman/performance/__init__.py +19 -0
  59. infoman/performance/cli.py +215 -0
  60. infoman/performance/config.py +166 -0
  61. infoman/performance/reporter.py +519 -0
  62. infoman/performance/runner.py +303 -0
  63. infoman/performance/standards.py +222 -0
  64. infoman/service/__init__.py +8 -0
  65. infoman/service/app.py +67 -0
  66. infoman/service/core/__init__.py +0 -0
  67. infoman/service/core/auth.py +105 -0
  68. infoman/service/core/lifespan.py +132 -0
  69. infoman/service/core/monitor.py +57 -0
  70. infoman/service/core/response.py +37 -0
  71. infoman/service/exception/__init__.py +7 -0
  72. infoman/service/exception/error.py +274 -0
  73. infoman/service/exception/exception.py +25 -0
  74. infoman/service/exception/handler.py +238 -0
  75. infoman/service/infrastructure/__init__.py +8 -0
  76. infoman/service/infrastructure/base.py +212 -0
  77. infoman/service/infrastructure/db_cache/__init__.py +8 -0
  78. infoman/service/infrastructure/db_cache/manager.py +194 -0
  79. infoman/service/infrastructure/db_relation/__init__.py +41 -0
  80. infoman/service/infrastructure/db_relation/manager.py +300 -0
  81. infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
  82. infoman/service/infrastructure/db_relation/mysql.py +52 -0
  83. infoman/service/infrastructure/db_relation/pgsql.py +54 -0
  84. infoman/service/infrastructure/db_relation/sqllite.py +25 -0
  85. infoman/service/infrastructure/db_vector/__init__.py +40 -0
  86. infoman/service/infrastructure/db_vector/manager.py +201 -0
  87. infoman/service/infrastructure/db_vector/qdrant.py +322 -0
  88. infoman/service/infrastructure/mq/__init__.py +15 -0
  89. infoman/service/infrastructure/mq/manager.py +178 -0
  90. infoman/service/infrastructure/mq/nats/__init__.py +0 -0
  91. infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
  92. infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
  93. infoman/service/launch.py +284 -0
  94. infoman/service/middleware/__init__.py +7 -0
  95. infoman/service/middleware/base.py +41 -0
  96. infoman/service/middleware/logging.py +51 -0
  97. infoman/service/middleware/rate_limit.py +301 -0
  98. infoman/service/middleware/request_id.py +21 -0
  99. infoman/service/middleware/white_list.py +24 -0
  100. infoman/service/models/__init__.py +8 -0
  101. infoman/service/models/base.py +441 -0
  102. infoman/service/models/type/embed.py +70 -0
  103. infoman/service/routers/__init__.py +18 -0
  104. infoman/service/routers/health_router.py +311 -0
  105. infoman/service/routers/monitor_router.py +44 -0
  106. infoman/service/utils/__init__.py +8 -0
  107. infoman/service/utils/cache/__init__.py +0 -0
  108. infoman/service/utils/cache/cache.py +192 -0
  109. infoman/service/utils/module_loader.py +10 -0
  110. infoman/service/utils/parse.py +10 -0
  111. infoman/service/utils/resolver/__init__.py +8 -0
  112. infoman/service/utils/resolver/base.py +47 -0
  113. infoman/service/utils/resolver/resp.py +102 -0
  114. infoman/service/vector/__init__.py +20 -0
  115. infoman/service/vector/base.py +56 -0
  116. infoman/service/vector/qdrant.py +125 -0
  117. infoman/service/vector/service.py +67 -0
  118. infoman/utils/__init__.py +2 -0
  119. infoman/utils/decorators/__init__.py +8 -0
  120. infoman/utils/decorators/cache.py +137 -0
  121. infoman/utils/decorators/retry.py +99 -0
  122. infoman/utils/decorators/safe_execute.py +99 -0
  123. infoman/utils/decorators/timing.py +99 -0
  124. infoman/utils/encryption/__init__.py +8 -0
  125. infoman/utils/encryption/aes.py +66 -0
  126. infoman/utils/encryption/ecc.py +108 -0
  127. infoman/utils/encryption/rsa.py +112 -0
  128. infoman/utils/file/__init__.py +0 -0
  129. infoman/utils/file/handler.py +22 -0
  130. infoman/utils/hash/__init__.py +0 -0
  131. infoman/utils/hash/hash.py +61 -0
  132. infoman/utils/http/__init__.py +8 -0
  133. infoman/utils/http/client.py +62 -0
  134. infoman/utils/http/info.py +94 -0
  135. infoman/utils/http/result.py +19 -0
  136. infoman/utils/notification/__init__.py +8 -0
  137. infoman/utils/notification/feishu.py +35 -0
  138. infoman/utils/text/__init__.py +8 -0
  139. infoman/utils/text/extractor.py +111 -0
  140. infomankit-0.3.23.dist-info/METADATA +632 -0
  141. infomankit-0.3.23.dist-info/RECORD +143 -0
  142. infomankit-0.3.23.dist-info/WHEEL +4 -0
  143. infomankit-0.3.23.dist-info/entry_points.txt +5 -0
@@ -0,0 +1,94 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/4/11 18:51
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+ import re
10
+
11
+
12
+ class ClientInfoExtractor:
13
+
14
+ @staticmethod
15
+ def client_ip(request) -> str:
16
+ x_forwarded_for = request.headers.get("X-Forwarded-For")
17
+ if x_forwarded_for:
18
+ client_ip = x_forwarded_for.split(",")[0].strip()
19
+ else:
20
+ client_ip = request.headers.get("X-Real-IP", request.client.host)
21
+ return client_ip or "unknown"
22
+
23
+ @staticmethod
24
+ def user_agent(request) -> str:
25
+ return request.headers.get("User-Agent", "Unknown")
26
+
27
+ @staticmethod
28
+ def time_zone(request) -> str:
29
+ return request.headers.get("TimeZone", "")
30
+
31
+ @staticmethod
32
+ def info(request) -> dict:
33
+ return {
34
+ "ip": ClientInfoExtractor.ip_address(request),
35
+ "timezone": ClientInfoExtractor.time_zone(request),
36
+ "useragent": ClientInfoExtractor.user_agent(request),
37
+ }
38
+
39
+ @staticmethod
40
+ def ip_address(request) -> str:
41
+ cf_connecting_ip = request.headers.get("CF-Connecting-IP")
42
+ if cf_connecting_ip and cf_connecting_ip.strip():
43
+ return cf_connecting_ip.strip()
44
+
45
+ # 2. 部分CDN使用的 True-Client-IP
46
+ true_client_ip = request.headers.get("True-Client-IP")
47
+ if true_client_ip and true_client_ip.strip():
48
+ return true_client_ip.strip()
49
+
50
+ # 3. X-Forwarded-For(可能包含多个IP,格式: client, proxy1, proxy2)
51
+ xff = request.headers.get("X-Forwarded-For")
52
+ if xff:
53
+ ip_list = [ip.strip() for ip in xff.split(",") if ip.strip()]
54
+ for ip in ip_list:
55
+ if not ClientInfoExtractor.is_private_ip(ip):
56
+ return ip
57
+
58
+ # 如果都是内网IP,返回第一个
59
+ if ip_list:
60
+ return ip_list[0]
61
+
62
+ # 4. X-Real-IP(Nginx/Caddy传递的单值IP)
63
+ x_real_ip = request.headers.get("X-Real-IP")
64
+ if x_real_ip and x_real_ip.strip():
65
+ return x_real_ip.strip()
66
+
67
+ # 5. 兜底:直连场景使用 client.host
68
+ fallback_ip = request.client.host if request.client else "unknown"
69
+ return fallback_ip
70
+
71
+
72
+ @staticmethod
73
+ def is_private_ip(ip: str) -> bool:
74
+ """
75
+ 判断是否为内网IP
76
+
77
+ 内网IP段:
78
+ - 127.0.0.0/8 (localhost)
79
+ - 10.0.0.0/8 (私有网络A类)
80
+ - 172.16.0.0/12 (私有网络B类)
81
+ - 192.168.0.0/16 (私有网络C类)
82
+ - ::1 (IPv6 localhost)
83
+ - fc00::/7 (IPv6 私有网络)
84
+ """
85
+ # IPv4 内网IP正则
86
+ ipv4_private_pattern = r"^(127\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)"
87
+ if re.match(ipv4_private_pattern, ip):
88
+ return True
89
+
90
+ # IPv6 内网IP判断
91
+ if ip.startswith("::1") or ip.startswith("fc") or ip.startswith("fd"):
92
+ return True
93
+
94
+ return False
@@ -0,0 +1,19 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/7/29 14:42
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+
10
+
11
+ class HttpResult(object):
12
+
13
+ def __init__(
14
+ self, succeed: bool, content: bytes, text: str = "", message: str = ""
15
+ ):
16
+ self.succeed = succeed
17
+ self.content = content
18
+ self.text = text
19
+ self.message = message
@@ -0,0 +1,8 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/9/29 08:01
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
@@ -0,0 +1,35 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/9/29 08:01
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+ import json
10
+ import aiohttp
11
+ from infoman.logger import logger
12
+
13
+
14
+ class RobotManager(object):
15
+
16
+ @classmethod
17
+ async def publish_message(cls, url, message):
18
+ try:
19
+ headers = {"Content-Type": "application/json"}
20
+ json_data = {"msg_type": "text", "content": {"text": message}}
21
+
22
+ async with aiohttp.ClientSession() as session:
23
+ async with session.post(
24
+ url, headers=headers, data=json.dumps(json_data)
25
+ ) as response:
26
+ if response.status == 200:
27
+ logger.info("RobotManager publish_message sent successfully")
28
+ else:
29
+ logger.info(
30
+ f"RobotManager publish_message. Status code: {response.status}"
31
+ )
32
+ response_text = await response.text()
33
+ logger.info(f"RobotManager publish_message: {response_text}")
34
+ except Exception as e:
35
+ logger.info(f"RobotManager error: {e}")
@@ -0,0 +1,8 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/1/5 16:25
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
@@ -0,0 +1,111 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2024/1/5 16:25
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+
10
+ import re
11
+ import json
12
+ from typing import Optional, Dict, List, Union
13
+
14
+
15
+ def extract_json_from_string(s: str) -> Optional[Union[Dict, List]]:
16
+ if not s:
17
+ return None
18
+
19
+ json_pattern = re.compile(r"(\{[^{}]*}|$[^\[$]*])", re.DOTALL)
20
+ candidates = []
21
+
22
+ for match in json_pattern.finditer(s):
23
+ candidate = match.group(0)
24
+ try:
25
+ if candidate.startswith("{") or candidate.startswith("["):
26
+ candidates.append((match.start(), match.end(), candidate))
27
+ except (IndexError, AttributeError):
28
+ continue
29
+
30
+ for start, end, candidate in candidates:
31
+ if (
32
+ candidate.startswith("{") and candidate.count("{") == candidate.count("}")
33
+ ) or (
34
+ candidate.startswith("[") and candidate.count("[") == candidate.count("]")
35
+ ):
36
+ try:
37
+ parsed = json.loads(candidate)
38
+ return parsed
39
+ except json.JSONDecodeError:
40
+ expanded = _expand_json_boundary(s, start, end)
41
+ if expanded:
42
+ try:
43
+ return json.loads(expanded)
44
+ except json.JSONDecodeError:
45
+ continue
46
+ continue
47
+
48
+ return _robust_json_parse(s)
49
+
50
+
51
+ def _expand_json_boundary(s: str, start: int, end: int) -> Optional[str]:
52
+ stack = []
53
+ in_string = False
54
+ escape = False
55
+
56
+ for i in range(start, len(s)):
57
+ c = s[i]
58
+
59
+ if c == '"' and not escape:
60
+ in_string = not in_string
61
+ elif not in_string:
62
+ if c == "{" or c == "[":
63
+ stack.append(c)
64
+ elif c == "}" and stack and stack[-1] == "{":
65
+ stack.pop()
66
+ elif c == "]" and stack and stack[-1] == "[":
67
+ stack.pop()
68
+
69
+ escape = c == "\\" and not escape
70
+
71
+ if not stack and not in_string:
72
+ return s[start : i + 1]
73
+
74
+ return None
75
+
76
+
77
+ def _robust_json_parse(s: str) -> Optional[Union[Dict, List]]:
78
+ stack = []
79
+ in_string = False
80
+ escape = False
81
+ start_index = None
82
+ structures = []
83
+
84
+ for i, c in enumerate(s):
85
+ if c == '"' and not escape:
86
+ in_string = not in_string
87
+ elif not in_string:
88
+ if c == "{" or c == "[":
89
+ if not stack:
90
+ start_index = i
91
+ stack.append(c)
92
+ elif c == "}" and stack and stack[-1] == "{":
93
+ stack.pop()
94
+ if not stack:
95
+ structures.append((start_index, i + 1))
96
+ elif c == "]" and stack and stack[-1] == "[":
97
+ stack.pop()
98
+ if not stack:
99
+ structures.append((start_index, i + 1))
100
+
101
+ escape = c == "\\" and not escape
102
+
103
+ structures.sort(key=lambda x: x[1] - x[0], reverse=True)
104
+
105
+ for start, end in structures:
106
+ try:
107
+ return json.loads(s[start:end])
108
+ except json.JSONDecodeError:
109
+ continue
110
+
111
+ return None