summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ATRI/data/service/limit.service.json1
-rw-r--r--ATRI/exceptions.py4
-rw-r--r--ATRI/log.py32
-rw-r--r--ATRI/plugins/admin.py145
-rw-r--r--ATRI/plugins/anime-search/__init__.py89
-rw-r--r--ATRI/plugins/anime-search/data_source.py34
-rw-r--r--ATRI/plugins/anti-rubbish.py166
-rw-r--r--ATRI/plugins/call-owner.py63
-rw-r--r--ATRI/plugins/code-runner.py86
-rw-r--r--ATRI/plugins/drifting-bottle/__init__.py0
-rw-r--r--ATRI/plugins/essential.py8
-rw-r--r--ATRI/plugins/funny.py7
-rw-r--r--ATRI/plugins/rich/__init__.py20
-rw-r--r--ATRI/plugins/status.py50
-rw-r--r--ATRI/plugins/tex.py52
-rw-r--r--ATRI/plugins/utils/__init__.py51
-rw-r--r--ATRI/plugins/utils/data_source.py35
-rw-r--r--ATRI/rule.py20
-rw-r--r--ATRI/service/limit.py89
-rw-r--r--ATRI/utils/file.py27
-rw-r--r--ATRI/utils/request.py6
-rw-r--r--config.yml6
22 files changed, 892 insertions, 99 deletions
diff --git a/ATRI/data/service/limit.service.json b/ATRI/data/service/limit.service.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/ATRI/data/service/limit.service.json
@@ -0,0 +1 @@
+{} \ No newline at end of file
diff --git a/ATRI/exceptions.py b/ATRI/exceptions.py
index ab9e5d3..ebf23de 100644
--- a/ATRI/exceptions.py
+++ b/ATRI/exceptions.py
@@ -86,6 +86,10 @@ class RequestTimeOut(BaseBotException):
prompt = "网页/接口请求超时"
+class GetStatusError(BaseBotException):
+ prompt = "获取状态失败"
+
+
@run_postprocessor # type: ignore
async def _(matcher: Matcher, exception: Optional[Exception],
event: MessageEvent, state: dict) -> None:
diff --git a/ATRI/log.py b/ATRI/log.py
index 71258a9..59cfa34 100644
--- a/ATRI/log.py
+++ b/ATRI/log.py
@@ -1,21 +1,41 @@
+import sys
from pathlib import Path
from datetime import datetime
from nonebot.log import logger, default_format
+from .config import nonebot_config
+
LOGGER_DIR = Path('.') / 'ATRI' / 'data' / 'logs'
LOGGER_DIR.parent.mkdir(exist_ok=True, parents=True)
-NOW_TIME = datetime.now().strftime('%Y%m%d-%H%M%S')
+NOW_TIME = datetime.now().strftime('%Y%m%d-%H')
+
+log_format = (
+ "\033[36mATRI\033[0m "
+ "| <g>{time:MM-DD HH:mm:ss}</g> "
+ "| <lvl>{level}</lvl> "
+ "<c><u>{name}</u></c> >> "
+ "{message}"
+)
+
+
+logger.remove()
+logger.add(
+ sys.stdout,
+ level="DEBUG" if nonebot_config["debug"] else "INFO",
+ colorize=True,
+ format=log_format
+)
logger.add(
- LOGGER_DIR / 'info' / f"{NOW_TIME}-INFO.log",
+ LOGGER_DIR / "info" / f"{NOW_TIME}-INFO.log",
rotation="10 MB",
enqueue=True,
level="INFO",
encoding="utf-8",
- format=default_format
+ format=log_format
)
logger.add(
@@ -24,7 +44,7 @@ logger.add(
enqueue=True,
level="WARNING",
encoding="utf-8",
- format=default_format
+ format=log_format
)
logger.add(
@@ -33,7 +53,7 @@ logger.add(
enqueue=True,
level="ERROR",
encoding="utf-8",
- format=default_format
+ format=log_format
)
logger.add(
@@ -42,5 +62,5 @@ logger.add(
enqueue=True,
level="DEBUG",
encoding="utf-8",
- format=default_format
+ format=log_format
)
diff --git a/ATRI/plugins/admin.py b/ATRI/plugins/admin.py
index 1279017..6cc3ed6 100644
--- a/ATRI/plugins/admin.py
+++ b/ATRI/plugins/admin.py
@@ -1,17 +1,24 @@
import json
+import time
from pathlib import Path
from datetime import datetime
from nonebot.permission import SUPERUSER
-from nonebot.plugin import on_command, on_message
+from nonebot.plugin import on_command, on_message, CommandGroup
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent
)
+from nonebot.typing import T_State
-from ATRI.exceptions import WriteError
-from ATRI.log import logger
+from ATRI.exceptions import WriteError, read_error
+from ATRI.utils.file import open_file
+from ATRI.log import (
+ logger,
+ LOGGER_DIR,
+ NOW_TIME
+)
ADMIN_DIR = Path('.') / 'ATRI' / 'data' / 'database' / 'admin'
@@ -22,10 +29,10 @@ chat_monitor = on_message()
@chat_monitor.handle()
async def _chat_monitor(bot: Bot, event: GroupMessageEvent) -> None:
- now_time = datetime.now().strftime('%Y-%m-%d')
-
+ now_time = datetime.now().strftime('%Y-%m-%d')
GROUP_DIR = ADMIN_DIR / f"{event.group_id}"
path = GROUP_DIR / f"{now_time}.chat.json"
+ now_time = datetime.now().strftime('%Y%m%d-%H%M%S')
if not GROUP_DIR.exists():
GROUP_DIR.mkdir()
@@ -35,6 +42,8 @@ async def _chat_monitor(bot: Bot, event: GroupMessageEvent) -> None:
except:
data = {}
data[event.message_id] = {
+ "date": now_time,
+ "time": time.time(),
"post_type": event.post_type,
"sub_type": event.sub_type,
"user_id": event.user_id,
@@ -159,10 +168,124 @@ async def _request_group(bot: Bot, event: MessageEvent) -> None:
await request_friend.finish("阿...请检查输入——!")
-getcookies = on_command(
- "获取cookies",
- permission=SUPERUSER)
+broadcast = on_command(
+ "/broadcast",
+ permission=SUPERUSER
+)
+
+async def _broadcast(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ msg = str(event.message).strip()
+ if msg:
+ state["msg"] = msg
+
[email protected]("msg", prompt="请告诉咱需要群发的内容~!")
+async def _bd(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ msg = state["msg"]
+ group_list = await bot.get_group_list()
+ succ_list = []
+ err_list = []
+
+ for group in group_list:
+ try:
+ await bot.send_group_msg(group_id=group["group_id"],
+ message=msg)
+ except:
+ err_list.append(group["group_id"])
+
+ msg0 = ""
+ for i in err_list:
+ msg0 += f" {i}\n"
+
+ repo_msg = (
+ f"推送消息:\n{msg}\n"
+ "————————\n"
+ f"总共:{len(group_list)}\n"
+ f"成功推送:{len(succ_list)}\n"
+ f"失败[{len(err_list)}]个:\n"
+ ) + msg0
+
+ await broadcast.finish(repo_msg)
+
+
+track_error = on_command(
+ "/track",
+ permission=SUPERUSER
+)
+
+@track_error.handle()
+async def _track_error(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ msg = str(event.message).strip()
+ if msg:
+ state["msg"] = msg
+
+@track_error.got("msg", prompt="请告诉咱追踪ID!")
+async def _(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ track_id = state["msg"]
+ data = {}
+
+ try:
+ data = read_error(track_id)
+ except:
+ await track_error.finish("Ignore track ID!")
+
+ msg0 = (
+ f"ID: {track_id}\n"
+ f"Time: {data['time']}\n"
+ f"Prompt: {data['prompt']}\n"
+ f"{data['error_content']}"
+ )
+
+ await track_error.finish(msg0)
+
+
+get_log = on_command(
+ "/getlog",
+ permission=SUPERUSER
+)
-async def _get(bot: Bot, event: MessageEvent) -> None:
- print(await bot.get_cookies())
+@get_log.handle()
+async def _get_log(bot: Bot, event: MessageEvent) -> None:
+ msg = str(event.message).split(" ")
+ try:
+ rows = msg[1]
+ except:
+ await get_log.finish("格式/getlog level rows")
+
+ if msg[0] == "info":
+ level = "info"
+ elif msg[0] == "warning":
+ level = "warning"
+ elif msg[0] == "error":
+ level = "error"
+ elif msg[0] == "debug":
+ level = "debug"
+ else:
+ await get_log.finish("格式/getlog level rows")
+
+ path = LOGGER_DIR / level / f"{NOW_TIME}-INFO.log" # type: ignore
+ logs = await open_file(path, "readlines")
+
+ try:
+ content = logs[int(rows):] # type: ignore
+ except IndexError:
+ await get_log.finish(f"行数错误...max: {len(logs)}") # type: ignore
+
+ await get_log.finish("\n".join(content).replace("ATRI", "ATRI")) # type: ignore
+
+
+shutdown = on_command("/shutdown", permission=SUPERUSER)
+
+async def _shutdown(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ msg = str(event.message).strip()
+ if msg:
+ state["msg"] = msg
+
[email protected]("msg", prompt="WARNING,此项操作将强行终止bot运行,是否继续(y/n)")
+async def __shutdown(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ if state["msg"] == "y":
+ await bot.send(event, "咱还会醒来的,一定")
+ exit(0)
+ else:
+ await shutdown.finish("再考虑下先吧 ;w;")
diff --git a/ATRI/plugins/anime-search/__init__.py b/ATRI/plugins/anime-search/__init__.py
new file mode 100644
index 0000000..61f523b
--- /dev/null
+++ b/ATRI/plugins/anime-search/__init__.py
@@ -0,0 +1,89 @@
+import re
+import json
+
+from nonebot.adapters.cqhttp.message import MessageSegment
+from nonebot.plugin import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.adapters.cqhttp.message import Message
+from nonebot.typing import T_State
+
+from ATRI.rule import is_in_banlist, is_in_dormant
+from ATRI.exceptions import RequestTimeOut
+from ATRI.utils.request import get_bytes
+
+from .data_source import to_simple_string
+
+
+URL = "https://trace.moe/api/search?url="
+
+
+anime_search = on_command(
+ "/anime",
+ rule=is_in_banlist() & is_in_dormant()
+)
+
+@anime_search.handle()
+async def _anime_search(bot: Bot,
+ event: MessageEvent,
+ state: T_State) -> None:
+ msg = str(event.message).strip()
+ if msg:
+ state["msg"] = msg
+
+@anime_search.got("msg", prompt="请发送咱一张图片~!")
+async def _(bot: Bot,
+ event: MessageEvent,
+ state: T_State) -> None:
+ msg = state["msg"]
+ img = re.findall(r"url=(.*?)]", msg)
+ if not img:
+ await anime_search.reject("请发送图片而不是其它东西!!")
+
+ try:
+ req = await get_bytes(URL + img[0])
+ except RequestTimeOut:
+ raise RequestTimeOut("Request failed!")
+
+ data = json.loads(req)["docs"]
+ try:
+ d = {}
+ for i in range(len(data)):
+ if data[i]["title_chinese"] in d.keys():
+ d[data[i]["title_chinese"]][0] += data[i]["similarity"]
+ else:
+ m = data[i]["at"] / 60
+ s = data[i]["at"] % 60
+
+ if not data[i]["episode"]:
+ n = 1
+ else:
+ n = data[i]["episode"]
+
+ d[to_simple_string(data[i]["title_chinese"])] = [
+ data[i]["similarity"],
+ f"第{n}集",
+ f"{int(m)}分{int(s)}秒处"
+ ]
+ except Exception as err:
+ raise Exception(f"Invalid data.\n{err}")
+
+ result = sorted(
+ d.items(),
+ key=lambda x:x[1],
+ reverse=True
+ )
+
+ t = 0
+
+ msg0 = f"{MessageSegment.at(event.user_id)}\nResult [{len(d)}]:"
+ for i in result:
+ t += 1
+ s = "%.2f%%" % (i[1][0] * 100)
+ msg0 = msg0 + (
+ "\n——————————\n"
+ f"({t}) Similarity: {s}\n"
+ f"Name: {i[0]}\n"
+ f"Time: {i[1][1]} {i[1][2]}"
+ )
+
+ await anime_search.finish(Message(msg0))
diff --git a/ATRI/plugins/anime-search/data_source.py b/ATRI/plugins/anime-search/data_source.py
new file mode 100644
index 0000000..3646162
--- /dev/null
+++ b/ATRI/plugins/anime-search/data_source.py
@@ -0,0 +1,34 @@
+SIMPLE = "万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释里鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾鼋鼌鼍鼗鼹齄齐齑齿龀龁龂龃龄龅龆龇龈龉龊龋龌龙龚龛龟志制咨只里系范松没尝尝闹面准钟别闲干尽脏拼"
+TRADITION = "萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備復夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋裏钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽黿鼂鼉鞀鼴齇齊齏齒齔齕齗齟齡齙齠齜齦齬齪齲齷龍龔龕龜誌製谘隻裡係範鬆冇嚐嘗鬨麵準鐘彆閒乾儘臟拚"
+
+
+def to_tradition_string(str):
+ output_str_list = []
+ str_len = len(str)
+
+ for i in range(str_len):
+ found_index = SIMPLE.find(str[i])
+
+ if not (found_index == -1):
+ output_str_list.append(TRADITION[found_index])
+
+ else:
+ output_str_list.append(str[i])
+
+ return "".join(output_str_list)
+
+
+def to_simple_string(str):
+ output_str_list = []
+ str_len = len(str)
+
+ for i in range(str_len):
+ found_index = TRADITION.find(str[i])
+
+ if not (found_index == -1):
+ output_str_list.append(SIMPLE[found_index])
+
+ else:
+ output_str_list.append(str[i])
+
+ return "".join(output_str_list) \ No newline at end of file
diff --git a/ATRI/plugins/anti-rubbish.py b/ATRI/plugins/anti-rubbish.py
new file mode 100644
index 0000000..b6ef12a
--- /dev/null
+++ b/ATRI/plugins/anti-rubbish.py
@@ -0,0 +1,166 @@
+import json
+from pathlib import Path
+from datetime import datetime
+from typing import Optional
+
+from nonebot.plugin import on_command, on_message
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
+
+from ATRI.log import logger
+from ATRI.rule import is_in_banlist
+from ATRI.config import nonebot_config
+from ATRI.utils.file import write_file
+from ATRI.utils.apscheduler import scheduler
+from ATRI.exceptions import WriteError
+
+
+RUBBISH_DIR = Path('.') / 'ATRI' / 'data' / 'database' / 'anti-rubbish'
+now_time = datetime.now().strftime('%Y%m%d-%H%M%S')
+
+
+# 365 x 24 不间断监听啥b发屎人
+# 日您🐎的,自己在厕所吃完自助餐还不够,还要分享给群友
+# 👴就搁这公示公示这些啥b
+# 每日0点如有发屎记录则全群通报
+anti_rubbish = on_message()
+
+@anti_rubbish.handle()
+async def _anti_rubbish(bot: Bot, event: GroupMessageEvent) -> None:
+ msg = str(event.message).strip()
+ user = int(event.user_id)
+ group = event.group_id
+ key_word: dict = NoobRubbish.get_keyword()
+ noob_data: dict = NoobRubbish.read_noobs(group)
+ noob_data.setdefault(user, {})
+
+ for key in key_word.keys():
+ if key in msg:
+ noob_data[user].setdefault(key, 1)
+ noob_data[user][key] += 1
+ await write_file(NoobRubbish._get_noob(group), json.dumps(noob_data))
+ logger.info(
+ f"GET 吃屎人 {user}[@群{group}] 第{noob_data[user][key]}次: {msg}")
+
+
+rubbish = on_command("/rubbish", rule=is_in_banlist())
+
+async def _rubbish(bot: Bot, event: GroupMessageEvent) -> None:
+ cmd = str(event.message).split(" ")
+ user = int(event.user_id)
+ group = event.group_id
+
+ if cmd[0] == "list":
+ noob_data: dict = NoobRubbish.read_noobs(group)
+ noob_list = ""
+ for key in noob_data.keys():
+ noob_list += f"{key}\n"
+
+ if not noob_list:
+ await rubbish.finish("此群很干净呢~!")
+ else:
+ msg = (
+ f"截至{now_time}\n"
+ f"吃过厕所自助餐的有:\n"
+ ) + noob_list
+ await rubbish.finish(msg)
+
+ elif cmd[0] == "read":
+ try:
+ user = cmd[1]
+ except:
+ await rubbish.finish("格式/rubbish read qq")
+
+ noob_data: dict = NoobRubbish.read_noob(group, int(user))
+ if not noob_data:
+ await rubbish.finish("该群友很干净!")
+ else:
+ noob_keys = ""
+ for key in noob_data.keys():
+ noob_keys += f"{key}-{noob_data[key]}次\n"
+ msg = (
+ f"截至{now_time}\n"
+ f"此群友吃的屎的种类,以及次数:\n"
+ ) + noob_keys
+ await rubbish.finish(msg)
+
+ elif cmd[0] == "update":
+ if user not in nonebot_config["superusers"]:
+ await rubbish.finish("没权限呢...")
+
+ key_word = cmd[1]
+ data = NoobRubbish.get_keyword()
+ data[key_word] = now_time
+ await NoobRubbish.store_keyword(data)
+ await rubbish.finish(f"勉強しました!\n[{key_word}]")
+
+ elif cmd[0] == "del":
+ if user not in nonebot_config["superusers"]:
+ await rubbish.finish("没权限呢...")
+
+ key_word = cmd[1]
+ data = NoobRubbish.get_keyword()
+ del data[key_word]
+ await NoobRubbish.store_keyword(data)
+ await rubbish.finish(f"清除~![{key_word}]")
+
+ else:
+ await rubbish.finish("请检查格式~!详细请查阅文档")
+
+
+# @scheduler.scheduled_job(
+# "cron",
+# hour=0,
+# misfire_grace_time=120
+# )
+# async def _():
+# group = GroupMessageEvent.group_id
+# noob_data = NoobRubbish.read_noobs(group)
+
+
+class NoobRubbish:
+ @staticmethod
+ def _get_noob(group: Optional[int] = None) -> Path:
+ file_name = f"{now_time}.noob.json"
+ GROUP_DIR = RUBBISH_DIR / f"{group}"
+ path = GROUP_DIR / file_name
+
+ if not GROUP_DIR.exists():
+ GROUP_DIR.mkdir()
+ return path
+
+ @classmethod
+ def read_noobs(cls, group: int) -> dict:
+ try:
+ data = json.loads(cls._get_noob(group).read_bytes())
+ except:
+ data = {}
+ return data
+
+ @classmethod
+ def read_noob(cls, group: int, user: Optional[int]) -> dict:
+ try:
+ data = json.loads(cls._get_noob(group).read_bytes())
+ except:
+ data = {}
+ data.setdefault(user, {})
+ return data
+
+ @staticmethod
+ def get_keyword() -> dict:
+ file_name = "keyword.json"
+ path = RUBBISH_DIR / file_name
+ try:
+ data = json.loads(path.read_bytes())
+ except:
+ data = {}
+ return data
+
+ @staticmethod
+ async def store_keyword(data: dict) -> None:
+ file_name = "keyword.json"
+ path = RUBBISH_DIR / file_name
+ try:
+ await write_file(path, json.dumps(data))
+ except WriteError:
+ raise WriteError("Writing file failed!")
diff --git a/ATRI/plugins/call-owner.py b/ATRI/plugins/call-owner.py
new file mode 100644
index 0000000..f6174f5
--- /dev/null
+++ b/ATRI/plugins/call-owner.py
@@ -0,0 +1,63 @@
+from nonebot.permission import SUPERUSER
+from nonebot.plugin import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import (
+ Bot,
+ MessageEvent,
+ GroupMessageEvent
+)
+
+from ATRI.rule import is_in_banlist
+from ATRI.config import nonebot_config
+from ATRI.utils.apscheduler import scheduler
+from ATRI.utils.list import count_list
+
+
+repo_list = []
+
+
+repo = on_command("来杯红茶", rule=is_in_banlist())
+
+async def _repo(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ msg = str(event.message).strip()
+ if msg:
+ state["msg"] = msg
+
[email protected]("msg", prompt="请告诉咱需要反馈的内容~!")
+async def _repo_(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ global repo_list
+ msg = state["msg"]
+ user = event.user_id
+
+ if count_list(repo_list, user) == 5:
+ await repo.finish("吾辈已经喝了五杯红茶啦!明天再来吧。")
+
+ repo_list.append(user)
+
+ for sup in nonebot_config["superusers"]:
+ await bot.send_private_msg(
+ user_id=sup,
+ message=f"来自用户[{user}]反馈:\n{msg}"
+ )
+
+ await repo.finish("吾辈的心愿已由咱转告给咱的维护者了~!")
+
+
+ "cron",
+ hour=0,
+ misfire_grace_time=60
+)
+async def _() -> None:
+ global repo_list
+ repo_list = []
+
+
+reset_repo = on_command("重置红茶", permission=SUPERUSER)
+
+@reset_repo.handle()
+async def _reset_repo(bot: Bot, event: MessageEvent) -> None:
+ global repo_list
+ repo_list = []
+ await reset_repo.finish("红茶重置完成~!")
diff --git a/ATRI/plugins/code-runner.py b/ATRI/plugins/code-runner.py
new file mode 100644
index 0000000..ef39afe
--- /dev/null
+++ b/ATRI/plugins/code-runner.py
@@ -0,0 +1,86 @@
+"""
+Idea from: https://github.com/cczu-osa/aki
+"""
+import json
+from nonebot.plugin import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+
+from ATRI.rule import is_in_banlist, is_in_dormant
+from ATRI.utils.request import post_bytes
+from ATRI.exceptions import RequestTimeOut
+
+
+RUN_API_URL_FORMAT = 'https://glot.io/run/{}?version=latest'
+SUPPORTED_LANGUAGES = {
+ 'assembly': {'ext': 'asm'},
+ 'bash': {'ext': 'sh'},
+ 'c': {'ext': 'c'},
+ 'clojure': {'ext': 'clj'},
+ 'coffeescript': {'ext': 'coffe'},
+ 'cpp': {'ext': 'cpp'},
+ 'csharp': {'ext': 'cs'},
+ 'erlang': {'ext': 'erl'},
+ 'fsharp': {'ext': 'fs'},
+ 'go': {'ext': 'go'},
+ 'groovy': {'ext': 'groovy'},
+ 'haskell': {'ext': 'hs'},
+ 'java': {'ext': 'java', 'name': 'Main'},
+ 'javascript': {'ext': 'js'},
+ 'julia': {'ext': 'jl'},
+ 'kotlin': {'ext': 'kt'},
+ 'lua': {'ext': 'lua'},
+ 'perl': {'ext': 'pl'},
+ 'php': {'ext': 'php'},
+ 'python': {'ext': 'py'},
+ 'ruby': {'ext': 'rb'},
+ 'rust': {'ext': 'rs'},
+ 'scala': {'ext': 'scala'},
+ 'swift': {'ext': 'swift'},
+ 'typescript': {'ext': 'ts'},
+}
+
+
+code_runner = on_command("/code", rule=is_in_banlist() & is_in_dormant())
+
+@code_runner.handle()
+async def _code_runner(bot: Bot, event: MessageEvent) -> None:
+ msg = str(event.message).split("\n")
+ laug = msg[0].replace("\r", "")
+ if laug not in SUPPORTED_LANGUAGES:
+ await code_runner.finish("该语言暂不支持...")
+
+ code = msg[1]
+ try:
+ req = await post_bytes(
+ RUN_API_URL_FORMAT.format(laug),
+ json={
+ "files": [{
+ "name": (SUPPORTED_LANGUAGES[laug].get("name", "main") +
+ f".{SUPPORTED_LANGUAGES[laug]['ext']}"),
+ "content": code
+ }],
+ "stdin": "",
+ "command": ""
+ }
+ )
+ except RequestTimeOut:
+ raise RequestTimeOut("Failed to request!")
+
+ payload = json.loads(req)
+ sent = False
+ for k in ['stdout', 'stderr', 'error']:
+ v = payload.get(k)
+ lines = v.splitlines()
+ lines, remained_lines = lines[:10], lines[10:]
+ out = '\n'.join(lines)
+ out, remained_out = out[:60 * 10], out[60 * 10:]
+
+ if remained_lines or remained_out:
+ out += f"\n(输出过多,已忽略剩余内容)"
+
+ if out:
+ await bot.send(event, f"{k}:\n\n{out}")
+ sent = True
+
+ if not sent:
+ await code_runner.finish("运行完成,没有任何输出")
diff --git a/ATRI/plugins/drifting-bottle/__init__.py b/ATRI/plugins/drifting-bottle/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ATRI/plugins/drifting-bottle/__init__.py
diff --git a/ATRI/plugins/essential.py b/ATRI/plugins/essential.py
index 22f641f..a8ba021 100644
--- a/ATRI/plugins/essential.py
+++ b/ATRI/plugins/essential.py
@@ -87,7 +87,7 @@ async def _request_friend_event(bot, event: FriendRequestEvent) -> None:
try:
data = json.loads(path.read_bytes())
- except FileExistsError:
+ except:
data = {}
data[event.flag] = {
"user_id": event.user_id,
@@ -127,7 +127,7 @@ async def _request_group_event(bot, event: GroupRequestEvent) -> None:
try:
data = json.loads(path.read_bytes())
- except FileExistsError:
+ except:
data = {}
data[event.flag] = {
"user_id": event.user_id,
@@ -243,7 +243,8 @@ async def _lucky_read_bag_event(bot, event: LuckyKingNotifyEvent) -> None:
group_file_upload_event = on_notice()
@group_file_upload_event.handle()
-async def _group_file_upload_event(bot, event: GroupUploadNoticeEvent) -> None:
+async def _group_file_upload_event(bot,
+ event: GroupUploadNoticeEvent) -> None:
await group_file_upload_event.finish("让我康康传了啥好东西")
@@ -268,6 +269,7 @@ async def _recall_event(bot: Bot, event) -> None:
f"{repo}"
)
+ await bot.send(event, "咱看到惹~!")
for superuser in nonebot_config["superusers"]:
await HttpPost.send_private_msg(
user_id=int(superuser),
diff --git a/ATRI/plugins/funny.py b/ATRI/plugins/funny.py
index a31cfdf..c691abd 100644
--- a/ATRI/plugins/funny.py
+++ b/ATRI/plugins/funny.py
@@ -41,8 +41,7 @@ me_to_you = on_message(
@me_to_you.handle()
async def _me_to_you(bot: Bot, event: MessageEvent) -> None:
- rd = randint(0, 5)
- if rd == 1:
+ if randint(0, 5) == 5:
msg = str(event.message)
- if "我" in msg:
- await me_to_you.finish(msg.replace('我', '你'))
+ if "我" in msg and "CQ" not in msg:
+ await me_to_you.finish(msg.replace("我", "你"))
diff --git a/ATRI/plugins/rich/__init__.py b/ATRI/plugins/rich/__init__.py
index 6bea2ff..d20a234 100644
--- a/ATRI/plugins/rich/__init__.py
+++ b/ATRI/plugins/rich/__init__.py
@@ -5,19 +5,36 @@ from aiohttp.client import ClientSession
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.plugin import on_message
-from ATRI.rule import is_in_banlist, is_in_dormant
from ATRI.utils.request import get_bytes
+from ATRI.utils.list import count_list, del_list_aim
+from ATRI.rule import (
+ is_in_banlist,
+ is_in_dormant,
+)
+
from .data_source import dec
+
+waiting_list = []
+
+
bilibili_rich = on_message(
rule=is_in_banlist() & is_in_dormant()
)
@bilibili_rich.handle()
async def _bilibili_rich(bot: Bot, event: MessageEvent) -> None:
+ global waiting_list
msg = str(event.raw_message)
+ user = event.user_id
bv = False
+ if count_list(waiting_list, user) == 5:
+ waiting_list = del_list_aim(waiting_list, user)
+ return
+
+ waiting_list.append(user)
+
if "qqdocurl" not in msg:
if "av" in msg:
av = re.findall(r"(av\d+)", msg)[0].replace('av', '')
@@ -58,4 +75,3 @@ async def _bilibili_rich(bot: Bot, event: MessageEvent) -> None:
"にまねげぴのTencent rich!"
)
await bilibili_rich.finish(repo)
- \ No newline at end of file
diff --git a/ATRI/plugins/status.py b/ATRI/plugins/status.py
new file mode 100644
index 0000000..576d45e
--- /dev/null
+++ b/ATRI/plugins/status.py
@@ -0,0 +1,50 @@
+import psutil
+
+from nonebot.plugin import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+
+from ATRI.rule import is_in_banlist
+from ATRI.exceptions import GetStatusError
+
+
+ping = on_command("/ping", rule=is_in_banlist())
+
+async def _ping(bot: Bot, event: MessageEvent) -> None:
+ await ping.finish("I'm fine.")
+
+
+status = on_command("/status", rule=is_in_banlist())
+
+async def _status(bot: Bot, event: MessageEvent) -> None:
+ try:
+ cpu = psutil.cpu_percent(interval=1)
+ mem = psutil.virtual_memory().percent
+ disk = psutil.disk_usage("/").percent
+ inteSENT = psutil.net_io_counters().bytes_sent / 1000000 # type: ignore
+ inteRECV = psutil.net_io_counters().bytes_sent / 1000000 # type: ignore
+ except GetStatusError:
+ raise GetStatusError("Failed to get status.")
+
+ msg = "アトリは、高性能ですから!"
+
+ if cpu > 80: # type: ignore
+ msg = "咱感觉有些头晕..."
+ if mem > 80:
+ msg = "咱感觉有点头晕并且有点累..."
+ elif mem > 80:
+ msg = "咱感觉有点累..."
+ elif disk > 80:
+ msg = "咱感觉身体要被塞满了..."
+
+ msg0 = (
+ "Self status:\n"
+ f"* CPU: {cpu}%\n"
+ f"* MEM: {mem}%\n"
+ f"* DISK: {disk}%\n"
+ f"* netSENT: {inteSENT}MB\n"
+ f"* netRECV: {inteRECV}MB\n"
+ ) + msg
+
+ await status.finish(msg0)
diff --git a/ATRI/plugins/tex.py b/ATRI/plugins/tex.py
new file mode 100644
index 0000000..01eabf7
--- /dev/null
+++ b/ATRI/plugins/tex.py
@@ -0,0 +1,52 @@
+import re
+from urllib.parse import quote_plus
+from nonebot.adapters.cqhttp.message import Message, MessageSegment
+
+from nonebot.plugin import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.typing import T_State
+
+from ATRI.exceptions import RequestTimeOut
+from ATRI.rule import is_in_banlist, is_in_dormant
+from ATRI.utils.request import post_bytes
+
+
+ZHIHU_TEX_SVG_URL_FORMAT = 'https://www.zhihu.com/equation?tex='
+LATEX2PNG_API_URL = 'http://latex2png.com/'
+LATEX2PNG_IMAGE_URL_FORMAT = 'http://latex2png.com/output//'
+
+
+tex = on_command("/tex", rule=is_in_banlist() & is_in_dormant())
+
+async def _tex(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ tex_code = str(event.message).strip()
+ if tex_code:
+ state["tex_code"] = tex_code
+
[email protected]("tex_code", prompt="请告诉咱需要生成图片的的Tex公式")
+async def __tex(bot: Bot, event: MessageEvent, state: T_State) -> None:
+ tex_code = state["tex_code"]
+ try:
+ req = await post_bytes(
+ LATEX2PNG_API_URL,
+ params={
+ "latex": tex_code,
+ "res": "600",
+ "color": "000000"
+ }
+ )
+ except RequestTimeOut:
+ raise RequestTimeOut("Failed to request!")
+
+ html = str(req)
+ m = re.search(r"latex_[0-9a-z]+\.png", html)
+ if not m:
+ await tex.finish("生成失败,等会再试试吧...")
+
+ await tex.finish(
+ Message(
+ MessageSegment.image(LATEX2PNG_IMAGE_URL_FORMAT + m.group(0)) +
+ "\n" + ZHIHU_TEX_SVG_URL_FORMAT + quote_plus(tex_code)
+ )
+ )
diff --git a/ATRI/plugins/utils/__init__.py b/ATRI/plugins/utils/__init__.py
index e69de29..1bf1461 100644
--- a/ATRI/plugins/utils/__init__.py
+++ b/ATRI/plugins/utils/__init__.py
@@ -0,0 +1,51 @@
+import re
+
+from nonebot.plugin import on_command
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+
+from ATRI.rule import (
+ is_in_banlist,
+ is_in_dormant,
+ is_in_service
+)
+from .data_source import roll_dice
+
+
+__plugin_name__ = "roll"
+
+roll = on_command(
+ "/roll",
+ rule=is_in_banlist() & is_in_dormant()
+ & is_in_service(__plugin_name__)
+)
+
+async def _roll(bot: Bot, event: MessageEvent, state: dict) -> None:
+ args = str(event.message).strip()
+ if args:
+ state['resu'] = args
+
[email protected]("resu", prompt="roll 参数不能为空~!\ndemo:1d10 或 2d10+2d10")
+async def _(bot: Bot, event: MessageEvent, state: dict) -> None:
+ resu = state['resu']
+ match = re.match(r'^([\dd+\s]+?)$', resu)
+
+ if not match:
+ await roll.finish("请输入正确的参数!!\ndemo:1d10 或 2d10+2d10")
+
+ await roll.finish(roll_dice(resu))
+
+
+# __plugin_name__ = "fakemsg"
+
+# fakemsg = on_command(
+# "/fakemsg",
+# rule=is_in_banlist() & is_in_dormant()
+# & is_in_service(__plugin_name__)
+# )
+
+# @fakemsg.handle()
+# async def _fakemsg(bot: Bot, event: MessageEvent, state: dict) -> None:
+# ...
+
+# @fakemsg.got() \ No newline at end of file
diff --git a/ATRI/plugins/utils/data_source.py b/ATRI/plugins/utils/data_source.py
index b83cd33..f41a1d1 100644
--- a/ATRI/plugins/utils/data_source.py
+++ b/ATRI/plugins/utils/data_source.py
@@ -1,3 +1,34 @@
-from nonebot.adapters.cqhttp.message import MessageSegment
+import re
+import random
-MessageSegment. \ No newline at end of file
+
+def roll_dice(par: str) -> str:
+ result = 0
+ proc = ''
+ proc_list = []
+ p = par.split("+")
+
+ for i in p:
+ args = re.findall(r"(\d{0,10})(?:(d)(\d{1,10}))", i)
+ args = list(args[0])
+
+ args[0] = args[0] or 1
+ if int(args[0]) >= 5000 or int(args[2]) >= 5000:
+ return "阿...好大......"
+
+ for a in range(1, int(args[0]) + 1):
+ rd = random.randint(1, int(args[2]))
+ result = result + rd
+
+ if len(proc_list) <= 10:
+ proc_list.append(rd)
+
+ if len(proc_list) <= 10:
+ proc += "+".join(map(str, proc_list))
+ elif len(proc_list) > 10:
+ proc += "太长了不展示了就酱w"
+ else:
+ proc += str(result)
+
+ result = f"{par}=({proc})={result}"
+ return result
diff --git a/ATRI/rule.py b/ATRI/rule.py
index 586faf9..abc90f8 100644
--- a/ATRI/rule.py
+++ b/ATRI/rule.py
@@ -47,7 +47,7 @@ exciting_repo = [
"请稍等!您冲得太快了!"
]
-def is_too_exciting(times: int) -> Rule:
+def is_too_exciting(times: int, repo: bool) -> Rule:
def del_list(user: str) -> None:
global exciting_user
exciting_user = del_list_aim(exciting_user, user)
@@ -57,10 +57,11 @@ def is_too_exciting(times: int) -> Rule:
user = event.get_user_id()
if user in exciting_user:
- await bot.send(
- event,
- choice(exciting_repo)
- )
+ if repo:
+ await bot.send(
+ event,
+ choice(exciting_repo)
+ )
return False
else:
if count_list(exciting_user, user) == times:
@@ -76,10 +77,11 @@ def is_too_exciting(times: int) -> Rule:
misfire_grace_time=1,
)
- await bot.send(
- event,
- choice(exciting_repo)
- )
+ if repo:
+ await bot.send(
+ event,
+ choice(exciting_repo)
+ )
return False
else:
exciting_user.append(user)
diff --git a/ATRI/service/limit.py b/ATRI/service/limit.py
index d5a8a04..2ea3f95 100644
--- a/ATRI/service/limit.py
+++ b/ATRI/service/limit.py
@@ -1,54 +1,39 @@
import json
-import aiofiles
+from pathlib import Path
+from typing import Optional
-from ATRI.exceptions import WriteError
+from ATRI.utils.file import write_file
from . import SERVICE_DIR
class Limit:
-
- file_name = "limit.service.json"
- path = SERVICE_DIR / file_name
- path.parent.mkdir(exist_ok=True, parents=True)
- try:
- data = json.loads(path.read_bytes())
- except:
- data = {}
-
- @classmethod
- def _filling_service(cls, service, group: int = None):
- # Determine whether the service exists in global variables.
- if service not in cls.data["global"]:
- cls.data["global"][service] = True
- # Similary, for group.
- if service not in cls.data[group]:
- cls.data[group][service] = True
+ @staticmethod
+ def _get_file(group: Optional[int] = None) -> Path:
+ file_name = f"{group}.service.json"
+ LIMIT_DIR = SERVICE_DIR / "limit"
+ path = LIMIT_DIR / file_name
+ if not LIMIT_DIR.exists():
+ LIMIT_DIR.mkdir()
+ return path
@classmethod
- def get_service(cls) -> dict:
- return cls.data
-
- @classmethod
- async def auth_service(
- cls, service: str, group: int = None) -> bool:
- cls.data.setdefault("global", {})
- cls.data.setdefault(group, {})
- cls._filling_service(service, group)
-
+ def _read_file(cls, group: Optional[int] = None) -> dict:
try:
- async with aiofiles.open(
- cls.path, 'w', encoding='utf-8') as target:
- await target.write(
- json.dumps(
- cls.data
- )
- )
- except WriteError:
- raise WriteError("Writing file failed!")
+ data = json.loads(cls._get_file(group).read_bytes())
+ except:
+ data = {}
+ return data
+
+ @classmethod
+ async def auth_service(cls, service: str, group: Optional[int] = None) -> bool:
+ data = cls._read_file(group)
+ if service not in data:
+ data[service] = True
+ await write_file(cls._get_file(group), json.dumps(data))
- if cls.data["global"][service]:
- return True if cls.data[group][service] else False
+ if data[service]:
+ return True
else:
return False
@@ -57,22 +42,12 @@ class Limit:
cls,
service: str,
status: bool,
- group: int = None
+ group: Optional[int] = None
) -> None:
- cls._filling_service(service, group)
+ data = cls._read_file(group)
+ if service not in data:
+ data[service] = True
+ await write_file(cls._get_file(group), json.dumps(data))
- if group:
- cls.data[group][service] = status
- else:
- cls.data["global"][service] = status
-
- try:
- async with aiofiles.open(
- cls.path, 'w', encoding='utf-8') as target:
- await target.write(
- json.dumps(
- cls.data
- )
- )
- except WriteError:
- raise WriteError("Writing file failed!")
+ data[service] = status
+ await write_file(cls._get_file(group), json.dumps(data))
diff --git a/ATRI/utils/file.py b/ATRI/utils/file.py
new file mode 100644
index 0000000..4699f5d
--- /dev/null
+++ b/ATRI/utils/file.py
@@ -0,0 +1,27 @@
+import aiofiles
+from pathlib import Path
+
+from ATRI.exceptions import WriteError
+
+
+async def write_file(path: Path, text, encoding='utf-8') -> None:
+ try:
+ async with aiofiles.open(path, 'w', encoding=encoding) as target:
+ await target.write(text)
+ except WriteError:
+ raise WriteError("Writing file failed!")
+
+
+async def open_file(path: Path, method, encoding='utf-8'):
+ try:
+ async with aiofiles.open(path, 'r', encoding=encoding) as target:
+ if method == "read":
+ return target.read()
+ elif method == "readlines":
+ return await target.readlines()
+ elif method == "readline":
+ return await target.readline()
+ else:
+ return target.readable()
+ except EOFError:
+ raise EOFError("File not fond!")
diff --git a/ATRI/utils/request.py b/ATRI/utils/request.py
index bf05b56..31285e8 100644
--- a/ATRI/utils/request.py
+++ b/ATRI/utils/request.py
@@ -18,9 +18,11 @@ async def get_bytes(url: str, headers: Optional[dict] = None) -> bytes:
return result
-async def post_bytes(url: str, params: Optional[dict] = None) -> bytes:
+async def post_bytes(url: str,
+ params: Optional[dict] = None,
+ json: Optional[dict] = None) -> bytes:
"""异步以 Post 方式请求 url"""
async with ClientSession() as session:
- async with session.post(url, params=params) as r:
+ async with session.post(url, params=params, json=json) as r:
result = await r.read()
return result
diff --git a/config.yml b/config.yml
index befb1d1..3a73f28 100644
--- a/config.yml
+++ b/config.yml
@@ -1,7 +1,7 @@
BotSelfConfig:
host: "127.0.0.1"
- port: 8080
- debug: true
+ port: 25565
+ debug: false
superusers: ["1234567890"]
nickname: ["ATRI", "Atri", "atri", "亚托莉", "アトリ"]
command_start: ["", "/"]
@@ -11,4 +11,4 @@ BotSelfConfig:
HttpPost:
host: "127.0.0.1"
- port: 8081 \ No newline at end of file
+ port: 23333 \ No newline at end of file