nonebot-plugin-proxy-probe 0.2.2__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.
- nonebot_plugin_proxy_probe/__init__.py +26 -0
- nonebot_plugin_proxy_probe/assets//321/205/320/236/320/257/321/207/320/265/320/256/321/205/320/275/320/247/321/204/342/225/234/320/243.ttf +0 -0
- nonebot_plugin_proxy_probe/cache.py +82 -0
- nonebot_plugin_proxy_probe/commands.py +130 -0
- nonebot_plugin_proxy_probe/config.py +29 -0
- nonebot_plugin_proxy_probe/manager.py +360 -0
- nonebot_plugin_proxy_probe/models.py +145 -0
- nonebot_plugin_proxy_probe/probe.py +1184 -0
- nonebot_plugin_proxy_probe/render.py +266 -0
- nonebot_plugin_proxy_probe-0.2.2.dist-info/METADATA +269 -0
- nonebot_plugin_proxy_probe-0.2.2.dist-info/RECORD +14 -0
- nonebot_plugin_proxy_probe-0.2.2.dist-info/WHEEL +5 -0
- nonebot_plugin_proxy_probe-0.2.2.dist-info/licenses/LICENSE +674 -0
- nonebot_plugin_proxy_probe-0.2.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
UNAVAILABLE = "无法探测代理后地址"
|
|
8
|
+
NOT_PROBED = "未探测代理后地址"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class ProxyRecord:
|
|
13
|
+
ip: str
|
|
14
|
+
port: int
|
|
15
|
+
proxy_status: str = ""
|
|
16
|
+
public_ip: str = NOT_PROBED
|
|
17
|
+
location: str = NOT_PROBED
|
|
18
|
+
|
|
19
|
+
def to_dict(self) -> dict[str, Any]:
|
|
20
|
+
return asdict(self)
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_dict(cls, data: dict[str, Any]) -> "ProxyRecord":
|
|
24
|
+
return cls(
|
|
25
|
+
ip=str(data.get("ip", "")),
|
|
26
|
+
port=int(data.get("port", 0)),
|
|
27
|
+
proxy_status=str(data.get("proxy_status", "")),
|
|
28
|
+
public_ip=str(data.get("public_ip", NOT_PROBED)),
|
|
29
|
+
location=str(data.get("location", NOT_PROBED)),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class PipelineProgress:
|
|
35
|
+
total: int = 0
|
|
36
|
+
scan_completed: int = 0
|
|
37
|
+
open_count: int = 0
|
|
38
|
+
proxy_tested: int = 0
|
|
39
|
+
proxy_count: int = 0
|
|
40
|
+
geo_tested: int = 0
|
|
41
|
+
geo_success: int = 0
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> dict[str, int]:
|
|
44
|
+
return asdict(self)
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_dict(cls, data: dict[str, Any]) -> "PipelineProgress":
|
|
48
|
+
return cls(
|
|
49
|
+
total=max(0, int(data.get("total", 0))),
|
|
50
|
+
scan_completed=max(0, int(data.get("scan_completed", 0))),
|
|
51
|
+
open_count=max(0, int(data.get("open_count", 0))),
|
|
52
|
+
proxy_tested=max(0, int(data.get("proxy_tested", 0))),
|
|
53
|
+
proxy_count=max(0, int(data.get("proxy_count", 0))),
|
|
54
|
+
geo_tested=max(0, int(data.get("geo_tested", 0))),
|
|
55
|
+
geo_success=max(0, int(data.get("geo_success", 0))),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class CacheState:
|
|
61
|
+
scan_time: str = "未扫描"
|
|
62
|
+
refresh_time: str = "未刷新"
|
|
63
|
+
local_ip: str = "未获取"
|
|
64
|
+
target_ip: str = "未获取"
|
|
65
|
+
running: bool = False
|
|
66
|
+
operation: str = ""
|
|
67
|
+
task_status: str = "空闲"
|
|
68
|
+
task_current: int = 0
|
|
69
|
+
task_total: int = 0
|
|
70
|
+
progress: PipelineProgress = field(default_factory=PipelineProgress)
|
|
71
|
+
results: list[ProxyRecord] = field(default_factory=list)
|
|
72
|
+
|
|
73
|
+
def to_dict(self) -> dict[str, Any]:
|
|
74
|
+
return {
|
|
75
|
+
"version": 2,
|
|
76
|
+
"scan_time": self.scan_time,
|
|
77
|
+
"refresh_time": self.refresh_time,
|
|
78
|
+
"local_ip": self.local_ip,
|
|
79
|
+
"target_ip": self.target_ip,
|
|
80
|
+
"running": self.running,
|
|
81
|
+
"operation": self.operation,
|
|
82
|
+
"task_status": self.task_status,
|
|
83
|
+
"task_current": self.task_current,
|
|
84
|
+
"task_total": self.task_total,
|
|
85
|
+
"progress": self.progress.to_dict(),
|
|
86
|
+
"results": [item.to_dict() for item in self.results],
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def from_dict(cls, data: dict[str, Any]) -> "CacheState":
|
|
91
|
+
raw_results = data.get("results") or []
|
|
92
|
+
results: list[ProxyRecord] = []
|
|
93
|
+
for item in raw_results:
|
|
94
|
+
if not isinstance(item, dict):
|
|
95
|
+
continue
|
|
96
|
+
try:
|
|
97
|
+
record = ProxyRecord.from_dict(item)
|
|
98
|
+
except (TypeError, ValueError):
|
|
99
|
+
continue
|
|
100
|
+
if record.ip and 1 <= record.port <= 65535:
|
|
101
|
+
results.append(record)
|
|
102
|
+
|
|
103
|
+
progress_data = data.get("progress")
|
|
104
|
+
if not isinstance(progress_data, dict):
|
|
105
|
+
progress_data = {}
|
|
106
|
+
progress = PipelineProgress.from_dict(progress_data)
|
|
107
|
+
# 旧缓存只有三个“完成 IP 数”,无法还原开放端口总数。用结果列表
|
|
108
|
+
# 推导保守值;下一次完整扫描后会写入精确漏斗统计。
|
|
109
|
+
if (
|
|
110
|
+
"open_count" not in progress_data
|
|
111
|
+
and any(
|
|
112
|
+
key in progress_data
|
|
113
|
+
for key in ("proxy_completed", "geo_completed")
|
|
114
|
+
)
|
|
115
|
+
):
|
|
116
|
+
geo_tested = sum(
|
|
117
|
+
item.public_ip != NOT_PROBED for item in results
|
|
118
|
+
)
|
|
119
|
+
geo_success = sum(
|
|
120
|
+
item.public_ip not in (NOT_PROBED, UNAVAILABLE)
|
|
121
|
+
for item in results
|
|
122
|
+
)
|
|
123
|
+
progress = PipelineProgress(
|
|
124
|
+
total=progress.total,
|
|
125
|
+
scan_completed=progress.scan_completed,
|
|
126
|
+
open_count=len(results),
|
|
127
|
+
proxy_tested=len(results),
|
|
128
|
+
proxy_count=len(results),
|
|
129
|
+
geo_tested=geo_tested,
|
|
130
|
+
geo_success=geo_success,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return cls(
|
|
134
|
+
scan_time=str(data.get("scan_time", "未扫描")),
|
|
135
|
+
refresh_time=str(data.get("refresh_time", "未刷新")),
|
|
136
|
+
local_ip=str(data.get("local_ip", "未获取")),
|
|
137
|
+
target_ip=str(data.get("target_ip", "未获取")),
|
|
138
|
+
running=bool(data.get("running", False)),
|
|
139
|
+
operation=str(data.get("operation", "")),
|
|
140
|
+
task_status=str(data.get("task_status", "空闲")),
|
|
141
|
+
task_current=max(0, int(data.get("task_current", 0))),
|
|
142
|
+
task_total=max(0, int(data.get("task_total", 0))),
|
|
143
|
+
progress=progress,
|
|
144
|
+
results=results,
|
|
145
|
+
)
|