Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
UNIkeEN committed Sep 30, 2024
1 parent 92ba1f0 commit b4f7488
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 28 deletions.
26 changes: 18 additions & 8 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@
ChatWithNLP = EmptyPlugin
print('ChatWithNLP not imported: {}'.format(e))
from plugins.chatWithAnswerbook import ChatWithAnswerbook
try:
from plugins.sjtuActivity import SjtuActivity, SjtuDektMonitor
except NotPublishedException as e:
SjtuActivity, SjtuDektMonitor = EmptyPlugin, EmptyPlugin
print('SjtuActivity, SjtuDektMonitor not imported: {}'.format(e))
# try:
# from plugins.getDekt_v2 import SjtuDekt, SjtuDektMonitor
# except NotPublishedException as e:
# SjtuDekt, SjtuDektMonitor = EmptyPlugin, EmptyPlugin
# print('SjtuDekt, SjtuDektMonitor not imported: {}'.format(e))
from plugins.getJwc import GetSjtuNews, GetJwc, SjtuJwcMonitor#, SubscribeJwc
from plugins.sjtuSchoolGate import SjtuSchoolGate
from plugins.sjtuBwc import SjtuBwc, SjtuBwcMonitor
Expand All @@ -99,8 +99,9 @@
from plugins.groupActReport import ActReportPlugin, ActRankPlugin, YourActReportPlugin
from plugins.groupWordCloud import wordCloudPlugin, GenWordCloud, GenPersonWordCloud
from plugins.randomNum import TarotRandom, RandomNum, ThreeKingdomsRandom
from plugins.sjtuClassroom import SjtuClassroom, SjtuClassroomRecommend, SjtuClassroomPeopleNum
from plugins.sjtuClassroom import SjtuClassroom, SjtuClassroomRecommend, SjtuClassroomPeopleNum, SjtuJsQuery
from plugins.sjtuClassroomRecorder import SjtuClassroomRecorder, DrawClassroomPeopleCount
from plugins.sjtuActivity import SjtuActivity, SjtuDektMonitor
from plugins.makeJoke import MakeJoke
from plugins.uniAgenda import GetUniAgenda
from plugins.chess import ChessPlugin, ChessHelper
Expand Down Expand Up @@ -153,7 +154,6 @@
except NotPublishedException as e:
SMPParkourRank = EmptyAddGroupPlugin
print('SMPParkourRank not imported: {}'.format(e))

try:
from plugins.sjtuElectromobileCharge import GetSjtuCharge
except NotPublishedException as e:
Expand All @@ -163,6 +163,15 @@
from plugins.gocqWatchDog import GocqWatchDog
from plugins.xhsSubscribe import XhsSubscribe, XhsSubscribeHelper
from plugins.douyinSubscribe import DouyinSubscribe, DouyinSubscribeHelper

from plugins.notPublished.sjtuSql import (
SearchSjtuSqlAllPrivate,
SearchSjtuSqlAll,
SearchSjtuSql,
SearchSjtuSqlPIC,
)
from plugins.notPublished.sjtuSqlGroupingVerication import SjtuSqlGroupingVerify
from plugins.test import TestLagrange
###### end not published plugins

def sqlInit():
Expand Down Expand Up @@ -214,7 +223,7 @@ def sqlInit():
PluginGroupManager([UpdateNewsAndReport(), UpdateMoyuCalendar()], 'newsreport')],'news'), # 新闻
PluginGroupManager([WeiboHotSearch(), BaiduHotSearch(), ZhihuHotSearch(),], 'hotsearch'),
PluginGroupManager([SjtuCanteenInfo(),SjtuLibInfo(), SjtuClassroom(), SjtuClassroomPeopleNum(),
DrawClassroomPeopleCount(), SjtuSchoolGate(),
DrawClassroomPeopleCount(), SjtuSchoolGate(), SjtuJsQuery(),
SjtuClassroomRecommend(), GetMddStatus(), GetSjtuCharge(), SjtuActivity(),#IcokeUserBind(), #SubscribeMdd(), # 交大餐厅, 图书馆, 核酸点, 麦当劳
PluginGroupManager([MonitorMddStatus()], 'mddmonitor'),
PluginGroupManager([SjtuDektMonitor()], 'dektmonitor'),], 'sjtuinfo'),
Expand Down Expand Up @@ -288,6 +297,7 @@ def sqlInit():
RandomNum(), ThreeKingdomsRandom(), TarotRandom(),
EmojiKitchen(),
# ChooseSong(),
SjtuJsQuery(),
SjtuClassroom(), SjtuClassroomPeopleNum(), SjtuClassroomRecommend(), DrawClassroomPeopleCount(), SjtuSchoolGate(),
]
GuildPluginList:List[GuildStandardPlugin] = []
Expand Down
4 changes: 3 additions & 1 deletion plugins/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ def text_to_emoji(text):
return text_with_emoji

