初始提交:恶意 IP 特征+行为融合检测系统
- 特征检测(规则/签名)与行为检测(24h 统计)单进程运行 - 融合名单按首次发现时间倒序,展示位置/归属(GeoIP + ASN) - 钉钉融合推送(加签、24h 节流、去重) - 页面状态灯、CSV 导出、Docker 镜像构建文件
This commit is contained in:
commit
2d76ed6672
42 files changed
+10645
No files matched your search
@@ -0,0 +1,77 @@
|
||||
"""Terminal rendering helpers (CJK-aware column widths)."""
|
||||
|
||||
import unicodedata
|
||||
|
||||
|
||||
def display_width(text):
|
||||
width = 0
|
||||
for char in str(text):
|
||||
if unicodedata.east_asian_width(char) in ("W", "F"):
|
||||
width += 2
|
||||
else:
|
||||
width += 1
|
||||
return width
|
||||
|
||||
|
||||
def clip(text, limit=60):
|
||||
text = "" if text is None else str(text)
|
||||
text = text.replace("\n", " ").replace("\r", " ").replace("\t", " ")
|
||||
if len(text) <= limit:
|
||||
return text
|
||||
return text[: max(0, limit - 1)] + "…"
|
||||
|
||||
|
||||
def table(headers, rows, align=None):
|
||||
"""Render a plain-text table. *align* is a list of ``l``/``r`` per column."""
|
||||
rows = [["" if cell is None else str(cell) for cell in row] for row in rows]
|
||||
if align is None:
|
||||
align = ["l"] * len(headers)
|
||||
widths = [display_width(header) for header in headers]
|
||||
for row in rows:
|
||||
for index, cell in enumerate(row[: len(widths)]):
|
||||
widths[index] = max(widths[index], display_width(cell))
|
||||
|
||||
def render(cells):
|
||||
parts = []
|
||||
for index, cell in enumerate(cells):
|
||||
padding = widths[index] - display_width(cell)
|
||||
if align[index] == "r":
|
||||
parts.append(" " * padding + cell)
|
||||
else:
|
||||
parts.append(cell + " " * padding)
|
||||
return " ".join(parts).rstrip()
|
||||
|
||||
lines = [render(headers), " ".join("-" * width for width in widths)]
|
||||
lines.extend(render(row) for row in rows)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def human_bytes(size):
|
||||
if not isinstance(size, (int, float)):
|
||||
return str(size)
|
||||
value = float(size)
|
||||
for unit in ("B", "KiB", "MiB", "GiB", "TiB"):
|
||||
if value < 1024 or unit == "TiB":
|
||||
if unit == "B":
|
||||
return "%d B" % value
|
||||
return "%.1f %s" % (value, unit)
|
||||
value /= 1024.0
|
||||
return str(size)
|
||||
|
||||
|
||||
def percent(part, total):
|
||||
if not total:
|
||||
return "-"
|
||||
return "%.1f%%" % (100.0 * part / total)
|
||||
|
||||
|
||||
def kv_block(pairs):
|
||||
"""Render aligned ``key: value`` lines."""
|
||||
if not pairs:
|
||||
return ""
|
||||
width = max(display_width(key) for key, _ in pairs)
|
||||
lines = []
|
||||
for key, value in pairs:
|
||||
padding = " " * (width - display_width(key))
|
||||
lines.append("%s%s : %s" % (key, padding, "" if value is None else value))
|
||||
return "\n".join(lines)
|
||||
Reference in new issue
Block a user