2020-02-19 15:31:39 +00:00
|
|
|
|
""" PagerMaid module that contains utilities related to system status. """
|
|
|
|
|
|
|
|
|
|
from os import remove, popen
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from speedtest import Speedtest
|
|
|
|
|
from telethon import functions
|
|
|
|
|
from platform import python_version, uname
|
|
|
|
|
from wordcloud import WordCloud
|
|
|
|
|
from telethon import version as telethon_version
|
|
|
|
|
from sys import platform
|
|
|
|
|
from re import sub
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from pagermaid import log, config, redis_status
|
|
|
|
|
from pagermaid.utils import execute, upload_attachment
|
|
|
|
|
from pagermaid.listener import listener
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="sysinfo",
|
2020-02-19 15:31:39 +00:00
|
|
|
|
description="通过 neofetch 检索系统信息。")
|
|
|
|
|
async def sysinfo(context):
|
|
|
|
|
""" Retrieve system information via neofetch. """
|
|
|
|
|
await context.edit("加载系统信息中 . . .")
|
|
|
|
|
result = await execute("neofetch --config none --stdout")
|
|
|
|
|
await context.edit(f"`{result}`")
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="fortune",
|
2020-02-19 15:31:39 +00:00
|
|
|
|
description="读取 fortune cookies 信息。")
|
|
|
|
|
async def fortune(context):
|
|
|
|
|
""" Reads a fortune cookie. """
|
|
|
|
|
result = await execute("fortune")
|
|
|
|
|
if result == "/bin/sh: fortune: command not found":
|
|
|
|
|
await context.edit("`出错了呜呜呜 ~ 此系统上没有 fortune cookies`")
|
|
|
|
|
return
|
|
|
|
|
await context.edit(result)
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="fbcon",
|
2020-02-19 15:31:39 +00:00
|
|
|
|
description="拍摄当前绑定的帧缓冲控制台的屏幕截图。")
|
|
|
|
|
async def tty(context):
|
|
|
|
|
""" Screenshots a TTY and prints it. """
|
|
|
|
|
await context.edit("拍摄帧缓冲控制台的屏幕截图中 . . .")
|
|
|
|
|
reply_id = context.message.reply_to_msg_id
|
2020-04-05 13:10:47 +00:00
|
|
|
|
result = await execute("fbdump | convert - image.png")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
if result == "/bin/sh: fbdump: command not found":
|
2020-02-29 02:02:38 +00:00
|
|
|
|
await context.edit("出错了呜呜呜 ~ 此系统上没有安装 fbdump")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
remove("image.png")
|
|
|
|
|
return
|
|
|
|
|
if result == "/bin/sh: convert: command not found":
|
2020-02-29 02:02:38 +00:00
|
|
|
|
await context.edit("出错了呜呜呜 ~ 此系统上没有安装 ImageMagick")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
remove("image.png")
|
|
|
|
|
return
|
|
|
|
|
if result == "Failed to open /dev/fb0: Permission denied":
|
2020-02-29 02:02:38 +00:00
|
|
|
|
await context.edit("出错了呜呜呜 ~ 运行 PagerMaid-Modify 的用户不在视频组中。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
return
|
2020-04-05 13:10:47 +00:00
|
|
|
|
if not await upload_attachment("./image.png", context.chat_id, reply_id,
|
2020-02-19 15:31:39 +00:00
|
|
|
|
caption="绑定的帧缓冲区的屏幕截图。",
|
|
|
|
|
preview=False, document=False):
|
2020-04-05 13:10:47 +00:00
|
|
|
|
await context.edit("出错了呜呜呜 ~ 由于发生意外错误,导致文件生成失败。请确保已安装 apt 包 fbcat 和 imagemagick,且你的机器有显卡。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
return
|
|
|
|
|
await context.delete()
|
2020-04-05 13:10:47 +00:00
|
|
|
|
try:
|
|
|
|
|
remove("./image.png")
|
|
|
|
|
except:
|
|
|
|
|
pass
|
2020-02-19 15:31:39 +00:00
|
|
|
|
await log("Screenshot of binded framebuffer console taken.")
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="status",
|
2020-04-04 15:02:09 +00:00
|
|
|
|
description="输出 PagerMaid-Modify 的运行状态。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
async def status(context):
|
2021-03-28 02:02:13 +00:00
|
|
|
|
database = "在线" if redis_status() else "离线"
|
|
|
|
|
text = (f"**PagerMaid-Modify 运行状态** \n"
|
2020-02-19 15:31:39 +00:00
|
|
|
|
f"主机名: `{uname().node}` \n"
|
|
|
|
|
f"主机平台: `{platform}` \n"
|
|
|
|
|
f"Kernel 版本: `{uname().release}` \n"
|
|
|
|
|
f"Python 版本: `{python_version()}` \n"
|
2021-03-28 02:02:13 +00:00
|
|
|
|
f"Telethon 版本: `{telethon_version.__version__}` \n"
|
|
|
|
|
f"数据库状态: `{database}`"
|
2020-02-19 15:31:39 +00:00
|
|
|
|
)
|
2021-03-28 02:02:13 +00:00
|
|
|
|
await context.edit(text)
|
|
|
|
|
dialogs = await context.client.get_dialogs()
|
|
|
|
|
dialogs = len(dialogs)
|
|
|
|
|
text += f"\n对话总数: `{dialogs}`"
|
|
|
|
|
await context.edit(text)
|
2020-02-19 15:31:39 +00:00
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="speedtest",
|
2020-02-29 02:02:38 +00:00
|
|
|
|
description="执行 speedtest 脚本并发送结果。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
async def speedtest(context):
|
|
|
|
|
""" Tests internet speed using speedtest. """
|
|
|
|
|
await context.edit("执行测试脚本 . . .")
|
|
|
|
|
test = Speedtest()
|
|
|
|
|
test.get_best_server()
|
|
|
|
|
test.download()
|
|
|
|
|
test.upload()
|
|
|
|
|
test.results.share()
|
|
|
|
|
result = test.results.dict()
|
|
|
|
|
await context.edit(
|
|
|
|
|
f"**Speedtest** \n"
|
|
|
|
|
f"Upload: `{unit_convert(result['upload'])}` \n"
|
|
|
|
|
f"Download: `{unit_convert(result['download'])}` \n"
|
|
|
|
|
f"Latency: `{result['ping']}` \n"
|
|
|
|
|
f"Timestamp: `{result['timestamp']}`"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="connection",
|
2020-04-04 15:02:09 +00:00
|
|
|
|
description="显示运行 PagerMaid-Modify 的服务器和 Telegram 服务器之间的连接信息。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
async def connection(context):
|
|
|
|
|
""" Displays connection information between PagerMaid and Telegram. """
|
|
|
|
|
datacenter = await context.client(functions.help.GetNearestDcRequest())
|
|
|
|
|
await context.edit(
|
|
|
|
|
f"**连接信息** \n"
|
|
|
|
|
f"国家: `{datacenter.country}` \n"
|
|
|
|
|
f"连接到的数据中心: `{datacenter.this_dc}` \n"
|
|
|
|
|
f"最近的数据中心: `{datacenter.nearest_dc}`"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="ping",
|
2020-04-04 15:02:09 +00:00
|
|
|
|
description="计算运行 PagerMaid-Modify 的服务器和 Telegram 服务器之间的延迟。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
async def ping(context):
|
|
|
|
|
""" Calculates latency between PagerMaid and Telegram. """
|
|
|
|
|
start = datetime.now()
|
|
|
|
|
await context.edit("Pong!")
|
|
|
|
|
end = datetime.now()
|
|
|
|
|
duration = (end - start).microseconds / 1000
|
|
|
|
|
await context.edit(f"Pong!|{duration}")
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 15:17:55 +00:00
|
|
|
|
@listener(is_plugin=False, outgoing=True, command="topcloud",
|
2020-04-04 15:02:09 +00:00
|
|
|
|
description="生成一张资源占用的词云图片。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
async def topcloud(context):
|
|
|
|
|
""" Generates a word cloud of resource-hungry processes. """
|
|
|
|
|
await context.edit("生成图片中 . . .")
|
|
|
|
|
command_list = []
|
|
|
|
|
if not Path('/usr/bin/top').is_symlink():
|
|
|
|
|
output = str(await execute("top -b -n 1")).split("\n")[7:]
|
|
|
|
|
else:
|
|
|
|
|
output = str(await execute("top -b -n 1")).split("\n")[4:]
|
|
|
|
|
for line in output[:-1]:
|
|
|
|
|
line = sub(r'\s+', ' ', line).strip()
|
|
|
|
|
fields = line.split(" ")
|
|
|
|
|
try:
|
|
|
|
|
if fields[11].count("/") > 0:
|
|
|
|
|
command = fields[11].split("/")[0]
|
|
|
|
|
else:
|
|
|
|
|
command = fields[11]
|
|
|
|
|
|
|
|
|
|
cpu = float(fields[8].replace(",", "."))
|
|
|
|
|
mem = float(fields[9].replace(",", "."))
|
|
|
|
|
|
|
|
|
|
if command != "top":
|
|
|
|
|
command_list.append((command, cpu, mem))
|
|
|
|
|
except BaseException:
|
|
|
|
|
pass
|
|
|
|
|
command_dict = {}
|
|
|
|
|
for command, cpu, mem in command_list:
|
|
|
|
|
if command in command_dict:
|
|
|
|
|
command_dict[command][0] += cpu
|
|
|
|
|
command_dict[command][1] += mem
|
|
|
|
|
else:
|
|
|
|
|
command_dict[command] = [cpu + 1, mem + 1]
|
|
|
|
|
|
|
|
|
|
resource_dict = {}
|
|
|
|
|
|
|
|
|
|
for command, [cpu, mem] in command_dict.items():
|
|
|
|
|
resource_dict[command] = (cpu ** 2 + mem ** 2) ** 0.5
|
|
|
|
|
|
|
|
|
|
width, height = None, None
|
|
|
|
|
try:
|
|
|
|
|
width, height = ((popen("xrandr | grep '*'").read()).split()[0]).split("x")
|
|
|
|
|
width = int(width)
|
|
|
|
|
height = int(height)
|
|
|
|
|
except BaseException:
|
|
|
|
|
pass
|
|
|
|
|
if not width or not height:
|
|
|
|
|
width = int(config['width'])
|
|
|
|
|
height = int(config['height'])
|
|
|
|
|
background = config['background']
|
|
|
|
|
margin = int(config['margin'])
|
|
|
|
|
|
|
|
|
|
cloud = WordCloud(
|
|
|
|
|
background_color=background,
|
|
|
|
|
width=width - 2 * int(margin),
|
|
|
|
|
height=height - 2 * int(margin)
|
|
|
|
|
).generate_from_frequencies(resource_dict)
|
|
|
|
|
|
|
|
|
|
cloud.to_file("cloud.png")
|
2020-04-04 15:02:09 +00:00
|
|
|
|
await context.edit("正在上传图片中 . . .")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
await context.client.send_file(
|
|
|
|
|
context.chat_id,
|
|
|
|
|
"cloud.png",
|
|
|
|
|
reply_to=None,
|
|
|
|
|
caption="正在运行的进程。"
|
|
|
|
|
)
|
|
|
|
|
remove("cloud.png")
|
|
|
|
|
await context.delete()
|
2020-04-04 15:02:09 +00:00
|
|
|
|
await log("生成了一张资源占用的词云图片。")
|
2020-02-19 15:31:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def unit_convert(byte):
|
|
|
|
|
""" Converts byte into readable formats. """
|
|
|
|
|
power = 2 ** 10
|
|
|
|
|
zero = 0
|
|
|
|
|
units = {
|
|
|
|
|
0: '',
|
|
|
|
|
1: 'Kb/s',
|
|
|
|
|
2: 'Mb/s',
|
|
|
|
|
3: 'Gb/s',
|
|
|
|
|
4: 'Tb/s'}
|
|
|
|
|
while byte > power:
|
|
|
|
|
byte /= power
|
|
|
|
|
zero += 1
|
|
|
|
|
return f"{round(byte, 2)} {units[zero]}"
|