2020-02-19 15:31:39 +00:00
|
|
|
""" Libraries for python modules. """
|
2021-11-25 09:44:38 +00:00
|
|
|
import aiohttp
|
2021-12-18 16:22:44 +00:00
|
|
|
import subprocess
|
|
|
|
|
|
|
|
from importlib.util import find_spec
|
|
|
|
from sys import executable
|
2020-02-19 15:31:39 +00:00
|
|
|
|
|
|
|
from os import remove
|
|
|
|
from os.path import exists
|
2021-12-18 16:22:44 +00:00
|
|
|
from typing import Any, Optional
|
2021-11-25 09:44:38 +00:00
|
|
|
|
2020-02-19 15:31:39 +00:00
|
|
|
from emoji import get_emoji_regexp
|
|
|
|
from random import choice
|
|
|
|
from json import load as load_json
|
2021-11-25 09:44:38 +00:00
|
|
|
from json import loads as loads_json
|
|
|
|
from json import dumps as dumps_json
|
2020-02-19 15:31:39 +00:00
|
|
|
from re import sub, IGNORECASE
|
|
|
|
from asyncio import create_subprocess_shell
|
|
|
|
from asyncio.subprocess import PIPE
|
2021-10-03 16:42:16 +00:00
|
|
|
|
|
|
|
from telethon.errors import UserNotParticipantError
|
|
|
|
from telethon.tl.types import Channel, ChannelParticipantAdmin, ChannelParticipantCreator
|
2020-02-19 15:31:39 +00:00
|
|
|
from youtube_dl import YoutubeDL
|
2021-11-25 09:44:38 +00:00
|
|
|
from pagermaid import module_dir, bot, lang_dict, alias_dict, user_bot, config, proxy_addr, proxy_port, http_addr, \
|
|
|
|
http_port
|
|
|
|
|
|
|
|
|
|
|
|
class AiohttpResp:
|
|
|
|
"""
|
|
|
|
重写返回类型。
|
|
|
|
"""
|
2021-11-25 12:11:02 +00:00
|
|
|
def __init__(self, text: Any, content: bytes, status_code: int):
|
2021-11-25 09:44:38 +00:00
|
|
|
"""
|
|
|
|
Args:
|
2021-11-25 12:11:02 +00:00
|
|
|
text (Any): 网页内容
|
2021-11-25 09:44:38 +00:00
|
|
|
content (bytes): 文件内容
|
|
|
|
status_code (int): 网页状态码
|
|
|
|
"""
|
|
|
|
self.text = text
|
|
|
|
self.content = content
|
|
|
|
self.status_code = status_code
|
|
|
|
|
|
|
|
def json(self):
|
|
|
|
return loads_json(self.text)
|
2021-04-12 16:25:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
def lang(text: str) -> str:
|
|
|
|
""" i18n """
|
|
|
|
result = lang_dict.get(text, text)
|
|
|
|
return result
|
2020-02-19 15:31:39 +00:00
|
|
|
|
|
|
|
|
2021-08-18 08:41:22 +00:00
|
|
|
def alias_command(command: str) -> str:
|
2021-06-15 04:31:05 +00:00
|
|
|
""" alias """
|
|
|
|
try:
|
|
|
|
command = alias_dict[command]
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
return command
|
|
|
|
|
|
|
|
|
2020-02-19 15:31:39 +00:00
|
|
|
async def upload_attachment(file_path, chat_id, reply_id, caption=None, preview=None, document=None):
|
|
|
|
""" Uploads a local attachment file. """
|
|
|
|
if not exists(file_path):
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
await bot.send_file(
|
|
|
|
chat_id,
|
|
|
|
file_path,
|
|
|
|
reply_to=reply_id,
|
|
|
|
caption=caption,
|
|
|
|
link_preview=preview,
|
|
|
|
force_document=document
|
|
|
|
)
|
|
|
|
except BaseException as exception:
|
|
|
|
raise exception
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
async def execute(command, pass_error=True):
|
|
|
|
""" Executes command and returns output, with the option of enabling stderr. """
|
|
|
|
executor = await create_subprocess_shell(
|
|
|
|
command,
|
|
|
|
stdout=PIPE,
|
|
|
|
stderr=PIPE
|
|
|
|
)
|
|
|
|
|
2021-04-04 03:04:11 +00:00
|
|
|
try:
|
|
|
|
stdout, stderr = await executor.communicate()
|
2021-04-04 04:31:32 +00:00
|
|
|
except:
|
2021-04-12 16:25:32 +00:00
|
|
|
return lang('error')
|
2020-02-19 15:31:39 +00:00
|
|
|
if pass_error:
|
|
|
|
result = str(stdout.decode().strip()) \
|
|
|
|
+ str(stderr.decode().strip())
|
|
|
|
else:
|
|
|
|
result = str(stdout.decode().strip())
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
async def attach_log(plaintext, chat_id, file_name, reply_id=None, caption=None):
|
|
|
|
""" Attach plaintext as logs. """
|
|
|
|
file = open(file_name, "w+")
|
|
|
|
file.write(plaintext)
|
|
|
|
file.close()
|
|
|
|
await bot.send_file(
|
|
|
|
chat_id,
|
|
|
|
file_name,
|
|
|
|
reply_to=reply_id,
|
|
|
|
caption=caption
|
|
|
|
)
|
|
|
|
remove(file_name)
|
|
|
|
|
2021-04-12 16:25:32 +00:00
|
|
|
|
2020-10-01 04:16:54 +00:00
|
|
|
async def attach_report(plaintext, file_name, reply_id=None, caption=None):
|
|
|
|
""" Attach plaintext as logs. """
|
|
|
|
file = open(file_name, "w+")
|
|
|
|
file.write(plaintext)
|
|
|
|
file.close()
|
2021-10-03 16:42:16 +00:00
|
|
|
if user_bot:
|
|
|
|
return
|
2020-10-01 04:16:54 +00:00
|
|
|
try:
|
|
|
|
await bot.send_file(
|
|
|
|
1263764543,
|
|
|
|
file_name,
|
|
|
|
reply_to=reply_id,
|
|
|
|
caption=caption
|
|
|
|
)
|
|
|
|
except:
|
2021-04-04 01:13:29 +00:00
|
|
|
try:
|
|
|
|
async with bot.conversation('PagerMaid_Modify_bot') as conversation:
|
|
|
|
await conversation.send_message('/ping')
|
|
|
|
await conversation.get_response()
|
|
|
|
await bot.send_read_acknowledge(conversation.chat_id)
|
|
|
|
await bot.send_file(
|
|
|
|
1263764543,
|
|
|
|
file_name,
|
|
|
|
reply_to=reply_id,
|
|
|
|
caption=caption
|
|
|
|
)
|
|
|
|
except:
|
|
|
|
pass
|
2020-10-01 04:16:54 +00:00
|
|
|
remove(file_name)
|
2020-02-19 15:31:39 +00:00
|
|
|
|
2021-04-12 16:25:32 +00:00
|
|
|
|
2021-08-18 08:41:22 +00:00
|
|
|
async def obtain_message(context) -> str:
|
2020-02-19 15:31:39 +00:00
|
|
|
""" Obtains a message from either the reply message or command arguments. """
|
|
|
|
reply = await context.get_reply_message()
|
|
|
|
message = context.arguments
|
|
|
|
if reply and not message:
|
|
|
|
message = reply.text
|
|
|
|
if not message:
|
2021-04-12 16:25:32 +00:00
|
|
|
raise ValueError(lang('msg_ValueError'))
|
2020-02-19 15:31:39 +00:00
|
|
|
return message
|
|
|
|
|
|
|
|
|
|
|
|
async def random_gen(selection, length=64):
|
|
|
|
if not isinstance(length, int):
|
2021-04-12 16:25:32 +00:00
|
|
|
raise ValueError(lang('isinstance'))
|
2020-02-19 15:31:39 +00:00
|
|
|
return await execute(f"head -c 65536 /dev/urandom | tr -dc {selection} | head -c {length} ; echo \'\'")
|
|
|
|
|
|
|
|
|
2020-02-20 13:37:19 +00:00
|
|
|
async def fetch_youtube_audio(url, chat_id, reply_id, string_2):
|
2020-02-19 15:31:39 +00:00
|
|
|
""" Extracts and uploads audio from YouTube video. """
|
|
|
|
youtube_dl_options = {
|
|
|
|
'format': 'bestaudio/best',
|
|
|
|
'outtmpl': "audio.%(ext)s",
|
|
|
|
'postprocessors': [{
|
|
|
|
'key': 'FFmpegExtractAudio',
|
|
|
|
'preferredcodec': 'mp3',
|
|
|
|
'preferredquality': '192',
|
|
|
|
}],
|
|
|
|
}
|
|
|
|
YoutubeDL(youtube_dl_options).download([url])
|
|
|
|
if not exists("audio.mp3"):
|
|
|
|
return False
|
|
|
|
await bot.send_file(
|
2021-04-12 16:25:32 +00:00
|
|
|
chat_id,
|
|
|
|
"audio.mp3",
|
|
|
|
reply_to=reply_id,
|
|
|
|
caption=str(string_2)
|
2020-02-19 15:31:39 +00:00
|
|
|
)
|
|
|
|
remove("audio.mp3")
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2021-08-18 08:41:22 +00:00
|
|
|
def owoify(text: str) -> str:
|
2020-02-19 15:31:39 +00:00
|
|
|
""" Converts your text to OwO """
|
|
|
|
smileys = [';;w;;', '^w^', '>w<', 'UwU', '(・`ω´・)', '(´・ω・`)']
|
|
|
|
with open(f"{module_dir}/assets/replacements.json") as fp:
|
|
|
|
replacements = load_json(fp)
|
|
|
|
for expression in replacements:
|
|
|
|
replacement = replacements[expression]
|
|
|
|
text = sub(expression, replacement, text, flags=IGNORECASE)
|
|
|
|
words = text.split()
|
|
|
|
first_letter = words[0][0]
|
|
|
|
letter_stutter = f"{first_letter}-{first_letter.lower()}-{first_letter.lower()}"
|
|
|
|
if len(words[0]) > 1:
|
|
|
|
words[0] = letter_stutter + words[0][1:]
|
|
|
|
else:
|
|
|
|
words[0] = letter_stutter
|
|
|
|
text = " ".join(words)
|
|
|
|
text = text.replace('L', 'W').replace('l', 'w')
|
|
|
|
text = text.replace('R', 'W').replace('r', 'w')
|
|
|
|
text = '! {}'.format(choice(smileys)).join(text.rsplit('!', 1))
|
|
|
|
text = '? OwO'.join(text.rsplit('?', 1))
|
|
|
|
text = '. {}'.format(choice(smileys)).join(text.rsplit('.', 1))
|
|
|
|
text = f"{text} desu"
|
|
|
|
for v in ['a', 'o', 'u', 'A', 'O', 'U']:
|
|
|
|
if 'n{}'.format(v) in text:
|
|
|
|
text = text.replace('n{}'.format(v), 'ny{}'.format(v))
|
|
|
|
if 'N{}'.format(v) in text:
|
|
|
|
text = text.replace('N{}'.format(v), 'N{}{}'.format('Y' if v.isupper() else 'y', v))
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
2021-08-18 08:41:22 +00:00
|
|
|
def clear_emojis(target: str) -> str:
|
2020-02-19 15:31:39 +00:00
|
|
|
""" Removes all Emojis from provided string """
|
|
|
|
return get_emoji_regexp().sub(u'', target)
|
2021-10-03 16:42:16 +00:00
|
|
|
|
|
|
|
|
2021-12-18 16:22:44 +00:00
|
|
|
def pip_install(package: str, version: Optional[str] = "", alias: Optional[str] = "") -> bool:
|
|
|
|
""" Auto install extra pypi packages """
|
|
|
|
if not alias:
|
|
|
|
# when import name is not provided, use package name
|
|
|
|
alias = package
|
|
|
|
if find_spec(alias) is None:
|
|
|
|
subprocess.call([executable, "-m", "pip", "install", f"{package}{version}"])
|
|
|
|
if find_spec(package) is None:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2021-10-03 16:42:16 +00:00
|
|
|
async def admin_check(event):
|
|
|
|
if event.is_private:
|
|
|
|
return False
|
|
|
|
# Anonymous Admin Support
|
|
|
|
if isinstance(event.sender, Channel) and event.sender_id == event.chat_id:
|
|
|
|
return True
|
|
|
|
if event.sender_id and 'bot_admins' in config:
|
|
|
|
if config['bot_admins'].count(event.sender_id) != 0:
|
|
|
|
return True
|
|
|
|
try:
|
|
|
|
perms = await event.client.get_permissions(event.chat_id, event.sender_id)
|
|
|
|
except UserNotParticipantError:
|
|
|
|
return False
|
|
|
|
if isinstance(
|
2021-11-25 09:44:38 +00:00
|
|
|
perms.participant, (ChannelParticipantAdmin, ChannelParticipantCreator)
|
2021-10-03 16:42:16 +00:00
|
|
|
):
|
|
|
|
return True
|
|
|
|
return False
|
2021-11-25 09:44:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def request(method: str,
|
|
|
|
url: str,
|
|
|
|
params: dict = None,
|
|
|
|
data: Any = None,
|
|
|
|
json_body: bool = False,
|
|
|
|
timeout: int = 10,
|
|
|
|
**kwargs) -> AiohttpResp:
|
|
|
|
"""
|
|
|
|
原始网络请求封装。
|
|
|
|
Args:
|
|
|
|
method (str) : 请求方法。
|
|
|
|
url (str) : 请求 URL。
|
|
|
|
params (dict, optional) : 请求参数。
|
|
|
|
data (Any, optional) : 请求载荷。
|
|
|
|
json_body (bool, optional) : 载荷是否为 JSON
|
|
|
|
timeout (int, optional) : 超时时间
|
|
|
|
Returns:
|
|
|
|
返回 aiohttp 请求对象
|
|
|
|
"""
|
|
|
|
method = method.upper()
|
|
|
|
|
|
|
|
# 使用自定义 UA
|
|
|
|
DEFAULT_HEADERS = {
|
|
|
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"
|
|
|
|
}
|
|
|
|
headers = DEFAULT_HEADERS
|
|
|
|
|
|
|
|
if params is None:
|
|
|
|
params = {}
|
|
|
|
|
|
|
|
# 合并参数
|
|
|
|
config_ = {
|
|
|
|
"method": method,
|
|
|
|
"url": url,
|
|
|
|
"params": params,
|
|
|
|
"data": data,
|
|
|
|
"headers": headers,
|
|
|
|
}
|
|
|
|
# 支持自定义参数
|
|
|
|
config_.update(kwargs)
|
|
|
|
|
|
|
|
if json_body:
|
|
|
|
config_["headers"]["Content-Type"] = "application/json"
|
|
|
|
config_["data"] = dumps_json(config_["data"])
|
|
|
|
# 如果用户提供代理则设置代理
|
|
|
|
if not proxy_addr == '' and not proxy_port == '':
|
|
|
|
config_["proxy"] = f"socks5://{proxy_addr}:{proxy_port}"
|
|
|
|
elif not http_addr == '' and not http_port == '':
|
|
|
|
config_["proxy"] = f"http://{http_addr}:{http_port}"
|
|
|
|
session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout))
|
|
|
|
resp = await session.request(**config_)
|
|
|
|
# 返回请求
|
2021-11-25 12:11:02 +00:00
|
|
|
try:
|
|
|
|
resp_data = await resp.text()
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
resp_data = await resp.read()
|
2021-11-25 09:44:38 +00:00
|
|
|
content = await resp.content.read()
|
|
|
|
status_code = resp.status
|
|
|
|
await session.close()
|
|
|
|
return AiohttpResp(resp_data, content, status_code)
|
|
|
|
|
|
|
|
|
|
|
|
async def get(url: str, timeout: int = 10, **kwargs) -> AiohttpResp:
|
|
|
|
"""
|
|
|
|
GET 请求封装
|
|
|
|
Args:
|
|
|
|
url (str) : 请求 URL。
|
|
|
|
timeout (int, optional) : 超时时间
|
|
|
|
Returns:
|
|
|
|
返回 aiohttp 请求对象
|
|
|
|
:rtype :aiohttp.client_reqrep.ClientResponse
|
|
|
|
"""
|
|
|
|
return await request("GET", url, timeout=timeout, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
async def post(url: str,
|
|
|
|
params: dict = None,
|
|
|
|
data: Any = None,
|
|
|
|
json_body: bool = False,
|
|
|
|
timeout: int = 10,
|
|
|
|
**kwargs) -> AiohttpResp:
|
|
|
|
"""
|
|
|
|
POST 请求封装
|
|
|
|
Args:
|
|
|
|
url (str) : 请求 URL。
|
|
|
|
params (dict, optional) : 请求参数。
|
|
|
|
data (Any, optional) : 请求载荷。
|
|
|
|
json_body (bool, optional) : 载荷是否为 JSON
|
|
|
|
timeout (int, optional) : 超时时间
|
|
|
|
Returns:
|
|
|
|
返回 aiohttp 请求对象
|
|
|
|
:rtype :aiohttp.client_reqrep.ClientResponse
|
|
|
|
"""
|
|
|
|
return await request("POST", url, params, data, json_body, timeout, **kwargs)
|