diff --git a/alas.py b/alas.py index 7802c6a2e..b943eda7e 100644 --- a/alas.py +++ b/alas.py @@ -591,6 +591,7 @@ from module.scheduler_watcher import * from datetime import datetime, timedelta from module.counter import MaxCounter from typing import Dict +from module.device.my_assets import my_OTHERS_LOGIN_CONFIRM class FailedTaskCounter: @@ -745,6 +746,40 @@ class AzurLaneAutoScript(AzurLaneAutoScript): ) exit(1) + def delay_all_tasks(self): + target = datetime.now() + timedelta(minutes=self.config.others_login.interval) + + self.config.task_delay(target=target, task=self.config.task.command) + + for i in self.config.pending_task: + self.config.task_delay(target=target, task=i.command) + + for i in self.config.waiting_task: + if i.next_run < target: + self.config.task_delay(target=target, task=i.command) + + def handle_OthersLogin(self, e) -> bool: + logger.warning("Detected others' login") + self.delay_all_tasks() + + method = self.config.Optimization_WhenTaskQueueEmpty + if method == "goto_main": + self.config.Optimization_WhenTaskQueueEmpty = "stay_there" + logger.warning("You should never goto main when you need to delay tasks as others login, change to stay there instead.") + self.device.click(my_OTHERS_LOGIN_CONFIRM) + + if method == "stay_there": + self.device.click(my_OTHERS_LOGIN_CONFIRM) + if self.config.others_login.need_notify: + handle_notify( + self.config.Error_OnePushConfig, + title=f"Alas <{self.config_name}>: account's owner logs in", + content=f"Delay some tasks to {datetime.now() + timedelta(minutes=self.config.others_login.interval, seconds=-1)}", + ) + self.config.save() + self.config.update() + return True + def run(self, command, skip_first_screenshot=False): try: if not skip_first_screenshot: @@ -767,6 +802,8 @@ class AzurLaneAutoScript(AzurLaneAutoScript): return self.handle_ScriptError(e) except RequestHumanTakeover as e: return self.handle_RequestHumanTakeover(e) + except OthersLogin as e: + return self.handle_OthersLogin(e) except Exception as e: return self.handle_Exception(e) diff --git a/assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png b/assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png new file mode 100644 index 000000000..2c3c3eff6 Binary files /dev/null and b/assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png differ diff --git a/assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png b/assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png new file mode 100644 index 000000000..2917e859f Binary files /dev/null and b/assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png differ diff --git a/config/template.json b/config/template.json index c8151a292..144389f7b 100644 --- a/config/template.json +++ b/config/template.json @@ -155,6 +155,11 @@ "MaxRetryTimes": 5, "Notify": false }, + "OthersLogin": { + "Enable": false, + "Interval": 180, + "Notify": true + }, "Storage": { "Storage": {} } diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 86083894e..99e9bfb51 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -665,6 +665,20 @@ "value": false } }, + "OthersLogin": { + "Enable": { + "type": "checkbox", + "value": false + }, + "Interval": { + "type": "input", + "value": 180 + }, + "Notify": { + "type": "checkbox", + "value": true + } + }, "Storage": { "Storage": { "type": "storage", diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 853147323..c200fe6d5 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -974,4 +974,11 @@ GuildCoin: Color: value: ^AAAAAA display: hide - Record: 2020-01-01 00:00:00 \ No newline at end of file + Record: 2020-01-01 00:00:00 + +# ==================== OthersLogin ==================== + +OthersLogin: + Enable: false + Interval: 180 + Notify: true \ No newline at end of file diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index d6aefb02d..643f49889 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -24,6 +24,7 @@ Alas: - SchedulerWatcher - GameRestart - InstanceRestart + - OthersLogin # ==================== Cheat ==================== diff --git a/module/config/config.py b/module/config/config.py index 320d2ce45..a398c33de 100644 --- a/module/config/config.py +++ b/module/config/config.py @@ -795,6 +795,15 @@ class MultiSetWrapper: from module.config.full_config import AzurLaneFullConfig from module.scheduler_watcher import AzurLaneSchedulerWatcher from module.log_res.log_res import LogRes +from cached_property import cached_property +from dataclasses import dataclass + + +@dataclass +class OthersLoginSetting: + enabled: bool + interval: int + need_notify: bool class AzurLaneConfig(AzurLaneConfig): @@ -812,3 +821,12 @@ class AzurLaneConfig(AzurLaneConfig): @property def log_res(self): return LogRes(self) + + @cached_property + def others_login(self): + full_config = self.full_config + return OthersLoginSetting( + enabled=full_config.Restart_OthersLogin_Enable, + interval=full_config.Restart_OthersLogin_Interval, + need_notify=full_config.Restart_OthersLogin_Notify, + ) diff --git a/module/config/config_generated.py b/module/config/config_generated.py index ed5a959df..a830a24c5 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -618,5 +618,10 @@ class GeneratedConfig: GuildCoin_Color = '^AAAAAA' GuildCoin_Record = datetime.datetime(2020, 1, 1, 0, 0) + # Group `OthersLogin` + OthersLogin_Enable = False + OthersLogin_Interval = 180 + OthersLogin_Notify = True + # Group `Storage` Storage_Storage = {} diff --git a/module/config/full_config_generated.py b/module/config/full_config_generated.py index 155ea7fce..de6951d5e 100644 --- a/module/config/full_config_generated.py +++ b/module/config/full_config_generated.py @@ -107,6 +107,9 @@ class FullGeneratedConfig: Restart_InstanceRestart_Enable = None Restart_InstanceRestart_MaxRetryTimes = None Restart_InstanceRestart_Notify = None + Restart_OthersLogin_Enable = None + Restart_OthersLogin_Interval = None + Restart_OthersLogin_Notify = None Restart_Storage_Storage = None # Task `PowerLimit` diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 86c9c2065..ab55b91fb 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -3382,6 +3382,24 @@ "help": "GuildCoin.Record.help" } }, + "OthersLogin": { + "_info": { + "name": "OthersLogin._info.name", + "help": "OthersLogin._info.help" + }, + "Enable": { + "name": "OthersLogin.Enable.name", + "help": "OthersLogin.Enable.help" + }, + "Interval": { + "name": "OthersLogin.Interval.name", + "help": "OthersLogin.Interval.help" + }, + "Notify": { + "name": "OthersLogin.Notify.name", + "help": "OthersLogin.Notify.help" + } + }, "Storage": { "_info": { "name": "Task status", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index eb00a9553..016423fb5 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -3382,6 +3382,24 @@ "help": "GuildCoin.Record.help" } }, + "OthersLogin": { + "_info": { + "name": "OthersLogin._info.name", + "help": "OthersLogin._info.help" + }, + "Enable": { + "name": "OthersLogin.Enable.name", + "help": "OthersLogin.Enable.help" + }, + "Interval": { + "name": "OthersLogin.Interval.name", + "help": "OthersLogin.Interval.help" + }, + "Notify": { + "name": "OthersLogin.Notify.name", + "help": "OthersLogin.Notify.help" + } + }, "Storage": { "_info": { "name": "Storage._info.name", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 488242b62..49a9856d3 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -3382,6 +3382,24 @@ "help": "GuildCoin.Record.help" } }, + "OthersLogin": { + "_info": { + "name": "顶号检测", + "help": "修改以下的配置后要重新启动Alas实例" + }, + "Enable": { + "name": "启用", + "help": "" + }, + "Interval": { + "name": "顶号后将任务推迟 X 分钟", + "help": "" + }, + "Notify": { + "name": "通知", + "help": "" + } + }, "Storage": { "_info": { "name": "任务状态", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 65403e11d..d95d9f940 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -3382,6 +3382,24 @@ "help": "GuildCoin.Record.help" } }, + "OthersLogin": { + "_info": { + "name": "OthersLogin._info.name", + "help": "OthersLogin._info.help" + }, + "Enable": { + "name": "OthersLogin.Enable.name", + "help": "OthersLogin.Enable.help" + }, + "Interval": { + "name": "OthersLogin.Interval.name", + "help": "OthersLogin.Interval.help" + }, + "Notify": { + "name": "OthersLogin.Notify.name", + "help": "OthersLogin.Notify.help" + } + }, "Storage": { "_info": { "name": "任務狀態", diff --git a/module/device/device.py b/module/device/device.py index 9e9402d58..0a119a450 100644 --- a/module/device/device.py +++ b/module/device/device.py @@ -333,3 +333,27 @@ class Device(Screenshot, Control, AppControl): super().app_stop() self.stuck_record_clear() self.click_record_clear() + + +from module.device.my_assets import * +from module.ocr.ocr import Ocr +from module.exception import OthersLogin + +OthersLoginNotifyOcr = Ocr(buttons=my_OTHERS_LOGIN_NOTIFY, lang="cnocr") +OTHERS_LOGIN_NOTIFY_SERVER = { + "cn": "登录", + "jp": "蜴所" +} + + +class Device(Device): + def screenshot(self): + img = super().screenshot() + + if self.config.others_login.enabled: + if my_OTHERS_LOGIN_CONFIRM.appear_on(img): + if self.config.SERVER in OTHERS_LOGIN_NOTIFY_SERVER.keys(): + if OthersLoginNotifyOcr.ocr(img) == OTHERS_LOGIN_NOTIFY_SERVER[self.config.SERVER]: + raise OthersLogin + + return img diff --git a/module/device/my_assets.py b/module/device/my_assets.py new file mode 100644 index 000000000..b147cd419 --- /dev/null +++ b/module/device/my_assets.py @@ -0,0 +1,8 @@ +from module.base.button import Button +from module.base.template import Template + +# This file was automatically generated by dev_tools/button_extract.py. +# Don't modify it manually. + +my_OTHERS_LOGIN_CONFIRM = Button(area={'cn': (561, 488, 721, 534), 'en': (561, 488, 721, 534), 'jp': (561, 488, 721, 534), 'tw': (561, 488, 721, 534)}, color={'cn': (100, 147, 205), 'en': (100, 147, 205), 'jp': (100, 147, 205), 'tw': (100, 147, 205)}, button={'cn': (561, 488, 721, 534), 'en': (561, 488, 721, 534), 'jp': (561, 488, 721, 534), 'tw': (561, 488, 721, 534)}, file={'cn': './assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png', 'en': './assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png', 'jp': './assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png', 'tw': './assets/cn/device/my_OTHERS_LOGIN_CONFIRM.png'}) +my_OTHERS_LOGIN_NOTIFY = Button(area={'cn': (664, 330, 712, 360), 'en': (664, 330, 712, 360), 'jp': (664, 330, 712, 360), 'tw': (664, 330, 712, 360)}, color={'cn': (144, 149, 160), 'en': (144, 149, 160), 'jp': (144, 149, 160), 'tw': (144, 149, 160)}, button={'cn': (664, 330, 712, 360), 'en': (664, 330, 712, 360), 'jp': (664, 330, 712, 360), 'tw': (664, 330, 712, 360)}, file={'cn': './assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png', 'en': './assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png', 'jp': './assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png', 'tw': './assets/cn/device/my_OTHERS_LOGIN_NOTIFY.png'}) diff --git a/module/exception.py b/module/exception.py index e0d3ecf39..c29c4981d 100644 --- a/module/exception.py +++ b/module/exception.py @@ -61,3 +61,7 @@ class RequestHumanTakeover(Exception): # Request human takeover # Alas is unable to handle such error, probably because of wrong settings. pass + + +class OthersLogin(Exception): + pass