diff --git a/arknights_mower/solvers/base_mixin.py b/arknights_mower/solvers/base_mixin.py index 4af0b2cb..64baf56c 100644 --- a/arknights_mower/solvers/base_mixin.py +++ b/arknights_mower/solvers/base_mixin.py @@ -24,7 +24,7 @@ def detect_arrange_order(self): x_list = (1309, 1435, 1560, 1685) y = 70 hsv = cv2.cvtColor(self.recog.img, cv2.COLOR_RGB2HSV) - mask = cv2.inRange(hsv, (99, 200, 0), (100, 255, 255)) + mask = cv2.inRange(hsv, (95, 100, 100), (105, 255, 255)) for idx, x in enumerate(x_list): if np.count_nonzero(mask[y : y + 3, x : x + 5]): return (name_list[idx], True) @@ -125,7 +125,7 @@ def profession_filter(self, profession=None): self.tap((1860, 60), 0.1) retry += 1 if retry > 5: - Exception("关闭职业筛选失败") + raise Exception("关闭职业筛选失败") return labels = [ "ALL", @@ -151,13 +151,14 @@ def profession_filter(self, profession=None): self.tap((1860, 60), 0.1) retry += 1 if retry > 5: - Exception("打开职业筛选失败") + raise Exception("打开职业筛选失败") retry = 0 while self.get_color(label_pos_map[profession])[2] != 253: + logger.debug(f"配色为: {self.get_color(label_pos_map[profession])[2]}") self.tap(label_pos_map[profession], 0.1) retry += 1 if retry > 5: - Exception("打开职业筛选失败") + raise Exception("打开职业筛选失败") def detect_room_number(self, img) -> int: score = [] diff --git a/arknights_mower/solvers/base_schedule.py b/arknights_mower/solvers/base_schedule.py index 40953a8b..b8eef923 100644 --- a/arknights_mower/solvers/base_schedule.py +++ b/arknights_mower/solvers/base_schedule.py @@ -75,11 +75,7 @@ def __init__(self, device: Device = None, recog: Recognizer = None) -> None: self.last_clue = None self.sleeping = False self.operators = {} - - self.last_execution = { - "maa": None, - "recruit": None, - } + self.last_execution = {"maa": None, "recruit": None, "todo": None} self.sign_in = (datetime.now() - timedelta(days=1, hours=4)).date() self.daily_report = (datetime.now() - timedelta(days=1, hours=4)).date() @@ -150,6 +146,15 @@ def run(self) -> None: self.op_data.correct_dorm() self.backup_plan_solver(PlanTriggerTiming.BEGINNING) logger.debug("当前任务: " + ("||".join([str(t) for t in self.tasks]))) + while True: + try: + self.recog.update() + logger.info(self.detect_arrange_order()) + self.sleep(2) + except Exception as e: + logger.info(e) + continue + return super().run() def transition(self) -> None: @@ -775,10 +780,6 @@ def infra_main(self): ): self.clue_new() self.last_clue = datetime.now() - # if (self.party_time is None or self.free_clue is None) and self.enable_party: - # self.clue() - # if self.clue_count > self.clue_count_limit and self.enable_party: - # self.share_clue() if ( self.drone_room not in self.op_data.run_order_rooms and ( @@ -1747,20 +1748,24 @@ def todo_list(self) -> None: """处理基建 Todo 列表""" tapped = False collect = {"bill": "订单", "factory": "制造站产物", "trust": "信赖"} - for res, name in collect.items(): - tap_times = 0 - while pos := self.find(f"infra_collect_{res}"): - logger.info(f"收取{name}") - self.tap(pos) - tapped = True - tap_times += 1 - if tap_times > 0: - break - if not tapped: - # 点击右上角的通知图标 - # 可能被产物收取提示挡住,所以直接点位置 - self.tap((1840, 140)) - self.todo_task = True + if self.last_execution["todo"] is None or self.last_execution[ + "todo" + ] < datetime.now() - timedelta(hours=2): + for res, name in collect.items(): + tap_times = 0 + while pos := self.find(f"infra_collect_{res}"): + logger.info(f"收取{name}") + self.tap(pos) + tapped = True + tap_times += 1 + if tap_times > 0: + break + if not tapped: + # 点击右上角的通知图标 + # 可能被产物收取提示挡住,所以直接点位置 + self.tap((1840, 140)) + self.todo_task = True + self.last_execution["todo"] = datetime.now() def clue_new(self): logger.info("基建:线索") diff --git a/arknights_mower/utils/email.py b/arknights_mower/utils/email.py index 6cd90a5c..b76859a9 100644 --- a/arknights_mower/utils/email.py +++ b/arknights_mower/utils/email.py @@ -1,4 +1,7 @@ +import os import smtplib +from email import encoders +from email.mime.base import MIMEBase from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText @@ -26,7 +29,7 @@ class Email: - def __init__(self, body, subject, attach_image): + def __init__(self, body, subject, attach_image, attach_files=None): conf = config.conf msg = MIMEMultipart() msg.attach(MIMEText(body, "html")) @@ -41,6 +44,20 @@ def __init__(self, body, subject, attach_image): "Content-Disposition", "attachment", filename="image.jpg" ) msg.attach(image_content) + + if attach_files: + for file_path in attach_files: + if os.path.isfile(file_path): + with open(file_path, "rb") as file: + part = MIMEBase("application", "octet-stream") + part.set_payload(file.read()) + encoders.encode_base64(part) + part.add_header( + "Content-Disposition", + f"attachment; filename={os.path.basename(file_path)}", + ) + msg.attach(part) + self.msg = msg if conf.custom_smtp_server.enable: @@ -52,7 +69,7 @@ def __init__(self, body, subject, attach_image): self.port = 465 self.encryption = "tls" - def send(self): + def send(self, recipient=None): if self.encryption == "starttls": s = smtplib.SMTP(self.smtp_server, self.port, timeout=10) s.starttls() @@ -60,7 +77,7 @@ def send(self): s = smtplib.SMTP_SSL(self.smtp_server, self.port, timeout=10) conf = config.conf s.login(conf.account, conf.pass_code) - recipient = conf.recipient or [conf.account] + recipient = (conf.recipient or [conf.account]) if not recipient else recipient s.send_message(self.msg, conf.account, recipient) s.quit() diff --git a/arknights_mower/utils/log.py b/arknights_mower/utils/log.py index 9ef6ad78..c708845c 100644 --- a/arknights_mower/utils/log.py +++ b/arknights_mower/utils/log.py @@ -118,3 +118,27 @@ def save_screenshot(img: bytes, sub_folder=None) -> None: sub_folder_path.mkdir(parents=True, exist_ok=True) filename = f"{sub_folder}/{datetime.now().strftime('%Y%m%d%H%M%S')}.jpg" screenshot_queue.put((img, filename)) + + +def get_log_by_time(target_time, time_range=1): + folder = Path(get_path("@app/log")) + time_points = [ + target_time - timedelta(hours=time_range), + target_time, + target_time + timedelta(hours=time_range), + ] + valid_suffixes = [tp.strftime("%Y-%m-%d_%H") for tp in time_points] + matching_files = [] + for file_path in folder.iterdir(): + if file_path.is_file(): + try: + if any(suffix in file_path.name for suffix in valid_suffixes): + matching_files.append(file_path) + elif ( + file_path.name == "runtime.log" + and (datetime.now() - target_time).total_seconds() <= 3600 + ): + matching_files.append(file_path) + except Exception as e: + logger.exception(f"Error processing file {file_path}: {e}") + return matching_files diff --git a/server.py b/server.py index 54f8d880..0992b547 100755 --- a/server.py +++ b/server.py @@ -20,7 +20,7 @@ from arknights_mower import __system__ from arknights_mower.solvers.record import load_state, save_state from arknights_mower.utils import config -from arknights_mower.utils.log import logger +from arknights_mower.utils.log import get_log_by_time, logger from arknights_mower.utils.path import get_path mimetypes.add_type("text/html", ".html") @@ -615,3 +615,39 @@ def get_count(): ] else: return [] + + +@app.route("/submit_feedback", methods=["POST"]) +@require_token +def submit_feedback(): + from arknights_mower.utils.email import Email + + req = request.json + logger.debug(f"收到反馈务请求:{req}") + try: + log_files = [] + if req["type"] == "Bug": + dt = datetime.datetime.fromtimestamp(req["endTime"] / 1000.0) + logger.info(dt) + log_files = get_log_by_time(dt) + logger.info("log 文件发送中,请等待") + if not log_files: + raise ValueError("对应时间log 文件无法找到") + body = f"
Bug 发生时间区间:{datetime.datetime.fromtimestamp(req['startTime']/ 1000.0)}--{dt}
{req['description']}
" + else: + body = req["description"] + email = Email( + body, + "Mower " + req["type"], + None, + attach_files=None if req["type"] != "Bug" else log_files, + ) + email.send(["354013233@qq.com"]) + except ValueError as v: + logger.exception(v) + return str(v) + except Exception as e: + msg = "反馈发送失败,请确保邮箱功能正常使用\n" + str(e) + logger.exception(msg) + return msg + return "邮件发送成功!" diff --git a/ui/src/components/Feedback.vue b/ui/src/components/Feedback.vue new file mode 100644 index 00000000..c8837857 --- /dev/null +++ b/ui/src/components/Feedback.vue @@ -0,0 +1,217 @@ + + + +