class MakeAbstract(StandardPlugin):
def __init__(self):
self.pattern = re.compile('^(抽象|-abstract)\s+\S+')
def judgeTrigger(self, msg: str, data: Any) -> bool:
return msg.startswith('-abstract') or msg.startswith('抽象')
return self.pattern.match(msg) != None
def executeEvent(self, msg: str, data: Any) -> Optional[str]:
target = data['group_id'] if data['message_type']=='group' else data['user_id']
if msg.startswith('抽象'):
Expand Down
2 changes: 1 addition & 1 deletion plugins/chatWithAnswerbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class ChatWithAnswerbook(StandardPlugin): # 答案之书
def judgeTrigger(self, msg:str, data:Any) -> bool:
return startswith_in(msg, ['小🦄,','小🦄,'])
return startswith_in(msg, ['小🦄', '小马'])
def executeEvent(self, msg:str, data:Any) -> Union[None, str]:
target = data['group_id'] if data['message_type']=='group' else data['user_id']
txt = random.choice(BOOK_DICT)
Expand Down
32 changes: 25 additions & 7 deletions plugins/getJwc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from utils.standardPlugin import StandardPlugin, CronStandardPlugin, GuildStandardPlugin
from typing import Set, Union, Any, List
from typing import Set, Union, Any, List, Dict
import mysql.connector
from utils.responseImage import *
import requests
Expand All @@ -16,7 +16,7 @@
import qrcode
import os, os.path

def createJwcSql():
def createJwcSql() -> None:
mydb, mycursor = newSqlSession()
mycursor.execute("""
create table if not exists `sjtuJwc` (
Expand All @@ -26,13 +26,13 @@ def createJwcSql():
primary key (`jwc_seq`)
)charset=utf8mb4, collate=utf8mb4_unicode_ci;""")

def appendJwcUrl(url:str):
def appendJwcUrl(url:str) -> None:
mydb, mycursor = newSqlSession()
mycursor.execute("""
insert into `sjtuJwc` (`url`, `update_time`) values (%s, %s)
""", (url, datetime.now()))

def getSjtuGk():
def getSjtuGk() -> List[Dict[str, Any]]:
"""交大信息公开网"""
pageUrl = 'https://gk.sjtu.edu.cn'
req = requests.get(pageUrl)
Expand Down Expand Up @@ -68,7 +68,7 @@ def loadPrevUrls()->Set[str]:
result.add(url)
return result

def getSjtuNews():
def getSjtuNews() -> List[Dict[str, Any]]:
"""交大新闻网"""
pageUrl = 'https://news.sjtu.edu.cn/jdyw/index.html'
req = requests.get(pageUrl)
Expand Down Expand Up @@ -142,8 +142,7 @@ def drawSjtuNews()->str:
a.generateImage(savePath)
return savePath

def getJwc()->list:
pageUrl = 'https://jwc.sjtu.edu.cn/xwtg/tztg.htm'
def getJwcPage(pageUrl:str)->List[Dict[str, Any]]:
req = requests.get(pageUrl)
if req.status_code != requests.codes.ok:
warning("jwc.sjtu.edu.cn API failed!")
Expand Down Expand Up @@ -180,6 +179,25 @@ def getJwc()->list:
print("exception in getJwc: {}".format(e))
return newsList

def mergeJwcList(jwcDicts:List[List[Dict[str, Any]]]) -> List[Dict[str, Any]]:
result = []
pageUrls = set()
for d in jwcDicts:
for jwcPage in d:
link = jwcPage['link']
if link in pageUrls: continue
pageUrls.add(link)
result.append(jwcPage)
return result

def getJwc() -> List[Dict[str, Any]]:
jwcUrls = ['https://jwc.sjtu.edu.cn/xwtg/tztg.htm',
'https://jwc.sjtu.edu.cn/index/mxxsdtz.htm']
jwcDicts = []
for url in jwcUrls:
jwcDicts.append(getJwcPage(url))
return mergeJwcList(jwcDicts)

