ezKit 2.0.28__tar.gz → 2.0.30__tar.gz
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.
- {ezkit-2.0.28/ezKit.egg-info → ezkit-2.0.30}/PKG-INFO +1 -1
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/bandwagon.py +36 -0
- ezkit-2.0.30/ezKit/linux.py +45 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/utils.py +21 -0
- {ezkit-2.0.28 → ezkit-2.0.30/ezKit.egg-info}/PKG-INFO +1 -1
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit.egg-info/SOURCES.txt +1 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/setup.py +1 -1
- {ezkit-2.0.28 → ezkit-2.0.30}/LICENSE +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/MANIFEST.in +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/README.md +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/__init__.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/__zabbix.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/asyncdatabase.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/cipher.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/database.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/errorcode.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/fastapix.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/http.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/redix.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/sendemail.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit/stock.py +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit.egg-info/dependency_links.txt +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit.egg-info/requires.txt +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/ezKit.egg-info/top_level.txt +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/pyproject.toml +0 -0
- {ezkit-2.0.28 → ezkit-2.0.30}/setup.cfg +0 -0
|
@@ -2,12 +2,17 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from datetime import datetime, timedelta, timezone
|
|
5
|
+
from decimal import ROUND_HALF_UP, Decimal
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
import requests
|
|
8
9
|
|
|
9
10
|
BASE_URL = "https://api.64clouds.com/v1"
|
|
10
11
|
|
|
12
|
+
GB = Decimal(1024) ** 3
|
|
13
|
+
|
|
14
|
+
TWO_PLACES = Decimal("0.01")
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
@dataclass(slots=True)
|
|
13
18
|
class BandwagonConfig:
|
|
@@ -103,3 +108,34 @@ def expiration_date(info: dict) -> str:
|
|
|
103
108
|
# 将时间戳转为 UTC+8 时间
|
|
104
109
|
date = datetime.fromtimestamp(info["data_next_reset"], tz=timezone(timedelta(hours=8))).strftime("%Y-%m-%d")
|
|
105
110
|
return date
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# --------------------------------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _to_gb(value: int | str | float) -> Decimal:
|
|
117
|
+
"""字节转 GB(Decimal 精确)"""
|
|
118
|
+
return (Decimal(str(value)) / GB).quantize(TWO_PLACES, rounding=ROUND_HALF_UP)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def bandwidth_allowance(info: dict) -> dict[str, Decimal]:
|
|
122
|
+
"""
|
|
123
|
+
计算带宽配额使用情况(精确计算,保留两位小数)
|
|
124
|
+
返回值单位:GB / %
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
total = _to_gb(info["plan_monthly_data"])
|
|
128
|
+
used = _to_gb(info["data_counter"])
|
|
129
|
+
available = total - used
|
|
130
|
+
|
|
131
|
+
if total == 0:
|
|
132
|
+
usage_percent = Decimal("0.00")
|
|
133
|
+
else:
|
|
134
|
+
usage_percent = (used / total * 100).quantize(TWO_PLACES, rounding=ROUND_HALF_UP)
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
"total": total, # Decimal('123.45')
|
|
138
|
+
"used": used, # Decimal('67.89')
|
|
139
|
+
"available": available,
|
|
140
|
+
"usage_percent": usage_percent, # Decimal('54.32')
|
|
141
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
|
|
3
|
+
from . import utils
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_uptime_info():
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
return int(utils.read_file("/proc/uptime").split()[0])
|
|
10
|
+
except Exception:
|
|
11
|
+
return 0
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_memory_info() -> dict:
|
|
15
|
+
|
|
16
|
+
meminfo = {}
|
|
17
|
+
|
|
18
|
+
with open("/proc/meminfo", encoding="utf-8") as f:
|
|
19
|
+
|
|
20
|
+
for line in f:
|
|
21
|
+
key, value = line.split(":", 1)
|
|
22
|
+
meminfo[key] = int(value.strip().split()[0]) * 1024 # kB -> bytes
|
|
23
|
+
|
|
24
|
+
total = meminfo.get("MemTotal", 0)
|
|
25
|
+
available = meminfo.get("MemAvailable", 0)
|
|
26
|
+
used = total - available
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
"total": utils.bytes_to_gigabyte(total),
|
|
30
|
+
"used": utils.bytes_to_gigabyte(used),
|
|
31
|
+
"available": utils.bytes_to_gigabyte(available),
|
|
32
|
+
"usage_percent": round(used / total * 100, 2) if total else 0,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_disk_info(path: str = "/") -> dict:
|
|
37
|
+
|
|
38
|
+
usage = shutil.disk_usage(path)
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
"total": utils.bytes_to_gigabyte(usage.total),
|
|
42
|
+
"used": utils.bytes_to_gigabyte(usage.used),
|
|
43
|
+
"available": utils.bytes_to_gigabyte(usage.free),
|
|
44
|
+
"usage_percent": round(usage.used / usage.total * 100, 2),
|
|
45
|
+
}
|
|
@@ -489,3 +489,24 @@ def resolve_path(
|
|
|
489
489
|
|
|
490
490
|
|
|
491
491
|
# --------------------------------------------------------------------------------------------------
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def bytes_to_gigabyte(value: int) -> float:
|
|
495
|
+
"""Convert bytes to gigabytes"""
|
|
496
|
+
|
|
497
|
+
try:
|
|
498
|
+
return round(value / 1024 / 1024 / 1024, 2)
|
|
499
|
+
except Exception:
|
|
500
|
+
return 0
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
# --------------------------------------------------------------------------------------------------
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def read_file(path: str) -> str:
|
|
507
|
+
"""Read file"""
|
|
508
|
+
|
|
509
|
+
try:
|
|
510
|
+
return Path(path).read_text(encoding="utf-8").strip()
|
|
511
|
+
except Exception:
|
|
512
|
+
return ""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|