You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from typing import Union, List, Tuple, Iterator, Any
from zipfile import ZipFile, ZIP_DEFLATED
from aiohttp import ClientSession, ClientTimeout
from nonebot import require
from pandas import DataFrame, Series
from os import path
task = "receiving"
task_file = "receiving_pictures"
mysql = require("botdb").MySQLdbMethods()
readfile = require("readfile").ReadFile("data", "class_system")
class Image:
def __init__(self, data):
self.name = data.get("file").split(".")[0]
self.url = data.get("url")
class SaveImage:
def __init__(self, class_name: str, file_name: str = None):
self.class_name = class_name
self.image_path = path.join(class_name, "images", "tasks_file")
self.file_name = file_name
def join(self, img: Union[Image, str]) -> str:
return path.join(readfile.path, self.image_path, f"{img if isinstance(img, str) else img.name}.jpg")
def for_in_name(self, images: List[Union[Image, str]]) -> Iterator[str]:
for img in images:
yield self.join(img)
async def save(self, images: List[Image]):
for img in images:
async with self.session.get(img.url) as res:
await readfile.write(
path.join(self.image_path, f"{self.file_name or img.name}.jpg"),
await res.read(), mode="wb")
def remove(self, image: Union[str, Image]):
readfile.remove(
self.image_path,
f"{image if isinstance(image, str) else image.name}.jpg"
)
async def __aenter__(self):
self.session = ClientSession(timeout=ClientTimeout(total=10 * 60))
return self
async def __aexit__(self, *args):
await self.session.close()
# 查询任务
class SelectTasks:
def __init__(self, class_name: str, index: int = None):
self.class_name = class_name
self.index = index
self.index_err = False
def __await__(self):
return self._init().__await__()
async def get_tasks(self) -> DataFrame:
"""获取所有任务"""
await mysql.execute(f"select * from {task} where class_name=%s", [self.class_name])
return mysql.form()
async def select_user_in_task(self, series: Union[Series, int]) -> DataFrame:
"""选择某项任务,列出所有提交任务的用户"""
if isinstance(series, int):
series = self[series]
await mysql.execute(f"select * from {task_file} where create_time=%s and class_name=%s and title=%s",
[str(series["create_time"]), self.class_name, series["title"]])
return mysql.form()
async def select_user_not_in_task(self, users: Union[list, set]) -> DataFrame:
await mysql.execute(f"select * from user_info where 班级=%s and qq not in({','.join(['%s'] * len(users))})",
[self.class_name, *users])
return mysql.form()
async def set_task(self, index: int = None) -> List[DataFrame]:
"""设置task的已经提交人数并且返回索引值对应的用户如果索引值为空则返回所有超出则不返回"""
task_user: List[DataFrame] = [await self.select_user_in_task(series) for i, series in self
if i == index or index is None]
if index is None:
self.tasks['completed'] = [f"(提交{i.shape[0]}人)" for i in task_user]
elif index in self:
self.tasks.loc[index, 'completed'] = f"(提交{task_user[0].shape[0]}人)"
else:
self.index_err = True
return task_user
async def _init(self):
self.tasks: DataFrame = await self.get_tasks()
self.length = self.tasks.shape[0]
self.task_user = await self.set_task(self.index)
return self
@staticmethod
def submitted(user: DataFrame) -> str:
if user.shape[0]:
return "已提交\n" + ("\n".join([f"{v['user_name']} | {str(v['push_time']).split('.')[0]}"
for i, v in user.iterrows()]))
else:
return "咦,文件呢?怎么还没人提交呀!"
@staticmethod
def not_submitted(user: DataFrame) -> str:
if user.shape[0]:
return "未提交\n" + (" ".join(user['姓名']))
return "咦,所有人都交了哎!"
async def text_one(self):
"""只回复一条消息"""
return await self.text().__anext__()
async def text(self):
if self.index_err:
yield f"咦,我怎么不知道有{self.index + 1}号???"
else:
if self.length:
if self.index is None:
yield "\n".join(
[f"{i + 1}.{v['title']}{v['completed']} \n "
f"发起时间:{v['create_time'].date()}" for i, v in self])
else:
yield self.submitted(self.task_user[0])
user = await self.select_user_not_in_task(list(self.task_user[0]["user_id"]))
yield self.not_submitted(user)
else:
yield "干什么呀!你们班还没添加任务呢!"
def __str__(self):
return self.text()
def __iter__(self) -> Iterator[Tuple[Any, Series]]:
return iter(self.tasks.iterrows())
def __getitem__(self, item: int) -> Union[Series, None]:
if 0 <= item < self.length:
return self.tasks.loc[item]
return None
def __contains__(self, index: int):
return index is not None and 0 <= index < self.length
def __bool__(self):
return not (not self.length or self.index_err)
# 添加任务
class AddTask(SelectTasks):
def __init__(self, title: str, user_id: int, class_name: str, jop: str):
super().__init__(class_name)
self.jop = jop # 发起人所担任职务
self.title = title # 发起的标题
self.user_id = user_id # 发起人的id
self.class_name = class_name # 发起的班级
async def repeat_task(self, tasks: DataFrame = None):
"""
查询是否为重复任务
重复任务返回False
不是重复任务返回True
"""
if not tasks:
tasks = await self.get_tasks()
return self.title not in list(tasks["title"])
async def add_task(self):
"""创建一个文件收取的任务"""
await mysql.execute_commit(f"insert into {task} (title,initiate,type,class_name) value (%s,%s,%s,%s)",
[self.title, self.user_id, "image", self.class_name])
async def __aenter__(self):
if await self.repeat_task():
await self.add_task()
return f"{self.title}”创建成功 ^_^"
return "歪,你有个还有一个一模一样的任务呢!能不能先删掉那个重复的 >_<!!"
async def __aexit__(self, *args):
...
# 提交任务
class PushTaskFile(SelectTasks):
def __call__(self, user_name: str, user_id: int, index: int):
self.user_name = user_name
self.user_id = user_id
self.index = index
return self
def is_exists(self) -> Union[bool, str]:
"""用户是否提交过"""
task_user = self.task_user[0] if len(self.task_user) == 1 else self.task_user[self.index]
user_id = list(task_user["user_id"])
if self.user_id in user_id:
return task_user["file_name"][user_id.index(self.user_id)]
return False
@staticmethod
async def file_exists(image: Image) -> bool:
"""文件是否已存在"""
await mysql.execute(f"select file_name from {task_file} where file_name=%s", [image.name])
return bool(list(mysql.form()["file_name"]))
async def insert(self, file_name: str, index: int = None):
_task = self[index or self.index]
await mysql.execute_commit(f"insert into {task_file} (title,user_id,user_name,class_name,file_name,create_time)"
"value (%s,%s,%s,%s,%s,%s)",
[_task['title'], self.user_id, self.user_name,
self.class_name, file_name, str(_task['create_time']).split(".")[0]])
async def delete(self, index: int = None):
index = index or self.index
await mysql.execute_commit(f"delete from {task_file} where class_name=%s and title=%s and user_id=%s",
[self.class_name, self[index]['title'], self.user_id])
async def save(self, image: Image):
async with SaveImage(self.class_name) as res:
file = self.is_exists()
if file:
res.remove(file)
await self.delete()
await res.save([image])
await self.insert(image.name)
return "提交成功! ^_^"
# 导出任务
class ExportTask(SelectTasks):
def __call__(self, index: int):
"""
:参数 index:
任务序号
:返回: ExportTask
"""
self.index = index
self.task_user = self.task_user[0] if len(self.task_user) == 1 else self.task_user[index]
return self
def zip(self) -> Tuple[str, str]:
"""
:说明:
将文件打包成压缩文件保存到本地
:返回:
文件路径 文件名称
"""
file = SaveImage(self.class_name)
file_name = f"{self.class_name}{self[self.index]['title']}.zip"
file_path = path.join(readfile.path, self.class_name, file_name)
with ZipFile(file_path, "w", ZIP_DEFLATED) as zip_file:
for i, img in self.task_user.iterrows():
# 文件名以用户名称+qq组成
zip_file.write(file.join(img["file_name"]), f"{img['user_name']}{img['user_id']}.jpg")
return file_path, file_name
# 删除任务
class DeleteTask(SelectTasks):
def __call__(self, index: int):
"""
:参数 index:
任务序号
:返回: DeleteTask
"""
self.index = index
self.task_user = self.task_user[0] if len(self.task_user) == 1 else self.task_user[index]
return self
async def delete_table(self) -> str:
"""
:说明:
删除数据表,先删除文件表在删除任务表
:返回:
表格标题
"""
title = self[self.index]["title"]
await mysql.execute_commit(f"delete from {task_file} where class_name=%s and title=%s",
[self.class_name, title])
await mysql.execute_commit(f"delete from {task} where class_name=%s and title=%s",
[self.class_name, title])
return title
def delete_file(self):
"""
:说明:
删除任务文件
"""
file = SaveImage(self.class_name)
for i, img in self.task_user.iterrows():
file.remove(img["file_name"])
async def delete(self):
"""
:说明:
先删除文件然后删除表格
:返回:
回复消息
"""
self.delete_file()
title = await self.delete_table()
return f"{title}”删除成功!"