class SjtuJwcMonitor(StandardPlugin, CronStandardPlugin):
monitorSemaphore = Semaphore()
def __init__(self) -> None:
Expand Down
4 changes: 3 additions & 1 deletion plugins/groupBan.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List, Any, Dict, Optional, Union, Set, Tuple
from utils.basicEvent import set_group_ban, isGroupOwner, send, warning
from utils.configAPI import getGroupAdmins
from utils.basicConfigs import ROOT_ADMIN_ID, SAVE_TMP_PATH, ROOT_PATH
from utils.basicConfigs import ROOT_ADMIN_ID, SAVE_TMP_PATH, ROOT_PATH, BOT_SELF_QQ
from utils.sqlUtils import newSqlSession
from utils.responseImage_beta import *
from threading import Semaphore
Expand Down Expand Up @@ -119,6 +119,8 @@ def unbanUser(self, groupId:int, banId:int, data: Any):
@staticmethod
def checkBanAuthentication(banTarget:int, enforcementPersonnel:int, groupId:int)->Tuple[bool, str]:
groupAdmins = getGroupAdmins(groupId)
if banTarget == BOT_SELF_QQ:
return False, "BOT无法被ban"
if enforcementPersonnel not in groupAdmins:
return False, '非群BOT管理员无法使用该功能'
if banTarget in ROOT_ADMIN_ID or isGroupOwner(group_id=groupId, user_id=banTarget):
Expand Down
9 changes: 8 additions & 1 deletion plugins/messageRecorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,21 @@ def executeEvent(self, msg: str, data: Any) -> Union[None, str]:
card = data['sender']['card']
if card == None:
card = ''
backendTime:int = data['time'] # timestamp in second
'''
# FIX: backend time error
systemTime:int = int(time.time())
if abs(backendTime - systemTime) > 60:
backendTime = systemTime
'''
mycursor.execute("""
insert ignore into `messageRecord`
(`message_id`, `message_seq`, `time`, `user_id`,
`message`, `group_id`, `nickname`, `card`)
values (%d, %d, from_unixtime(%d), %d, '%s', %d, '%s', '%s')"""%(
data['message_id'],
data['message_seq'],
data['time'],
backendTime,
data['user_id'],
escape_string(data['message']),
data['group_id'],
Expand Down
134 changes: 125 additions & 9 deletions plugins/sjtuClassroom.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from typing import List, Tuple, Optional, Union, Dict, Any
import requests
import datetime
from utils.responseImage_beta import ResponseImage
from utils.responseImage_beta import ResponseImage, PALETTE_SJTU_RED, PALETTE_GREEN, PALETTE_GREY_BORDER, FONT_SYHT_M28, draw_rounded_rectangle
from utils.hotSearchImage import HotSearchImage, Colors, Fonts
import os.path
from matplotlib import pyplot as plt
from io import BytesIO
from PIL import Image, ImageDraw

headers = {
"Accept": "application/json, text/javascript, */*; q=0.01",
Expand Down Expand Up @@ -148,22 +149,22 @@ def standarlizingBuildingStr(buildingStr:str)->Optional[str]:
return None


def standarlizingBuildingTimeStr(Str:str)->Optional[str]:
def standarlizingBuildingTimeStr(Str:str)->Optional[Tuple[str, int, int]]:
"""
东上 3 5 => (东上院,3,5)
东中 3 5 => (东中院,3,5)
你好 => None
"""
pattern1 = re.compile(r'^(上|中|下|东上|东中|东下)院?\s*(\d+)\s+(\d+)$')
if pattern1.match(Str) != None:
building,startSection,endSection = pattern1.findall(Str)[0]
building, startSection, endSection = pattern1.findall(Str)[0]
building +='院'
return building,startSection,endSection
return building, int(startSection), int(endSection)
pattern2 = re.compile(r'^(陈瑞球楼?|球楼?)\s*(\d+)\s+(\d+)$')
if pattern2.match(Str) != None:
building = '陈瑞球楼'
_,startSection,endSection = pattern2.findall(Str)[0]
return building,startSection,endSection
_, startSection, endSection = pattern2.findall(Str)[0]
return building, int(startSection), int(endSection)
return None

def getWeekDay(targetDate:datetime.date)->str:
Expand Down Expand Up @@ -428,7 +429,124 @@ def getRoomrecommend():
rimg.generateImage(savePath)
return savePath

def processJsInfo(jsInfo: Dict[str, List[Dict[str, Any]]]) -> List[Tuple[str, List[bool]]]:
result:List[Tuple[str, List[bool]]] = []
for floor in jsInfo.get('floorList', []):
for room in floor.get('children', {}):
roomName:str = room.get('name', 'unknow')
roomSecs = [False] * 15 # 是否有课
for course in room.get('roomCourseList', []):
startSec:int = course.get('startSection', 0)
endSec:int = course.get('endSection', 0)
for sec in range(startSec, endSec + 1):
roomSecs[sec] = True # TODO: IndexError
result.append((roomName, roomSecs))
return sorted(result, key=lambda x: x[0])

def drawJs(jsInfo: List[Tuple[str, List[bool]]], targetBuilding: str, savePath: str) -> Optional[str]:
img = ResponseImage(
title=f'教室空闲时间',
titleColor=PALETTE_SJTU_RED,
primaryColor=PALETTE_SJTU_RED,
)

# sub img
cell_size = 50
padding = 10
width = (len(jsInfo[0][1]) - 2) * (cell_size + padding) + 100
height = (len(jsInfo) - 1) * (cell_size + padding)
sub_img = Image.new("RGB", (width, height), "white")
draw = ImageDraw.Draw(sub_img)

for i, (room_name, availability) in enumerate(jsInfo):
draw.text((0, i * cell_size + i * padding + 12), room_name.replace(targetBuilding, ""), fill="black", font = FONT_SYHT_M28)

for j, available in enumerate(availability[1:]):
color = PALETTE_GREY_BORDER if available else PALETTE_GREEN
draw_rounded_rectangle(
sub_img,
(
j * cell_size + j * padding + 100,
i * cell_size + i * padding,
(j + 1) * cell_size + j * padding + 100,
(i + 1) * cell_size + i * padding,
),
fill=color
)

time_slots = [
"08:00-08:45",
"08:55-09:40",
"10:00-10:45",
"10:55-11:40",
"12:00-12:45",
"12:55-13:40",
"14:00-14:45",
"14:55-15:40",
"16:00-16:45",
"16:55-17:40",
"18:00-18:45",
"18:55-19:40",
"20:00-20:45",
"20:55-21:40"
]

time_axis_img = Image.new("RGB", (200, width), "white")
draw = ImageDraw.Draw(time_axis_img)
for i, time in enumerate(time_slots):
bbox = FONT_SYHT_M28.getbbox(time)
left = 200 - bbox[2] + bbox[0]
draw.text((left, i * cell_size + i * padding + 112), time, fill="black", font = FONT_SYHT_M28)
time_axis_img = time_axis_img.rotate(90, expand=True)

img.addCard(
ResponseImage.RichContentCard(
raw_content=[
('title', f"目标楼栋: {targetBuilding}"),
('subtitle', f"{datetime.datetime.now().strftime('%Y-%m-%d')},绿色为空闲"),
('separator', ''),
('illustration', sub_img),
('illustration', time_axis_img),
('text', '\n')
]
)
)


img.generateImage(savePath)
return savePath

class SjtuJsQuery(StandardPlugin):
def __init__(self) -> None:
self.triggerPattern = re.compile(r'^-js\s+(.*)$')
def judgeTrigger(self, msg:str, data:Any) -> bool:
return self.triggerPattern.match(msg) != None
def executeEvent(self, msg:str, data:Any) -> Union[None, str]:
target = data['group_id'] if data['message_type']=='group' else data['user_id']
buildingStr = standarlizingBuildingStr(self.triggerPattern.findall(msg)[0])
if buildingStr == None:
send(target, '教学楼解析错误,请重新输入查询参数,例如:\n"-js 东上"、"-js 下院"、"-js 东中"', data['message_type'])
return "OK"
savePath = os.path.join(ROOT_PATH, SAVE_TMP_PATH, 'js-%d-%s.png'%(target, buildingStr))
jsInfo = processJsInfo(getRoomCourse(buildingStr, datetime.date.today()))
courseImgPath = drawJs(jsInfo, buildingStr, savePath)
if courseImgPath == None:
send(target, f'[CQ:reply,id={data["message_id"]}]图片绘制失败', data['message_type'])
else:
send(target, '[CQ:image,file=file:///%s]'%courseImgPath, data['message_type'])
return "OK"
def getPluginInfo(self, )->Any:
return {
'name': 'SjtuClassroom',
'description': '教学楼空闲查询',
'commandDescription': '-js [东上/东中/...]',
'usePlace': ['group', 'private', ],
'showInHelp': True,
'pluginConfigTableNames': [],
'version': '1.0.0',
'author': 'Unicorn',
}

class SjtuClassroom(StandardPlugin):
def __init__(self) -> None:
self.triggerPattern = re.compile(r'^(教室|教室查询)\s+(.*)$')
Expand Down Expand Up @@ -473,9 +591,7 @@ def executeEvent(self,msg:str, data:Any) -> Union[None, str]:
if result == None:
send(target, '教室推荐参数解析错误,请重新输入查询参数,例如:\n"教室推荐 东上 3 5"、"教室推荐 东下 5 8"', data['message_type'])
return "OK"
building,startSection,endSection = result
startSection = int(startSection)
endSection = int(endSection)
building, startSection, endSection = result
courseImgPath = getRoomRecommend(building,startSection,endSection)
if courseImgPath == None:
send(target, f'[CQ:reply,id={data["message_id"]}]未查询到教室信息,可能结果是:不存在空闲教室或命令格式错误', data['message_type'])
Expand Down
Loading

0 comments on commit b4f7488

Please sign in to comment.