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.
- infoman/__init__.py +1 -0
- infoman/cli/README.md +378 -0
- infoman/cli/__init__.py +7 -0
- infoman/cli/commands/__init__.py +3 -0
- infoman/cli/commands/init.py +312 -0
- infoman/cli/scaffold.py +634 -0
- infoman/cli/templates/Makefile.template +132 -0
- infoman/cli/templates/app/__init__.py.template +3 -0
- infoman/cli/templates/app/app.py.template +4 -0
- infoman/cli/templates/app/models_base.py.template +18 -0
- infoman/cli/templates/app/models_entity_init.py.template +11 -0
- infoman/cli/templates/app/models_schemas_init.py.template +11 -0
- infoman/cli/templates/app/repository_init.py.template +11 -0
- infoman/cli/templates/app/routers_init.py.template +15 -0
- infoman/cli/templates/app/services_init.py.template +11 -0
- infoman/cli/templates/app/static_index.html.template +39 -0
- infoman/cli/templates/app/static_main.js.template +31 -0
- infoman/cli/templates/app/static_style.css.template +111 -0
- infoman/cli/templates/app/utils_init.py.template +11 -0
- infoman/cli/templates/config/.env.dev.template +43 -0
- infoman/cli/templates/config/.env.prod.template +43 -0
- infoman/cli/templates/config/README.md.template +28 -0
- infoman/cli/templates/docker/.dockerignore.template +60 -0
- infoman/cli/templates/docker/Dockerfile.template +47 -0
- infoman/cli/templates/docker/README.md.template +240 -0
- infoman/cli/templates/docker/docker-compose.yml.template +81 -0
- infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
- infoman/cli/templates/docker/mysql_init.sql.template +15 -0
- infoman/cli/templates/project/.env.example.template +1 -0
- infoman/cli/templates/project/.gitignore.template +60 -0
- infoman/cli/templates/project/Makefile.template +38 -0
- infoman/cli/templates/project/README.md.template +137 -0
- infoman/cli/templates/project/deploy.sh.template +97 -0
- infoman/cli/templates/project/main.py.template +10 -0
- infoman/cli/templates/project/manage.sh.template +97 -0
- infoman/cli/templates/project/pyproject.toml.template +47 -0
- infoman/cli/templates/project/service.sh.template +203 -0
- infoman/config/__init__.py +25 -0
- infoman/config/base.py +67 -0
- infoman/config/db_cache.py +237 -0
- infoman/config/db_relation.py +181 -0
- infoman/config/db_vector.py +39 -0
- infoman/config/jwt.py +16 -0
- infoman/config/llm.py +16 -0
- infoman/config/log.py +627 -0
- infoman/config/mq.py +26 -0
- infoman/config/settings.py +65 -0
- infoman/llm/__init__.py +0 -0
- infoman/llm/llm.py +297 -0
- infoman/logger/__init__.py +57 -0
- infoman/logger/context.py +191 -0
- infoman/logger/core.py +358 -0
- infoman/logger/filters.py +157 -0
- infoman/logger/formatters.py +138 -0
- infoman/logger/handlers.py +276 -0
- infoman/logger/metrics.py +160 -0
- infoman/performance/README.md +583 -0
- infoman/performance/__init__.py +19 -0
- infoman/performance/cli.py +215 -0
- infoman/performance/config.py +166 -0
- infoman/performance/reporter.py +519 -0
- infoman/performance/runner.py +303 -0
- infoman/performance/standards.py +222 -0
- infoman/service/__init__.py +8 -0
- infoman/service/app.py +67 -0
- infoman/service/core/__init__.py +0 -0
- infoman/service/core/auth.py +105 -0
- infoman/service/core/lifespan.py +132 -0
- infoman/service/core/monitor.py +57 -0
- infoman/service/core/response.py +37 -0
- infoman/service/exception/__init__.py +7 -0
- infoman/service/exception/error.py +274 -0
- infoman/service/exception/exception.py +25 -0
- infoman/service/exception/handler.py +238 -0
- infoman/service/infrastructure/__init__.py +8 -0
- infoman/service/infrastructure/base.py +212 -0
- infoman/service/infrastructure/db_cache/__init__.py +8 -0
- infoman/service/infrastructure/db_cache/manager.py +194 -0
- infoman/service/infrastructure/db_relation/__init__.py +41 -0
- infoman/service/infrastructure/db_relation/manager.py +300 -0
- infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
- infoman/service/infrastructure/db_relation/mysql.py +52 -0
- infoman/service/infrastructure/db_relation/pgsql.py +54 -0
- infoman/service/infrastructure/db_relation/sqllite.py +25 -0
- infoman/service/infrastructure/db_vector/__init__.py +40 -0
- infoman/service/infrastructure/db_vector/manager.py +201 -0
- infoman/service/infrastructure/db_vector/qdrant.py +322 -0
- infoman/service/infrastructure/mq/__init__.py +15 -0
- infoman/service/infrastructure/mq/manager.py +178 -0
- infoman/service/infrastructure/mq/nats/__init__.py +0 -0
- infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
- infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
- infoman/service/launch.py +284 -0
- infoman/service/middleware/__init__.py +7 -0
- infoman/service/middleware/base.py +41 -0
- infoman/service/middleware/logging.py +51 -0
- infoman/service/middleware/rate_limit.py +301 -0
- infoman/service/middleware/request_id.py +21 -0
- infoman/service/middleware/white_list.py +24 -0
- infoman/service/models/__init__.py +8 -0
- infoman/service/models/base.py +441 -0
- infoman/service/models/type/embed.py +70 -0
- infoman/service/routers/__init__.py +18 -0
- infoman/service/routers/health_router.py +311 -0
- infoman/service/routers/monitor_router.py +44 -0
- infoman/service/utils/__init__.py +8 -0
- infoman/service/utils/cache/__init__.py +0 -0
- infoman/service/utils/cache/cache.py +192 -0
- infoman/service/utils/module_loader.py +10 -0
- infoman/service/utils/parse.py +10 -0
- infoman/service/utils/resolver/__init__.py +8 -0
- infoman/service/utils/resolver/base.py +47 -0
- infoman/service/utils/resolver/resp.py +102 -0
- infoman/service/vector/__init__.py +20 -0
- infoman/service/vector/base.py +56 -0
- infoman/service/vector/qdrant.py +125 -0
- infoman/service/vector/service.py +67 -0
- infoman/utils/__init__.py +2 -0
- infoman/utils/decorators/__init__.py +8 -0
- infoman/utils/decorators/cache.py +137 -0
- infoman/utils/decorators/retry.py +99 -0
- infoman/utils/decorators/safe_execute.py +99 -0
- infoman/utils/decorators/timing.py +99 -0
- infoman/utils/encryption/__init__.py +8 -0
- infoman/utils/encryption/aes.py +66 -0
- infoman/utils/encryption/ecc.py +108 -0
- infoman/utils/encryption/rsa.py +112 -0
- infoman/utils/file/__init__.py +0 -0
- infoman/utils/file/handler.py +22 -0
- infoman/utils/hash/__init__.py +0 -0
- infoman/utils/hash/hash.py +61 -0
- infoman/utils/http/__init__.py +8 -0
- infoman/utils/http/client.py +62 -0
- infoman/utils/http/info.py +94 -0
- infoman/utils/http/result.py +19 -0
- infoman/utils/notification/__init__.py +8 -0
- infoman/utils/notification/feishu.py +35 -0
- infoman/utils/text/__init__.py +8 -0
- infoman/utils/text/extractor.py +111 -0
- infomankit-0.3.23.dist-info/METADATA +632 -0
- infomankit-0.3.23.dist-info/RECORD +143 -0
- infomankit-0.3.23.dist-info/WHEEL +4 -0
- 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,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,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
|