keyword 添加图片/文件缓存功能 (#122)

-replyset cache 1 开启
-replyset cache 0 关闭
-replyset cache clear 清除cache设置
-replyset cache remove 刷新cache,可以使用global和plain/regex 规则id,具体参照 [具体参照 Keyword 进阶版教程](https://telegra.ph/Keyword-插件使用教程---进阶篇-02-07)
This commit is contained in:
c3b2a 2021-02-08 20:25:46 +08:00 committed by GitHub
parent ae7b3c3aab
commit 628bd476e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 227 additions and 132 deletions

View File

@ -1,7 +1,7 @@
import re, time, asyncio, requests, os, json
from io import BytesIO
from os import path, mkdir, remove
from shutil import copyfile, move
from os import path, mkdir, remove, makedirs
from shutil import copyfile, move, rmtree
from uuid import uuid4
from base64 import b64encode, b64decode
from importlib import import_module
@ -128,6 +128,31 @@ def valid_time(chat_id):
return True
def has_cache(chat_id, mode, trigger, filename):
basepath = f"data/keyword_cache/{chat_id}/{mode}:{encode(trigger)}"
filepath = f"{basepath}/{filename}"
if not path.exists(basepath):
makedirs(basepath)
return (False, filepath)
if not path.exists(filepath):
return (False, filepath)
return (True, filepath)
def cache_opened(chat_id, mode, trigger):
rule_data = get_redis(f"keyword.{chat_id}.single"
f".{mode}.{encode(trigger)}").get("cache", None)
chat_data = get_redis(f"keyword.{chat_id}.settings").get("cache", None)
global_data = get_redis("keyword.settings").get("cache", None)
if rule_data:
return True if rule_data == "1" else False
elif chat_data:
return True if chat_data == "1" else False
elif global_data:
return True if global_data == "1" else False
return False
async def del_msg(context, t_lim):
await asyncio.sleep(t_lim)
try:
@ -136,7 +161,7 @@ async def del_msg(context, t_lim):
pass
async def send_reply(chat_id, reply_msg, context):
async def send_reply(chat_id, trigger, mode, reply_msg, context):
try:
real_chat_id = chat_id
chat = context.chat
@ -144,12 +169,13 @@ async def send_reply(chat_id, reply_msg, context):
replace_data = {}
if chat_id < 0:
replace_data = {
"user_id": sender.id,
"first_name": sender.first_name,
"last_name": sender.last_name if sender.last_name else "",
"chat_id": chat.id,
"chat_name": chat.title
}
if sender:
replace_data["user_id"] = sender.id
replace_data["first_name"] = sender.first_name
replace_data["last_name"] = sender.last_name if sender.last_name else ""
else:
replace_data["user_id"] = chat_id
if sender:
@ -185,33 +211,38 @@ async def send_reply(chat_id, reply_msg, context):
chat_id = int(s[4:])
type_parse.remove(s)
break
if "plain" == re_type:
if ("file" in type_parse or "photo" in type_parse) and len(re_msg.split()) >= 2:
if could_send_msg:
update_last_time = True
await bot.send_message(chat_id, re_msg, reply_to=None)
elif "reply" == re_type and chat_id == real_chat_id:
if could_send_msg:
update_last_time = True
await bot.send_message(chat_id, re_msg, reply_to=context.id)
elif ("file" in type_parse or "photo" in type_parse) and len(re_msg.split()) >= 2:
if could_send_msg:
update_last_time = True
if not path.exists("/tmp"):
mkdir("/tmp")
re_data = re_msg.split()
file_name = "/tmp/" + re_data[0]
if re_data[1][0:7] == "file://":
copyfile(re_data[1][7:], file_name)
re_data = re_msg.split(" ")
cache_exists, cache_path = has_cache(chat_id, mode, trigger, re_data[0])
is_opened = cache_opened(chat_id, mode, trigger)
filename = "/tmp/" + re_data[0]
if is_opened:
filename = cache_path
if not cache_exists:
if re_data[1][0:7] == "file://":
re_data[1] = re_data[1][7:]
copyfile(" ".join(re_data[1:]), filename)
else:
fileget = requests.get(" ".join(re_data[1:]))
with open(filename, "wb") as f:
f.write(fileget.content)
else:
file_get = requests.get(" ".join(re_data[1:]))
with open(file_name, "wb") as f:
f.write(file_get.content)
if re_data[1][0:7] == "file://":
re_data[1] = re_data[1][7:]
copyfile(" ".join(re_data[1:]), filename)
else:
fileget = requests.get(" ".join(re_data[1:]))
with open(filename, "wb") as f:
f.write(fileget.content)
reply_to = None
if "reply" in type_parse:
reply_to = context.id
await bot.send_file(chat_id, file_name,
await bot.send_file(chat_id, filename,
reply_to=reply_to, force_document=("file" in type_parse))
remove(file_name)
if not is_opened:
remove(filename)
elif ("tgfile" in type_parse or "tgphoto" in type_parse) and len(re_msg.split()) >= 2:
if could_send_msg:
update_last_time = True
@ -221,8 +252,13 @@ async def send_reply(chat_id, reply_msg, context):
file_name = "/tmp/" + re_data[0]
_data = BytesIO()
re_data[1] = re_data[1].split("/")[-2:]
msg_chat_id = int(re_data[1][0])
try:
msg_chat_id = int(re_data[1][0])
except:
async with bot.conversation(re_data[1][0]) as conversation:
msg_chat_id = conversation.chat_id
msg_id_inchat = int(re_data[1][1])
await bot.send_message(chat_id, f"{msg_chat_id, msg_id_inchat}")
media_msg = (await bot.get_messages(msg_chat_id, msg_id_inchat))[0]
_data = BytesIO()
if media_msg and media_msg.media:
@ -238,15 +274,23 @@ async def send_reply(chat_id, reply_msg, context):
await bot.send_file(chat_id, file_name, reply_to=reply_to,
force_document=("tgfile" in type_parse))
remove(file_name)
elif "plain" in type_parse:
if could_send_msg:
update_last_time = True
await bot.send_message(chat_id, re_msg, reply_to=None)
elif "reply" in type_parse and chat_id == real_chat_id:
if could_send_msg:
update_last_time = True
await bot.send_message(chat_id, re_msg, reply_to=context.id)
elif "op" in type_parse:
if re_msg == "delete":
await context.delete()
elif re_msg.split()[0] == "sleep" and len(re_msg.split()) == 2:
sleep_time = re_msg.split()[1]
await asyncio.sleep(float(sleep_time))
chat_id = real_chat_id
except:
chat_id = real_chat_id
pass
chat_id = real_chat_id
if update_last_time:
global group_last_time
group_last_time[int(chat_id)] = time.time()
@ -386,8 +430,16 @@ async def reply_set(context):
redis_data = f"keyword.{chat_id}.single.{params[0]}.{rule_data}"
del params[0:2]
settings_dict = get_redis(redis_data)
cmd_list = ["help", "mode", "list", "freq", "show", "clear"]
cmd_dict = {"help": (1,), "mode": (2,), "list": (2, 3), "freq": (2,), "show": (1,), "clear": (1,)}
cmd_list = ["help", "mode", "list", "freq", "show", "cache", "clear"]
cmd_dict = {
"help": (1,),
"mode": (2,),
"list": (2, 3),
"freq": (2,),
"show": (1,),
"cache": (2,),
"clear": (1,)
}
if len(params) < 1:
await context.edit("参数错误")
await del_msg(context, 5)
@ -405,7 +457,12 @@ async def reply_set(context):
await del_msg(context, 15)
return
elif params[0] == "show":
defaults = {"mode": "未设置", "list": "未设置", "freq": "未设置"}
defaults = {
"mode": "未设置 (默认黑名单)",
"list": "未设置 (默认为空)",
"freq": "未设置 (默认为 1)",
"cache": "未设置 (默认关闭)"
}
msg = "Settings: \n"
for k, v in defaults.items():
msg += f"`{k}` -> `{settings_dict[k] if k in settings_dict else v}`\n"
@ -520,6 +577,41 @@ async def reply_set(context):
await context.edit("频率需为正数")
await del_msg(context, 5)
return
elif params[0] == "cache":
if params[1] == "0":
settings_dict["cache"] = "0"
redis.set(redis_data, save_rules(settings_dict, None))
await context.edit("已关闭缓存功能")
await del_msg(context, 5)
return
elif params[1] == "1":
settings_dict["cache"] = "1"
redis.set(redis_data, save_rules(settings_dict, None))
await context.edit("已开启缓存功能")
await del_msg(context, 5)
return
elif params[1] == "remove":
if redis_data == "keyword.settings":
rmtree("data/keyword_cache")
elif redis_data.split(".")[2] == "single":
rmtree(f"data/keyword_cache/{chat_id}/"
f"{redis_data.split('.')[3]}:{redis_data.split('.')[4]}")
else:
rmtree(f"data/keyword_cache/{chat_id}")
await context.edit("已删除缓存")
await del_msg(context, 5)
return
elif params[1] == "clear":
if "cache" in settings_dict:
del settings_dict["cache"]
redis.set(redis_data, save_rules(settings_dict, None))
await context.edit("清除成功")
await del_msg(context, 5)
return
else:
await context.edit(f"参数错误")
await del_msg(context, 5)
return
elif params[0] == "clear":
redis.delete(redis_data)
await context.edit("清除成功")
@ -537,106 +629,109 @@ async def reply_set(context):
async def funcset(context):
if not path.exists("plugins/keyword_func"):
mkdir("plugins/keyword_func")
params = context.parameter
params = " ".join(params).split("\n")
cmd = []
if len(params) >= 1:
cmd = params[0].split()
if len(cmd) > 0:
if len(cmd) == 1 and cmd[0] == "ls":
send_msg = "Functions:\n"
count = 1
for p in os.listdir("plugins/keyword_func"):
if path.isfile(f"plugins/keyword_func/{p}"):
try:
send_msg += f"{count}: `{p[:-3]}`\n"
count += 1
except:
pass
await context.edit(send_msg)
return
elif len(cmd) == 2 and cmd[0] == "show":
file_path = f"plugins/keyword_func/{cmd[1]}.py"
if path.exists(file_path) and path.isfile(file_path):
await bot.send_file(context.chat_id, file_path)
await context.edit("发送成功")
await del_msg(context, 5)
else:
await context.edit("函数不存在")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "del":
file_path = f"plugins/keyword_func/{cmd[1]}.py"
if path.exists(file_path) and path.isfile(file_path):
remove(file_path)
await context.edit("删除成功PagerMaid-Modify 正在重新启动。")
await bot.disconnect()
else:
await context.edit("函数不存在")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "new":
message = await context.get_reply_message()
if context.media:
message = context
cmd[1] = cmd[1].replace(".py", "")
if message and message.media:
try:
data = BytesIO()
await bot.download_file(message.media.document, data)
with open(f"plugins/keyword_func/{cmd[1]}.py", "wb") as f:
f.write(data.getvalue())
await context.edit(f"函数 {cmd[1]} 已添加PagerMaid-Modify 正在重新启动。")
await bot.disconnect()
except:
await context.edit("函数添加失败")
try:
params = context.parameter
params = " ".join(params).split("\n")
cmd = []
if len(params) >= 1:
cmd = params[0].split()
if len(cmd) > 0:
if len(cmd) == 1 and cmd[0] == "ls":
send_msg = "Functions:\n"
count = 1
for p in os.listdir("plugins/keyword_func"):
if path.isfile(f"plugins/keyword_func/{p}"):
try:
send_msg += f"{count}: `{p[:-3]}`\n"
count += 1
except:
pass
await context.edit(send_msg)
return
elif len(cmd) == 2 and cmd[0] == "show":
file_path = f"plugins/keyword_func/{cmd[1]}.py"
if path.exists(file_path) and path.isfile(file_path):
await bot.send_file(context.chat_id, file_path)
await context.edit("发送成功")
await del_msg(context, 5)
else:
await context.edit("未回复消息或回复的消息中不包含文件")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "install":
func_name = cmd[1]
func_online = \
json.loads(
requests.get("https://raw.githubusercontent.com/xtaodada/PagerMaid_Plugins/master"
"/keyword_func/list.json").content)['list']
if func_name in func_online:
func_directory = f"{working_dir}/plugins/keyword_func/"
file_path = func_name + ".py"
func_content = requests.get(
f"https://raw.githubusercontent.com/xtaodada/PagerMaid_Plugins/master"
f"/keyword_func/{func_name}.py").content
with open(file_path, 'wb') as f:
f.write(func_content)
if path.exists(f"{func_directory}{file_path}"):
remove(f"{func_directory}{file_path}")
move(file_path, func_directory)
else:
move(file_path, func_directory)
await context.edit(f"函数 {path.basename(file_path)[:-3]} 已添加PagerMaid-Modify 正在重新启动。")
await log(f"成功安装函数 {path.basename(file_path)[:-3]}.")
await bot.disconnect()
await context.edit("函数不存在")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "del":
file_path = f"plugins/keyword_func/{cmd[1]}.py"
if path.exists(file_path) and path.isfile(file_path):
remove(file_path)
await context.edit("删除成功PagerMaid-Modify 正在重新启动。")
await bot.disconnect()
else:
await context.edit("函数不存在")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "new":
message = await context.get_reply_message()
if context.media:
message = context
cmd[1] = cmd[1].replace(".py", "")
if message and message.media:
try:
data = BytesIO()
await bot.download_file(message.media.document, data)
with open(f"plugins/keyword_func/{cmd[1]}.py", "wb") as f:
f.write(data.getvalue())
await context.edit(f"函数 {cmd[1]} 已添加PagerMaid-Modify 正在重新启动。")
await bot.disconnect()
except:
await context.edit("函数添加失败")
await del_msg(context, 5)
else:
await context.edit("未回复消息或回复的消息中不包含文件")
await del_msg(context, 5)
return
elif len(cmd) == 2 and cmd[0] == "install":
func_name = cmd[1]
func_online = \
json.loads(
requests.get("https://raw.githubusercontent.com/xtaodada/PagerMaid_Plugins/master"
"/keyword_func/list.json").content)['list']
if func_name in func_online:
func_directory = f"{working_dir}/plugins/keyword_func/"
file_path = func_name + ".py"
func_content = requests.get(
f"https://raw.githubusercontent.com/xtaodada/PagerMaid_Plugins/master"
f"/keyword_func/{func_name}.py").content
with open(file_path, 'wb') as f:
f.write(func_content)
if path.exists(f"{func_directory}{file_path}"):
remove(f"{func_directory}{file_path}")
move(file_path, func_directory)
else:
move(file_path, func_directory)
await context.edit(f"函数 {path.basename(file_path)[:-3]} 已添加PagerMaid-Modify 正在重新启动。")
await log(f"成功安装函数 {path.basename(file_path)[:-3]}.")
await bot.disconnect()
else:
await context.edit(f"{func_name} 函数不存在")
await del_msg(context, 5)
return
elif len(cmd) == 1 and cmd[0] == "help":
await context.edit("""
`-funcset new <func_name>` (要回复带有文件的信息或自己附带文件)
`-funcset install <func_name>` 云端获取函数文件
`-funcset del <func_name>`
`-funcset show <func_name>` (发送文件)
`-funcset ls` (列出所有函数)""")
else:
await context.edit(f"{func_name} 函数不存在")
await context.edit("参数错误")
await del_msg(context, 5)
return
elif len(cmd) == 1 and cmd[0] == "help":
await context.edit("""
`-funcset new <func_name>` (要回复带有文件的信息或自己附带文件)
`-funcset install <func_name>` 云端获取函数文件
`-funcset del <func_name>`
`-funcset show <func_name>` (发送文件)
`-funcset ls` (列出所有函数)""")
return
else:
await context.edit("参数错误")
await del_msg(context, 5)
return
else:
await context.edit("参数错误")
await del_msg(context, 5)
return
except:
pass
@listener(incoming=True, ignore_edited=True)
@ -646,7 +741,7 @@ async def auto_reply(context):
try:
chat_id = context.chat_id
sender_id = context.sender_id
if context.id not in read_context:
if f"{chat_id}:{context.id}" not in read_context:
plain_dict = get_redis(f"keyword.{chat_id}.plain")
regex_dict = get_redis(f"keyword.{chat_id}.regex")
g_settings = get_redis("keyword.settings")
@ -675,8 +770,8 @@ async def auto_reply(context):
if tmp:
could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", []))
if could_reply:
read_context[context.id] = None
await send_reply(chat_id, parse_multi(v), context)
read_context[f"{chat_id}:{context.id}"] = None
await send_reply(chat_id, k, "plain", parse_multi(v), context)
for k, v in regex_dict.items():
pattern = re.compile(k)
if pattern.search(send_text):
@ -685,7 +780,7 @@ async def auto_reply(context):
if tmp:
could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", []))
if could_reply:
read_context[context.id] = None
read_context[f"{chat_id}:{context.id}"] = None
catch_pattern = r"\$\{regex_(?P<str>((?!\}).)+)\}"
count = 0
while re.search(catch_pattern, v) and count < 20:
@ -698,8 +793,8 @@ async def auto_reply(context):
capture_data = ""
v = v.replace("${regex_%s}" % group_name, capture_data)
count += 1
await send_reply(chat_id, parse_multi(v), context)
await send_reply(chat_id, k, "regex", parse_multi(v), context)
else:
del read_context[context.id]
del read_context[f"{chat_id}:{context.id}"]
except:
pass

View File

@ -362,10 +362,10 @@
},
{
"name": "keyword",
"version": "2.4",
"version": "2.5",
"section": "chat",
"maintainer": "c3b2a, xtaodada",
"size": "28.6 kb",
"size": "32.9 kb",
"supported": true,
"des-short": "群组关键词自动回复插件",
"des": "命令: keyword, replyset, funcset。"