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.
@@ -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
+ )