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]
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://":
copyfile(re_data[1][7:], file_name)
re_data[1] = re_data[1][7:]
copyfile(" ".join(re_data[1:]), filename)
else:
file_get = requests.get(" ".join(re_data[1:]))
with open(file_name, "wb") as f:
f.write(file_get.content)
fileget = requests.get(" ".join(re_data[1:]))
with open(filename, "wb") as f:
f.write(fileget.content)
else:
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:]
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,14 +274,22 @@ 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:
pass
chat_id = real_chat_id
if update_last_time:
global group_last_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,6 +629,7 @@ async def reply_set(context):
async def funcset(context):
if not path.exists("plugins/keyword_func"):
mkdir("plugins/keyword_func")
try:
params = context.parameter
params = " ".join(params).split("\n")
cmd = []
@ -637,6 +730,8 @@ async def funcset(context):
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。"