mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-18 15:14:18 +02:00
Commited backup
This commit is contained in:
443
CakesTwix/Hikka-Modules/InlineSystemInfo.py
Normal file
443
CakesTwix/Hikka-Modules/InlineSystemInfo.py
Normal file
@@ -0,0 +1,443 @@
|
||||
"""
|
||||
|
||||
█▀▀ ▄▀█ █▄▀ █▀▀ █▀ ▀█▀ █░█░█ █ ▀▄▀
|
||||
█▄▄ █▀█ █░█ ██▄ ▄█ ░█░ ▀▄▀▄▀ █ █░█
|
||||
|
||||
Copyleft 2022 t.me/CakesTwix
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
||||
"""
|
||||
|
||||
__version__ = (1, 4, 5)
|
||||
|
||||
# requires: psutil py-cpuinfo
|
||||
# meta pic: https://img.icons8.com/external-xnimrodx-lineal-color-xnimrodx/512/000000/external-pc-computer-xnimrodx-lineal-color-xnimrodx.png
|
||||
# meta developer: @cakestwix_mods
|
||||
# scope: inline
|
||||
# scope: hikka_min 1.1.2
|
||||
|
||||
# For version info
|
||||
import telethon
|
||||
import aiogram
|
||||
import git
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
from typing import Union
|
||||
import platform
|
||||
import cpuinfo
|
||||
import psutil
|
||||
from aiogram.utils.markdown import quote_html
|
||||
from os.path import exists
|
||||
from .. import loader, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# https://www.adamsmith.haus/python/answers/how-to-remove-empty-lines-from-a-string-in-python
|
||||
def remove_empty_lines(string_with_empty_lines):
|
||||
lines = string_with_empty_lines.split("\n")
|
||||
non_empty_lines = [line for line in lines if line.strip() != ""]
|
||||
|
||||
return "".join(line + "\n" for line in non_empty_lines)
|
||||
|
||||
|
||||
backslash = "\n"
|
||||
|
||||
|
||||
def get_os_release():
|
||||
if not exists("/etc/os-release"):
|
||||
return False
|
||||
|
||||
list_ = []
|
||||
with open("/etc/os-release") as f:
|
||||
list_.extend(item.split("=") for item in f.readlines())
|
||||
return {item[0]: item[1].replace(backslash, "").replace('"', "") for item in list_}
|
||||
|
||||
|
||||
# https://stackoverflow.com/questions/2756737/check-linux-distribution-name
|
||||
def get_distro():
|
||||
"""
|
||||
Name of your Linux distro
|
||||
"""
|
||||
if not exists("/etc/issue"):
|
||||
return False
|
||||
|
||||
with open("/etc/issue") as f:
|
||||
return f.read().split()[0]
|
||||
|
||||
|
||||
def progressbar(iteration: int, length: int) -> str:
|
||||
percent = ("{0:." + str(1) + "f}").format(100 * (iteration / float(100)))
|
||||
filledLength = int(length * iteration // 100)
|
||||
return "█" * filledLength + "▒" * (length - filledLength)
|
||||
|
||||
|
||||
# From Hikka https://github.com/hikariatama/Hikka/blob/master/hikka/utils.py#L459-L461
|
||||
def chunks(_list: Union[list, tuple, set], n: int, /) -> list:
|
||||
"""Split provided `_list` into chunks of `n`"""
|
||||
return [_list[i : i + n] for i in range(0, len(_list), n)]
|
||||
|
||||
|
||||
def bytes2human(n):
|
||||
# http://code.activestate.com/recipes/578019
|
||||
# >>> bytes2human(10000)
|
||||
# '9.8K'
|
||||
# >>> bytes2human(100001221)
|
||||
# '95.4M'
|
||||
symbols = ("K", "M", "G", "T", "P", "E", "Z", "Y")
|
||||
prefix = {s: 1 << (i + 1) * 10 for i, s in enumerate(symbols)}
|
||||
for s in reversed(symbols):
|
||||
if n >= prefix[s]:
|
||||
value = float(n) / prefix[s]
|
||||
return "%.1f%s" % (value, s)
|
||||
return "%sB" % n
|
||||
|
||||
|
||||
@loader.tds
|
||||
class InlineSystemInfoMod(loader.Module):
|
||||
"""🖥 Get detailed information about your server"""
|
||||
|
||||
strings = {
|
||||
"name": "🖥 InlineSystemInfo",
|
||||
}
|
||||
|
||||
AddressFamily = {
|
||||
2: "IPv4",
|
||||
10: "IPv6",
|
||||
28: "IPv6",
|
||||
17: "Link",
|
||||
18: "Link",
|
||||
}
|
||||
|
||||
def menu_keyboard(self) -> list:
|
||||
keyboard = [
|
||||
[
|
||||
{
|
||||
"text": "😼 General",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("General",),
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
keyboard.extend(
|
||||
iter(
|
||||
chunks(
|
||||
[
|
||||
{
|
||||
"text": "🧠 CPU",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("CPU",),
|
||||
},
|
||||
{
|
||||
"text": "🐧 Linux",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Linux",),
|
||||
},
|
||||
{
|
||||
"text": "🗄 Memory",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Memory",),
|
||||
},
|
||||
{
|
||||
"text": "🌐 Network Address",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Network Address",),
|
||||
},
|
||||
{
|
||||
"text": "🌐 Network Stats",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Network Stats",),
|
||||
},
|
||||
{
|
||||
"text": "💽 Disk",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Disk",),
|
||||
},
|
||||
{
|
||||
"text": "🌡 Sensors",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Sensors",),
|
||||
},
|
||||
{
|
||||
"text": "🐍 Python",
|
||||
"callback": self.change_stuff,
|
||||
"args": ("Python",),
|
||||
}
|
||||
],
|
||||
3,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
keyboard.append([{"text": "🚫 Close", "callback": self.inline__close}])
|
||||
try:
|
||||
return keyboard[3].remove([])
|
||||
except ValueError:
|
||||
return keyboard
|
||||
|
||||
def general_info(self):
|
||||
string = "😼 <b>System Info</b>\n"
|
||||
string += f" ├──<b>CPU Name</b>: <code>{self.cpu_info.get('brand_raw', 'Undetermined.')}</code> {self.cpu_count_logic}/{self.cpu_count} ({self.cpu_info['arch_string_raw']})\n"
|
||||
string += f" ├──<b>RAM</b>: {progressbar(self.virtual_memory.percent, 10)} <code>({bytes2human(self.virtual_memory.used)}/{bytes2human(self.virtual_memory.total)})</code>\n"
|
||||
string += f" └──<b>Swap</b>: {progressbar(self.swap_memory.percent, 10)} <code>({bytes2human(self.swap_memory.used)}/{bytes2human(self.swap_memory.total)})</code>\n\n"
|
||||
|
||||
string += "🐧 <b>Linux Info</b>\n"
|
||||
string += f" ├──<b>Name</b>: <code>{get_distro()}</code>\n"
|
||||
string += f" └──<b>Kernel</b>: <code>{platform.release()}</code>\n\n"
|
||||
|
||||
if hasattr(self, "disk_partitions"):
|
||||
for disk_root in psutil.disk_partitions("/"):
|
||||
if disk_root.mountpoint == '/':
|
||||
disk_usage = psutil.disk_usage(disk_root.mountpoint)
|
||||
|
||||
string += "💽 <b>Disk Info</b> <code>(/)</code>\n"
|
||||
string += f" └──<b>{disk_root.device}</b>\n"
|
||||
string += f" ├── <b>Mount</b> {disk_root.mountpoint}\n"
|
||||
string += f" ├── <b>FS</b> {disk_root.fstype}\n"
|
||||
string += f" ├── <b>Disk Usage</b> {disk_usage.percent}% ({bytes2human(disk_usage.used)}/{bytes2human(disk_usage.total)})\n"
|
||||
string += f" │ └──{progressbar(disk_usage.percent, 10)}\n"
|
||||
string += f" └── <b>Options</b> {disk_root.opts}\n\n"
|
||||
|
||||
return string
|
||||
|
||||
def cpu_string(self):
|
||||
string = "🧠 <b>CPU Info</b>\n"
|
||||
string += f"⦁ <b>Name</b>: {self.cpu_info.get('brand_raw', 'Undetermined.')} ({self.cpu_info['arch_string_raw']})\n"
|
||||
string += f"⦁ <b>Count</b>: {self.cpu_count_logic} ({self.cpu_count})\n"
|
||||
string += (
|
||||
f"⦁ <b>Freq</b>: {self.cpu_freq[0]} (max: {self.cpu_freq[2]} / min: {self.cpu_freq[1]})\n"
|
||||
if hasattr(self, "cpu_freq") and self.cpu_freq
|
||||
else ""
|
||||
)
|
||||
string += f"⦁ <b>Flags</b>: {' '.join(self.cpu_info.get('flags', 'No flags'))}\n"
|
||||
string += (
|
||||
f"⦁ <b>Load avg</b>: {self.loadavg[0]} {self.loadavg[1]} {self.loadavg[2]}\n"
|
||||
if hasattr(self, "loadavg")
|
||||
else ""
|
||||
)
|
||||
|
||||
return string
|
||||
|
||||
def disks_string(self):
|
||||
if not hasattr(self, "disk_partitions"):
|
||||
return None
|
||||
|
||||
string = "💽 <b>Disk Info</b>\n"
|
||||
for disk in self.disk_partitions:
|
||||
disk_usage = psutil.disk_usage(disk.mountpoint)
|
||||
|
||||
string += f"<b>{disk.device}</b>\n"
|
||||
string += f"├── <b>Mount</b> {disk.mountpoint}\n"
|
||||
string += f"├── <b>FS</b> {disk.fstype}\n"
|
||||
string += f"├── <b>Disk Usage</b> {disk_usage.percent}% ({bytes2human(disk_usage.used)}/{bytes2human(disk_usage.total)})\n"
|
||||
string += f"│ └──{progressbar(disk_usage.percent, 10)}\n"
|
||||
string += f"└── <b>Options</b> {disk.opts}\n\n"
|
||||
|
||||
return string
|
||||
|
||||
def network_addr_string(self):
|
||||
if not hasattr(self, "net_if_addrs"):
|
||||
return None
|
||||
|
||||
string = "🌐 <b>Network Info</b>\n"
|
||||
string += "<b>Address</b>:\n"
|
||||
for interf in self.net_if_addrs:
|
||||
interface = self.net_if_addrs[interf]
|
||||
string += f"<b>{interf}</b>\n"
|
||||
for addr in interface:
|
||||
attr = [
|
||||
a
|
||||
for a in dir(psutil.net_if_addrs()[interf][0])
|
||||
if not a.startswith("__")
|
||||
and not a.startswith("_")
|
||||
and not callable(getattr(psutil.net_if_addrs()[interf][0], a))
|
||||
]
|
||||
string += f"{self.AddressFamily[getattr(addr, 'family')]}\n"
|
||||
for item in attr[:-1]:
|
||||
string += f"├── {item}: {getattr(addr, item)}\n"
|
||||
string += f"└── {attr[-1]}: {getattr(addr, attr[-1])}\n"
|
||||
string += "\n"
|
||||
|
||||
return string
|
||||
|
||||
def memory_string(self):
|
||||
string = "🗄 <b>Memory Info</b>\n"
|
||||
string += f"<b>RAM</b>: {progressbar(self.virtual_memory.percent, 10)} <code>({bytes2human(self.virtual_memory.used)}/{bytes2human(self.virtual_memory.total)})</code>\n"
|
||||
string += f"<b>Swap</b>: {progressbar(self.swap_memory.percent, 10)} <code>({bytes2human(self.swap_memory.used)}/{bytes2human(self.swap_memory.total)})</code>\n"
|
||||
|
||||
return string
|
||||
|
||||
def sensors_string(self):
|
||||
string = None
|
||||
if hasattr(self, "sensors_temperatures"):
|
||||
string = "🌡 <b>Sensors Info</b>\n" + "<b>Temperature</b>:\n"
|
||||
for sensor_name in self.sensors_temperatures:
|
||||
sensor = self.sensors_temperatures[sensor_name]
|
||||
string += f"<b>{sensor_name}</b>\n"
|
||||
for sensor_info in sensor:
|
||||
attr = [
|
||||
a
|
||||
for a in dir(sensor_info)
|
||||
if not a.startswith("__")
|
||||
and not a.startswith("_")
|
||||
and not callable(getattr(sensor_info, a))
|
||||
]
|
||||
for item in attr[:-1]:
|
||||
string += f"├── {item}: {getattr(sensor_info, item)}\n"
|
||||
string += f"└── {attr[-1]}: {getattr(sensor_info, attr[-1])}\n"
|
||||
string += "\n"
|
||||
|
||||
if hasattr(self, "sensors_fans"):
|
||||
string += "<b>Fans</b>:"
|
||||
for sensor_name in self.sensors_fans:
|
||||
sensor = self.sensors_fans[sensor_name]
|
||||
string += f"<b>{sensor_name}</b>\n"
|
||||
for sensor_info in sensor:
|
||||
attr = [
|
||||
a
|
||||
for a in dir(sensor_info)
|
||||
if not a.startswith("__")
|
||||
and not a.startswith("_")
|
||||
and not callable(getattr(sensor_info, a))
|
||||
]
|
||||
for item in attr[:-1]:
|
||||
string += f"├── {item}: {getattr(sensor_info, item)}\n"
|
||||
string += f"└── {attr[-1]}: {getattr(sensor_info, attr[-1])}\n"
|
||||
|
||||
return string
|
||||
|
||||
def network_stats_string(self):
|
||||
if not hasattr(self, "net_if_stats"):
|
||||
return None
|
||||
|
||||
string = "🌐 <b>Network Info</b>\n" + "<b>Stats</b>:\n"
|
||||
for interf in self.net_if_stats:
|
||||
interface = self.net_if_stats[interf]
|
||||
string += f"<b>{interf}</b>\n"
|
||||
string += f"└── {quote_html(interface)}\n\n"
|
||||
|
||||
return string
|
||||
|
||||
def linux_string(self):
|
||||
os_release = get_os_release()
|
||||
|
||||
string = f"""🐧 <b>Linux Info</b>
|
||||
Name: {get_distro()}
|
||||
Kernel: {platform.release()}
|
||||
Hostname: {platform.node()}
|
||||
{f'glibc ver: {platform.glibc()[1]}' if hasattr(platform, 'glibc') else ''}
|
||||
Boot time: {self.boot_time if hasattr(self, "boot_time") else "Termux moment"}
|
||||
|
||||
"""
|
||||
if os_release:
|
||||
string += f"""<b>\n /etc/os-releases Info:</b>
|
||||
Pretty Name: {os_release["PRETTY_NAME"]}
|
||||
Name: {os_release["NAME"]}
|
||||
Version: {os_release.get("VERSION", "Not available")}
|
||||
Documentation: {os_release.get("DOCUMENTATION_URL", "Not available")}
|
||||
Support: {os_release.get("SUPPORT_URL", "Not available")}
|
||||
Bug Report: {os_release["BUG_REPORT_URL"]}
|
||||
"""
|
||||
|
||||
return remove_empty_lines(string)
|
||||
|
||||
def python_string(self):
|
||||
string = "🐍 <b>Python Info</b>\n"
|
||||
string += f" ├──<b>Version</b>: <code>{platform.python_version()}</code>\n"
|
||||
string += f" ├──<b>Version (More details)</b>: <code>{cpuinfo.get_cpu_info()['python_version']}</code>\n"
|
||||
string += f" └──<b>Python Packages version</b>\n"
|
||||
string += f" ├──<b>Telethon</b>: <code>{telethon.__version__}</code>\n"
|
||||
string += f" ├──<b>AIOgram</b>: <code>{aiogram.__version__}</code>\n"
|
||||
string += f" ├──<b>Cpuinfo</b>: <code>{cpuinfo.get_cpu_info()['cpuinfo_version_string']}</code>\n"
|
||||
string += f" ├──<b>psutil</b>: <code>{psutil.__version__}</code>\n"
|
||||
string += f" └──<b>git</b>: <code>{git.__version__}</code>\n"
|
||||
|
||||
return string
|
||||
|
||||
def __init__(self):
|
||||
# CPU stuff
|
||||
self.cpu_count_logic = psutil.cpu_count()
|
||||
self.cpu_count = psutil.cpu_count(logical=False)
|
||||
|
||||
try:
|
||||
self.cpu_freq = psutil.cpu_freq()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
self.cpu_info = cpuinfo.get_cpu_info()
|
||||
|
||||
# Network
|
||||
try:
|
||||
self.net_if_addrs = psutil.net_if_addrs()
|
||||
self.net_if_stats = psutil.net_if_stats()
|
||||
except PermissionError:
|
||||
pass
|
||||
|
||||
def update_data(self):
|
||||
# Memory
|
||||
self.virtual_memory = psutil.virtual_memory()
|
||||
self.swap_memory = psutil.swap_memory()
|
||||
|
||||
# Sensors
|
||||
if hasattr(psutil, "sensors_temperatures"):
|
||||
self.sensors_temperatures = psutil.sensors_temperatures()
|
||||
if hasattr(psutil, "sensors_fans"):
|
||||
self.sensors_fans = psutil.sensors_fans()
|
||||
|
||||
# self.sensors_battery = psutil.sensors_battery()
|
||||
|
||||
# CPU stuff
|
||||
self.cpu_percent = psutil.cpu_percent(interval=None)
|
||||
|
||||
# Linux stuff
|
||||
self.loadavg = psutil.getloadavg()
|
||||
|
||||
# Disks
|
||||
try:
|
||||
self.disk_partitions = psutil.disk_partitions()
|
||||
except PermissionError:
|
||||
pass
|
||||
|
||||
# Other
|
||||
self.boot_time = datetime.datetime.fromtimestamp(psutil.boot_time()).strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# Generate string
|
||||
self.info_string = {
|
||||
"General": self.general_info(),
|
||||
"CPU": self.cpu_string(),
|
||||
"Disk": self.disks_string(),
|
||||
"Network Address": self.network_addr_string(),
|
||||
"Network Stats": self.network_stats_string(),
|
||||
"Memory": self.memory_string(),
|
||||
"Sensors": self.sensors_string(),
|
||||
"Linux": self.linux_string(),
|
||||
"Python": self.python_string(),
|
||||
}
|
||||
|
||||
async def client_ready(self, client, db) -> None:
|
||||
if utils.get_platform_name() == '🕶 Termux':
|
||||
raise loader.LoadError("No Termux support. Change your host")
|
||||
|
||||
async def systeminfocmd(self, message):
|
||||
"""Get information about your server"""
|
||||
await utils.run_sync(self.update_data)
|
||||
|
||||
await self.inline.form(
|
||||
text=self.general_info(),
|
||||
message=message,
|
||||
reply_markup=self.menu_keyboard(),
|
||||
)
|
||||
|
||||
# Inline callback
|
||||
|
||||
async def change_stuff(self, call, stuff):
|
||||
if self.info_string[stuff] != None:
|
||||
await call.edit(text=self.info_string[stuff], reply_markup=self.menu_keyboard())
|
||||
else:
|
||||
await call.answer("No data :(")
|
||||
|
||||
async def inline__close(self, call) -> None:
|
||||
await call.delete()
|
||||
Reference in New Issue
Block a user