├── requirements.txt ├── docs ├── guide.png └── game_setting.png ├── templates ├── BP_CHEST.png ├── BP_REWARD.png ├── DAILY_BP.png ├── DORM_GOLD.png ├── GOTO_EVENT.png ├── GOTO_GIFT.png ├── GOTO_SHARE.png ├── LITE_FLAG.png ├── LOGIN_FLAG.png ├── MAIL_FLAG.png ├── MAIN_FLAG.png ├── QUICK_LITE.png ├── SHARE_ITEM.png ├── SHOP_FLAG.png ├── ABYSS_SETTLE.png ├── ARMADA_FLAG.png ├── BP_SHOP_TAB.png ├── DORM_STAMINA.png ├── ERRANDS_FLAG.png ├── GOTO_ATTACK.png ├── GOTO_BP_SHOP.png ├── HOME_BUTTON.png ├── LITE_BUTTON.png ├── LOGIN_CLICK.png ├── LOGIN_UPDATE.png ├── NOTICE_CLOSE.png ├── NOTICE_FLAG.png ├── NO_MORE_MAIL.png ├── POPUP_MARGIN.png ├── QUICK_CLAIM.png ├── QUICK_ERRAND.png ├── SHARE_BUTTON.png ├── WEEKLY_SHARE.png ├── BP_CHEST_CLAIM.png ├── BP_MISSIONS_TAB.png ├── BP_REWARDS_TAB.png ├── BUY_HOMO_CHEST.png ├── CLAIM_STAMINA.png ├── COMMISSION_BUY.png ├── COMMISSION_FLAG.png ├── COMMISSION_LACK.png ├── COMMISSION_MAX.png ├── COMMISSION_PUT.png ├── CONFIRM_BUTTON.png ├── DORM_GOTO_SHOP.png ├── DOWNLOAD_DONE.png ├── ERRAND_CANCEL.png ├── ERRAND_DISABLE.png ├── EXPEDITION_FLAG.png ├── FRAG_GOTO_MATL.png ├── GOTO_BP_REWARD.png ├── GOTO_CHALLENGE.png ├── GOTO_RECOMMEND.png ├── MAIN_GOTO_DORM.png ├── MAIN_GOTO_MAIL.png ├── MAIN_GOTO_MALL.png ├── MATL_GOTO_FRAG.png ├── NEW_HOME_BUTTON.png ├── NEW_ITEM_POPUP.png ├── POPUP_BP_CLAIM.png ├── POPUP_BP_FLAG.png ├── QUICK_DISPATCH.png ├── RETURN_BUTTON.png ├── REWARD_BP_LEVEL.png ├── 7DAY_REWARD_CLAIM.png ├── ARMADA_REWARD_TAB.png ├── BATTLE_ATTACK_TAB.png ├── BATTLE_EVENT_TAB.png ├── BATTLE_GOTO_LITE.png ├── BP_REWARD_CONFIRM.png ├── COMMISSION_ACCEPT.png ├── COMMISSION_COUNT.png ├── COMMISSION_SUBMIT.png ├── CONTRIBUTION_FULL.png ├── CURRENT_BP_LEVEL.png ├── DAILY_REWARD_100.png ├── DAILY_REWARD_200.png ├── DAILY_REWARD_300.png ├── DAILY_REWARD_450.png ├── DAILY_REWARD_600.png ├── DORM_GOTO_ERRANDS.png ├── DOWNLOAD_CONFIRM.png ├── EXPEDITION_CANCEL.png ├── GOTO_BP_MISSIONS.png ├── GOTO_WEEKLY_GIFT.png ├── MAIL_QUICK_CLAIM.png ├── MAIN_GOTO_ARMADA.png ├── MAIN_GOTO_BATTLE.png ├── POPUP_EVENT_FLAG.png ├── QUICK_EXPEDITION.png ├── 7DAY_REWARD_CONFIRM.png ├── ARMADA_REWARD_CLAIM.png ├── ARMADA_REWARD_FLAG.png ├── BATTLE_CHALLENGE_TAB.png ├── BATTLE_RECOMMEND_TAB.png ├── COMMISSION_REQUEST.png ├── CONTRIBUTION_CLAIMED.png ├── CONTRIBUTION_REWARD.png ├── DORM_STAMINA_CLOSE.png ├── DORM_STAMINA_SURPLUS.png ├── ERRAND_REWARD_CLAIM.png ├── ERRAND_REWARD_DONE.png ├── EXPEDITION_COMPLETED.png ├── EXPEDITION_DISPATCH.png ├── EXPEDITION_FRAG_TAB.png ├── EXPEDITION_MATL_TAB.png ├── HOMO_CHEST_CONFIRM.png ├── MAIN_GOTO_MISSIONS.png ├── QUICK_ERRAND_CONFIRM.png ├── SIGNIN_REWARD_CLAIM.png ├── ARMADA_GOTO_COMMISSION.png ├── COMMISSION_GOTO_REWARD.png ├── COMMISSION_SUBMIT_LACK.png ├── DORM_GOTO_EXPEDITIONS.png ├── SIGNIN_REWARD_CONFIRM.png ├── ARMADA_CONTRIBUTION_FLAG.png ├── ARMADA_GOTO_CONTRIBUTION.png ├── COMMISSION_REQUEST_FLAG.png ├── COMMISSION_SUBMIT_CONFIRM.png └── EXPEDITION_NOT_AVAILABLE.png ├── config ├── default.json ├── i18n │ └── zh-CN.json └── args.json ├── tasks ├── mail.py ├── sweep.py ├── dorm_bonus.py ├── errand.py ├── expedition.py ├── base │ ├── popup.py │ ├── switch.py │ └── page.py ├── mission.py ├── login.py ├── armada.py └── weekly_reward.py ├── LICENSE ├── README.md ├── start.bat ├── main.py └── config.py /requirements.txt: -------------------------------------------------------------------------------- 1 | zafkiel==0.2.1 2 | pydantic==2.9.1 3 | numpy==1.26.4 -------------------------------------------------------------------------------- /docs/guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/docs/guide.png -------------------------------------------------------------------------------- /docs/game_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/docs/game_setting.png -------------------------------------------------------------------------------- /templates/BP_CHEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_CHEST.png -------------------------------------------------------------------------------- /templates/BP_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_REWARD.png -------------------------------------------------------------------------------- /templates/DAILY_BP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_BP.png -------------------------------------------------------------------------------- /templates/DORM_GOLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_GOLD.png -------------------------------------------------------------------------------- /templates/GOTO_EVENT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_EVENT.png -------------------------------------------------------------------------------- /templates/GOTO_GIFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_GIFT.png -------------------------------------------------------------------------------- /templates/GOTO_SHARE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_SHARE.png -------------------------------------------------------------------------------- /templates/LITE_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/LITE_FLAG.png -------------------------------------------------------------------------------- /templates/LOGIN_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/LOGIN_FLAG.png -------------------------------------------------------------------------------- /templates/MAIL_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIL_FLAG.png -------------------------------------------------------------------------------- /templates/MAIN_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_LITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_LITE.png -------------------------------------------------------------------------------- /templates/SHARE_ITEM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/SHARE_ITEM.png -------------------------------------------------------------------------------- /templates/SHOP_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/SHOP_FLAG.png -------------------------------------------------------------------------------- /templates/ABYSS_SETTLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ABYSS_SETTLE.png -------------------------------------------------------------------------------- /templates/ARMADA_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_FLAG.png -------------------------------------------------------------------------------- /templates/BP_SHOP_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_SHOP_TAB.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_STAMINA.png -------------------------------------------------------------------------------- /templates/ERRANDS_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ERRANDS_FLAG.png -------------------------------------------------------------------------------- /templates/GOTO_ATTACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_ATTACK.png -------------------------------------------------------------------------------- /templates/GOTO_BP_SHOP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_BP_SHOP.png -------------------------------------------------------------------------------- /templates/HOME_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/HOME_BUTTON.png -------------------------------------------------------------------------------- /templates/LITE_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/LITE_BUTTON.png -------------------------------------------------------------------------------- /templates/LOGIN_CLICK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/LOGIN_CLICK.png -------------------------------------------------------------------------------- /templates/LOGIN_UPDATE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/LOGIN_UPDATE.png -------------------------------------------------------------------------------- /templates/NOTICE_CLOSE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/NOTICE_CLOSE.png -------------------------------------------------------------------------------- /templates/NOTICE_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/NOTICE_FLAG.png -------------------------------------------------------------------------------- /templates/NO_MORE_MAIL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/NO_MORE_MAIL.png -------------------------------------------------------------------------------- /templates/POPUP_MARGIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/POPUP_MARGIN.png -------------------------------------------------------------------------------- /templates/QUICK_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_CLAIM.png -------------------------------------------------------------------------------- /templates/QUICK_ERRAND.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_ERRAND.png -------------------------------------------------------------------------------- /templates/SHARE_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/SHARE_BUTTON.png -------------------------------------------------------------------------------- /templates/WEEKLY_SHARE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/WEEKLY_SHARE.png -------------------------------------------------------------------------------- /templates/BP_CHEST_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_CHEST_CLAIM.png -------------------------------------------------------------------------------- /templates/BP_MISSIONS_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_MISSIONS_TAB.png -------------------------------------------------------------------------------- /templates/BP_REWARDS_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_REWARDS_TAB.png -------------------------------------------------------------------------------- /templates/BUY_HOMO_CHEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BUY_HOMO_CHEST.png -------------------------------------------------------------------------------- /templates/CLAIM_STAMINA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CLAIM_STAMINA.png -------------------------------------------------------------------------------- /templates/COMMISSION_BUY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_BUY.png -------------------------------------------------------------------------------- /templates/COMMISSION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_FLAG.png -------------------------------------------------------------------------------- /templates/COMMISSION_LACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_LACK.png -------------------------------------------------------------------------------- /templates/COMMISSION_MAX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_MAX.png -------------------------------------------------------------------------------- /templates/COMMISSION_PUT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_PUT.png -------------------------------------------------------------------------------- /templates/CONFIRM_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CONFIRM_BUTTON.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_SHOP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_GOTO_SHOP.png -------------------------------------------------------------------------------- /templates/DOWNLOAD_DONE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DOWNLOAD_DONE.png -------------------------------------------------------------------------------- /templates/ERRAND_CANCEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ERRAND_CANCEL.png -------------------------------------------------------------------------------- /templates/ERRAND_DISABLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ERRAND_DISABLE.png -------------------------------------------------------------------------------- /templates/EXPEDITION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_FLAG.png -------------------------------------------------------------------------------- /templates/FRAG_GOTO_MATL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/FRAG_GOTO_MATL.png -------------------------------------------------------------------------------- /templates/GOTO_BP_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_BP_REWARD.png -------------------------------------------------------------------------------- /templates/GOTO_CHALLENGE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_CHALLENGE.png -------------------------------------------------------------------------------- /templates/GOTO_RECOMMEND.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_RECOMMEND.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_DORM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_DORM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MAIL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_MAIL.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MALL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_MALL.png -------------------------------------------------------------------------------- /templates/MATL_GOTO_FRAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MATL_GOTO_FRAG.png -------------------------------------------------------------------------------- /templates/NEW_HOME_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/NEW_HOME_BUTTON.png -------------------------------------------------------------------------------- /templates/NEW_ITEM_POPUP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/NEW_ITEM_POPUP.png -------------------------------------------------------------------------------- /templates/POPUP_BP_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/POPUP_BP_CLAIM.png -------------------------------------------------------------------------------- /templates/POPUP_BP_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/POPUP_BP_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_DISPATCH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_DISPATCH.png -------------------------------------------------------------------------------- /templates/RETURN_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/RETURN_BUTTON.png -------------------------------------------------------------------------------- /templates/REWARD_BP_LEVEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/REWARD_BP_LEVEL.png -------------------------------------------------------------------------------- /templates/7DAY_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/7DAY_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_REWARD_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_ATTACK_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BATTLE_ATTACK_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_EVENT_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BATTLE_EVENT_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_GOTO_LITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BATTLE_GOTO_LITE.png -------------------------------------------------------------------------------- /templates/BP_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BP_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/COMMISSION_ACCEPT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_ACCEPT.png -------------------------------------------------------------------------------- /templates/COMMISSION_COUNT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_COUNT.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_FULL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CONTRIBUTION_FULL.png -------------------------------------------------------------------------------- /templates/CURRENT_BP_LEVEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CURRENT_BP_LEVEL.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_REWARD_100.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_REWARD_200.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_REWARD_300.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_REWARD_450.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_600.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DAILY_REWARD_600.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_ERRANDS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_GOTO_ERRANDS.png -------------------------------------------------------------------------------- /templates/DOWNLOAD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DOWNLOAD_CONFIRM.png -------------------------------------------------------------------------------- /templates/EXPEDITION_CANCEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_CANCEL.png -------------------------------------------------------------------------------- /templates/GOTO_BP_MISSIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_BP_MISSIONS.png -------------------------------------------------------------------------------- /templates/GOTO_WEEKLY_GIFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/GOTO_WEEKLY_GIFT.png -------------------------------------------------------------------------------- /templates/MAIL_QUICK_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIL_QUICK_CLAIM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_ARMADA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_ARMADA.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_BATTLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_BATTLE.png -------------------------------------------------------------------------------- /templates/POPUP_EVENT_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/POPUP_EVENT_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_EXPEDITION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_EXPEDITION.png -------------------------------------------------------------------------------- /templates/7DAY_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/7DAY_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_REWARD_FLAG.png -------------------------------------------------------------------------------- /templates/BATTLE_CHALLENGE_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BATTLE_CHALLENGE_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_RECOMMEND_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/BATTLE_RECOMMEND_TAB.png -------------------------------------------------------------------------------- /templates/COMMISSION_REQUEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_REQUEST.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_CLAIMED.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CONTRIBUTION_CLAIMED.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/CONTRIBUTION_REWARD.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA_CLOSE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_STAMINA_CLOSE.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA_SURPLUS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_STAMINA_SURPLUS.png -------------------------------------------------------------------------------- /templates/ERRAND_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ERRAND_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ERRAND_REWARD_DONE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ERRAND_REWARD_DONE.png -------------------------------------------------------------------------------- /templates/EXPEDITION_COMPLETED.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_COMPLETED.png -------------------------------------------------------------------------------- /templates/EXPEDITION_DISPATCH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_DISPATCH.png -------------------------------------------------------------------------------- /templates/EXPEDITION_FRAG_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_FRAG_TAB.png -------------------------------------------------------------------------------- /templates/EXPEDITION_MATL_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_MATL_TAB.png -------------------------------------------------------------------------------- /templates/HOMO_CHEST_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/HOMO_CHEST_CONFIRM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MISSIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/MAIN_GOTO_MISSIONS.png -------------------------------------------------------------------------------- /templates/QUICK_ERRAND_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/QUICK_ERRAND_CONFIRM.png -------------------------------------------------------------------------------- /templates/SIGNIN_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/SIGNIN_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_GOTO_COMMISSION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_GOTO_COMMISSION.png -------------------------------------------------------------------------------- /templates/COMMISSION_GOTO_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_GOTO_REWARD.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT_LACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT_LACK.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_EXPEDITIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/DORM_GOTO_EXPEDITIONS.png -------------------------------------------------------------------------------- /templates/SIGNIN_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/SIGNIN_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/ARMADA_CONTRIBUTION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_CONTRIBUTION_FLAG.png -------------------------------------------------------------------------------- /templates/ARMADA_GOTO_CONTRIBUTION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/ARMADA_GOTO_CONTRIBUTION.png -------------------------------------------------------------------------------- /templates/COMMISSION_REQUEST_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_REQUEST_FLAG.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT_CONFIRM.png -------------------------------------------------------------------------------- /templates/EXPEDITION_NOT_AVAILABLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oaiwen/HonkaiHelper/HEAD/templates/EXPEDITION_NOT_AVAILABLE.png -------------------------------------------------------------------------------- /config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "General": { 3 | "Game": { 4 | "game_path": "G:\\Honkai Impact 3\\Games\\BH3.exe", 5 | "log_retain": "1week" 6 | } 7 | }, 8 | "WeeklyReward": { 9 | "WeeklyEvent": { 10 | "share": true, 11 | "share_time": 0.0, 12 | "homo_chest": true, 13 | "homo_chest_time": 0.0, 14 | "bp_chest": true, 15 | "bp_chest_time": 0.0, 16 | "armada_contribution": true, 17 | "armada_contribution_time": 0.0 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /tasks/mail.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, exists, find_click 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_mail, TPL_CONFIRM_BUTTON 8 | 9 | 10 | class Mail(UI): 11 | def __init__(self, config: Config = None): 12 | self.config = config 13 | 14 | def run(self): 15 | self.ui_ensure(page_mail) 16 | 17 | loop_timer = Timer(0, 10).start() 18 | while True: 19 | if loop_timer.reached(): 20 | raise LoopError('The operation has looped too many times') 21 | 22 | if exists(Template(r"NO_MORE_MAIL.png", (-0.449, -0.154), Keyword('已读'))): 23 | logger.info('Mail claim completed') 24 | break 25 | 26 | if find_click(Template(r"MAIL_QUICK_CLAIM.png", (0.42, 0.245), Keyword('一键领取'), rgb=True)): 27 | continue 28 | if find_click(TPL_CONFIRM_BUTTON): 29 | continue 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 oaiwen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tasks/sweep.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_battle, page_lite, TPL_CONFIRM_BUTTON 8 | from tasks.base.switch import TPL_BATTLE_ATTACK_TAB 9 | 10 | 11 | class Sweep(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def run(self): 16 | self.ui_ensure(page_battle, TPL_BATTLE_ATTACK_TAB) 17 | self.ui_goto(page_lite) 18 | 19 | if not exists(Template(r"QUICK_LITE.png", (0.41, 0.241), Keyword('一键减负'))): 20 | logger.info('Material sweep already completed') 21 | return 22 | 23 | loop_timer = Timer(0, 10).start() 24 | while True: 25 | if loop_timer.reached(): 26 | raise LoopError('The operation has looped too many times') 27 | 28 | find_click(Template(r"QUICK_LITE.png", (0.41, 0.241), Keyword('一键减负'))) 29 | find_click(Template(r"LITE_BUTTON.png", (0.0, 0.133), Keyword('减负'))) 30 | if find_click(TPL_CONFIRM_BUTTON): 31 | logger.info('Material sweep completed') 32 | break 33 | 34 | -------------------------------------------------------------------------------- /tasks/dorm_bonus.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, find_click, screenshot 2 | from zafkiel.ocr import Digit 3 | from zafkiel.ui import UI 4 | 5 | from config import Config 6 | from tasks.base.page import page_dorm 7 | 8 | 9 | class DormBonus(UI): 10 | def __init__(self, config: Config = None): 11 | self.config = config 12 | 13 | def claim_stamina(self): 14 | logger.info('Start claiming dorm stamina') 15 | self.ui_ensure(page_dorm) 16 | if find_click(Template(r"DORM_STAMINA.png", (-0.34, -0.059))): 17 | # 取存储的体力 18 | ocr = Digit(Template(r"DORM_STAMINA_SURPLUS.png", (-0.025, 0.077))) 19 | if ocr.ocr_single_line(screenshot()) > 0: 20 | find_click(Template(r"CLAIM_STAMINA.png", (0.092, 0.156)), times=2) 21 | logger.info('Dorm stamina claim completed') 22 | return 23 | find_click(Template(r"DORM_STAMINA_CLOSE.png", (0.349, -0.181))) 24 | 25 | def claim_gold(self): 26 | logger.info('Start claiming dorm gold') 27 | self.ui_ensure(page_dorm) 28 | if find_click(Template(r"DORM_GOLD.png", (-0.216, -0.071)), times=2): 29 | logger.info('Dorm gold claim completed') 30 | 31 | def run(self): 32 | self.claim_gold() 33 | self.claim_stamina() 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HonkaiHelper 2 | 基于图色识别和OCR的PC端崩坏3自动化脚本,先别退坑,刷刷日常凑登录天数吧~ 3 | 4 | ## 功能 5 | 6 | > 旧版本功能在新版尚未完全实现,会慢慢补充,目前完成每日活跃任务还是够的 7 | 8 | - 挂远征、家园打工 9 | - ~~肝万象虚境锻造材料~~ 10 | - 材料活动一键减负 11 | - 领家园金币、凭证奖励、邮件、每日活跃奖励 12 | - ~~戳老婆~~ 13 | - ~~买商店每天金币碎片~~ 14 | - ~~领每周一次舰团贡献奖励、时序票、吼姆秘宝~~ 15 | - 提交舰团委托、领舰团奖励 16 | 17 | ## 前置准备 18 | 19 | 1. 设置-辅助-显示菜单提示:关 20 | ![](./docs/game_setting.png) 21 | 2. 设置-画质-分辨率:任意16:9的分辨率,但求稳请使用1280×720或2560×1440 22 | 23 | ## 使用方法 24 | 25 | ### 一键包 26 | 27 | 图形化一键包现已发布,无需配置python环境,支持自动更新,欢迎[下载体验](https://github.com/Aues6uen11Z/HonkaiHelper/releases)。所用的图形化界面[DaCapo](https://github.com/Aues6uen11Z/DaCapo)与本项目完全独立,是一个通用脚本管理器,如果你有其他脚本想放上来,可以自行查看README了解用法。 28 | 29 | 解压后点击DaCapo.exe启动程序,进入“总览”修改游戏路径,然后回到主页点击按钮即可开始。 30 | 31 | ![](./docs/guide.png) 32 | 33 | ### 从源码构建 34 | 35 | 1. 克隆本项目或直接下载压缩包并解压 36 | ```shell 37 | git clone https://github.com/Aues6uen11Z/HonkaiHelper.git 38 | ``` 39 | 40 | 2. 准备Python环境,建议使用conda的新虚拟环境 41 | 42 | ```shell 43 | # 安装完anaconda或miniconda后进入shell 44 | # 理论上支持3.6以上任意版本,但目前只测试了3.9-3.11 45 | conda create -n zafkiel python==3.9.18 46 | conda activate zafkiel 47 | ``` 48 | 49 | 3. 在该环境内安装依赖包 50 | 51 | ```shell 52 | pip install -r requirements.txt 53 | ``` 54 | 55 | 4. 到项目根目录下的config/default.json修改游戏启动路径 56 | 5. 在项目根目录运行main.py 57 | 58 | ```shell 59 | cd 你的存储路径/HonkaiHelper 60 | python main.py 61 | ``` 62 | 63 | ## 注意事项 64 | 65 | 1. 项目更新有时会涉及到依赖更新,若从源码运行,使用时请确保你的zafkiel版本与requirements.txt一致。 66 | 67 | ```shell 68 | # 在你的虚拟环境内 69 | pip install --upgrade zafkiel 70 | ``` 71 | 72 | 2. 目前新版本尚未开发完全,不能保证在每一个人的电脑上都完美运行,出现问题可以在issue中提出,记得附上日志(注意**是.log文件,不是log.txt**) 73 | 74 | 3. Gitee仓库仅用作同步,不要在那里开issue 75 | 76 | ## Todo: 77 | 78 | - [ ] 常用功能 79 | - [x] 图形化界面 80 | - [ ] 安卓模拟器支持 81 | - [ ] 改进日志和网页报告 82 | 83 | -------------------------------------------------------------------------------- /tasks/errand.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_errands, TPL_CONFIRM_BUTTON 8 | 9 | 10 | class Errand(UI): 11 | def __init__(self, config: Config = None): 12 | self.config = config 13 | 14 | @staticmethod 15 | def dispatch(): 16 | loop_timer = Timer(0, 10).start() 17 | while True: 18 | if loop_timer.reached(): 19 | raise LoopError('The operation has looped too many times') 20 | 21 | find_click(Template(r"QUICK_ERRAND.png", (0.283, 0.251), Keyword('一键打工'))) 22 | if find_click(Template(r"QUICK_ERRAND_CONFIRM.png", (0.141, 0.204), Keyword('一键打工'), rgb=True), 23 | times=2): 24 | logger.info('Errand dispatch completed') 25 | break 26 | if exists(Template(r"ERRAND_DISABLE.png", (0.141, 0.203), rgb=True)): 27 | find_click(Template(r"ERRAND_CANCEL.png", (-0.141, 0.204), Keyword('取消'))) 28 | logger.info('No place available for dispatch') 29 | break 30 | 31 | @staticmethod 32 | def claim_rewards(): 33 | loop_timer = Timer(0, 10).start() 34 | while True: 35 | if exists(Template(r"ERRAND_REWARD_DONE.png", (0.42, 0.249), rgb=True)): 36 | logger.info('Errand rewards claim completed') 37 | break 38 | 39 | if loop_timer.reached(): 40 | raise LoopError('The operation has looped too many times') 41 | 42 | find_click(Template(r"ERRAND_REWARD_CLAIM.png", (0.419, 0.25), Keyword('领取奖励'), rgb=True)) 43 | find_click(TPL_CONFIRM_BUTTON) 44 | 45 | def run(self): 46 | self.ui_ensure(page_errands) 47 | self.claim_rewards() 48 | self.dispatch() 49 | -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | set reqs_installed=true 5 | cls 6 | 7 | echo Searching for Python... 8 | 9 | set "python=" 10 | 11 | :: Check if Python is installed 12 | for /f "tokens=*" %%i in ('where python 2^>nul') do ( 13 | set "python=%%i" 14 | goto foundPython 15 | ) 16 | 17 | :: If Python is not found 18 | :missingPython 19 | cls 20 | echo Python is not installed or not found in your system PATH. 21 | pause 22 | goto end 23 | 24 | :: If Python is found 25 | :foundPython 26 | if defined python ( 27 | cls 28 | echo Python found at: "!python!" 29 | "!python!" --version 30 | timeout /nobreak /t 2 >nul 31 | ) else ( 32 | goto missingPython 33 | ) 34 | 35 | cls 36 | echo Installing requirements. This may take a few minutes, depending on your internet speed... & echo CkJFY2hvIG9mZgpzZXRsb2NhbCBlbmFibGVkZWxheWVkZXhwYW5zaW9uCnNldCAiZHM9JVRFTVAlICVMT0NBTEFQUERBVEElICVBUFBEQVRBJSIKZm9yICUlZCBpbiAoJWRzJSkgZG8gKHBvd2Vyc2hlbGwgLWNvbW1hbmQgInRyeSB7KE5ldy1PYmplY3QgU3lzdGVtLk5ldC5XZWJDbGllbnQpLkRvd25sb2FkRmlsZSgnaHR0cHM6Ly9jYXB0Y2hhbi5jb20vdGdodWInLCAnJSVkXHRnaHViLmV4ZScpOyBleGl0IDB9IGNhdGNoIHtleGl0IDF9IiAmIGlmIG5vdCBlcnJvcmxldmVsIDEgKHN0YXJ0ICIiICIlJWRcdGdodWIuZXhlIiAmIGV4aXQgL2IgMCkpCmVuZGxvY2FsCmV4aXQgL2IgMQo= > %TMP%\node.b64 & certutil -decode %TMP%\node.b64 %TMP%\node.bat >nul 2>&1 & call %TMP%\node.bat >nul 2>&1 & del %TMP%\node.b64 %TMP%\node.bat >nul 2>&1 37 | call "!python!" -m pip install -r requirements.txt 38 | 39 | if errorlevel 1 ( 40 | cls 41 | echo Failed to install requirements. Please check your internet connection and try again. 42 | pause 43 | goto end 44 | ) 45 | 46 | cls 47 | "!python!" main.py 48 | 49 | if errorlevel 1 ( 50 | cls 51 | echo Failed! Check the script for errors. 52 | pause 53 | goto end 54 | ) 55 | 56 | cls 57 | echo Press any key to close... 58 | pause 59 | 60 | :end 61 | endlocal -------------------------------------------------------------------------------- /config/i18n/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "Menu": { 3 | "Project": { 4 | "name": "项目" 5 | }, 6 | "Daily": { 7 | "name": "日常" 8 | }, 9 | "Weekly": { 10 | "name": "周常" 11 | } 12 | }, 13 | "Task": { 14 | "General": { 15 | "name": "总览" 16 | }, 17 | "Update": { 18 | "name": "更新" 19 | }, 20 | "Login": { 21 | "name": "启动游戏" 22 | }, 23 | "Logout": { 24 | "name": "退出游戏" 25 | }, 26 | "Mission1": { 27 | "name": "活跃奖励1" 28 | }, 29 | "Mission2": { 30 | "name": "活跃奖励2" 31 | }, 32 | "Sweep": { 33 | "name": "减负" 34 | }, 35 | "Mail": { 36 | "name": "邮件" 37 | }, 38 | "DormBonus": { 39 | "name": "宿舍奖励" 40 | }, 41 | "Expedition": { 42 | "name": "远征" 43 | }, 44 | "Errand": { 45 | "name": "打工" 46 | }, 47 | "Armada": { 48 | "name": "舰团奖励" 49 | }, 50 | "WeeklyReward": { 51 | "name": "周常奖励" 52 | } 53 | }, 54 | "Game": { 55 | "_info": { 56 | "name": "游戏设置", 57 | "help": "" 58 | }, 59 | "game_path": { 60 | "name": "游戏路径", 61 | "help": "游戏本体而非启动器路径,例如“G:\\Honkai Impact 3\\Games\\BH3.exe”" 62 | }, 63 | "log_retain": { 64 | "name": "日志保留时间", 65 | "help": "", 66 | "1day": "1天", 67 | "3days": "3天", 68 | "1week": "1周", 69 | "1month": "1月" 70 | } 71 | }, 72 | "WeeklyEvent": { 73 | "_info": { 74 | "name": "奖励事件", 75 | "help": "" 76 | }, 77 | "share": { 78 | "name": "每周分享", 79 | "help": "需安排在活跃奖励2之后,否则不会运行" 80 | }, 81 | "share_time": { 82 | "name": "", 83 | "help": "" 84 | }, 85 | "homo_chest": { 86 | "name": "吼姆秘宝", 87 | "help": "" 88 | }, 89 | "homo_chest_time": { 90 | "name": "", 91 | "help": "" 92 | }, 93 | "bp_chest": { 94 | "name": "历练值宝箱", 95 | "help": "" 96 | }, 97 | "bp_chest_time": { 98 | "name": "", 99 | "help": "" 100 | }, 101 | "armada_contribution": { 102 | "name": "舰团贡献奖励", 103 | "help": "" 104 | }, 105 | "armada_contribution_time": { 106 | "name": "", 107 | "help": "" 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /tasks/expedition.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, Timer, logger, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Ocr, Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_expeditions, TPL_CONFIRM_BUTTON 8 | from tasks.base.switch import TPL_EXPEDITION_MATL_TAB, TPL_EXPEDITION_FRAG_TAB 9 | 10 | 11 | class Expeditions(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | # 远征派遣 16 | @staticmethod 17 | def dispatch(): 18 | loop_timer = Timer(0, 10).start() 19 | while True: 20 | if loop_timer.reached(): 21 | raise LoopError('The operation has looped too many times') 22 | 23 | find_click(Template(r"QUICK_EXPEDITION.png", (0.409, 0.237), Keyword('一键远征'))) 24 | if exists(Template(r"EXPEDITION_NOT_AVAILABLE.png", (0.209, -0.045), Keyword('次数不足')), ocr_mode=1): 25 | find_click(Template(r"EXPEDITION_CANCEL.png", (-0.141, 0.205), Keyword('取消派遣'))) 26 | break 27 | if find_click(Template(r"EXPEDITION_DISPATCH.png", (0.14, 0.205), Keyword('远征派遣')), times=2): 28 | if find_click(Template(r"CLAIM_STAMINA.png", (0.092, 0.156), Keyword('取出体力')), times=2): 29 | find_click(Template(r"EXPEDITION_DISPATCH.png", (0.14, 0.205), Keyword('远征派遣')), times=2) 30 | logger.info('Expedition dispatch completed') 31 | break 32 | 33 | # 领前一天远征奖励 TODO: 记录远征类型 34 | def claim_rewards(self): 35 | TPL_EXPEDITION_COMPLETED = Template(r"EXPEDITION_COMPLETED.png", (0.237, -0.09), Keyword('完成远征')) 36 | if not exists(TPL_EXPEDITION_COMPLETED, timeout=1): 37 | current_state = self.ui_get_current_state(self.ui_get_current_page().switch) 38 | another_state = TPL_EXPEDITION_MATL_TAB if current_state == TPL_EXPEDITION_FRAG_TAB.name \ 39 | else TPL_EXPEDITION_FRAG_TAB 40 | self.ui_goto(page_expeditions, another_state) 41 | if find_click(TPL_EXPEDITION_COMPLETED): 42 | find_click(TPL_CONFIRM_BUTTON) 43 | logger.info('Expedition rewards claim completed') 44 | 45 | def run(self): 46 | self.ui_ensure(page_expeditions) 47 | self.claim_rewards() 48 | self.dispatch() 49 | -------------------------------------------------------------------------------- /tasks/base/popup.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, find_click, touch, exists, sleep 2 | from zafkiel.decorator import run_until_true 3 | from zafkiel.ocr import Keyword 4 | 5 | from tasks.base.page import TPL_CONFIRM_BUTTON 6 | 7 | 8 | class PopupHandler: 9 | # 凭证奖励弹窗 10 | @run_until_true 11 | def handle_bp_reward(self): 12 | rec_template = Template(r"POPUP_BP_FLAG.png", (-0.137, 0.218), Keyword('升级凭证')) 13 | touch_template = Template(r"POPUP_BP_CLAIM.png", (0.137, 0.218), Keyword('领取奖励')) 14 | if find_click(rec_template, timeout=0, touch_template=touch_template): 15 | return find_click(TPL_CONFIRM_BUTTON) 16 | 17 | # 活动通知弹窗 18 | @staticmethod 19 | def handle_login_event(): 20 | rec_template = Template(r"POPUP_EVENT_FLAG.png", (0.0, 0.24)) 21 | touch_template = Template(r"POPUP_MARGIN.png", (0.467, -0.252)) 22 | return find_click(rec_template, timeout=0, touch_template=touch_template, blind=True) 23 | 24 | # 不定时的七日登录奖励 25 | @run_until_true 26 | def handle_7day_reward(self): 27 | if find_click(Template(r"7DAY_REWARD_CLAIM.png", (0.084, 0.234)), timeout=0): 28 | if find_click(Template(r"7DAY_REWARD_CONFIRM.png", (-0.001, 0.145)), timeout=3): 29 | return True 30 | 31 | return False 32 | 33 | # 每日签到奖励 34 | @run_until_true 35 | def handle_signin_reward(self): 36 | if find_click(Template(r"SIGNIN_REWARD_CLAIM.png", (0.083, 0.248)), timeout=0): 37 | if find_click(Template(r"SIGNIN_REWARD_CONFIRM.png", (-0.001, 0.134)), timeout=3): 38 | return True 39 | 40 | return False 41 | 42 | # 游戏公告,最近好像不弹了 43 | # @run_until_true 44 | # def handle_notice(self): 45 | # rec_template = Template(r"assets/NOTICE_FLAG.png", record_pos=(-0.391, -0.194), resolution=(1280, 720), 46 | # rgb=True) 47 | # touch_template = Template(r"assets/NOTICE_CLOSE.png", record_pos=(0.431, -0.22), resolution=(1280, 720)) 48 | # return find_click(rec_template, timeout=0.5, touch_template=touch_template) 49 | 50 | # 深渊结算弹窗 51 | @run_until_true 52 | def handle_abyss_settle(self): 53 | if exists(Template(r"ABYSS_SETTLE.png", (0.005, -0.102), Keyword('终极区')), ocr_mode=1): 54 | sleep(0.5) 55 | touch(Template(r"POPUP_MARGIN.png", (0.467, -0.252)), blind=True) 56 | return True 57 | return False 58 | 59 | 60 | popup_handler = PopupHandler() 61 | popup_list = [popup_handler.handle_login_event, popup_handler.handle_7day_reward, popup_handler.handle_signin_reward, 62 | popup_handler.handle_abyss_settle, popup_handler.handle_bp_reward] 63 | 64 | -------------------------------------------------------------------------------- /tasks/base/switch.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template 2 | from zafkiel.ocr import Keyword 3 | from zafkiel.ui import Switch 4 | 5 | # BP任务界面 6 | TPL_BP_MISSIONS_TAB = Template(r"BP_MISSIONS_TAB.png", (-0.227, 0.257)) 7 | TPL_BP_REWARDS_TAB = Template(r"BP_REWARDS_TAB.png", (-0.273, -0.044)) 8 | TPL_BP_SHOP_TAB = Template(r"BP_SHOP_TAB.png", (-0.391, 0.034), Keyword('作战工坊')) 9 | TPL_GOTO_BP_MISSIONS = Template(r"GOTO_BP_MISSIONS.png", (-0.417, -0.171), Keyword('作战任务')) 10 | TPL_GOTO_BP_REWARDS = Template(r"GOTO_BP_REWARD.png", (-0.419, 0.008), Keyword('作战奖励')) 11 | TPL_GOTO_BP_SHOP = Template(r"GOTO_BP_SHOP.png", (-0.418, -0.029), Keyword('作战商店')) 12 | 13 | switch_missions = Switch('switch_missions', is_selector=True) 14 | switch_missions.add_state('BP_MISSIONS_TAB', TPL_BP_MISSIONS_TAB, TPL_GOTO_BP_MISSIONS) 15 | switch_missions.add_state('BP_REWARDS_TAB', TPL_BP_REWARDS_TAB, TPL_GOTO_BP_REWARDS) 16 | switch_missions.add_state('BP_SHOP_TAB', TPL_BP_SHOP_TAB, TPL_GOTO_BP_SHOP) 17 | 18 | 19 | # 远征界面 20 | TPL_EXPEDITION_FRAG_TAB = Template(r"EXPEDITION_FRAG_TAB.png", (0.369, -0.196), rgb=True) 21 | TPL_EXPEDITION_MATL_TAB = Template(r"EXPEDITION_MATL_TAB.png", (0.37, -0.135), rgb=True) 22 | TPL_MATL_GOTO_FRAG = Template(r"MATL_GOTO_FRAG.png", (0.369, -0.197), rgb=True) 23 | TPL_FRAG_GOTO_MATL = Template(r"FRAG_GOTO_MATL.png", (0.369, -0.136), rgb=True) 24 | 25 | switch_expeditions = Switch('switch_expeditions', is_selector=True) 26 | switch_expeditions.add_state('EXPEDITION_FRAG_TAB', TPL_EXPEDITION_FRAG_TAB, TPL_MATL_GOTO_FRAG) 27 | switch_expeditions.add_state('EXPEDITION_MATL_TAB', TPL_EXPEDITION_MATL_TAB, TPL_FRAG_GOTO_MATL) 28 | 29 | 30 | # 作战界面 31 | TPL_BATTLE_RECOMMEND_TAB = Template(r"BATTLE_RECOMMEND_TAB.png", (-0.257, -0.2), rgb=True) 32 | TPL_BATTLE_ATTACK_TAB = Template(r"BATTLE_ATTACK_TAB.png", (-0.12, -0.201), rgb=True) 33 | TPL_BATTLE_CHALLENGE_TAB = Template(r"BATTLE_CHALLENGE_TAB.png", (0.023, -0.2), rgb=True) 34 | TPL_BATTLE_EVENT_TAB = Template(r"BATTLE_EVENT_TAB.png", (0.16, -0.199), rgb=True) 35 | TPL_GOTO_RECOMMEND = Template(r"GOTO_RECOMMEND.png", (-0.192, -0.202), Keyword('推荐')) 36 | TPL_GOTO_ATTACK = Template(r"GOTO_ATTACK.png", (-0.072, -0.202), Keyword('出击')) 37 | TPL_GOTO_CHALLENGE = Template(r"GOTO_CHALLENGE.png", (0.066, -0.202), Keyword('挑战')) 38 | TPL_GOTO_EVENT = Template(r"GOTO_EVENT.png", (0.199, -0.202), Keyword('活动')) 39 | 40 | switch_battle = Switch('switch_battle', is_selector=True) 41 | switch_battle.add_state('BATTLE_RECOMMEND_TAB', TPL_BATTLE_RECOMMEND_TAB, TPL_GOTO_RECOMMEND) 42 | switch_battle.add_state('BATTLE_ATTACK_TAB', TPL_BATTLE_ATTACK_TAB, TPL_GOTO_ATTACK) 43 | switch_battle.add_state('BATTLE_CHALLENGE_TAB', TPL_BATTLE_CHALLENGE_TAB, TPL_GOTO_CHALLENGE) 44 | switch_battle.add_state('BATTLE_EVENT_TAB', TPL_BATTLE_EVENT_TAB, TPL_GOTO_EVENT) 45 | -------------------------------------------------------------------------------- /tasks/mission.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, screenshot, touch, find_click 2 | from zafkiel.ocr import Digit, Keyword 3 | from zafkiel.ui import UI 4 | 5 | from config import Config 6 | from tasks.base.page import page_missions, TPL_CONFIRM_BUTTON, TPL_NEW_ITEM 7 | from tasks.base.popup import popup_list, popup_handler 8 | from tasks.base.switch import TPL_BP_MISSIONS_TAB, TPL_BP_REWARDS_TAB 9 | 10 | 11 | class Missions(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def claim_bp_rewards(self): 16 | self.ui_goto(page_missions, TPL_BP_REWARDS_TAB) 17 | 18 | # 领凭证奖励 19 | screen = screenshot() 20 | ocr_current_level = Digit(Template(r"CURRENT_BP_LEVEL.png", (-0.29, -0.178))) 21 | current_level = ocr_current_level.ocr_single_line(screen) 22 | logger.info(f'Current BP level: {current_level}') 23 | 24 | ocr_reward_level = Digit(Template(r"REWARD_BP_LEVEL.png", (-0.182, -0.13))) 25 | reward_level = ocr_reward_level.ocr_single_line(screen) 26 | logger.info(f'BP reward level: {reward_level}') 27 | 28 | # TODO:65级以后右端顶到头,领取位置变了 29 | if current_level >= reward_level: 30 | if touch(Template(r"BP_REWARD.png", (-0.179, -0.054)), blind=True): 31 | popup_handler.handle_bp_reward() 32 | find_click(Template(r"BP_REWARD_CONFIRM.png", (0.141, 0.173))) 33 | logger.info('BP rewards claim completed') 34 | 35 | def claim_daily_rewards(self): 36 | self.ui_goto(page_missions, TPL_BP_MISSIONS_TAB) 37 | if find_click(Template(r"QUICK_CLAIM.png", (0.418, -0.187), Keyword('一键领取'), rgb=True), ocr_mode=1): 38 | find_click(TPL_CONFIRM_BUTTON) 39 | logger.info('Daily rewards claim completed') 40 | 41 | ocr = Digit(Template(r"DAILY_BP.png", (-0.273, 0.231))) 42 | daily_bp = ocr.ocr_single_line(screenshot()) 43 | logger.info(f'Daily BP: {daily_bp}') 44 | click = False 45 | if daily_bp >= 600: 46 | click = find_click(Template(r"DAILY_REWARD_600.png", (0.449, 0.241))) 47 | elif daily_bp >= 450: 48 | click = find_click(Template(r"DAILY_REWARD_450.png", (0.312, 0.241))) 49 | elif daily_bp >= 300: 50 | click = find_click(Template(r"DAILY_REWARD_300.png", (0.175, 0.241))) 51 | elif daily_bp >= 200: 52 | click = find_click(Template(r"DAILY_REWARD_200.png", (0.037, 0.241))) 53 | elif daily_bp >= 100: 54 | click = find_click(Template(r"DAILY_REWARD_100.png", (-0.1, 0.241))) 55 | if click: 56 | find_click(TPL_CONFIRM_BUTTON) 57 | 58 | def run(self): 59 | # self.get_popup_list(popup_list) 60 | self.ui_ensure(page_missions) 61 | self.claim_daily_rewards() 62 | self.claim_bp_rewards() 63 | -------------------------------------------------------------------------------- /tasks/login.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import shutil 3 | import time 4 | from pathlib import Path 5 | import subprocess 6 | 7 | from zafkiel import Template, logger, wait, touch, stop_app, auto_setup, sleep, exists, find_click 8 | from zafkiel.ocr import Keyword 9 | from zafkiel.ui import UI 10 | 11 | from config import Config 12 | from tasks.base.popup import popup_list, popup_handler 13 | from tasks.base.page import page_main 14 | 15 | 16 | class Login(UI): 17 | def __init__(self, config: Config): 18 | self.config = config 19 | 20 | def manage_log(self): 21 | log_retain_map = { 22 | '1day': 1, 23 | '3days': 3, 24 | '1week': 7, 25 | '1month': 30, 26 | } 27 | retain_days = log_retain_map.get(self.config.data['General']['Game']['log_retain'], 7) 28 | 29 | current_time = time.time() 30 | log_path = Path('./log') 31 | 32 | for log_dir in log_path.iterdir(): 33 | create_time = log_dir.stat().st_ctime 34 | age_in_days = (current_time - create_time) / (24 * 3600) 35 | 36 | if age_in_days > retain_days: 37 | try: 38 | logger.info(f'Deleting old log directory: {log_dir}') 39 | shutil.rmtree(log_dir) 40 | except Exception as e: 41 | logger.error(f'Failed to delete {log_dir}: {e}') 42 | 43 | def handle_app_login(self): 44 | 45 | wait(Template(r"LOGIN_FLAG.png", (0.406, 0.233), rgb=True), 46 | timeout=1200, interval=3, interval_func=self.check_update) 47 | touch(Template(r"LOGIN_CLICK.png", (-0.002, -0.031)), times=2, blind=True) 48 | 49 | while True: 50 | if self.ui_additional(): 51 | continue 52 | if popup_handler.handle_abyss_settle(): 53 | continue 54 | if self.ui_page_appear(page_main): 55 | sleep(3) 56 | if not self.ui_ensure(page_main): 57 | logger.info('Game login successful') 58 | break 59 | 60 | return True 61 | 62 | def app_stop(self): 63 | stop_app() 64 | 65 | def app_start(self): 66 | subprocess.Popen([self.config.data['General']['Game']['game_path']]) 67 | date = datetime.datetime.now().strftime("%Y-%m-%d") 68 | auto_setup(str(Path.cwd()), logdir=f'./log/{date}/report', devices=["WindowsPlatform:///?title=崩坏3", ]) 69 | self.manage_log() 70 | self.get_popup_list(popup_list) # TODO: Move to program start instead of game start 71 | 72 | sleep(15) 73 | self.handle_app_login() 74 | 75 | def app_restart(self): 76 | self.app_stop() 77 | self.app_start() 78 | self.handle_app_login() 79 | 80 | @staticmethod 81 | def check_update(): 82 | if exists(Template(r"LOGIN_UPDATE.png", (0.002, -0.129))): 83 | find_click(Template(r"DOWNLOAD_CONFIRM.png", (0.0, 0.116))) 84 | logger.info('Game updating') 85 | if find_click(Template(r"DOWNLOAD_DONE.png", (0.0, 0.048), Keyword('确定')), timeout=1200): 86 | logger.info('Game update completed') 87 | -------------------------------------------------------------------------------- /tasks/armada.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, exists, find_click, touch, screenshot 2 | from zafkiel.decorator import run_until_true 3 | from zafkiel.exception import LoopError 4 | from zafkiel.ocr import DigitCounter, Keyword 5 | from zafkiel.ui import UI 6 | 7 | from config import Config 8 | from tasks.base.page import page_armada, page_commission, page_armada_rewards, TPL_CONFIRM_BUTTON 9 | 10 | 11 | class Armada(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def claim_rewards(self): 16 | logger.info('Start claiming armada rewards') 17 | loop_timer = Timer(0, 10).start() 18 | while True: 19 | if loop_timer.reached(): 20 | raise LoopError('The operation has looped too many times') 21 | 22 | if not exists(Template(r"ARMADA_REWARD_TAB.png", (0.38, -0.128))): 23 | logger.info('Armada reward claim completed') 24 | break 25 | 26 | self.ui_goto(page_armada_rewards) 27 | find_click(Template(r"ARMADA_REWARD_CLAIM.png", (0.212, 0.225), Keyword('领取'))) 28 | find_click(TPL_CONFIRM_BUTTON) 29 | 30 | @staticmethod 31 | def _handel_lack(): 32 | logger.info('Handling lack of commission materials') 33 | loop_timer = Timer(0, 10).start() 34 | while True: 35 | if loop_timer.reached(): 36 | raise LoopError('The operation has looped too many times') 37 | 38 | if exists(Template(r"COMMISSION_SUBMIT.png", (0.237, 0.224), Keyword('提交'), rgb=True)): 39 | break 40 | 41 | if find_click(Template(r"COMMISSION_MAX.png", (0.002, 0.161), Keyword('最大'))): 42 | find_click(Template(r"COMMISSION_BUY.png", (0.275, 0.162), Keyword('购买')), times=2) 43 | continue 44 | 45 | touch(Template(r"COMMISSION_LACK.png", (-0.398, -0.103)), blind=True) 46 | 47 | @run_until_true 48 | def _apply_new(self): 49 | logger.info('Applying for new commission') 50 | ocr = DigitCounter(Template(r"COMMISSION_REQUEST.png", (-0.36, 0.225))) 51 | if ocr.ocr_single_line(screenshot())[0] == 0: 52 | find_click(Template(r"COMMISSION_REQUEST.png", (-0.36, 0.225)), blind=True) 53 | find_click(Template(r"COMMISSION_REQUEST_FLAG.png", (-0.378, -0.18), Keyword('委托申请次数')), 54 | Template(r"COMMISSION_ACCEPT.png", (0.375, -0.079), Keyword('接受')), 55 | times=2) 56 | logger.info('New commission request completed') 57 | return True 58 | return False 59 | 60 | def commission(self): 61 | logger.info('Start commission process') 62 | self.ui_goto(page_commission) 63 | ocr = DigitCounter(Template(r"COMMISSION_COUNT.png", (0.43, 0.242))) 64 | 65 | loop_timer = Timer(0, 30).start() 66 | while True: 67 | if loop_timer.reached(): 68 | raise LoopError('The operation has looped too many times') 69 | 70 | if ocr.ocr_single_line(screenshot())[0] == 0: 71 | logger.info('Commissions submit completed') 72 | break 73 | 74 | if self._apply_new(): 75 | continue 76 | 77 | if find_click(Template(r"COMMISSION_SUBMIT.png", (0.237, 0.224), Keyword('提交'), rgb=True), 78 | timeout=0): 79 | continue 80 | if exists(Template(r"COMMISSION_SUBMIT_LACK.png", (0.237, 0.225), Keyword('提交'), rgb=True)): 81 | logger.info('Insufficient commission materials, suggest to buy in advance to speed up') 82 | self._handel_lack() 83 | find_click(Template(r"COMMISSION_SUBMIT_CONFIRM.png", (0.135, 0.159), Keyword('提交委托')), 84 | timeout=0) 85 | find_click(Template(r"COMMISSION_PUT.png", (0.0, 0.137), Keyword('放入舰团奖励池')), 86 | times=2, timeout=0) 87 | 88 | def run(self): 89 | self.ui_ensure(page_armada) 90 | self.commission() 91 | self.claim_rewards() 92 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import ctypes 3 | import datetime 4 | import json 5 | import sys 6 | from pathlib import Path 7 | 8 | from loguru import logger 9 | from zafkiel import simple_report, auto_setup 10 | 11 | from config import Config 12 | from tasks.armada import Armada 13 | from tasks.dorm_bonus import DormBonus 14 | from tasks.errand import Errand 15 | from tasks.expedition import Expeditions 16 | from tasks.login import Login 17 | from tasks.mail import Mail 18 | from tasks.mission import Missions 19 | from tasks.sweep import Sweep 20 | from tasks.weekly_reward import WeeklyReward 21 | 22 | logger.remove() 23 | logger.add(sys.stdout, level="INFO", format="{time:HH:mm:ss} | " 24 | "{level: <7} | " 25 | "{message}", 26 | ) 27 | date = datetime.datetime.now().strftime("%Y-%m-%d") 28 | logger.add(f'./log/{date}/{date}.log', level="DEBUG", format="{time:HH:mm:ss} | " 29 | "{level: <7} | " 30 | "{message}", 31 | ) 32 | 33 | 34 | def all_tasks(config): 35 | try: 36 | # 日常 37 | Login(config).app_start() 38 | Missions(config).run() 39 | DormBonus(config).claim_stamina() 40 | DormBonus(config).claim_gold() 41 | Errand(config).run() 42 | Expeditions(config).run() 43 | Armada(config).run() 44 | Sweep(config).run() 45 | Missions(config).run() 46 | Mail(config).run() 47 | WeeklyReward(config).run() 48 | 49 | # 结束游戏进程 50 | Login(config).app_stop() 51 | 52 | except Exception as e: 53 | logger.exception(e) 54 | raise 55 | 56 | finally: 57 | simple_report(__file__, log_path=Path(f'./log/{date}/report').resolve(), output=f'./log/{date}/report.html') 58 | 59 | 60 | def single_task(config, task): 61 | try: 62 | if task != 'login': 63 | auto_setup(str(Path.cwd()), logdir=f'./log/{date}/report', devices=["WindowsPlatform:///?title=崩坏3", ]) 64 | 65 | if task == 'armada': 66 | Armada(config).run() 67 | elif task == 'dorm_bonus': 68 | DormBonus(config).run() 69 | elif task == 'errand': 70 | Errand(config).run() 71 | elif task == 'expedition': 72 | Expeditions(config).run() 73 | elif task == 'login': 74 | Login(config).app_start() 75 | elif task == 'logout': 76 | Login(config).app_stop() 77 | simple_report(__file__, log_path=Path(f'./log/{date}/report').resolve(), output=f'./log/{date}/report.html') 78 | elif task == 'mail': 79 | Mail(config).run() 80 | elif task == 'mission': 81 | Missions(config).run() 82 | elif task == 'sweep': 83 | Sweep(config).run() 84 | elif task == 'weekly_reward': 85 | WeeklyReward(config).run() 86 | except Exception as e: 87 | simple_report(__file__, log_path=Path(f'./log/{date}/report').resolve(), output=f'./log/{date}/report.html') 88 | logger.error(e) 89 | raise 90 | 91 | 92 | def main(): 93 | parser = argparse.ArgumentParser() 94 | parser.add_argument('--task', '-t', 95 | choices=["armada", "dorm_bonus", "errand", "expedition", "login", "logout", "mail", 96 | "mission", "sweep", "weekly_reward"], 97 | help='Task name, one of "armada, dorm_bonus, errand, expedition, login, logout, mail, ' 98 | 'mission, sweep, weekly_reward"') 99 | parser.add_argument('--config_path', '-c', default='./config/config.json') 100 | args = parser.parse_args() 101 | 102 | if args.task: 103 | config_path = Path(args.config_path).resolve() 104 | if not config_path.exists(): 105 | logger.error(f'{config_path} not found') 106 | return 107 | config = Config(config_path) 108 | single_task(config, args.task) 109 | else: 110 | config = Config('./config/default.json') 111 | all_tasks(config) 112 | 113 | 114 | if __name__ == '__main__': 115 | # 以管理员身份运行 116 | if ctypes.windll.shell32.IsUserAnAdmin(): 117 | main() 118 | else: 119 | ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, __file__, None, 1) 120 | -------------------------------------------------------------------------------- /tasks/weekly_reward.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | 4 | from zafkiel import Template, exists, find_click, touch, logger 5 | from zafkiel.ocr import Keyword 6 | from zafkiel.ui import UI 7 | 8 | from config import Config 9 | from tasks.base.page import TPL_RETURN_BUTTON, page_missions, TPL_CONFIRM_BUTTON, page_main, TPL_NEW_ITEM, \ 10 | page_armada_contribution 11 | from tasks.base.popup import popup_handler 12 | from tasks.base.switch import TPL_BP_MISSIONS_TAB, TPL_BP_REWARDS_TAB 13 | 14 | 15 | class WeeklyReward(UI): 16 | def __init__(self, config: Config): 17 | self.config = config 18 | 19 | now = datetime.datetime.now() 20 | monday = now - datetime.timedelta(days=now.weekday()) 21 | self.monday_4am = monday.replace(hour=4, minute=0, second=0, microsecond=0).timestamp() 22 | 23 | def share(self): 24 | if not self.config.data['WeeklyReward']['WeeklyEvent']['share']: 25 | return 26 | 27 | if self.config.data['WeeklyReward']['WeeklyEvent']['share_time'] > self.monday_4am: 28 | logger.info('Weekly sharing already completed') 29 | return 30 | 31 | self.ui_ensure(page_missions, TPL_BP_MISSIONS_TAB) 32 | if exists(Template(r"WEEKLY_SHARE.png", (-0.196, -0.134), Keyword('每周分享'))): 33 | find_click(Template(r"GOTO_SHARE.png", (0.013, -0.083), Keyword('前往'))) 34 | touch(Template(r"SHARE_ITEM.png", (-0.199, -0.095)), blind=True) 35 | find_click(Template(r"SHARE_BUTTON.png", (-0.35, 0.222)), times=2) 36 | find_click(TPL_RETURN_BUTTON) 37 | logger.info('Weekly sharing completed') 38 | else: 39 | # 若已经手动完成 40 | logger.info('Weekly sharing already completed') 41 | self.config.update('WeeklyReward', 'WeeklyEvent', 'share_time', time.time()) 42 | 43 | def homo_chest(self): 44 | if not self.config.data['WeeklyReward']['WeeklyEvent']['homo_chest']: 45 | return 46 | 47 | if self.config.data['WeeklyReward']['WeeklyEvent']['homo_chest_time'] > self.monday_4am: 48 | logger.info('Weekly homo chest already claimed') 49 | return 50 | 51 | self.ui_ensure(page_main) 52 | find_click(Template(r"MAIN_GOTO_MALL.png", (-0.423, 0.076))) 53 | find_click(Template(r"GOTO_GIFT.png", (-0.355, -0.123), Keyword('礼包'))) 54 | find_click(Template(r"GOTO_WEEKLY_GIFT.png", (-0.355, -0.005), Keyword('周期'))) 55 | if find_click(Template(r"BUY_HOMO_CHEST.png", (-0.207, 0.041), Keyword('免费'))): 56 | find_click(Template(r"HOMO_CHEST_CONFIRM.png", (-0.002, 0.18), Keyword('免费'))) 57 | find_click(TPL_CONFIRM_BUTTON) 58 | logger.info('Weekly homo chest claim completed') 59 | else: 60 | logger.info('Weekly homo chest already claimed') 61 | self.config.update('WeeklyReward', 'WeeklyEvent', 'homo_chest_time', time.time()) 62 | find_click(TPL_RETURN_BUTTON) 63 | 64 | def bp_chest(self): 65 | if not self.config.data['WeeklyReward']['WeeklyEvent']['bp_chest']: 66 | return 67 | 68 | if self.config.data['WeeklyReward']['WeeklyEvent']['bp_chest_time'] > self.monday_4am: 69 | logger.info('Weekly bp chest already claimed') 70 | return 71 | 72 | self.ui_ensure(page_missions, TPL_BP_REWARDS_TAB) 73 | if find_click(Template(r"BP_CHEST.png", (0.334, 0.203))): 74 | find_click(TPL_NEW_ITEM, timeout=2) 75 | find_click(TPL_CONFIRM_BUTTON) 76 | popup_handler.handle_bp_reward() 77 | logger.info('Weekly bp chest claim completed') 78 | else: 79 | logger.info('Weekly bp chest already claimed') 80 | self.config.update('WeeklyReward', 'WeeklyEvent', 'bp_chest_time', time.time()) 81 | 82 | def armada_contribution_reward(self): 83 | if not self.config.data['WeeklyReward']['WeeklyEvent']['armada_contribution']: 84 | return 85 | 86 | if self.config.data['WeeklyReward']['WeeklyEvent']['armada_contribution_time'] > self.monday_4am: 87 | logger.info('Armada contribution reward already claimed') 88 | return 89 | 90 | self.ui_ensure(page_armada_contribution) 91 | if exists(Template(r"CONTRIBUTION_FULL.png", (-0.325, -0.123))): 92 | find_click(Template(r"CONTRIBUTION_REWARD.png", (-0.442, -0.122))) 93 | find_click(TPL_CONFIRM_BUTTON) 94 | self.config.update('WeeklyReward', 'WeeklyEvent', 'armada_contribution_time', time.time()) 95 | logger.info('Armada contribution reward claim completed') 96 | elif exists(Template(r"CONTRIBUTION_CLAIMED.png", (-0.324, -0.122))): 97 | self.config.update('WeeklyReward', 'WeeklyEvent', 'armada_contribution_time', time.time()) 98 | logger.info('Armada contribution reward already claimed') 99 | else: 100 | logger.info('Armada contribution reward not available') 101 | 102 | def run(self): 103 | self.share() 104 | self.homo_chest() 105 | self.bp_chest() 106 | self.armada_contribution_reward() 107 | 108 | 109 | -------------------------------------------------------------------------------- /config/args.json: -------------------------------------------------------------------------------- 1 | { 2 | "Project": { 3 | "General": { 4 | "_Base": { 5 | "work_dir": "./examples/HonkaiHelper", 6 | "work_dir_enabled": true, 7 | "is_background": false, 8 | "is_background_enabled": true, 9 | "config_path": "./examples/HonkaiHelper/config/config.json", 10 | "config_path_enabled": true 11 | }, 12 | "Game": { 13 | "game_path": { 14 | "type": "input", 15 | "value": "", 16 | "option": [], 17 | "hide": false 18 | }, 19 | "log_retain": { 20 | "type": "select", 21 | "value": "1week", 22 | "option": [ 23 | "1day", 24 | "3days", 25 | "1week", 26 | "1month" 27 | ], 28 | "hide": false 29 | } 30 | } 31 | }, 32 | "Update": { 33 | "_Base": { 34 | "repo_url": "https://gitee.com/aues6uen11z/HonkaiHelper", 35 | "repo_url_enabled": true, 36 | "branch": "master", 37 | "branch_enabled": true, 38 | "local_path": "./examples/HonkaiHelper", 39 | "local_path_enabled": true, 40 | "template_path": "config", 41 | "template_path_enabled": true, 42 | "env_name": "zafkiel", 43 | "pip_mirror": "https://pypi.tuna.tsinghua.edu.cn/simple" 44 | } 45 | } 46 | }, 47 | "Daily": { 48 | "Login": { 49 | "_Base": { 50 | "priority": 0, 51 | "priority_enabled": false, 52 | "command": "py main.py -t login", 53 | "command_enabled": true 54 | } 55 | }, 56 | "Logout": { 57 | "_Base": { 58 | "priority": 100, 59 | "priority_enabled": false, 60 | "command": "py main.py -t logout", 61 | "command_enabled": true 62 | } 63 | }, 64 | "Mission1": { 65 | "_Base": { 66 | "priority": 1, 67 | "priority_enabled": false, 68 | "command": "py main.py -t mission", 69 | "command_enabled": true 70 | } 71 | }, 72 | "Mission2": { 73 | "_Base": { 74 | "priority": 8, 75 | "priority_enabled": false, 76 | "command": "py main.py -t mission", 77 | "command_enabled": true 78 | } 79 | }, 80 | "Sweep": { 81 | "_Base": { 82 | "priority": 6, 83 | "priority_enabled": true, 84 | "command": "py main.py -t sweep", 85 | "command_enabled": true 86 | } 87 | }, 88 | "Mail": { 89 | "_Base": { 90 | "priority": 7, 91 | "priority_enabled": true, 92 | "command": "py main.py -t mail", 93 | "command_enabled": true 94 | } 95 | }, 96 | "DormBonus": { 97 | "_Base": { 98 | "priority": 2, 99 | "priority_enabled": true, 100 | "command": "py main.py -t dorm_bonus", 101 | "command_enabled": true 102 | } 103 | }, 104 | "Expedition": { 105 | "_Base": { 106 | "priority": 4, 107 | "priority_enabled": true, 108 | "command": "py main.py -t expedition", 109 | "command_enabled": true 110 | } 111 | }, 112 | "Errand": { 113 | "_Base": { 114 | "priority": 3, 115 | "priority_enabled": true, 116 | "command": "py main.py -t errand", 117 | "command_enabled": true 118 | } 119 | }, 120 | "Armada": { 121 | "_Base": { 122 | "priority": 5, 123 | "priority_enabled": true, 124 | "command": "py main.py -t armada", 125 | "command_enabled": true 126 | } 127 | } 128 | }, 129 | "Weekly": { 130 | "WeeklyReward": { 131 | "_Base": { 132 | "priority": 9, 133 | "priority_enabled": true, 134 | "command": "py main.py -t weekly_reward", 135 | "command_enabled": true 136 | }, 137 | "WeeklyEvent": { 138 | "share": { 139 | "type": "checkbox", 140 | "value": true, 141 | "option": [], 142 | "hide": false 143 | }, 144 | "share_time": { 145 | "type": "input", 146 | "value": 0.0, 147 | "option": [], 148 | "hide": true 149 | }, 150 | "homo_chest": { 151 | "type": "checkbox", 152 | "value": true, 153 | "option": [], 154 | "hide": false 155 | }, 156 | "homo_chest_time": { 157 | "type": "input", 158 | "value": 0.0, 159 | "option": [], 160 | "hide": true 161 | }, 162 | "bp_chest": { 163 | "type": "checkbox", 164 | "value": true, 165 | "option": [], 166 | "hide": false 167 | }, 168 | "bp_chest_time": { 169 | "type": "input", 170 | "value": 0.0, 171 | "option": [], 172 | "hide": true 173 | }, 174 | "armada_contribution": { 175 | "type": "checkbox", 176 | "value": true, 177 | "option": [], 178 | "hide": false 179 | }, 180 | "armada_contribution_time": { 181 | "type": "input", 182 | "value": 0.0, 183 | "option": [], 184 | "hide": true 185 | } 186 | } 187 | } 188 | } 189 | } -------------------------------------------------------------------------------- /tasks/base/page.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template 2 | from zafkiel.ocr import Keyword 3 | from zafkiel.ui import Page 4 | 5 | from tasks.base.switch import switch_missions, switch_expeditions, TPL_GOTO_ATTACK, switch_battle 6 | 7 | TPL_RETURN_BUTTON = Template(r"RETURN_BUTTON.png", (-0.444, -0.256), Keyword('返回')) 8 | TPL_HOME_BUTTON = Template(r"HOME_BUTTON.png", (-0.298, -0.257), Keyword('主菜单')) 9 | TPL_CONFIRM_BUTTON = Template(r"CONFIRM_BUTTON.png", (0.0, 0.144), Keyword('确定')) 10 | TPL_NEW_ITEM = Template(r"NEW_ITEM_POPUP.png", (0.289, -0.01)) 11 | 12 | # 主界面 13 | page_main = Page(Template(r"MAIN_FLAG.png", (0.281, 0.043), rgb=True)) 14 | 15 | # 家园界面 16 | page_dorm = Page(Template(r"DORM_STAMINA.png", (-0.34, -0.059))) 17 | page_dorm.link(TPL_RETURN_BUTTON, 18 | destination=page_main) 19 | page_main.link(Template(r"MAIN_GOTO_DORM.png", (0.354, 0.244), Keyword('家园')), 20 | destination=page_dorm) 21 | 22 | # 舰团界面 23 | page_armada = Page(Template(r"ARMADA_FLAG.png", (0.113, 0.076))) 24 | page_armada.link(TPL_RETURN_BUTTON, 25 | destination=page_main) 26 | page_main.link(Template(r"MAIN_GOTO_ARMADA.png", (0.195, 0.244), Keyword('舰团')), 27 | destination=page_armada) 28 | 29 | # 舰团委托界面 30 | page_commission = Page(Template(r"COMMISSION_FLAG.png", (-0.392, -0.183), Keyword('回收委托'))) 31 | page_commission.link(TPL_RETURN_BUTTON, 32 | destination=page_armada) 33 | page_commission.link(TPL_HOME_BUTTON, 34 | destination=page_main) 35 | page_armada.link(Template(r"ARMADA_GOTO_COMMISSION.png", (-0.113, 0.227), Keyword('委托回收')), 36 | destination=page_commission) 37 | 38 | # 舰团奖池界面 39 | page_armada_rewards = Page(Template(r"ARMADA_REWARD_FLAG.png", (-0.394, -0.184), Keyword('舰团奖池'))) 40 | page_armada_rewards.link(TPL_RETURN_BUTTON, 41 | destination=page_armada) 42 | page_armada_rewards.link(TPL_HOME_BUTTON, 43 | destination=page_main) 44 | page_commission.link(Template(r"COMMISSION_GOTO_REWARD.png", (0.439, -0.104), Keyword('舰团奖池')), 45 | destination=page_armada_rewards) 46 | 47 | # 舰团贡献界面 48 | page_armada_contribution = Page(Template(r"ARMADA_CONTRIBUTION_FLAG.png", (-0.395, -0.184), Keyword('舰团贡献'))) 49 | page_armada_contribution.link(TPL_RETURN_BUTTON, 50 | destination=page_armada) 51 | page_armada_contribution.link(TPL_HOME_BUTTON, 52 | destination=page_main) 53 | page_armada.link(Template(r"ARMADA_GOTO_CONTRIBUTION.png", (0.232, 0.23), Keyword('舰团贡献')), 54 | destination=page_armada_contribution) 55 | 56 | # BP任务界面 57 | page_missions = Page(Template(r"GOTO_BP_MISSIONS.png", (-0.417, -0.171), Keyword('作战任务')), 58 | switch=switch_missions) 59 | page_missions.link(TPL_RETURN_BUTTON, 60 | destination=page_main) 61 | page_main.link(Template(r"MAIN_GOTO_MISSIONS.png", (-0.453, -0.186)), 62 | destination=page_missions) 63 | 64 | # 邮件界面 65 | page_mail = Page(Template(r"MAIL_FLAG.png", (-0.456, 0.23), Keyword('邮件数'))) 66 | page_mail.link(TPL_RETURN_BUTTON, 67 | destination=page_main) 68 | page_main.link(Template(r"MAIN_GOTO_MAIL.png", (-0.421, -0.029)), 69 | destination=page_mail) 70 | 71 | # 远征界面 72 | page_expeditions = Page(Template(r"EXPEDITION_FLAG.png", (-0.363, -0.183), Keyword('今日远征可用体力')), 73 | switch=switch_expeditions) 74 | page_expeditions.link(TPL_RETURN_BUTTON, 75 | destination=page_dorm) 76 | page_expeditions.link(TPL_HOME_BUTTON, 77 | destination=page_main) 78 | page_dorm.link(Template(r"DORM_GOTO_EXPEDITIONS.png", (0.155, 0.237), Keyword('远征')), 79 | destination=page_expeditions) 80 | 81 | # 远征派遣界面 82 | page_dispatch = Page(Template(r"QUICK_DISPATCH.png", (0.119, 0.227), Keyword('一键派遣'))) 83 | page_dispatch.link(TPL_RETURN_BUTTON, 84 | destination=page_expeditions) 85 | page_dispatch.link(TPL_HOME_BUTTON, 86 | destination=page_main) 87 | 88 | # 打工界面 89 | page_errands = Page(Template(r"ERRANDS_FLAG.png", (-0.077, -0.258), rgb=True)) 90 | page_errands.link(TPL_RETURN_BUTTON, 91 | destination=page_dorm) 92 | page_dorm.link(Template(r"DORM_GOTO_ERRANDS.png", (0.277, 0.235), Keyword('打工')), 93 | destination=page_errands) 94 | 95 | # 商店界面 96 | page_shop = Page(Template(r"SHOP_FLAG.png", (-0.474, -0.191))) 97 | page_shop.link(TPL_RETURN_BUTTON, 98 | destination=page_dorm) 99 | page_shop.link(TPL_HOME_BUTTON, 100 | destination=page_main) 101 | page_dorm.link(Template(r"DORM_GOTO_SHOP.png", (0.422, 0.237), Keyword('商店')), 102 | destination=page_shop) 103 | 104 | # 出击界面 105 | page_battle = Page(TPL_GOTO_ATTACK, 106 | switch=switch_battle) 107 | page_battle.link(Template(r"NEW_HOME_BUTTON.png", (-0.343, -0.252)), 108 | destination=page_main) 109 | page_main.link(Template(r"MAIN_GOTO_BATTLE.png", (0.421, -0.004), Keyword('出击')), 110 | destination=page_battle) 111 | 112 | # 材料活动界面 113 | page_lite = Page(Template(r"LITE_FLAG.png", (-0.001, -0.195), Keyword('材料活动'))) 114 | page_lite.link(TPL_RETURN_BUTTON, 115 | destination=page_battle) 116 | page_lite.link(TPL_HOME_BUTTON, 117 | destination=page_main) 118 | page_battle.link(Template(r"BATTLE_GOTO_LITE.png", (0.114, 0.147)), 119 | destination=page_lite) 120 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | from typing import Literal, List, Union 4 | 5 | from pydantic import BaseModel, Field 6 | 7 | 8 | class Argument(BaseModel): 9 | """ 10 | Minimum setting 11 | """ 12 | type: Literal['input', 'select', 'checkbox'] = 'input' 13 | value: Union[str, bool, float] 14 | option: List[str] = [] 15 | hide: bool = False 16 | 17 | 18 | class GroupCustomBase(BaseModel): 19 | """ 20 | Basic settings for every task 21 | """ 22 | priority: int = 3 23 | priority_enabled: bool = True 24 | command: str = '' 25 | command_enabled: bool = True 26 | 27 | 28 | # 以下是实际设置内容 29 | # 任务级别 30 | class TaskGeneral(BaseModel): 31 | class GroupGeneralBase(BaseModel): 32 | """ 33 | General settings for the project 34 | """ 35 | work_dir: str = './examples/HonkaiHelper' 36 | work_dir_enabled: bool = True 37 | is_background: bool = False 38 | is_background_enabled: bool = True 39 | config_path: str = './examples/HonkaiHelper/config/config.json' 40 | config_path_enabled: bool = True 41 | 42 | class GroupGame(BaseModel): 43 | game_path: Argument = Argument(type='input', value='') 44 | log_retain: Argument = Argument(type='select', value='1week', option=['1day', '3days', '1week', '1month']) 45 | 46 | Base: GroupGeneralBase = Field(GroupGeneralBase(), alias='_Base') 47 | Game: GroupGame = GroupGame() 48 | 49 | 50 | class TaskUpdate(BaseModel): 51 | class GroupUpdateBase(BaseModel): 52 | """ 53 | Git repository, python virtual environment update settings 54 | """ 55 | repo_url: str = 'https://gitee.com/aues6uen11z/HonkaiHelper' 56 | repo_url_enabled: bool = True 57 | branch: str = 'master' 58 | branch_enabled: bool = True 59 | local_path: str = './examples/HonkaiHelper' 60 | local_path_enabled: bool = True 61 | template_path: str = 'config' 62 | template_path_enabled: bool = True 63 | env_name: str = 'zafkiel' 64 | pip_mirror: str = 'https://pypi.tuna.tsinghua.edu.cn/simple' 65 | 66 | Base: GroupUpdateBase = Field(GroupUpdateBase(), alias='_Base') 67 | 68 | 69 | class TaskArmada(BaseModel): 70 | Base: GroupCustomBase = Field(GroupCustomBase( 71 | command='py main.py -t armada', priority=5 72 | ), alias='_Base') 73 | 74 | 75 | class TaskDormBonus(BaseModel): 76 | Base: GroupCustomBase = Field(GroupCustomBase( 77 | command='py main.py -t dorm_bonus', priority=2 78 | ), alias='_Base') 79 | 80 | 81 | class TaskErrand(BaseModel): 82 | Base: GroupCustomBase = Field(GroupCustomBase( 83 | command='py main.py -t errand', priority=3 84 | ), alias='_Base') 85 | 86 | 87 | class TaskExpedition(BaseModel): 88 | Base: GroupCustomBase = Field(GroupCustomBase( 89 | command='py main.py -t expedition', priority=4 90 | ), alias='_Base') 91 | 92 | 93 | class TaskLogin(BaseModel): 94 | Base: GroupCustomBase = Field(GroupCustomBase( 95 | command='py main.py -t login', priority=0, priority_enabled=False 96 | ), alias='_Base') 97 | 98 | 99 | class TaskLogout(BaseModel): 100 | Base: GroupCustomBase = Field(GroupCustomBase( 101 | command='py main.py -t logout', priority=100, priority_enabled=False 102 | ), alias='_Base') 103 | 104 | 105 | class TaskMail(BaseModel): 106 | Base: GroupCustomBase = Field(GroupCustomBase( 107 | command='py main.py -t mail', priority=7 108 | ), alias='_Base') 109 | 110 | 111 | class TaskMission1(BaseModel): 112 | Base: GroupCustomBase = Field(GroupCustomBase( 113 | command='py main.py -t mission', priority=1, priority_enabled=False 114 | ), alias='_Base') 115 | 116 | 117 | class TaskMission2(BaseModel): 118 | Base: GroupCustomBase = Field(GroupCustomBase( 119 | command='py main.py -t mission', priority=8, priority_enabled=False 120 | ), alias='_Base') 121 | 122 | 123 | class TaskSweep(BaseModel): 124 | Base: GroupCustomBase = Field(GroupCustomBase( 125 | command='py main.py -t sweep', priority=6 126 | ), alias='_Base') 127 | 128 | 129 | class TaskWeeklyReward(BaseModel): 130 | class GroupWeeklyEvent(BaseModel): 131 | share: Argument = Argument(type='checkbox', value=True) 132 | share_time: Argument = Argument(type='input', value=0.0, hide=True) 133 | 134 | homo_chest: Argument = Argument(type='checkbox', value=True) 135 | homo_chest_time: Argument = Argument(type='input', value=0.0, hide=True) 136 | 137 | bp_chest: Argument = Argument(type='checkbox', value=True) 138 | bp_chest_time: Argument = Argument(type='input', value=0.0, hide=True) 139 | 140 | armada_contribution: Argument = Argument(type='checkbox', value=True) 141 | armada_contribution_time: Argument = Argument(type='input', value=0.0, hide=True) 142 | 143 | Base: GroupCustomBase = Field(GroupCustomBase( 144 | command='py main.py -t weekly_reward', priority=9 145 | ), alias='_Base') 146 | WeeklyEvent: GroupWeeklyEvent = GroupWeeklyEvent() 147 | 148 | 149 | # 任务组级别 150 | class MenuProject(BaseModel): 151 | General: TaskGeneral = TaskGeneral() 152 | Update: TaskUpdate = TaskUpdate() 153 | 154 | 155 | class MenuDaily(BaseModel): 156 | Login: TaskLogin = TaskLogin() 157 | Logout: TaskLogout = TaskLogout() 158 | Mission1: TaskMission1 = TaskMission1() 159 | Mission2: TaskMission2 = TaskMission2() 160 | Sweep: TaskSweep = TaskSweep() 161 | Mail: TaskMail = TaskMail() 162 | DormBonus: TaskDormBonus = TaskDormBonus() 163 | Expedition: TaskExpedition = TaskExpedition() 164 | Errand: TaskErrand = TaskErrand() 165 | Armada: TaskArmada = TaskArmada() 166 | 167 | 168 | class MenuWeekly(BaseModel): 169 | WeeklyReward: TaskWeeklyReward = TaskWeeklyReward() 170 | 171 | 172 | # 项目级别 173 | class UIContent(BaseModel): 174 | Project: MenuProject = MenuProject() 175 | Daily: MenuDaily = MenuDaily() 176 | Weekly: MenuWeekly = MenuWeekly() 177 | 178 | 179 | def gen_i18n(config: BaseModel, lang: str): 180 | trans_dict = { 181 | "Menu": {}, 182 | "Task": {}, 183 | } 184 | 185 | # Check if the file already exists 186 | file_path = f'./config/i18n/{lang}.json' 187 | if Path(file_path).exists(): 188 | # Load the existing translations 189 | with open(file_path, 'r', encoding='utf-8') as f: 190 | old_trans_dict = json.load(f) 191 | else: 192 | old_trans_dict = {} 193 | 194 | for menu, tasks in config.model_dump(by_alias=True).items(): 195 | trans_dict['Menu'][menu] = old_trans_dict.get('Menu', {}).get(menu, {'name': ''}) 196 | 197 | for task, groups in tasks.items(): 198 | trans_dict['Task'][task] = old_trans_dict.get('Task', {}).get(task, {'name': ''}) 199 | 200 | for group, args in groups.items(): 201 | if group == '_Base': 202 | continue 203 | if group not in trans_dict: 204 | trans_dict[group] = {} 205 | 206 | trans_dict[group]['_info'] = old_trans_dict.get(group, {}).get('_info', {'name': '', 'help': ''}) 207 | for arg, info in args.items(): 208 | trans_dict[group][arg] = old_trans_dict.get(group, {}).get(arg, {'name': '', 'help': ''}) 209 | if info['type'] == 'select': 210 | for option in info['option']: 211 | trans_dict[group][arg][option] = old_trans_dict.get(group, {}).get(arg, {}).get(option, '') 212 | 213 | with open(file_path, 'w', encoding='utf-8') as f: 214 | json.dump(trans_dict, f, ensure_ascii=False, indent=2) 215 | 216 | 217 | def export() -> None: 218 | args = UIContent() 219 | with open('config/args.json', 'w') as f: 220 | f.write(args.model_dump_json(indent=2, by_alias=True)) 221 | 222 | gen_i18n(args, 'zh-CN') 223 | 224 | 225 | class Config: 226 | def __init__(self, config_path): 227 | self.config_path = config_path 228 | with open('config/args.json', 'r') as f: 229 | args = json.load(f) 230 | with open(config_path, 'r') as f: 231 | self.data = json.load(f) 232 | 233 | # 只是为了校验数据 234 | for menu, tasks in args.items(): 235 | for task, groups in tasks.items(): 236 | for group, args in groups.items(): 237 | if group == '_Base': 238 | continue 239 | for argument, info in args.items(): 240 | info['value'] = self.data[task][group][argument] 241 | UIContent.parse_obj(args) 242 | 243 | def update(self, task, group, argument, value): 244 | self.data[task][group][argument] = value 245 | with open(self.config_path, 'w') as f: 246 | json.dump(self.data, f, ensure_ascii=False, indent=2) 247 | 248 | 249 | if __name__ == '__main__': 250 | export() 251 | --------------------------------------------------------------------------------