diff --git a/.github/workflows/python beta.yml b/.github/workflows/python beta.yml new file mode 100644 index 0000000..4cd66a5 --- /dev/null +++ b/.github/workflows/python beta.yml @@ -0,0 +1,34 @@ +name: Github Beta commit to telegram + +on: + push: + branches: + - beta + +jobs: + build: + runs-on: ubuntu-latest + steps: + # 此步骤使用 GitHub 的 https://github.com/actions/checkout + - name: checkout actions + uses: actions/checkout@v1 + + # 设置python环境 + # 此步骤使用 GitHub 的 https://github.com/actions/setup-python + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + + # 安装依赖 + - name: Install dependencies + run: | + mkdir tmp && cd tmp + python -m pip install --upgrade pip + pip install requests + # 发送通知 + - name: Send notice + run: | + cd tmp + cp ../telegram_update_beta.py ./ + python telegram_update_beta.py ${{ secrets.TG_BOT_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index cf0c91d..6f7f6ca 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -23,9 +23,13 @@ jobs: # 安装依赖 - name: Install dependencies run: | + mkdir tmp && cd tmp python -m pip install --upgrade pip pip install requests # 发送通知 - name: Send notice - run: python telegram_update.py ${{ secrets.TG_BOT_TOKEN }} + run: | + cd tmp + cp ../telegram_update.py ./ + python telegram_update.py ${{ secrets.TG_BOT_TOKEN }} diff --git a/README.md b/README.md index 7f9260c..b343b4d 100644 --- a/README.md +++ b/README.md @@ -56,22 +56,38 @@ - `denyu` : 在某群中强制禁言某用户。 - `nthmsg` : 获取你发送的第 n 条消息。 - `portball` : 回复你要临时禁言的人的消息来实现XX秒的禁言。 + - `da` : 删除所有信息。 + - `diss` : 祖安对线语录。 + - `shangliu` : 上流对话工具。 + - `killallmembers` : 一键扬了群。 + - `aff` : 光速发Aff信息。 + - `stickertopic` : 贴纸转图片。 + - `vip` : vip 捐赠用户功能。 + - `calculator` : 小型计算器。 + - `paolu` : 一键跑路(删所有消息并禁言)。 + - `keyword` : 群组关键词自动回复插件。 + - `msgst` : 每天定时发送消息。 - profile (资料类) - `autochangename` : 自动更新 last_name 为时间等。 - `throwit` : 生成一张 扔头像 图片。 + - `mjx` : 随机带评价买家秀,随机涩气买家秀。 - `eat` : 生成一张 吃头像 图片。 - - `mjx` : 随机发一张淘宝买家秀 - daily (便民类) - `weather` : 查询天气。 - `xtao-some` : 一大堆便民功能。 - `yb-dl` : 上传 Youtube、Bilibili 视频到 telegram。 - `rate` : 汇率转换。 - - `netease` : 网易云热评。 + - `netease` : 随机一条网易云音乐热评。 - `hyperlink` : 生成隐藏链接。 - - `whois` : 查询域名信息 - - `resou` : 知乎,抖音,微博实时热搜 - - `tel` : 查询手机号码归属地等信息 - - `neteaseshuffle` : 随即一首网易云热门曲目 - - `neteasemusic` : 发送一首来自网易云的音乐 - - `shangliu` : 彩虹屁生成器,毒鸡汤生成器,营销号生成器 - - `diss` : 祖安语言生成器 + - `resou` : 微博,知乎,抖音实时热搜,B站实时排行榜。 + - `tel` : 查询手机号码归属地等信息。 + - `whois` : 查询域名whois信息。 + - `cosplay-multi` : 多网站随机获取Cos图。 + - `meizi` : 多网站随机获取写真。 + - `acg-multi` : 多网站随机获取ACG图。 + - `neteaseshuffle` : 随机网抑热歌。 + - `neteasemusic` : 网易云搜歌/随机热歌/点歌。 + - `videodl` : 下载YTB/B站视频。 + - `transfer` : 上传和下载文件。 + - `xjj` : 随机小姐姐写真。 + - `zpr` : 随机小姐姐或纸片人写真。 \ No newline at end of file diff --git a/aff.py b/aff.py index dc72fc0..055cade 100644 --- a/aff.py +++ b/aff.py @@ -10,7 +10,7 @@ from pagermaid.listener import listener async def aff(context): if not context.parameter: #发送aff信息 try: - with open("plugins/AffExtra/aff.txt", "r") as f: + with open("plugins/AffExtra/aff.txt", "r", encoding="UTF-8") as f: msg = f.read() except: msg = "" @@ -31,7 +31,7 @@ async def aff(context): msg = reply.message if not exists("plugins/AffExtra"): mkdir("plugins/AffExtra") - with open("plugins/AffExtra/aff.txt", "w") as f: + with open("plugins/AffExtra/aff.txt", "w", encoding="UTF-8") as f: f.write(msg) await context.edit("好耶 ! Aff信息保存成功。") sleep(3) diff --git a/eat.py b/eat.py index 0362206..990c501 100644 --- a/eat.py +++ b/eat.py @@ -48,7 +48,7 @@ async def eat(context): await context.edit("正在生成 吃头像 图片中 . . .") if context.reply_to_msg_id: reply_message = await context.get_reply_message() - user_id = reply_message.from_id + user_id = reply_message.sender_id target_user = await context.client(GetFullUserRequest(user_id)) if len(context.parameter) == 1: diu_round = True diff --git a/forcesend.py b/forcesend.py new file mode 100644 index 0000000..4dcae52 --- /dev/null +++ b/forcesend.py @@ -0,0 +1,34 @@ +""" 在不进群的情况下,向频道的附属群内强制发送消息。 """ + +# By tg @fruitymelon + +from pagermaid import log +from pagermaid.listener import listener + +helpmsg = """在不进群的情况下,强制向频道的附属群内发送消息。需要事先关注频道。 +用法:`-forcesend 消息内容` + +本插件用途狭窄,主要用于让别人以为你在群里。该群必须是频道的附属群,且你必须已经关注了对应的频道。 + +在该频道的任意一条消息的评论区,发送 `-forcesend 消息内容`,即可强行将文字发送到附属群内,但不出现在原频道消息的评论区中。 + +在普通群内使用 -forcesend 时,效果与直接发送消息基本没有区别。因此不做特殊判断。 +""" + +async def sendmsg(context, chat, origin_text): + text = origin_text.strip() + msg = await context.client.send_message(chat, text) + return msg + +@listener(is_plugin=True, outgoing=True, command="forcesend", diagnostics=True, ignore_edited=True, + description=helpmsg, + parameters="") +async def forcesend(context): + if not context.parameter: + await context.edit(helpmsg) + return + chat = await context.get_chat() + text = " ".join(context.parameter) + await context.delete() + await sendmsg(context, chat, text) + return diff --git a/ghs.py b/ghs.py new file mode 100644 index 0000000..bb3e125 --- /dev/null +++ b/ghs.py @@ -0,0 +1,41 @@ +import random +from time import sleep +from requests import get +from pagermaid.listener import listener +from os import remove + + +@listener(is_plugin=True, outgoing=True, command="ghs", + description="随机获取涩情写真") +async def ghs(context): + await context.edit("搞颜色中 . . .") + status = False + for _ in range (20): #最多重试20次 + website = random.randint(0,0) + filename = "ghs" + str(random.random())[2:] + ".png" + try: + if website == 0: + img = get("https://se.jiba.xyz/api.php") + if img.status_code == 200: + with open(filename, 'wb') as f: + f.write(img.content) + await context.edit("传颜色中 . . .") + await context.client.send_file(context.chat_id,filename,caption="#NSFW ⚠️色图警告⚠️") + status = True + break #成功了就赶紧结束啦! + except: + try: + remove(filename) + except: + pass + continue + try: + remove(filename) + except: + pass + try: + await context.delete() + except: + pass + if not status: + await context.client.send_message(context.chat_id,"出错了呜呜呜 ~ 试了好多好多次都无法访问到服务器(没有颜色搞啦!) 。") diff --git a/keyword.py b/keyword.py new file mode 100644 index 0000000..af27bab --- /dev/null +++ b/keyword.py @@ -0,0 +1,1047 @@ +import re, time, asyncio, requests, os, json +from io import BytesIO +from os import path, mkdir, remove, makedirs, chdir +from shutil import copyfile, move, rmtree +from uuid import uuid4 +from base64 import b64encode, b64decode +from importlib import import_module +from pagermaid import bot, redis, log, redis_status, working_dir +from pagermaid.listener import listener + +msg_freq = 1 +group_last_time = {} +read_context = {} + + +def is_num(x: str): + try: + x = int(x) + return isinstance(x, int) + except ValueError: + return False + + +def encode(s: str): + return str(b64encode(s.encode("utf-8")), "utf-8") + + +def decode(s: str): + return str(b64decode(s.encode("utf-8")), "utf-8") + + +def random_str(): + return str(uuid4()).replace("-", "") + + +def parse_rules(rules: str): + n_rules = {} + rules_parse = rules.split(";") + for p in rules_parse: + d = p.split(":") + if len(d) == 2: + key = decode(d[0]) + value = decode(d[1]) + n_rules[key] = value + return n_rules + + +def save_rules(rules: dict, placeholder: str): + n_rules = "" + for k, v in rules.items(): + if placeholder: + k = k.replace(placeholder, "'") + v = v.replace(placeholder, "'") + n_rules += encode(k) + ":" + encode(v) + ";" + return n_rules + + +def validate(user_id: str, mode: int, user_list: list): + if mode == 0: + return user_id not in user_list + elif mode == 1: + return user_id in user_list + else: + return False + + +def validsent(trig: int, tmp): + if tmp: + return tmp.get("trig", "0") + else: + return trig + + +def get_redis(db_key: str): + byte_data = redis.get(db_key) + byte_data = byte_data if byte_data else b"" + byte_data = str(byte_data, "ascii") + return parse_rules(byte_data) + + +def parse_multi(rule: str): + sep_ph = random_str() + col_ph = random_str() + rule = rule.replace(r"\||", sep_ph) + rule = rule.replace(r"\::", col_ph) + rule = rule.split("||") + n_rule = [] + for r in rule: + p = r.split("::") + p = [i.replace(sep_ph, "||") for i in p] + p = [i.replace(col_ph, "::") for i in p] + data = ["plain", ""] + if len(p) == 2: + data = p + else: + data[1] = p[0] + n_rule.append(data) + return n_rule + + +def get_capture(search_data, group_name: str): + try: + capture_data = search_data.group(group_name) + return capture_data + except: + return None + + +def get_rule(chat_id, rule_type, rule_index): + rule_index = int(rule_index) + rule_data = get_redis(f"keyword.{chat_id}.{rule_type}") + index = 0 + for k in rule_data.keys(): + if index == rule_index: + return encode(k) + index += 1 + return None + + +def valid_time(chat_id): + global msg_freq, group_last_time + cus_freq = get_redis(f"keyword.{chat_id}.settings").get("freq", msg_freq) + try: + cus_freq = float(cus_freq) + except: + cus_freq = msg_freq + n_time = time.time() + chat_id = int(chat_id) + if chat_id in group_last_time: + if n_time - group_last_time[chat_id] >= cus_freq: + return True + else: + return False + else: + 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 + + +def getsetting(chat_id, mode, trigger, name, default): + g_settings = get_redis("keyword.settings") + n_settings = get_redis(f"keyword.{chat_id}.settings") + s_settings = get_redis(f"keyword.{chat_id}.single.{mode}.{encode(trigger)}") + final = default + if s_settings.get(name, None): + final = s_settings[name] + elif n_settings.get(name, None): + final = n_settings[name] + elif g_settings.get(name, None): + final = g_settings[name] + return final + + +async def aexec(code, *args, **kwargs): + exec( + f"async def func(*args, **kwargs):" + + "".join(f"\n {p}" for p in code.split("\n")) + ) + return await locals()["func"](*args, **kwargs) + + +async def del_msg(context, t_lim): + await asyncio.sleep(t_lim) + try: + await context.delete() + except: + pass + + +async def send_reply(chat_id, trigger, mode, reply_msg, context): + try: + real_chat_id = chat_id + chat = context.chat + sender = context.sender + replace_data = {} + if chat_id < 0: + replace_data = { + "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: + replace_data["first_name"] = sender.first_name + replace_data["last_name"] = sender.last_name if sender.last_name else "" + if chat: + replace_data["chat_id"] = chat.id + last_name = chat.last_name + if not last_name: + last_name = "" + replace_data["chat_name"] = f"{chat.first_name} {last_name}" + update_last_time = False + could_send_msg = valid_time(chat_id) + message_list = [] + for re_type, re_msg in reply_msg: + try: + catch_pattern = r"\$\{func_(?P((?!\}).)+)\}" + count = 0 + bracket_str = random_str() + re_msg = re_msg.replace(r"\}", bracket_str) + while re.search(catch_pattern, re_msg) and count < 20: + func_exec = re.search(catch_pattern, re_msg).group("str") + try: + func_name = func_exec + func_args = None + if func_exec.strip().endswith(")"): + arg_index = func_exec.find("(") + func_name = func_exec[0:arg_index].replace(bracket_str, "}") + func_args = func_exec[arg_index + 1:-1].replace(bracket_str, "}") + module = f"import_module('data.keyword_func.{func_name}').main" + parameter = f"context{', %s' % func_args if func_args else ''}" + func_data = await eval(f"{module}({parameter})") + except: + func_data = "[RE]" + chdir(working_dir) + re_msg = re_msg.replace("${func_%s}" % func_exec, str(func_data)) + count += 1 + re_msg = re_msg.replace(bracket_str, "}") + for k, v in replace_data.items(): + re_type = re_type.replace(f"${k}", str(v)) + re_msg = re_msg.replace(f"${k}", str(v)) + type_parse = re_type.split(",") + edit_id = -1 + for s in type_parse: + if len(s) >= 5 and "ext_" == s[0:4] and is_num(s[4:]): + chat_id = int(s[4:]) + type_parse.remove(s) + elif len(s) >= 6 and "edit_" == s[0:5] and is_num(s[5:]): + edit_id = int(s[5:]) + type_parse.remove(s) + if ("file" in type_parse or "photo" in type_parse) and len(re_msg.split()) >= 2: + if could_send_msg: + update_last_time = True + re_data = re_msg.split(" ") + cache_exists, filename = has_cache(chat_id, mode, trigger, re_data[0]) + is_opened = cache_opened(chat_id, mode, trigger) + if is_opened: + 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: + 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 + redir = getsetting(chat_id, mode, trigger, "redir", "0") + reply = await context.get_reply_message() + if redir == "1" and reply: + reply_to = reply.id + if edit_id == -1: + message_list.append(await bot.send_file( + chat_id, + filename, + reply_to=reply_to, + force_document=("file" in type_parse) + )) + else: + edit_file = await bot.upload_file(filename) + message_list[edit_id] = await message_list[edit_id].edit( + file=edit_file, + force_document=("file" in type_parse) + ) + 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 + re_data = re_msg.split(" ") + re_data[0] = " ".join(re_data[0:-1]) + re_data[1] = re_data[-1:][0].split("/")[-2:] + cache_exists, filename = has_cache(chat_id, mode, trigger, re_data[0]) + is_opened = cache_opened(chat_id, mode, trigger) + _data = BytesIO() + 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]) + if is_opened: + if not cache_exists: + media_msg = await bot.get_messages(msg_chat_id, ids=msg_id_inchat, offset_id=0) + if media_msg and media_msg.media: + try: + await bot.download_file(media_msg.media.document, _data) + except: + await bot.download_file(media_msg.photo, _data) + with open(filename, "wb") as f: + f.write(_data.getvalue()) + else: + media_msg = await bot.get_messages(msg_chat_id, ids=msg_id_inchat, offset_id=0) + if media_msg and media_msg.media: + try: + await bot.download_file(media_msg.media.document, _data) + except: + await bot.download_file(media_msg.photo, _data) + with open(filename, "wb") as f: + f.write(_data.getvalue()) + reply_to = None + if "reply" in type_parse: + reply_to = context.id + redir = getsetting(chat_id, mode, trigger, "redir", "0") + reply = await context.get_reply_message() + if redir == "1" and reply: + reply_to = reply.id + if edit_id == -1: + message_list.append(await bot.send_file( + chat_id, + filename, + reply_to=reply_to, + force_document=("tgfile" in type_parse) + )) + else: + edit_file = await bot.upload_file(filename) + message_list[edit_id] = await message_list[edit_id].edit( + file=edit_file, + force_document=("tgfile" in type_parse) + ) + if not is_opened: + remove(filename) + elif "plain" in type_parse: + if could_send_msg: + update_last_time = True + if edit_id == -1: + message_list.append(await bot.send_message( + chat_id, + re_msg, + link_preview=("nopreview" not in type_parse) + )) + else: + message_list[edit_id] = await message_list[edit_id].edit( + re_msg, + link_preview=("nopreview" not in type_parse) + ) + elif "reply" in type_parse and chat_id == real_chat_id: + if could_send_msg: + update_last_time = True + if edit_id == -1: + reply_to = context.id + redir = getsetting(chat_id, mode, trigger, "redir", "0") + reply = await context.get_reply_message() + if redir == "1" and reply: + reply_to = reply.id + message_list.append(await bot.send_message( + chat_id, + re_msg, + reply_to=reply_to, + link_preview=("nopreview" not in type_parse) + )) + else: + message_list[edit_id] = await message_list[edit_id].edit( + re_msg, + link_preview=("nopreview" not in type_parse) + ) + 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)) + elif re_msg.split()[0] == "delself" and len(re_msg.split()) == 2: + await message_list[int(re_msg.split()[1])].delete() + elif re_msg.split()[0] == "trigger" and len(re_msg.split()) == 2: + await auto_reply(message_list[int(re_msg.split()[1])]) + elif re_msg.split("\n")[0].startswith("exec") and len(re_msg.split("\n")) >= 2: + args = [ + "\n".join(re_msg.split("\n")[1:]), + " ".join(re_msg.split("\n")[0].split(" ")[1:]) + ] + await eval(f"aexec(args[0]{f', {args[1]}' if args[1] else ''})") + chdir(working_dir) + except: + pass + chat_id = real_chat_id + if update_last_time: + global group_last_time + group_last_time[int(chat_id)] = time.time() + except: + pass + + +@listener(is_plugin=True, outgoing=True, command="keyword", + description="关键词自动回复", + parameters="``new '<规则>' '<回复信息>'` 或者 `del '<规则>'` 或者 `list` 或者 " + "`clear ") +async def reply(context): + if not redis_status(): + await context.edit("出错了呜呜呜 ~ Redis 离线,无法运行") + await del_msg(context, 5) + return + chat_id = context.chat_id + plain_dict = get_redis(f"keyword.{chat_id}.plain") + regex_dict = get_redis(f"keyword.{chat_id}.regex") + params = context.parameter + params = " ".join(params) + placeholder = random_str() + params = params.replace(r"\'", placeholder) + tmp_parse = params.split("'") + parse = [] + for i in range(len(tmp_parse)): + if len(tmp_parse[i].split()) != 0: + parse.append(tmp_parse[i]) + if len(parse) == 0 or ( + len(parse[0].split()) == 1 and parse[0].split()[0] in ("new", "del", "delid", "clear")) or len( + parse[0].split()) > 2: + await context.edit( + "[Code: -1] 格式错误,格式为 `-keyword` 加上 `new '<规则>' '<回复信息>'` 或者 " + "`del '<规则>'` 或者 `list` 或者 `clear `") + await del_msg(context, 10) + return + else: + parse[0] = parse[0].split() + if parse[0][0] == "new" and len(parse) == 3: + if parse[0][1] == "plain": + plain_dict[parse[1]] = parse[2] + redis.set(f"keyword.{chat_id}.plain", save_rules(plain_dict, placeholder)) + elif parse[0][1] == "regex": + regex_dict[parse[1]] = parse[2] + redis.set(f"keyword.{chat_id}.regex", save_rules(regex_dict, placeholder)) + else: + await context.edit( + "[Code: -1] 格式错误,格式为 `-keyword` 加上 `new '<规则>' '<回复信息>'` 或者 " + "`del '<规则>'` 或者 `list` 或者 `clear `") + await del_msg(context, 10) + return + await context.edit("设置成功") + await del_msg(context, 5) + elif parse[0][0] in ("del", "delid") and len(parse) == 2: + if parse[0][0] == "delid": + parse[1] = get_rule(chat_id, parse[0][1], parse[1]) + if parse[1]: + parse[1] = decode(parse[1]) + if parse[0][1] == "plain": + if parse[1] and parse[1] in plain_dict: + redis.delete(f"keyword.{chat_id}.single.plain.{encode(parse[1])}") + plain_dict.pop(parse[1]) + redis.set(f"keyword.{chat_id}.plain", save_rules(plain_dict, placeholder)) + else: + await context.edit("规则不存在") + await del_msg(context, 5) + return + elif parse[0][1] == "regex": + if parse[1] and parse[1] in regex_dict: + redis.delete(f"keyword.{chat_id}.single.regex.{encode(parse[1])}") + regex_dict.pop(parse[1]) + redis.set(f"keyword.{chat_id}.regex", save_rules(regex_dict, placeholder)) + else: + await context.edit("规则不存在") + await del_msg(context, 5) + return + else: + await context.edit( + "[Code: -1] 格式错误,格式为 `-keyword` 加上 `new '<规则>' '<回复信息>'` 或者 " + "`del '<规则>'` 或者 `list` 或者 `clear `") + await del_msg(context, 10) + return + await context.edit("删除成功") + await del_msg(context, 5) + elif parse[0][0] == "list" and len(parse) == 1: + plain_msg = "Plain: \n" + index = 0 + for k, v in plain_dict.items(): + plain_msg += f"`{index}`: `{k}` -> `{v}`\n" + index += 1 + regex_msg = "Regex: \n" + index = 0 + for k, v in regex_dict.items(): + regex_msg += f"`{index}`: `{k}` -> `{v}`\n" + index += 1 + await context.edit(plain_msg + "\n" + regex_msg) + elif parse[0][0] == "clear" and len(parse) == 1: + if parse[0][1] == "plain": + for k in plain_dict.keys(): + redis.delete(f"keyword.{chat_id}.single.plain.{encode(k)}") + redis.set(f"keyword.{chat_id}.plain", "") + elif parse[0][1] == "regex": + for k in regex_dict.keys(): + redis.delete(f"keyword.{chat_id}.single.regex.{encode(k)}") + redis.set(f"keyword.{chat_id}.regex", "") + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + await context.edit("清除成功") + await del_msg(context, 5) + else: + await context.edit( + "[Code: -1] 格式错误,格式为 `-keyword` 加上 `new '<规则>' '<回复信息>'` 或者 " + "`del '<规则>'` 或者 `list` 或者 `clear `") + await del_msg(context, 10) + return + + +@listener(outgoing=True, command="replyset", + description="自动回复设置", + parameters="help") +async def reply_set(context): + if not redis_status(): + await context.edit("出错了呜呜呜 ~ Redis 离线,无法运行") + await del_msg(context, 5) + return + chat_id = context.chat_id + params = context.parameter + redis_data = f"keyword.{chat_id}.settings" + if len(params) >= 1 and params[0] == "global": + redis_data = "keyword.settings" + del params[0] + elif len(params) >= 2 and params[0] in ("plain", "regex") and is_num(params[1]): + rule_data = get_rule(chat_id, params[0], params[1]) + if rule_data: + redis_data = f"keyword.{chat_id}.single.{params[0]}.{rule_data}" + del params[0:2] + settings_dict = get_redis(redis_data) + cmd_dict = { + "help": (1,), + "mode": (2,), + "list": (2, 3), + "freq": (2,), + "trig": (2,), + "show": (1,), + "cache": (2,), + "redir": (2,), + "status": (2,), + "clear": (1,) + } + if len(params) < 1: + await context.edit("参数错误") + await del_msg(context, 5) + return + if params[0] in cmd_dict and len(params) in cmd_dict[params[0]]: + if params[0] == "help": + await context.edit(''' +`-replyset show` 或 +`-replyset clear` 或 +`-replyset mode <0/1/clear>` ( 0 表示黑名单,1 表示白名单 ) 或 +`-replyset list [user_id]` 或 +`-replyset freq ` ( float 表示一个正的浮点数,clear 为清除 ) 或 +`-replyset trig <0/1/clear>` ( 0 为关闭,1 为开启,clear 为清除 ) 或 +`-replyset cache <0/1/clear>` ( 0 为关闭,1 为开启 ) 或 +`-replyset status <0/1/clear>` ( 0 为关闭,1 为开启 ) 。 +在 `-replyset` 后面加上 `global` 即为全局设置。 +在 `-replyset` 后面加上 `plain/regex` 规则序号 可以单独设置一条规则。''') + await del_msg(context, 15) + return + elif params[0] == "show": + defaults = { + "mode": "未设置 (默认黑名单)", + "list": "未设置 (默认为空)", + "freq": "未设置 (默认为 1)", + "trig": "未设置 (默认关闭)", + "cache": "未设置 (默认关闭)", + "redir": "未设置 (默认关闭)", + "status": "未设置 (默认开启)" + } + msg = "Settings: \n" + for k, v in defaults.items(): + msg += f"`{k}` -> `{settings_dict[k] if k in settings_dict else v}`\n" + await context.edit(msg) + return + elif params[0] == "mode": + if params[1] in ("0", "1"): + settings_dict["mode"] = params[1] + redis.set(redis_data, save_rules(settings_dict, None)) + if params[1] == "0": + await context.edit("模式已更改为黑名单") + elif params[1] == "1": + await context.edit("模式已更改为白名单") + await del_msg(context, 5) + return + elif params[1] == "clear": + if "mode" in settings_dict: + del settings_dict["mode"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("清除成功") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + elif params[0] == "list": + if params[1] == "show" and len(params) == 2: + user_list = settings_dict.get("list", None) + if user_list: + msg = "List: \n" + for p in user_list.split(","): + msg += f"`{p}`\n" + await context.edit(msg) + return + else: + await context.edit("列表为空") + await del_msg(context, 5) + return + elif params[1] == "add" and len(params) == 3: + if is_num(params[2]): + tmp = settings_dict.get("list", None) + if not tmp: + settings_dict["list"] = params[2] + else: + settings_dict["list"] += f",{params[2]}" + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("添加成功") + await del_msg(context, 5) + return + else: + await context.edit("user_id 需为整数") + await del_msg(context, 5) + return + elif params[1] == "del" and len(params) == 3: + if is_num(params[2]): + tmp = settings_dict.get("list", None) + if tmp: + user_list = settings_dict["list"].split(",") + if params[2] in user_list: + user_list.remove(params[2]) + settings_dict["list"] = ",".join(user_list) + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("删除成功") + await del_msg(context, 5) + return + else: + await context.edit("user_id 不在列表") + await del_msg(context, 5) + return + else: + await context.edit("列表为空") + await del_msg(context, 5) + return + else: + await context.edit("user_id 需为整数") + await del_msg(context, 5) + return + elif params[1] == "clear" and len(params) == 2: + if "list" in settings_dict: + del settings_dict["list"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("清除成功") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + elif params[0] == "freq": + if redis_data == f"keyword.{chat_id}.settings": + if params[1] == "clear": + if "freq" in settings_dict: + del settings_dict["freq"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("清除成功") + await del_msg(context, 5) + return + else: + try: + tmp = float(params[1]) + if tmp > 0: + settings_dict["freq"] = params[1] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("设置成功") + await del_msg(context, 5) + return + else: + await context.edit("频率需为正数") + await del_msg(context, 5) + return + except: + await context.edit("频率需为正数") + await del_msg(context, 5) + return + else: + await context.edit("此项无法使用全局设置和单独设置") + return + elif params[0] == "trig": + if params[1] == "0": + settings_dict["trig"] = "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["trig"] = "1" + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已开启自我触发") + await del_msg(context, 5) + return + elif params[1] == "clear": + if "trig" in settings_dict: + del settings_dict["trig"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已清除自我触发设置") + await del_msg(context, 5) + return + else: + 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("参数错误") + await del_msg(context, 5) + return + elif params[0] == "redir": + if params[1] == "0": + settings_dict["redir"] = "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["redir"] = "1" + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已开启回复穿透") + await del_msg(context, 5) + return + elif params[1] == "clear": + if "redir" in settings_dict: + del settings_dict["redir"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已清除回复穿透设置") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + elif params[0] == "status": + if redis_data == f"keyword.{chat_id}.settings": + if params[1] == "0": + settings_dict["status"] = "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["status"] = "1" + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已开启此聊天的关键词回复") + await del_msg(context, 5) + return + elif params[1] == "clear": + if "status" in settings_dict: + del settings_dict["status"] + redis.set(redis_data, save_rules(settings_dict, None)) + await context.edit("已清除此设置") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + else: + await context.edit("此项无法使用全局设置和单独设置") + return + elif params[0] == "clear": + redis.delete(redis_data) + await context.edit("清除成功") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + + +@listener(outgoing=True, command="funcset", + description="设置自定义函数", + parameters="help") +async def funcset(context): + if not path.exists("data/keyword_func"): + makedirs("data/keyword_func") + 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("data/keyword_func"): + if path.isfile(f"data/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"data/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"data/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"data/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"data/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 ` (要回复带有文件的信息或自己附带文件) +`-funcset install ` (云端获取函数文件) +`-funcset del ` +`-funcset show ` (发送文件) +`-funcset ls` (列出所有函数)""") + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + except: + pass + + +@listener(outgoing=True, command="keydata", + description="设置规则数据", + parameters="dump / load") +async def setdata(context): + try: + chat_id = context.chat_id + params = context.parameter + if params[0] == "dump": + data = redis.get(f"keyword.{chat_id}.{params[1]}") + if not data: + await context.edit("无规则数据") + await del_msg(context, 5) + return + data = str(data, "ascii") + await context.edit(data) + return + elif params[0] == "load": + redis.set(f"keyword.{chat_id}.{params[1]}", params[2]) + await context.edit("设置成功") + await del_msg(context, 5) + return + else: + await context.edit("参数错误") + await del_msg(context, 5) + return + except: + await context.edit("运行错误") + await del_msg(context, 5) + return + + +@listener(incoming=True, outgoing=True, ignore_edited=False) +async def auto_reply(context): + if not redis_status(): + return + try: + chat_id = context.chat_id + sender_id = context.sender_id + if f"{chat_id}:{context.id}" not in read_context: + n_settings = get_redis(f"keyword.{chat_id}.settings") + if n_settings.get("status", "1") == "0": + return + self_id = (await bot.get_me()).id + g_settings = get_redis("keyword.settings") + plain_dict = get_redis(f"keyword.{chat_id}.plain") + regex_dict = get_redis(f"keyword.{chat_id}.regex") + g_mode = g_settings.get("mode", None) + n_mode = n_settings.get("mode", None) + mode = "0" + g_list = g_settings.get("list", None) + n_list = n_settings.get("list", None) + user_list = [] + g_trig = g_settings.get("trig", None) + n_trig = n_settings.get("trig", None) + trig = "0" + if g_mode and n_mode: + mode = n_mode + elif g_mode or n_mode: + mode = g_mode if g_mode else n_mode + if g_list and n_list: + user_list = n_list + elif g_list or n_list: + user_list = g_list if g_list else n_list + if g_trig and n_trig: + trig = n_trig + elif g_trig or n_trig: + trig = g_trig if g_trig else n_trig + send_text = context.text + if not send_text: + send_text = "" + self_sent = self_id == sender_id + for k, v in plain_dict.items(): + if k in send_text: + tmp = get_redis(f"keyword.{chat_id}.single.plain.{encode(k)}") + could_reply = validate(str(sender_id), int(mode), user_list) + if tmp: + could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", [])) + if could_reply and (not self_sent or validsent(int(trig), tmp)): + 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): + tmp = get_redis(f"keyword.{chat_id}.single.regex.{encode(k)}") + could_reply = validate(str(sender_id), int(mode), user_list) + if tmp: + could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", [])) + if could_reply and (not self_sent or validsent(int(trig), tmp)): + read_context[f"{chat_id}:{context.id}"] = None + catch_pattern = r"\$\{regex_(?P((?!\}).)+)\}" + count = 0 + while re.search(catch_pattern, v) and count < 20: + search_data = re.search(k, send_text) + group_name = re.search(catch_pattern, v).group("str") + capture_data = get_capture(search_data, group_name) + if not capture_data: + capture_data = "" + if re.search(catch_pattern, capture_data): + capture_data = "" + v = v.replace("${regex_%s}" % group_name, capture_data) + count += 1 + await send_reply(chat_id, k, "regex", parse_multi(v), context) + except: + pass diff --git a/keyword_func/advanced.py b/keyword_func/advanced.py new file mode 100644 index 0000000..9a7effb --- /dev/null +++ b/keyword_func/advanced.py @@ -0,0 +1,356 @@ +import re, time, asyncio, requests, os, json +from io import BytesIO +from os import path, mkdir, remove, makedirs, chdir +from shutil import copyfile, move, rmtree +from uuid import uuid4 +from base64 import b64encode, b64decode +from importlib import import_module +from pagermaid import bot, redis, log, redis_status, working_dir +from pagermaid.listener import listener + +msg_freq = 1 +group_last_time = {} +read_context = {} + + +def is_num(x: str): + try: + x = int(x) + return isinstance(x, int) + except ValueError: + return False + + +def encode(s: str): + return str(b64encode(s.encode('utf-8')), 'utf-8') + + +def decode(s: str): + return str(b64decode(s.encode('utf-8')), 'utf-8') + + +def random_str(): + return str(uuid4()).replace('-', '') + + +def parse_rules(rules: str): + n_rules = {} + rules_parse = rules.split(";") + for p in rules_parse: + d = p.split(":") + if len(d) == 2: + key = decode(d[0]) + value = decode(d[1]) + n_rules[key] = value + return n_rules + + +def save_rules(rules: dict, placeholder: str): + n_rules = "" + for k, v in rules.items(): + if placeholder: + k = k.replace(placeholder, "'") + v = v.replace(placeholder, "'") + n_rules += encode(k) + ":" + encode(v) + ";" + return n_rules + + +def validate(user_id: str, mode: int, user_list: list): + if mode == 0: + return user_id not in user_list + elif mode == 1: + return user_id in user_list + else: + return False + + +def get_redis(db_key: str): + byte_data = redis.get(db_key) + byte_data = byte_data if byte_data else b"" + byte_data = str(byte_data, "ascii") + return parse_rules(byte_data) + + +def parse_multi(rule: str): + sep_ph = random_str() + col_ph = random_str() + rule = rule.replace(r"\||", sep_ph) + rule = rule.replace(r"\::", col_ph) + rule = rule.split("||") + n_rule = [] + for r in rule: + p = r.split("::") + p = [i.replace(sep_ph, "||") for i in p] + p = [i.replace(col_ph, "::") for i in p] + data = ['plain', ''] + if len(p) == 2: + data = p + else: + data[1] = p[0] + n_rule.append(data) + return n_rule + + +def get_capture(search_data, group_name: str): + try: + capture_data = search_data.group(group_name) + return capture_data + except: + return None + + +def get_rule(chat_id, rule_type, rule_index): + rule_index = int(rule_index) + rule_data = get_redis(f"keyword.{chat_id}.{rule_type}") + index = 0 + for k in rule_data.keys(): + if index == rule_index: + return encode(k) + index += 1 + return None + + +def valid_time(chat_id): + global msg_freq, group_last_time + cus_freq = get_redis(f"keyword.{chat_id}.settings").get("freq", msg_freq) + try: + cus_freq = float(cus_freq) + except: + cus_freq = msg_freq + n_time = time.time() + chat_id = int(chat_id) + if chat_id in group_last_time: + if n_time - group_last_time[chat_id] >= cus_freq: + return True + else: + return False + else: + 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: + await context.delete() + except: + pass + + +async def send_reply(chat_id, trigger, mode, reply_msg, context): + try: + real_chat_id = chat_id + chat = context.chat + sender = context.sender + replace_data = {} + if chat_id < 0: + replace_data = { + "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: + replace_data["first_name"] = sender.first_name + replace_data["last_name"] = sender.last_name if sender.last_name else "" + if chat: + replace_data["chat_id"] = chat.id + last_name = chat.last_name + if not last_name: + last_name = "" + replace_data["chat_name"] = f"{chat.first_name} {last_name}" + update_last_time = False + could_send_msg = valid_time(chat_id) + for re_type, re_msg in reply_msg: + try: + for k, v in replace_data.items(): + re_type = re_type.replace(f"${k}", str(v)) + re_msg = re_msg.replace(f"${k}", str(v)) + type_parse = re_type.split(",") + type_parse = [(p[4:] if p[0:3] == "adv" else "") for p in type_parse] + for s in type_parse: + if len(s) >= 5 and "ext_" == s[0:4] and is_num(s[4:]): + chat_id = int(s[4:]) + type_parse.remove(s) + break + if ("file" in type_parse or "photo" in type_parse) and len(re_msg.split()) >= 2: + if could_send_msg: + update_last_time = True + 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: + 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, filename, + reply_to=reply_to, force_document=("file" in type_parse)) + 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 + if not path.exists("/tmp"): + mkdir("/tmp") + re_data = re_msg.split() + 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: + if "tgfile" in type_parse: + await bot.download_file(media_msg.media.document, _data) + else: + await bot.download_file(media_msg.photo, _data) + with open(file_name, "wb") as f: + f.write(_data.getvalue()) + reply_to = None + if "reply" in type_parse: + reply_to = context.id + 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, + link_preview=("nopreview" not in type_parse)) + 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, + link_preview=("nopreview" not in type_parse)) + 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)) + except: + pass + chat_id = real_chat_id + if update_last_time: + global group_last_time + group_last_time[int(chat_id)] = time.time() + except: + pass + + +async def main(context): + if not redis_status(): + return + try: + chat_id = context.chat_id + sender_id = context.sender_id + 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") + n_settings = get_redis(f"keyword.{chat_id}.settings") + g_mode = g_settings.get("mode", None) + n_mode = n_settings.get("mode", None) + mode = "0" + g_list = g_settings.get("list", None) + n_list = n_settings.get("list", None) + user_list = [] + if g_mode and n_mode: + mode = n_mode + elif g_mode or n_mode: + mode = g_mode if g_mode else n_mode + if g_list and n_list: + user_list = n_list + elif g_list or n_list: + user_list = g_list if g_list else n_list + send_text = context.text + if not send_text: + send_text = "" + for k, v in plain_dict.items(): + if k in send_text: + tmp = get_redis(f"keyword.{chat_id}.single.plain.{encode(k)}") + could_reply = validate(str(sender_id), int(mode), user_list) + if tmp: + could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", [])) + if could_reply: + 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): + tmp = get_redis(f"keyword.{chat_id}.single.regex.{encode(k)}") + could_reply = validate(str(sender_id), int(mode), user_list) + if tmp: + could_reply = validate(str(sender_id), int(tmp.get("mode", "0")), tmp.get("list", [])) + if could_reply: + read_context[f"{chat_id}:{context.id}"] = None + catch_pattern = r"\$\{regex_(?P((?!\}).)+)\}" + count = 0 + while re.search(catch_pattern, v) and count < 20: + search_data = re.search(k, send_text) + group_name = re.search(catch_pattern, v).group("str") + capture_data = get_capture(search_data, group_name) + if not capture_data: + capture_data = "" + if re.search(catch_pattern, capture_data): + capture_data = "" + v = v.replace("${regex_%s}" % group_name, capture_data) + count += 1 + await send_reply(chat_id, k, "regex", parse_multi(v), context) + else: + del read_context[f"{chat_id}:{context.id}"] + except: + pass + return "" diff --git a/keyword_func/list.json b/keyword_func/list.json new file mode 100644 index 0000000..69b03a8 --- /dev/null +++ b/keyword_func/list.json @@ -0,0 +1 @@ +{"list": ["ranstr", "newkeyword", "advanced", "maf"]} diff --git a/keyword_func/maf.py b/keyword_func/maf.py new file mode 100644 index 0000000..e3d08de --- /dev/null +++ b/keyword_func/maf.py @@ -0,0 +1,33 @@ +from asyncio import sleep + + +async def del_msg(context, t): + await sleep(t) + try: + await context.delete() + except: + pass + + +async def main(context, text, tgurl, mode=0, re=1, t=-1): + ids = tgurl.split("/")[-2:] + try: + ids[0] = int(ids[0]) + except: + async with context.client.conversation(ids[0]) as conv: + ids[0] = conv.chat_id + message = await context.client.get_messages(ids[0], ids=int(ids[1])) + re_id = context.id + if message.photo: + data = message.photo + else: + data = message.media.document + if context.is_reply: + me = await context.client.get_me() + if context.sender.id == me.id: + msg = await context.get_reply_message() + re_id = msg.id + sent = await context.client.send_message(context.chat_id, text, file=data, force_document=mode, reply_to=(re_id if re else None)) + if t >= 0: + await del_msg(sent, t) + return "" diff --git a/keyword_func/newkeyword.py b/keyword_func/newkeyword.py new file mode 100644 index 0000000..b27b963 --- /dev/null +++ b/keyword_func/newkeyword.py @@ -0,0 +1,94 @@ +import json +from os import remove, mkdir +from os.path import isfile, exists +from telethon.tl.types import ChannelParticipantsAdmins + +extra_path = "plugins/keyword_func/extra" + + +def get_data(filename): + filepath = f"{extra_path}/{filename}" + if exists(filepath): + with open(filepath, "r") as f: + data = f.read() + return data + else: + return "" + + +def write_data(filename, data): + filepath = f"{extra_path}/{filename}" + with open(filepath, "w") as f: + f.write(data) + + +def init_file(filename): + if exists(extra_path): + if isfile(extra_path): + remove(extra_path) + mkdir(extra_path) + else: + mkdir(extra_path) + if not exists(f"{extra_path}/{filename}"): + with open(f"{extra_path}/{filename}", "w") as f: + f.write("{}") + + +async def main(context): + try: + chat_id = context.chat_id + if chat_id < 0: + admins = await context.client.get_participants(context.chat, filter=ChannelParticipantsAdmins) + text = context.text + if not text: + text = "" + if text.split()[0] == "/add": + if context.sender in admins: + try: + parse = text.split("\n") + parse[0] = " ".join(parse[0].split()[1:]) + init_file(f"newkeyword_{chat_id}.json") + data = json.loads(get_data(f"newkeyword_{chat_id}.json")) + data[parse[0]] = parse[1] + write_data(f"newkeyword_{chat_id}.json", json.dumps(data)) + await context.client.send_message(chat_id, "设置成功", reply_to=context.id) + except: + await context.client.send_message(chat_id, "设置失败", reply_to=context.id) + else: + await context.client.send_message(chat_id, "您无权进行此操作", reply_to=context.id) + elif text.split()[0] == "/del": + if context.sender in admins: + try: + init_file(f"newkeyword_{chat_id}.json") + data = json.loads(get_data(f"newkeyword_{chat_id}.json")) + del data[" ".join(text.split(" ")[1:])] + write_data(f"newkeyword_{chat_id}.json", json.dumps(data)) + await context.client.send_message(chat_id, "删除成功", reply_to=context.id) + except: + await context.client.send_message(chat_id, "删除失败", reply_to=context.id) + else: + await context.client.send_message(chat_id, "您无权进行此操作", reply_to=context.id) + elif text.split()[0] == "/list": + if context.sender in admins: + try: + init_file(f"newkeyword_{chat_id}.json") + data = json.loads(get_data(f"newkeyword_{chat_id}.json")) + message = "" + count = 1 + for k, v in data.items(): + message += f"`{count}` : `{k}` -> `{v}`\n" + count += 1 + await context.client.send_message(context.sender_id, message) + await context.client.send_message(chat_id, "已发送私聊", reply_to=context.id) + except: + await context.client.send_message(chat_id, "获取失败", reply_to=context.id) + else: + await context.client.send_message(chat_id, "您无权进行此操作", reply_to=context.id) + else: + data = json.loads(get_data(f"newkeyword_{chat_id}.json")) + for k, v in data.items(): + if k in text: + await context.client.send_message(chat_id, v, reply_to=context.id) + return "" + except: + return "" diff --git a/keyword_func/ranstr.py b/keyword_func/ranstr.py new file mode 100644 index 0000000..23c80b4 --- /dev/null +++ b/keyword_func/ranstr.py @@ -0,0 +1,14 @@ +import random +import string + +async def main(context): + try: + length = int(context.text.split()[1]) + except: + length = 8 + if length > 1000: + length = 100 + s = "" + for i in range(length): + s += random.choice(string.ascii_letters + string.digits) + return f"`{s}`" diff --git a/list.json b/list.json index 064abb8..13b4a82 100644 --- a/list.json +++ b/list.json @@ -42,33 +42,33 @@ }, { "name": "sendat", - "version": "1.2", + "version": "1.3", "section": "chat", "maintainer": "fruitymelon", - "size": "13.1 kb", + "size": "15.0 kb", "supported": true, "des-short": "定时发送消息。", - "des": "这个人很懒,什么都没有留下。" + "des": "命令:sendat,详情见 -help sendat" }, { "name": "weather", - "version": "1.0", + "version": "1.1", "section": "daily", "maintainer": "xtaodada", - "size": "1.5 kb", + "size": "2.9 kb", "supported": true, "des-short": "查询天气。", "des": "这个人很懒,什么都没有留下。" }, { "name": "xtao-some", - "version": "1.11", + "version": "1.154", "section": "daily", "maintainer": "xtaodada", "size": "18.8 kb", "supported": true, "des-short": "一大堆便民功能。", - "des": "超多功能 例如 -ip -pixiv -guess 等。" + "des": "超多功能 例如 -ip -ipping -guess -t -getdel 等。" }, { "name": "yb-dl", @@ -82,7 +82,7 @@ }, { "name": "throwit", - "version": "1.6", + "version": "1.61", "section": "profile", "maintainer": "xtaodada", "size": "6.9 kb", @@ -152,10 +152,10 @@ }, { "name": "portball", - "version": "1.41", + "version": "1.42", "section": "chat", "maintainer": "Pentacene", - "size": "4.3 kb", + "size": "2.8 kb", "supported": true, "des-short": "回复你要临时禁言的人的消息来实现XX秒的禁言。", "des": "portball <原因> <秒数>" @@ -192,7 +192,7 @@ }, { "name": "whois", - "version": "1.1", + "version": "1.12", "section": "daily", "maintainer": "KorenKrita", "size": "1.1 kb", @@ -202,7 +202,7 @@ }, { "name": "eat", - "version": "1.0", + "version": "1.01", "section": "profile", "maintainer": "SF_PICK", "size": "6.4 kb", @@ -222,7 +222,7 @@ }, { "name": "meizi", - "version": "1.7", + "version": "1.8", "section": "daily", "maintainer": "TNTcraftHIM", "size": "4.0 kb", @@ -282,10 +282,10 @@ }, { "name": "neteasemusic", - "version": "4.2", + "version": "4.3", "section": "daily", "maintainer": "TNTcraftHIM", - "size": "29.1 kb", + "size": "28.8 kb", "supported": true, "des-short": "网易云搜歌/随机热歌/点歌", "des": "可以在线搜索并且快速点歌(可回复信息点歌),也支持随机热歌功能,支持解锁VIP/灰色歌曲。命令:nem。" @@ -302,7 +302,7 @@ }, { "name": "videodl", - "version": "0.1", + "version": "0.1.1", "section": "daily", "maintainer": "TNTcraftHIM", "size": "5.3 kb", @@ -312,7 +312,7 @@ }, { "name": "aff", - "version": "1.1", + "version": "1.2", "section": "chat", "maintainer": "TNTcraftHIM", "size": "2.0 kb", @@ -332,13 +332,13 @@ }, { "name": "vip", - "version": "0.1", + "version": "0.2", "section": "chat", "maintainer": "xtaodada", "size": "4.0 kb", "supported": true, "des-short": "vip 捐赠用户功能", - "des": "命令:天气:weather 。" + "des": "命令:天气:weather Pixiv:pixiv。与 weather 插件冲突" }, { "name": "calculator", @@ -369,6 +369,76 @@ "supported": true, "des-short": "自动回复sticker", "des": "-ars" + }, + { + "name": "keyword", + "version": "2.61", + "section": "chat", + "maintainer": "c3b2a,xtaodada", + "size": "44.0 kb", + "supported": true, + "des-short": "关键词自动回复插件。", + "des": "命令: keyword, keydata, replyset, funcset。" + }, + { + "name": "msgst", + "version": "1.1", + "section": "chat", + "maintainer": "c3b2a", + "size": "3.1 kb", + "supported": true, + "des-short": "每天定时发送消息", + "des": "命令: msgst, msgset。" + }, + { + "name": "transfer", + "version": "1.0", + "section": "daily", + "maintainer": "c3b2a", + "size": "2.7 kb", + "supported": true, + "des-short": "上传和下载文件。", + "des": "命令: transfer" + }, + { + "name": "xjj", + "version": "1.0", + "section": "daily", + "maintainer": "Moriarty-989", + "size": "1.4 kb", + "supported": true, + "des-short": "随机小姐姐写真。", + "des": "命令: xjj" + }, + { + "name": "zpr", + "version": "1.0", + "section": "daily", + "maintainer": "Moriarty-989", + "size": "1.4 kb", + "supported": true, + "des-short": "随机小姐姐或纸片人写真。", + "des": "命令: xjj" + }, + { + "name": "forcesend", + "version": "1.0", + "section": "chat", + "maintainer": "fruitymelon", + "size": "1.3 kb", + "supported": true, + "des-short": "无需进群,向频道附属群内发送消息", + "des": "命令:forcesend" + }, + { + "name": "ghs", + "version": "1.0", + "section": "chat", + "maintainer": "akun", + "size": "1.3 kb", + "supported": true, + "des-short": "发送ghs获取一张色图", + "des": "命令:ghs" } ] } diff --git a/meizi.py b/meizi.py index 5d6a66e..16417ea 100644 --- a/meizi.py +++ b/meizi.py @@ -21,25 +21,25 @@ async def mz(context): elif website == 2: img = get("https://api.66mz8.com/api/rand.tbimg.php") elif website == 3: - img = get("https://api.isoyu.com/mm_images.php") + img = get("https://api.nmb.show/xiaojiejie2.php") elif website == 4: img = get("https://uploadbeta.com/api/pictures/random/?key=%E5%A5%B3") elif website == 5: - img = get("https://uploadbeta.com/api/pictures/random/?key=%E5%A6%B9%E5%AD%90") + img = get("https://uploadbeta.com/api/pictures/random/?key=%E5%86%85%E8%A1%A3") elif website == 6: img = get("https://uploadbeta.com/api/pictures/random/?key=%E6%8E%A8%E5%A5%B3%E9%83%8E") elif website == 7: - img = get("https://uploadbeta.com/api/pictures/random/?key=%E7%BE%8E%E5%A5%B3") + img = get("https://tvv.tw/xjj/meinv/img-ct.php") elif website == 8: img = get("https://api.diskgirl.com/image/api.php?t=xinggan&v=" + str(random.uniform(0, 100))) elif website == 9: img = get("https://api.lyiqk.cn/sexylady") elif website == 10: - img = get("https://api.pingping6.com/tools/acg3/index.php") + img = get("https://tvv.tw/xjj/meinv/img.php") elif website == 11: img = get("https://api.uomg.com/api/rand.img3") elif website == 12: - img = get("https://api.diskgirl.com/image/api.php?t=&v=0.9451485087333713") + img = get("https://api.nmb.show/xiaojiejie1.php") elif website == 13: img = get("https://uploadbeta.com/api/pictures/random/?key=%E6%80%A7%E6%84%9F") if img.status_code == 200: diff --git a/msgst.py b/msgst.py new file mode 100644 index 0000000..a114e9d --- /dev/null +++ b/msgst.py @@ -0,0 +1,83 @@ +import time, asyncio +from pagermaid import bot, redis, redis_status +from pagermaid.listener import listener + +def is_num(x: str): + try: + x = int(x) + return isinstance(x, int) + except ValueError: + return False + +def get_bot(): + data = [1527463252, "msg_schedule_bot"] + if redis_status(): + n_id = redis.get("msgst.bot_id") + n_un = redis.get("msgst.bot_un") + if n_id and is_num(str(n_id, "ascii")): data[0] = int(str(n_id, "ascii")) + if n_un: data[1] = str(n_un, "ascii") + return data + +async def del_msg(context, t_lim): + await asyncio.sleep(t_lim) + await context.delete() + +@listener(is_plugin=True, outgoing=True, command="msgst", + description="消息每天定时发送", + parameters="new 时:分:秒 消息` 或 `del ` 或 `list") +async def process(context): + params = [] + for p in context.parameter: + if len(p.split()) != 0: + params.append(p) + bot_data = get_bot() + if len(params) == 1 and params[0] == "bot": + await context.edit(str(bot_data)) + await del_msg(context, 10) + return + if len(params) >= 3 and params[0] == "new": params.insert(2, str(context.chat_id)) + async with bot.conversation(bot_data[1]) as conversation: + await conversation.send_message("/" + " ".join(params)) + response = await conversation.get_response() + await bot.send_read_acknowledge(conversation.chat_id) + await context.edit(response.text) + if len(params) > 0 and params[0] != "list": await del_msg(context, 10) + +@listener(is_plugin=True, outgoing=True, command="msgset", + description="定时发送 bot 服务端设置", + parameters="bot ` 或 `bot clear") +async def settings(context): + if not redis_status(): + await context.edit("出错了呜呜呜 ~ Redis 离线,无法运行") + await del_msg(context, 10) + return + params = [] + for p in context.parameter: + if len(p.split()) != 0: + params.append(p) + if len(params) > 0 and params[0] == "bot": + if len(params) == 3 and is_num(params[1]): + redis.set("msgst.bot_id", params[1]) + redis.set("msgst.bot_un", params[2]) + await context.edit("设置成功") + await del_msg(context, 10) + elif len(params) == 2 and params[1] == "clear": + redis.delete("msgst.bot_id") + redis.delete("msgst.bot_un") + await context.edit("清除成功") + await del_msg(context, 10) + else: + await context.edit("参数错误") + await del_msg(context, 10) + +@listener(incoming=True, ignore_edited=True) +async def sendmsg(context): + bot_data = get_bot() + if context.sender_id == bot_data[0]: + parse = context.text.split("|") + if parse[0] == "send_msg": + async with bot.conversation(bot_data[1]) as conversation: + await bot.send_read_acknowledge(conversation.chat_id) + s_time = int(time.time() + 1) - time.time() + await asyncio.sleep(s_time) + await bot.send_message(int(parse[1]), "|".join(parse[2:])) diff --git a/neteasemusic.py b/neteasemusic.py index d3ce9f7..3a7353f 100644 --- a/neteasemusic.py +++ b/neteasemusic.py @@ -28,8 +28,7 @@ async def nem(context): proxynum = 0 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063', "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "X-Real-IP": "223.252.199.66"} - proxy = [{'http': 'http://192.210.137.108:8080', 'https': 'http://192.210.137.108:8080'}, {'http': 'http://music.lolico.me:39000', 'https': 'http://music.lolico.me:39000'}, {'http': 'http://aimer.one:2333', - 'https': 'http://aimer.one:2333'}, {'http': 'http://fs2.ilogic.net.cn:5200', 'https': 'http://fs2.ilogic.net.cn:5200'}, {'http': 'http://64.64.250.246:8080', 'https': 'http://64.64.250.246:8080'}] + proxy = [{'http': 'http://music.lolico.me:39000', 'https': 'http://music.lolico.me:39000'}, {'http': 'http://netease.unlock.feiwuis.me:6958', 'https': 'https://netease.unlock.feiwuis.me:6958'}] helptext = "**使用方法:** `-nem` `<指令>` `<关键词>`\n\n指令s为搜索,p为点歌,id为歌曲ID点歌,r为随机热歌(无关键词)\n搜索在s后添加数字如`-nem` `s8` `<关键词>`调整结果数量\n搜索灰色歌曲请尽量**指定歌手**\n可回复搜索结果消息`-nem` `p` `<歌曲数字序号>`点歌" apifailtext = "出错了呜呜呜 ~ 试了好多好多次都无法访问到 API 服务器 。" diff --git a/portball.py b/portball.py index de44eef..0ea0ba5 100644 --- a/portball.py +++ b/portball.py @@ -5,78 +5,67 @@ from asyncio import sleep from datetime import timedelta from telethon.tl.types import ChannelParticipantsAdmins +@listener(is_plugin=True, outgoing=True, command="portball", + description="回复你要临时禁言的人的消息来实现XX秒的禁言", + parameters="<理由>(空格)<时间/秒>") -@listener(is_plugin=True, outgoing=True, incoming=True, command="portball", - description="回复你要临时禁言的人的消息来实现XX秒的禁言", - parameters="<理由>(空格)<时间/秒>") async def portball(context): - if context.is_group: - admins = await context.client.get_participants(context.chat, filter=ChannelParticipantsAdmins) - reply = await context.get_reply_message() - # if message sender is one of admins or group anonymous bot - if (context.sender in admins) or (context.sender_id == 1087968824): - # if this msg reply to a message - if reply: - action = context.arguments.split() - # get sender's last_name - if reply.sender.last_name == None: - last_name = '' - else: - last_name = reply.sender.last_name - # if something wrong with the command - if len(action) < 2: - notification = await bot.send_message(context.chat_id, '格式是\n-portball 理由 秒数\n真蠢', reply_to = context.id) - await sleep(10) - await notification.delete() - try: - await context.delete() - except: - pass - return False - # if time of portball less than 60 seconds - if int(action[1])<60: - notification = await bot.send_message(context.chat_id, '诶呀不要小于60秒啦', reply_to = context.id) - await sleep(10) - await notification.delete() - try: - await context.delete() - except: - pass - return False - # portball - try: - await bot.edit_permissions(context.chat_id, reply.sender.id, timedelta(seconds=int(action[1].replace(' ',''))), send_messages=False, send_media=False, send_stickers=False, send_gifs=False, send_games=False, send_inline=False, send_polls=False, invite_users=False, change_info=False, pin_messages=False) - portball_message = await bot.send_message( - context.chat_id, - f'[{reply.sender.first_name}{last_name}](tg://user?id={reply.sender.id}) 由于 {action[0]} 被塞了{action[1]}秒口球.\n' - f'到期自动拔出,无后遗症.', - reply_to = reply.id - ) - await context.delete() - await sleep(int(action[1].replace(' ',''))) - await portball_message.delete() - except rpcerrorlist.UserAdminInvalidError: - notification = await bot.send_message(context.chat_id, '错误:我没有管理员权限或我的权限比被封禁的人要小', reply_to = context.id) - await sleep(10) - await notification.delete() - except rpcerrorlist.ChatAdminRequiredError: - notification = await bot.send_message(context.chat_id, '错误:我没有管理员权限或我的权限比被封禁的人要小', reply_to = context.id) - await sleep(10) - await notification.delete() + if context.is_group: + reply = await context.get_reply_message() + if reply: + action = context.arguments.split() + if reply.sender.last_name == None: + last_name='' + else: + last_name = reply.sender.last_name - # if not reply to any message - else: - notification = await bot.send_message(context.chat_id, '你好蠢诶,都没有回复人,我哪知道你要搞谁的事情……', reply_to = context.id) - await sleep(10) - await notification.delete() - # if sender is not admin - else: - return - else: - notification = await bot.send_message(context.chat_id, '你好蠢诶,又不是群组,怎么禁言啦!', reply_to = context.id) - await sleep(10) - await notification.delete() - try: - await context.delete() - except: - pass + if len(action) < 2: + notification = await bot.send_message(context.chat_id, '格式是\n-portball 理由 秒数\n真蠢', reply_to = context.id) + await sleep(10) + await notification.delete() + try: + await context.delete() + except: + pass + return False + if int(action[1]) < 60: + notification = await bot.send_message(context.chat_id, '诶呀不要小于60秒啦', reply_to = context.id) + await sleep(10) + await notification.delete() + try: + await context.delete() + except: + pass + return False + try: + await bot.edit_permissions(context.chat_id, reply.sender.id, timedelta(seconds=int(action[1].replace(' ',''))), send_messages=False, send_media=False, send_stickers=False, send_gifs=False, send_games=False, send_inline=False, send_polls=False, invite_users=False, change_info=False, pin_messages=False) + portball_message = await bot.send_message( + context.chat_id, + f'[{reply.sender.first_name}{last_name}](tg://user?id={reply.sender.id}) 由于 {action[0]} 被塞了{action[1]}秒口球.\n' + f'到期自动拔出,无后遗症.', + reply_to = reply.id + ) + await context.delete() + await sleep(int(action[1].replace(' ',''))) + await portball_message.delete() + except rpcerrorlist.UserAdminInvalidError: + notification = await bot.send_message(context.chat_id, '错误:我没有管理员权限或我的权限比被封禁的人要小', reply_to = context.id) + await sleep(10) + await notification.delete() + except rpcerrorlist.ChatAdminRequiredError: + notification = await bot.send_message(context.chat_id, '错误:我没有管理员权限或我的权限比被封禁的人要小', reply_to = context.id) + await sleep(10) + await notification.delete() + else: + notification = await bot.send_message(context.chat_id, '你好蠢诶,都没有回复人,我哪知道你要搞谁的事情……', reply_to = context.id) + await sleep(10) + await notification.delete() + else: + notification = await bot.send_message(context.chat_id, '你好蠢诶,又不是群组,怎么禁言啦!', reply_to = context.id) + await sleep(10) + await notification.delete() + try: + await context.delete() + except: + pass + diff --git a/sendat.py b/sendat.py index 5115f08..6f0cf12 100644 --- a/sendat.py +++ b/sendat.py @@ -5,7 +5,7 @@ imported = True -import os, sys, time, traceback +import sys, time, traceback try: import dateparser @@ -15,9 +15,8 @@ except ImportError: import asyncio from pagermaid import log from pagermaid.listener import listener -from datetime import datetime -from dateutil import parser +DAY_SECS = 24 * 60 * 60 def logsync(message): sys.stdout.writelines(f"{message}\n") @@ -81,9 +80,9 @@ async def sendat(context): chat = await context.get_chat() args = " ".join(context.parameter).split("|") if not imported: - await context.edit("Please install dateparser first: python3 -m pip install dateparser\nAnd restart your pagermaid process") + await context.edit("请先安装依赖:`python3 -m pip install dateparser`\n随后,请重启 pagermaid。") return - await context.edit(f"tz data: {time.timezone} {time.tzname} {sign}{offset}") + await context.edit(f"debug: tz data: {time.timezone} {time.tzname} {sign}{offset}") if len(args) != 2: if args[0].find("rm ") == 0: # clear timer @@ -92,7 +91,7 @@ async def sendat(context): if target_id.isnumeric(): if len(mem) > int(target_id): mem[int(target_id)] = "" - await context.edit(f"id {target_id} removed.") + await context.edit(f"id {target_id} successfully removed.") else: await context.edit("id out of range.") return @@ -112,26 +111,35 @@ async def sendat(context): time_str = args[0][6:] if time_str.find(":") != -1: # then it should be absolute time - sleep_times = [abs(dateparser.parse(time_str, settings=settings).timestamp() - time.time()), 24 * 60 * 60] - index = 0 + target = dateparser.parse(time_str, settings=settings).timestamp() % DAY_SECS + if target >= DAY_SECS - 6: + # 太接近午夜,小概率直接 sleep 过头,特殊处理 + target = 0 mem[mem_id] = "|".join(args) + await sendmsg(context, chat, f"{args[0]} -> {target} sec after 00:00:00 UTC+0") await context.edit(f"Registered: id {mem_id}. You can use this id to cancel the timer.") - while True and mem[mem_id] != "": - last_time = time.time() - while time.time() < last_time + sleep_times[index] and mem[mem_id] != "": + last_sent = 0 + while mem[mem_id] != "": + if time.time() % DAY_SECS < target: + # 时间没到 await asyncio.sleep(2) + continue + if time.time() % DAY_SECS >= target and time.time() - last_sent < DAY_SECS - 10: + # 时间过了,第二天的没到 + await asyncio.sleep(2) + continue if mem[mem_id] != "": await sendmsg(context, chat, args[1]) - index = 1 + last_sent = time.time() mem[mem_id] = "" return - sleep_time = abs(dateparser.parse(time_str, settings=settings).timestamp() - time.time()) + sleep_time = time.time() - dateparser.parse(time_str, settings=settings).timestamp() if sleep_time < 5: await context.edit(f"Sleep time too short. Should be longer than 5 seconds. Got {sleep_time}") return mem[mem_id] = "|".join(args) await context.edit(f"Registered: id {mem_id}. You can use this id to cancel the timer.") - while True and mem[mem_id] != "": + while mem[mem_id] != "": last_time = time.time() while time.time() < last_time + sleep_time and mem[mem_id] != "": await asyncio.sleep(2) @@ -144,22 +152,32 @@ async def sendat(context): rest = " ".join(args[0][1:].split(" ")[1:]) if rest.find(":") != -1: # then it should be absolute time - sleep_times = [abs(dateparser.parse(rest, settings=settings).timestamp() - time.time()), 24 * 60 * 60] + target = dateparser.parse(rest, settings=settings).timestamp() % DAY_SECS + if target >= DAY_SECS - 6: + # 太接近午夜,小概率直接 sleep 过头,特殊处理 + target = 0 count = 0 mem[mem_id] = "|".join(args) await context.edit(f"Registered: id {mem_id}. You can use this id to cancel the timer.") + last_sent = 0 while count <= times and mem[mem_id] != "": - last_time = time.time() - while time.time() < last_time + sleep_times[0 if count == 0 else 1] and mem[mem_id] != "": + if time.time() % DAY_SECS < target: + # 时间没到 await asyncio.sleep(2) + continue + if time.time() % DAY_SECS >= target and time.time() - last_sent < DAY_SECS - 10: + # 时间过了,第二天的没到 + await asyncio.sleep(2) + continue if mem[mem_id] != "": await sendmsg(context, chat, args[1]) count += 1 + last_sent = time.time() mem[mem_id] = "" return - sleep_time = abs(dateparser.parse(rest, settings=settings).timestamp() - time.time()) + sleep_time = time.time() - dateparser.parse(rest, settings=settings).timestamp() if sleep_time < 5: - await context.edit("Sleep time too short. Should be longer than 5 seconds.") + await context.edit(f"Sleep time too short. Should be longer than 5 seconds. got {sleep_time}") return count = 0 mem[mem_id] = "|".join(args) @@ -191,15 +209,14 @@ async def sendat(context): return # absolute time - dt = parser.parse(args[0]) - delta = dt.timestamp() - time.time() - if delta < 3: + target_time = dateparser.parse(args[0], settings=settings).timestamp() + if target_time - time.time() < 3: await context.edit("Target time before now.") return mem[mem_id] = "|".join(args) + await context.edit(f"Registered: id {mem_id}. You can use this id to cancel the timer.") - while delta > 0 and mem[mem_id] != "": - delta = dt.timestamp() - time.time() + while target_time - time.time() > 0 and mem[mem_id] != "": await asyncio.sleep(2) if mem[mem_id] != "": await sendmsg(context, chat, args[1]) diff --git a/telegram_update.py b/telegram_update.py index 12cc638..ad93e65 100644 --- a/telegram_update.py +++ b/telegram_update.py @@ -3,14 +3,11 @@ from requests import get, post token = str(sys.argv[1]) main = json.loads(get("https://api.github.com/repos/xtaodada/PagerMaid_Plugins/commits/master").content) -push_content = {} -push_content['chat_id'] = '-1001441461877' -push_content['disable_web_page_preview'] = 'True' -push_content['parse_mode'] = 'markdown' -push_content['text'] = "#更新日志 #" + main['commit']['author'][ - 'name'].replace('_', '') + ' \n\n🔨 [' + main['sha'][0:7] + '](https://github.com/xtaodada/PagerMaid_Plugins/compare/' + \ - main[ - 'sha'] + '): ' + main['commit']['message'] +text = "#更新日志 #" + main['commit']['author']['name'].replace('_', '') + \ + ' \n\n🔨 [' + main['sha'][0:7] + '](https://github.com/Xtao-Labs/PagerMaid_Plugins/commit/' + \ + main['sha'] + '): ' + main['commit']['message'] +push_content = {'chat_id': '-1001441461877', 'disable_web_page_preview': 'True', 'parse_mode': 'markdown', + 'text': text} url = 'https://api.telegram.org/bot' + token + '/sendMessage' try: main_req = post(url, data=push_content) diff --git a/telegram_update_beta.py b/telegram_update_beta.py new file mode 100644 index 0000000..63dd87a --- /dev/null +++ b/telegram_update_beta.py @@ -0,0 +1,22 @@ +import json, time, sys +from requests import get, post + +token = str(sys.argv[1]) +main = json.loads(get("https://api.github.com/repos/xtaodada/PagerMaid_Plugins/commits/beta").content) +text = "#更新日志 #beta #" + main['commit']['author']['name'].replace('_', '') + \ + ' \n\n🔨 [' + main['sha'][0:7] + '](https://github.com/Xtao-Labs/PagerMaid_Plugins/commit/' + \ + main['sha'] + '): ' + main['commit']['message'] +push_content = {'chat_id': '-1001441461877', 'disable_web_page_preview': 'True', 'parse_mode': 'markdown', + 'text': text} +url = 'https://api.telegram.org/bot' + token + '/sendMessage' +try: + main_req = post(url, data=push_content) +except: + pass +push_content['chat_id'] = '-1001319957857' +time.sleep(1) +try: + main_req = get(url, data=push_content) +except: + pass +print(main['sha'] + " ok!") diff --git a/throwit/1.png b/throwit/1.png index c638e40..8234b41 100644 Binary files a/throwit/1.png and b/throwit/1.png differ diff --git a/throwit/3.png b/throwit/3.png index 938bc3f..616e935 100644 Binary files a/throwit/3.png and b/throwit/3.png differ diff --git a/transfer.py b/transfer.py new file mode 100644 index 0000000..1b97010 --- /dev/null +++ b/transfer.py @@ -0,0 +1,71 @@ +import asyncio, zipfile, os +from io import BytesIO +from uuid import uuid4 +from os.path import exists, isfile +from pagermaid import bot +from pagermaid.listener import listener + +async def make_zip(source_dir, output_filename): + zipf = zipfile.ZipFile(output_filename, "w") + pre_len = len(os.path.dirname(source_dir)) + for parent, dirnames, filenames in os.walk(source_dir): + for filename in filenames: + pathfile = os.path.join(parent, filename) + arcname = pathfile[pre_len:].strip(os.path.sep) + zipf.write(pathfile, arcname) + zipf.close() + +async def del_msg(context, t_lim): + await asyncio.sleep(t_lim) + try: + await context.delete() + except: + pass + +@listener(is_plugin=True, outgoing=True, command="transfer", + description="上传 / 下载文件", + parameters="upload ` 或 `download ") +async def transfer(context): + params = context.parameter + if len(params) < 2: + await context.edit("参数缺失") + await del_msg(context, 3) + return + params[1] = " ".join(params[1:]) + file_list = params[1].split("\n") + chat_id = context.chat_id + if params[0] == "upload": + index = 1 + for file_path in file_list: + await context.edit(f"正在上传第 {index} 个文件") + if exists(file_path): + if isfile(file_path): + await bot.send_file(chat_id, file_path, force_document=True) + else: + token = file_path.split("/") + token = token[len(token) - 1] + await make_zip(file_path, f"/tmp/{token}.zip") + await bot.send_file(chat_id, f"/tmp/{token}.zip", force_document=True) + os.remove(f"/tmp/{token}.zip") + index += 1 + await context.edit("上传完毕") + await del_msg(context, 3) + elif params[0] == "download": + message = await context.get_reply_message() + if message and message.media: + _file = BytesIO() + await bot.download_file(message.media.document, _file) + if not exists(file_list[0]): + with open(file_list[0], "wb") as f: + f.write(_file.getvalue()) + await context.edit(f"保存成功, 保存路径 {file_list[0]}") + await del_msg(context, 5) + else: + await context.edit("路径已存在文件") + await del_msg(context, 3) + else: + await context.edit("未回复消息或回复消息中不包含文件") + await del_msg(context, 3) + else: + await context.edit("未知命令") + await del_msg(context, 3) diff --git a/videodl.py b/videodl.py index 29bc661..8726fa5 100644 --- a/videodl.py +++ b/videodl.py @@ -8,7 +8,6 @@ from pagermaid import bot, log from pagermaid.listener import listener from telethon.tl.types import DocumentAttributeVideo from time import sleep -from re import search @listener(outgoing=True, command="vdl", @@ -33,7 +32,9 @@ async def vdl(context): try: from pytube import YouTube except ImportError: - await context.edit('(`pytube3`支持库未安装,YouTube视频无法下载\n请使用 `-sh` `pip3` `install` `pytube3` 安装,或自行ssh安装)') + await context.edit('`pytube`支持库未安装,YouTube视频无法下载\n请使用 `-sh pip3 install --user ' + 'git+https://github.com/nficano/pytube 或 -sh pip3 install pytube --upgrade ` 安装,或自行ssh安装\n\n已安装过 `pytube3` 的用户请使用 `-sh pip3 ' + 'uninstall pytube3 -y` 进行卸载') return url = url.replace('www.youtube.com/watch?v=', 'youtu.be/') if not await youtube_dl(url, context, reply_id): @@ -68,7 +69,8 @@ async def youtube_dl(url, context, reply_id): async def bilibili_dl(url, context, reply_id): url = 'https://tenapi.cn/bilivideo/?url=' + url - headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063', "X-Real-IP": "223.252.199.66"} + headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' + 'Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063', "X-Real-IP": "223.252.199.66"} for _ in range(20): # 最多尝试20次 status = False try: @@ -101,7 +103,8 @@ async def upload(as_file, filename, context, reply_id, caption, duration=0): if not exists("plugins/VideoDLExtra"): mkdir("plugins/VideoDLExtra") faster = requests.request( - "GET", "https://gist.githubusercontent.com/TNTcraftHIM/ca2e6066ed5892f67947eb2289dd6439/raw/86244b02c7824a3ca32ce01b2649f5d9badd2e49/FastTelethon.py") + "GET", "https://gist.githubusercontent.com/TNTcraftHIM/ca2e6066ed5892f67947eb2289dd6439/raw" + "/86244b02c7824a3ca32ce01b2649f5d9badd2e49/FastTelethon.py") for _ in range(6): # 最多尝试6次 if faster.status_code == 200: with open("plugins/VideoDLExtra/FastTelethon.py", "wb") as f: diff --git a/vip.py b/vip.py index 51c76ef..c93867e 100644 --- a/vip.py +++ b/vip.py @@ -1,3 +1,5 @@ +from requests import get +from os import remove from pagermaid import bot from pagermaid.listener import listener from pagermaid.utils import obtain_message @@ -18,3 +20,40 @@ async def weather(context): await bot.send_read_acknowledge(conversation.chat_id) weather_text = chat_response.text await context.edit(weather_text) + + +@listener(is_plugin=True, outgoing=True, command="pixiv", + description="查询插画信息 (或者回复一条消息)", + parameters="[<图片链接>] <图片序号>") +async def pixiv(context): + await context.edit("获取中 . . .") + try: + message = await obtain_message(context) + except ValueError: + await context.edit("出错了呜呜呜 ~ 无效的参数。") + return + async with bot.conversation('PagerMaid_Modify_bot') as conversation: + await conversation.send_message('/pixiv_api ' + message) + chat_response = await conversation.get_response() + await bot.send_read_acknowledge(conversation.chat_id) + pixiv_text = chat_response.text + pixiv_list = pixiv_text.split('|||||') + if len(pixiv_list) == 2: + pixiv_albums = pixiv_list[1].split('|||') + pixiv_album = [] + await context.edit("下载图片中 . . .") + for i in range(0, len(pixiv_albums)): + r = get(pixiv_albums[i]) + with open("pixiv." + str(i) + ".jpg", "wb") as code: + code.write(r.content) + pixiv_album.extend(["pixiv." + str(i) + ".jpg"]) + await context.client.send_file(context.chat_id, pixiv_album, + caption=pixiv_list[0]) + await context.delete() + for i in pixiv_album: + try: + remove(i) + except: + pass + else: + await context.edit(pixiv_text) diff --git a/weather.py b/weather.py index 44baf23..28e875f 100644 --- a/weather.py +++ b/weather.py @@ -1,4 +1,5 @@ import json +import datetime from requests import get from pagermaid.listener import listener from pagermaid.utils import obtain_message @@ -24,6 +25,14 @@ icons = { "50n": "🌫", } +def timestamp_to_time(timestamp, timeZoneShift): + timeArray = datetime.datetime.utcfromtimestamp(timestamp) + datetime.timedelta(seconds=timeZoneShift) + return timeArray.strftime("%H:%M") +def calcWindDirection(windDirection): + dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'] + ix = round(windDirection / (360. / len(dirs))) + return dirs[ix % len(dirs)] + @listener(is_plugin=True, outgoing=True, command="weather", description="查询天气", parameters="<城市>") @@ -34,17 +43,33 @@ async def weather(context): except ValueError: await context.edit("出错了呜呜呜 ~ 无效的参数。") return - req = get("http://api.openweathermap.org/data/2.5/weather?appid=973e8a21e358ee9d30b47528b43a8746&units=metric&lang=zh_cn&q=" + message) - if req.status_code == 200: - data = json.loads(req.text) - cityName = "{}, {}".format(data["name"], data["sys"]["country"]) - tempInC = round(data["main"]["temp"], 2) - tempInF = round((1.8 * tempInC) + 32, 2) - icon = data["weather"][0]["icon"] - desc = data["weather"][0]["description"] - res = "{}\n🌡{}℃ ({}F)\n{} {}".format( - cityName, tempInC, tempInF, icons[icon], desc - ) - await context.edit(res) - else: - await context.edit("出错了呜呜呜 ~ 无法访问到 openweathermap.org 。") \ No newline at end of file + try: + req = get("http://api.openweathermap.org/data/2.5/weather?appid=973e8a21e358ee9d30b47528b43a8746&units=metric&lang=zh_cn&q=" + message) + if req.status_code == 200: + data = json.loads(req.text) + cityName = "{}, {}".format(data["name"], data["sys"]["country"]) + timeZoneShift = data["timezone"] + temp_Max = round(data["main"]["temp_max"], 2) + temp_Min = round(data["main"]["temp_min"], 2) + pressure = data["main"]["pressure"] + humidity = data["main"]["humidity"] + windSpeed = data["wind"]["speed"] + windDirection = calcWindDirection(data["wind"]["deg"]) + sunriseTimeunix = data["sys"]["sunrise"] + sunriseTime = timestamp_to_time(sunriseTimeunix, timeZoneShift) + sunsetTimeunix = data["sys"]["sunset"] + sunsetTime = timestamp_to_time(sunsetTimeunix, timeZoneShift) + fellsTemp = data["main"]["feels_like"] + tempInC = round(data["main"]["temp"], 2) + tempInF = round((1.8 * tempInC) + 32, 2) + icon = data["weather"][0]["icon"] + desc = data["weather"][0]["description"] + res = "{} {}{} 💨{} {}m/s\n大气🌡 {}℃ ({}℉) 💦 {}% \n体感🌡 {}℃\n气压 {}hpa\n🌅{} 🌇{} ".format( + cityName, icons[icon], desc, windDirection, windSpeed, tempInC, tempInF, humidity, fellsTemp, pressure, sunriseTime, sunsetTime + ) + await context.edit(res) + if req.status_code == 404: + await context.edit("出错了呜呜呜 ~ 无效的城市名,请使用拼音输入 ~ ") + return + except Exception: + await context.edit("出错了呜呜呜 ~ 无法访问到 openweathermap.org 。") diff --git a/whois.py b/whois.py index 2a75b35..44ddc91 100644 --- a/whois.py +++ b/whois.py @@ -1,6 +1,6 @@ import json import os,sys,codecs -sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) + from requests import get from pagermaid.listener import listener from pagermaid.utils import obtain_message @@ -16,8 +16,8 @@ async def whois(context): return req = get("https://tenapi.cn/whois/?url=" + message) if req.status_code == 200: - data = json.loads(req.text) - res = '网址: ' + data['data']['url'] + '\n注册商: ' + str(data['data']['registrar']) + '\n联系人: ' + str(data['data']['registrant']) + '\n联系邮箱: ' + str(data['data']['mail']) + '\n注册时间: ' + str(data['data']['registration']) + '\n过期时间: ' + str(data['data']['expiration']) + '\nDNS: ' + str(data['data']['dns']) + data = json.loads(req.text)['data'] + res = '域名: `' + data['url'] + '`\n注册商: `' + str(data['registrar']) + '`\n联系人: `' + str(data['registrant']) + '`\n联系邮箱: `' + str(data['mail']) + '`\n注册时间: `' + str(data['registration']) + '`\n过期时间: `' + str(data['expiration']) + '`\nDNS: ' + str(data['dns']).replace('
', '\n') await context.edit(res) else: await context.edit("出错了呜呜呜 ~ 无法访问到 API 服务器 。") diff --git a/xjj.py b/xjj.py new file mode 100644 index 0000000..1a79c30 --- /dev/null +++ b/xjj.py @@ -0,0 +1,41 @@ +import random +from time import sleep +from requests import get +from pagermaid.listener import listener +from os import remove + + +@listener(is_plugin=True, outgoing=True, command="xjj", + description="随机小姐姐写真") +async def ghs(context): + await context.edit("拍小姐姐写真中 . . .") + status = False + for _ in range (10): #最多重试10次 + website = random.randint(0,0) + filename = "xjj" + str(random.random())[2:] + ".png" + try: + if website == 0: + img = get("https://api.pixivweb.com/api.php?return=img") + if img.status_code == 200: + with open(filename, 'wb') as f: + f.write(img.content) + await context.edit("写真我拍好辣,上传中 . . .") + await context.client.send_file(context.chat_id,filename,caption="小姐姐来辣~⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄)") + status = True + break #成功了就赶紧结束啦! + except: + try: + remove(filename) + except: + pass + continue + try: + remove(filename) + except: + pass + try: + await context.delete() + except: + pass + if not status: + await context.client.send_message(context.chat_id,"出错了呜呜呜 ~ 试了好多好多次都无法访问到服务器(没有颜色搞啦!) 。") diff --git a/xtao-some.py b/xtao-some.py index a8c6f71..a189d32 100644 --- a/xtao-some.py +++ b/xtao-some.py @@ -1,11 +1,10 @@ """ Pagermaid plugin base. """ import json, requests, re -from googletrans import Translator from urllib.parse import urlparse from pagermaid import bot, log from pagermaid.listener import listener, config from pagermaid.utils import clear_emojis, obtain_message, attach_log -from telethon.tl.types import ChannelParticipantsAdmins +from telethon.errors import ChatAdminRequiredError from os import remove @@ -38,29 +37,11 @@ async def guess(context): await context.edit("没有匹配到拼音首字母缩写") -@listener(is_plugin=True, outgoing=True, command="admin", - description="一键 AT 本群管理员(仅在群组中有效)") -async def admin(context): - await context.edit('正在获取管理员列表中...') - chat = await context.get_chat() - try: - admins = await context.client.get_participants(chat, filter=ChannelParticipantsAdmins) - except: - await context.edit('请在群组中使用。') - return True - admin_list = [] - for admin in admins: - if admin.first_name is not None: - admin_list.extend(['[' + admin.first_name + '](tg://user?id=' + str(admin.id) + ')']) - await context.edit(' , '.join(admin_list)) - - @listener(is_plugin=True, outgoing=True, command="wiki", description="查询维基百科词条", parameters="<词组>") async def wiki(context): - translator = Translator() - lang = config['application_language'] + lang = config['application_language'].replace('zh-cn', 'zh') await context.edit("获取中 . . .") try: message = await obtain_message(context) @@ -68,19 +49,26 @@ async def wiki(context): await context.edit("出错了呜呜呜 ~ 无效的参数。") return try: - wiki_json = json.loads(requests.get("https://zh.wikipedia.org/w/api.php?action=query&list=search&format=json&formatversion=2&srsearch=" + message).content.decode( - "utf-8")) + wiki_json = json.loads(requests.get("https://zh.wikipedia.org/w/api.php?action=query&list=search&format=json" + "&formatversion=2&srsearch=" + message).content.decode( + "utf-8")) except: await context.edit("出错了呜呜呜 ~ 无法访问到维基百科。") return if not len(wiki_json['query']['search']) == 0: wiki_title = wiki_json['query']['search'][0]['title'] - wiki_content = wiki_json['query']['search'][0]['snippet'].replace('', '**').replace('', '**') + wiki_content = wiki_json['query']['search'][0]['snippet'].replace('', '**').replace( + '', '**') wiki_time = wiki_json['query']['search'][0]['timestamp'].replace('T', ' ').replace('Z', ' ') try: await context.edit("正在生成翻译中 . . .") - wiki_content = translator.translate(clear_emojis(wiki_content), dest=lang) - message = '词条: [' + wiki_title + '](https://zh.wikipedia.org/zh-cn/' + wiki_title + ')\n\n' + wiki_content.text + '...\n\n此词条最后修订于 ' + wiki_time + USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0" + headers = {"user-agent": USER_AGENT} + wiki_content = json.loads(requests.get("https://xtaolink.cn/git/m/t.php?lang=" + lang + '&text=' + + clear_emojis(wiki_content), headers=headers) + .content.decode("utf-8"))['data']['target_text'] + message = '词条: [' + wiki_title + '](https://zh.wikipedia.org/zh-cn/' + wiki_title + ')\n\n' + \ + wiki_content + '...\n\n此词条最后修订于 ' + wiki_time except ValueError: await context.edit("出错了呜呜呜 ~ 找不到目标语言,请更正配置文件中的错误。") return @@ -105,7 +93,8 @@ async def ipinfo(context): else: url = url.path ipinfo_json = json.loads(requests.get( - "http://ip-api.com/json/" + url + "?fields=status,message,country,regionName,city,lat,lon,isp,org,as,mobile,proxy,hosting,query").content.decode( + "http://ip-api.com/json/" + url + "?fields=status,message,country,regionName,city,lat,lon,isp," + "org,as,mobile,proxy,hosting,query").content.decode( "utf-8")) if ipinfo_json['status'] == 'fail': pass @@ -142,7 +131,8 @@ async def ipinfo(context): else: url = url.path ipinfo_json = json.loads(requests.get( - "http://ip-api.com/json/" + url + "?fields=status,message,country,regionName,city,lat,lon,isp,org,as,mobile,proxy,hosting,query").content.decode( + "http://ip-api.com/json/" + url + "?fields=status,message,country,regionName,city,lat,lon,isp,org,as," + "mobile,proxy,hosting,query").content.decode( "utf-8")) if ipinfo_json['status'] == 'fail': pass @@ -196,8 +186,7 @@ async def ipping(context): else: url = url.path pinginfo = requests.get( - "https://helloacm.com/api/ping/?cached&host=" + url).content.decode( - "utf-8") + "https://steakovercooked.com/api/ping/?host=" + url).content.decode("utf-8") if pinginfo == 'null': pass elif not pinginfo == 'null': @@ -214,8 +203,7 @@ async def ipping(context): await context.edit('没有找到要查询的 ip/域名 ...') return True pinginfo = requests.get( - "https://helloacm.com/api/ping/?cached&host=" + url).content.decode( - "utf-8") + "https://steakovercooked.com/api/ping/?host=" + url).content.decode("utf-8") if pinginfo == 'null': pass elif not pinginfo == 'null': @@ -227,126 +215,6 @@ async def ipping(context): await context.edit('没有找到要查询的 ip/域名 ...') -@listener(is_plugin=True, outgoing=True, command="pixiv", - description="查询插画信息 (或者回复一条消息)", - parameters="[<图片链接>] <图片序号>") -async def pixiv(context): - reply = await context.get_reply_message() - await context.edit('正在查询中...') - try: - if reply: - try: - if context.arguments.strip() == '': - pixiv_page = 1 - else: - try: - pixiv_page = int(context.arguments.strip()) - except: - await context.edit('呜呜呜出错了...可能参数不是数字') - return True - except: - pass - for num in range(0, len(reply.entities)): - url = reply.message[reply.entities[num].offset:reply.entities[num].offset + reply.entities[num].length] - url = urlparse(url) - try: - url = str(re.findall(r"\d+\.?\d*", url.path)[0]) - pixiv_json = json.loads(requests.get( - "https://api.imjad.cn/pixiv/v2/?type=illust&id=" + url).content.decode( - "utf-8")) - except: - await context.edit('呜呜呜出错了...可能是链接不上 API 服务器') - return True - try: - pixiv_tag = pixiv_json['error']['user_message'] - await context.edit('没有找到要查询的 pixiv 作品...') - return True - except: - if pixiv_page > pixiv_json['illust']['page_count']: - await context.edit('呜呜呜出错了...可能是参数指定的页数大于插画页数') - return True - else: - pass - pixiv_tag = [] - pixiv_num = str(pixiv_json['illust']['page_count']) - pixiv_list = '[' + pixiv_json['illust']['title'] + '](https://www.pixiv.net/artworks/' + str( - pixiv_json['illust']['id']) + ')' + ' (' + str(pixiv_page) + '/' + pixiv_num + ')' - for nums in range(0, len(pixiv_json['illust']['tags'])): - pixiv_tag.extend(['#' + pixiv_json['illust']['tags'][nums]['name']]) - try: - await context.edit('正在下载图片中 ...') - try: - r = requests.get(pixiv_json['illust']['meta_single_page']['original_image_url'].replace('i.pximg.net','i.pixiv.cat')) - except: - r = requests.get(pixiv_json['illust']['meta_pages'][pixiv_page - 1]['image_urls']['original'].replace('i.pximg.net','i.pixiv.cat')) - with open("pixiv.jpg", "wb") as code: - code.write(r.content) - await context.edit('正在上传图片中 ...') - await context.client.send_file(context.chat_id, 'pixiv.jpg', - caption=pixiv_list + '\nTags: ' + ' , '.join(pixiv_tag), - reply_to=reply.id) - await context.delete() - remove('pixiv.jpg') - except: - pass - return True - else: - try: - url = urlparse(context.arguments.split()[0]) - if len(context.arguments.split()) == 1: - pixiv_page = 1 - else: - try: - pixiv_page = int(context.arguments.split()[1]) - except: - await context.edit('呜呜呜出错了...可能参数不是数字') - return True - except: - pass - try: - url = str(re.findall(r"\d+\.?\d*", url.path)[0]) - pixiv_json = json.loads(requests.get( - "https://api.imjad.cn/pixiv/v2/?type=illust&id=" + url).content.decode( - "utf-8")) - except: - await context.edit('呜呜呜出错了...可能是链接不上 API 服务器') - try: - pixiv_tag = pixiv_json['error']['user_message'] - await context.edit('没有找到要查询的 pixiv 作品...') - return True - except: - if pixiv_page > pixiv_json['illust']['page_count']: - await context.edit('呜呜呜出错了...可能是参数指定的页数大于插画页数') - return True - else: - pass - pixiv_tag = [] - pixiv_num = str(pixiv_json['illust']['page_count']) - pixiv_list = '[' + pixiv_json['illust']['title'] + '](https://www.pixiv.net/artworks/' + str( - pixiv_json['illust']['id']) + ')' + ' (' + str(pixiv_page) + '/' + pixiv_num + ')' - for nums in range(0, len(pixiv_json['illust']['tags'])): - pixiv_tag.extend(['#' + pixiv_json['illust']['tags'][nums]['name']]) - try: - await context.edit('正在下载图片中 ...') - try: - r = requests.get(pixiv_json['illust']['meta_single_page']['original_image_url'].replace('i.pximg.net','i.pixiv.cat')) - except: - r = requests.get(pixiv_json['illust']['meta_pages'][pixiv_page - 1]['image_urls']['original'].replace('i.pximg.net','i.pixiv.cat')) - with open("pixiv.jpg", "wb") as code: - code.write(r.content) - await context.edit('正在上传图片中 ...') - await context.client.send_file(context.chat_id, 'pixiv.jpg', - caption=pixiv_list + '\nTags: ' + ' , '.join(pixiv_tag)) - await context.delete() - remove('pixiv.jpg') - except: - pass - return True - await context.edit('没有找到要查询的 pixiv 作品 ...') - except: - await context.edit('没有找到要查询的 pixiv 作品 ...') - - @listener(is_plugin=True, outgoing=True, command="t", description="通过腾讯AI开放平台将目标消息翻译成指定的语言。", parameters="<文本>") @@ -368,8 +236,9 @@ async def tx_t(context): try: await context.edit("正在生成翻译中 . . .") tx_json = json.loads(requests.get( - "https://xtaolink.cn/git/m/t.php?lang=" + lang + '&text=' + clear_emojis(message), headers=headers).content.decode( - "utf-8")) + "https://xtaolink.cn/git/m/t.php?lang=" + lang + '&text=' + clear_emojis(message), + headers=headers).content.decode( + "utf-8")) if not tx_json['msg'] == 'ok': context.edit("出错了呜呜呜 ~ 翻译出错") return True @@ -384,3 +253,24 @@ async def tx_t(context): await attach_log(result, context.chat_id, "translation.txt", context.id) return await context.edit(result) + + +@listener(is_plugin=True, outgoing=True, command="getdel", + description="获取当前群组/频道的死号数。") +async def getdel(context): + """ PagerMaid getdel. """ + cid = str(context.chat_id) + pri = cid.startswith('-100') + if pri: + member_count = 0 + try: + await context.edit('遍历成员中。。。') + chat = await context.get_chat() + async for member in bot.iter_participants(chat): + if member.deleted: + member_count += 1 + await context.edit(f'此频道/群组的死号数:`{member_count}`') + except ChatAdminRequiredError: + await context.edit('未加入此频道。') + else: + await context.edit("请在在群组/频道发送。") diff --git a/zpr.py b/zpr.py new file mode 100644 index 0000000..c5f445b --- /dev/null +++ b/zpr.py @@ -0,0 +1,41 @@ +import random +from time import sleep +from requests import get +from pagermaid.listener import listener +from os import remove + + +@listener(is_plugin=True, outgoing=True, command="zpr", + description="随机小姐姐或纸片人写真") +async def ghs(context): + await context.edit("拍小姐姐或纸片人写真中 . . .") + status = False + for _ in range (10): #最多重试10次 + website = random.randint(0,0) + filename = "zpr" + str(random.random())[2:] + ".png" + try: + if website == 0: + img = get("https://api.pixivweb.com/anime18r.php?return=img") + if img.status_code == 200: + with open(filename, 'wb') as f: + f.write(img.content) + await context.edit("写真我拍好辣,上传中 . . .") + await context.client.send_file(context.chat_id,filename,caption="来辣~⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄)") + status = True + break #成功了就赶紧结束啦! + except: + try: + remove(filename) + except: + pass + continue + try: + remove(filename) + except: + pass + try: + await context.delete() + except: + pass + if not status: + await context.client.send_message(context.chat_id,"出错了呜呜呜 ~ 试了好多好多次都无法访问到服务器(没有颜色搞啦!) 。")