Opt: Use common API

This commit is contained in:
Horizon101011 2022-07-21 10:09:20 +08:00
parent 0af3593fd3
commit aa4d7b4b08
12 changed files with 358 additions and 133 deletions

20
alas.py
View File

@ -51,15 +51,11 @@ class AzurLaneAutoScript:
def checker(self):
try:
from module.server_checker import ServerChecker
checker = ServerChecker(server=self.config.Emulator_ServerPlatform)
except Exception as e:
logger.critical(e)
logger.warning('There may be something wrong with server checker.')
logger.warning('Server checker will be temporarily forced off.')
self.config.Emulator_ServerPlatform = 'disabled'
checker = ServerChecker(server=self.config.Emulator_ServerPlatform)
finally:
checker = ServerChecker(server=self.config.Emulator_ServerName)
return checker
except Exception as e:
logger.exception(e)
exit(1)
def run(self, command):
try:
@ -425,7 +421,7 @@ class AzurLaneAutoScript:
# So update it once recovered
if 'config' in self.__dict__:
del self.__dict__['config']
if self.checker.is_after_maintenance():
if self.checker.is_maintenance_over():
logger.info('Server maintenance is over. Restart game client to update.')
self.run('restart')
@ -435,8 +431,6 @@ class AzurLaneAutoScript:
logger.info(f"Alas [{self.config_name}] exited.")
break
task = self.get_next_task()
if not self.checker.is_available():
continue
# Skip first restart
if is_first and task == 'Restart':
@ -473,11 +467,7 @@ class AzurLaneAutoScript:
elif self.config.Error_HandleError:
# self.config.task_delay(success=False)
del self.__dict__['config']
self.checker.check_now()
if not self.checker.is_enabled():
if self.config.Emulator_ServerPlatform != 'disabled':
self.config.Emulator_ServerPlatform = 'disabled'
continue
else:
break

View File

@ -3,6 +3,7 @@
"Emulator": {
"Serial": "auto",
"PackageName": "auto",
"ServerName": "disabled",
"ScreenshotMethod": "ADB",
"ControlMethod": "minitouch",
"ScreenshotDedithering": false

View File

@ -29,16 +29,53 @@
"com.hkmanjuu.azurlane.gp.mc"
]
},
"ServerPlatform": {
"ServerName": {
"type": "select",
"value": "disabled",
"option": [
"disabled",
"cn_android",
"cn_ios",
"cn_channel",
"en",
"en_channel"
"cn_android-0",
"cn_android-1",
"cn_android-2",
"cn_android-3",
"cn_android-4",
"cn_android-5",
"cn_android-6",
"cn_android-7",
"cn_android-8",
"cn_android-9",
"cn_android-10",
"cn_android-11",
"cn_android-12",
"cn_android-13",
"cn_android-14",
"cn_android-15",
"cn_android-16",
"cn_android-17",
"cn_android-18",
"cn_android-19",
"cn_android-20",
"cn_android-21",
"cn_ios-0",
"cn_ios-1",
"cn_ios-2",
"cn_ios-3",
"cn_ios-4",
"cn_ios-5",
"cn_ios-6",
"cn_ios-7",
"cn_ios-8",
"cn_ios-9",
"cn_ios-10",
"cn_channel-0",
"cn_channel-1",
"cn_channel-2",
"cn_channel-3",
"en-0",
"en-1",
"en-2",
"en-3",
"en-4"
]
},
"ScreenshotMethod": {

View File

@ -24,9 +24,9 @@ Emulator:
PackageName:
value: auto
option: [auto, ]
ServerPlatform:
ServerName:
value: disabled
option: [disabled, cn_android, cn_ios, cn_channel, en, en_channel]
option: [disabled, ]
ScreenshotMethod:
value: ADB
option: [ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc]

View File

@ -20,6 +20,7 @@ class GeneratedConfig:
# Group `Emulator`
Emulator_Serial = 'auto'
Emulator_PackageName = 'auto' # auto, com.bilibili.azurlane, com.YoStarEN.AzurLane, com.YoStarJP.AzurLane, com.hkmanjuu.azurlane.gp, com.bilibili.blhx.huawei, com.bilibili.blhx.mi, com.tencent.tmgp.bilibili.blhx, com.bilibili.blhx.baidu, com.bilibili.blhx.qihoo, com.bilibili.blhx.oppo, com.bilibili.blhx.vivo, com.bilibili.blhx.mz, com.bilibili.blhx.uc, com.bilibili.blhx.mzw, com.yiwu.blhx.yx15, com.hkmanjuu.azurlane.gp.mc
Emulator_ServerName = 'disabled' # disabled, cn_android-0, cn_android-1, cn_android-2, cn_android-3, cn_android-4, cn_android-5, cn_android-6, cn_android-7, cn_android-8, cn_android-9, cn_android-10, cn_android-11, cn_android-12, cn_android-13, cn_android-14, cn_android-15, cn_android-16, cn_android-17, cn_android-18, cn_android-19, cn_android-20, cn_android-21, cn_ios-0, cn_ios-1, cn_ios-2, cn_ios-3, cn_ios-4, cn_ios-5, cn_ios-6, cn_ios-7, cn_ios-8, cn_ios-9, cn_ios-10, cn_channel-0, cn_channel-1, cn_channel-2, cn_channel-3, en-0, en-1, en-2, en-3, en-4
Emulator_ScreenshotMethod = 'ADB' # ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc
Emulator_ControlMethod = 'minitouch' # ADB, uiautomator2, minitouch, Hermit
Emulator_ScreenshotDedithering = False

View File

@ -7,7 +7,7 @@ from deploy.utils import DEPLOY_TEMPLATE, poor_yaml_read, poor_yaml_write
from module.base.timer import timer
from module.config.redirect_utils.shop_filter import bp_redirect
from module.config.redirect_utils.utils import upload_redirect, api_redirect
from module.config.server import to_server, to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE
from module.config.server import to_server, to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE, VALID_SERVER_LIST
from module.config.utils import *
CONFIG_IMPORT = '''
@ -282,6 +282,11 @@ class ConfigGenerator:
else:
value = f'{name} {package}'
deep_set(new, keys=['Emulator', 'PackageName', package], value=value)
# Game server names
for server, _list in VALID_SERVER_LIST.items():
for index in range(len(_list)):
path = ['Emulator', 'ServerName', f'{server}-{index}']
deep_set(new, keys=path, value=_list[index])
# GUI i18n
for path, _ in deep_iter(self.gui, depth=2):
group, key = path
@ -406,6 +411,16 @@ class ConfigGenerator:
deep_set(self.argument, keys='Emulator.PackageName.option', value=option)
deep_set(self.args, keys='Alas.Emulator.PackageName.option', value=option)
def insert_server(self):
option = deep_get(self.argument, keys='Emulator.ServerName.option')
server_list = []
for server, _list in VALID_SERVER_LIST.items():
for index in range(len(_list)):
server_list.append(f'{server}-{index}')
option += server_list
deep_set(self.argument, keys='Emulator.ServerName.option', value=option)
deep_set(self.args, keys='Alas.Emulator.ServerName.option', value=option)
@timer
def generate(self):
_ = self.args
@ -413,6 +428,7 @@ class ConfigGenerator:
_ = self.event
self.insert_event()
self.insert_package()
self.insert_server()
write_file(filepath_args(), self.args)
write_file(filepath_args('menu'), self.menu)
self.generate_code()

View File

@ -299,15 +299,52 @@
"com.yiwu.blhx.yx15": "CN com.yiwu.blhx.yx15",
"com.hkmanjuu.azurlane.gp.mc": "TW com.hkmanjuu.azurlane.gp.mc"
},
"ServerPlatform": {
"name": "Server Platform",
"help": "Select your server platform to enable server status detection\nScript will hang up when server is being maintained or network is broken",
"disabled": "Disabled",
"cn_android": "CN-Android",
"cn_ios": "CN-IOS",
"cn_channel": "CN-Channel",
"en": "EN",
"en_channel": "EN-Channel"
"ServerName": {
"name": "Server in Game Client",
"help": "Select the server where you are in the game to enable server status detection\nScript will hang up when server is being maintained or network is broken",
"disabled": "disabled",
"cn_android-0": "莱茵演习",
"cn_android-1": "巴巴罗萨",
"cn_android-2": "霸王行动",
"cn_android-3": "冰山行动",
"cn_android-4": "彩虹计划",
"cn_android-5": "发电机计划",
"cn_android-6": "瞭望台行动",
"cn_android-7": "十字路口行动",
"cn_android-8": "朱诺行动",
"cn_android-9": "杜立特空袭",
"cn_android-10": "地狱犬行动",
"cn_android-11": "开罗宣言",
"cn_android-12": "奥林匹克行动",
"cn_android-13": "小王冠行动",
"cn_android-14": "波茨坦公告",
"cn_android-15": "白色方案",
"cn_android-16": "瓦尔基里行动",
"cn_android-17": "曼哈顿计划",
"cn_android-18": "八月风暴",
"cn_android-19": "秋季旅行",
"cn_android-20": "水星行动",
"cn_android-21": "莱茵河卫兵",
"cn_ios-0": "夏威夷",
"cn_ios-1": "珊瑚海",
"cn_ios-2": "中途岛",
"cn_ios-3": "铁底湾",
"cn_ios-4": "所罗门",
"cn_ios-5": "马里亚纳",
"cn_ios-6": "莱特湾",
"cn_ios-7": "硫磺岛",
"cn_ios-8": "冲绳岛",
"cn_ios-9": "阿留申群岛",
"cn_ios-10": "马耳他",
"cn_channel-0": "皇家巡游",
"cn_channel-1": "大西洋宪章",
"cn_channel-2": "十字军行动",
"cn_channel-3": "龙骑兵行动",
"en-0": "Avrora",
"en-1": "Lexington",
"en-2": "Sandy",
"en-3": "Washington",
"en-4": "Amagi"
},
"ScreenshotMethod": {
"name": "Screenshot Method",

View File

@ -299,15 +299,52 @@
"com.yiwu.blhx.yx15": "CN com.yiwu.blhx.yx15",
"com.hkmanjuu.azurlane.gp.mc": "TW com.hkmanjuu.azurlane.gp.mc"
},
"ServerPlatform": {
"name": "Emulator.ServerPlatform.name",
"help": "Emulator.ServerPlatform.help",
"disabled": "Disabled",
"cn_android": "CN-Android",
"cn_ios": "CN-IOS",
"cn_channel": "CN-Channel",
"en": "EN",
"en_channel": "EN-Channel"
"ServerName": {
"name": "Emulator.ServerName.name",
"help": "Emulator.ServerName.help",
"disabled": "disabled",
"cn_android-0": "莱茵演习",
"cn_android-1": "巴巴罗萨",
"cn_android-2": "霸王行动",
"cn_android-3": "冰山行动",
"cn_android-4": "彩虹计划",
"cn_android-5": "发电机计划",
"cn_android-6": "瞭望台行动",
"cn_android-7": "十字路口行动",
"cn_android-8": "朱诺行动",
"cn_android-9": "杜立特空袭",
"cn_android-10": "地狱犬行动",
"cn_android-11": "开罗宣言",
"cn_android-12": "奥林匹克行动",
"cn_android-13": "小王冠行动",
"cn_android-14": "波茨坦公告",
"cn_android-15": "白色方案",
"cn_android-16": "瓦尔基里行动",
"cn_android-17": "曼哈顿计划",
"cn_android-18": "八月风暴",
"cn_android-19": "秋季旅行",
"cn_android-20": "水星行动",
"cn_android-21": "莱茵河卫兵",
"cn_ios-0": "夏威夷",
"cn_ios-1": "珊瑚海",
"cn_ios-2": "中途岛",
"cn_ios-3": "铁底湾",
"cn_ios-4": "所罗门",
"cn_ios-5": "马里亚纳",
"cn_ios-6": "莱特湾",
"cn_ios-7": "硫磺岛",
"cn_ios-8": "冲绳岛",
"cn_ios-9": "阿留申群岛",
"cn_ios-10": "马耳他",
"cn_channel-0": "皇家巡游",
"cn_channel-1": "大西洋宪章",
"cn_channel-2": "十字军行动",
"cn_channel-3": "龙骑兵行动",
"en-0": "Avrora",
"en-1": "Lexington",
"en-2": "Sandy",
"en-3": "Washington",
"en-4": "Amagi"
},
"ScreenshotMethod": {
"name": "Emulator.ScreenshotMethod.name",

View File

@ -299,15 +299,52 @@
"com.yiwu.blhx.yx15": "国服 一五游戏渠道服 com.yiwu.blhx.yx15",
"com.hkmanjuu.azurlane.gp.mc": "台服 com.hkmanjuu.azurlane.gp.mc"
},
"ServerPlatform": {
"name": "服务器平台",
"help": "选择服务器平台以启用服务器状态检测\n当服务器维护或网络不可用时挂起直到恢复",
"disabled": "不使用",
"cn_android": "国服-安卓端",
"cn_ios": "国服-IOS端",
"cn_channel": "国服-渠道服",
"en": "国际服",
"en_channel": "国际服-渠道服"
"ServerName": {
"name": "游戏内服务器",
"help": "选择游戏内所在的服务器以启用服务器状态检测\n当服务器维护或网络不可用时挂起直到恢复",
"disabled": "disabled",
"cn_android-0": "莱茵演习",
"cn_android-1": "巴巴罗萨",
"cn_android-2": "霸王行动",
"cn_android-3": "冰山行动",
"cn_android-4": "彩虹计划",
"cn_android-5": "发电机计划",
"cn_android-6": "瞭望台行动",
"cn_android-7": "十字路口行动",
"cn_android-8": "朱诺行动",
"cn_android-9": "杜立特空袭",
"cn_android-10": "地狱犬行动",
"cn_android-11": "开罗宣言",
"cn_android-12": "奥林匹克行动",
"cn_android-13": "小王冠行动",
"cn_android-14": "波茨坦公告",
"cn_android-15": "白色方案",
"cn_android-16": "瓦尔基里行动",
"cn_android-17": "曼哈顿计划",
"cn_android-18": "八月风暴",
"cn_android-19": "秋季旅行",
"cn_android-20": "水星行动",
"cn_android-21": "莱茵河卫兵",
"cn_ios-0": "夏威夷",
"cn_ios-1": "珊瑚海",
"cn_ios-2": "中途岛",
"cn_ios-3": "铁底湾",
"cn_ios-4": "所罗门",
"cn_ios-5": "马里亚纳",
"cn_ios-6": "莱特湾",
"cn_ios-7": "硫磺岛",
"cn_ios-8": "冲绳岛",
"cn_ios-9": "阿留申群岛",
"cn_ios-10": "马耳他",
"cn_channel-0": "皇家巡游",
"cn_channel-1": "大西洋宪章",
"cn_channel-2": "十字军行动",
"cn_channel-3": "龙骑兵行动",
"en-0": "Avrora",
"en-1": "Lexington",
"en-2": "Sandy",
"en-3": "Washington",
"en-4": "Amagi"
},
"ScreenshotMethod": {
"name": "模拟器截图方案",

View File

@ -299,9 +299,56 @@
"com.yiwu.blhx.yx15": "國服 com.yiwu.blhx.yx15",
"com.hkmanjuu.azurlane.gp.mc": "台服 MyCard渠道服 com.hkmanjuu.azurlane.gp.mc"
},
"ServerName": {
"name": "遊戲内伺服器",
"help": "選擇遊戲內所在的伺服器以啓用伺服器狀態檢測\n當伺服器維護或網路不可用時挂起直到恢複",
"disabled": "disabled",
"cn_android-0": "莱茵演习",
"cn_android-1": "巴巴罗萨",
"cn_android-2": "霸王行动",
"cn_android-3": "冰山行动",
"cn_android-4": "彩虹计划",
"cn_android-5": "发电机计划",
"cn_android-6": "瞭望台行动",
"cn_android-7": "十字路口行动",
"cn_android-8": "朱诺行动",
"cn_android-9": "杜立特空袭",
"cn_android-10": "地狱犬行动",
"cn_android-11": "开罗宣言",
"cn_android-12": "奥林匹克行动",
"cn_android-13": "小王冠行动",
"cn_android-14": "波茨坦公告",
"cn_android-15": "白色方案",
"cn_android-16": "瓦尔基里行动",
"cn_android-17": "曼哈顿计划",
"cn_android-18": "八月风暴",
"cn_android-19": "秋季旅行",
"cn_android-20": "水星行动",
"cn_android-21": "莱茵河卫兵",
"cn_ios-0": "夏威夷",
"cn_ios-1": "珊瑚海",
"cn_ios-2": "中途岛",
"cn_ios-3": "铁底湾",
"cn_ios-4": "所罗门",
"cn_ios-5": "马里亚纳",
"cn_ios-6": "莱特湾",
"cn_ios-7": "硫磺岛",
"cn_ios-8": "冲绳岛",
"cn_ios-9": "阿留申群岛",
"cn_ios-10": "马耳他",
"cn_channel-0": "皇家巡游",
"cn_channel-1": "大西洋宪章",
"cn_channel-2": "十字军行动",
"cn_channel-3": "龙骑兵行动",
"en-0": "Avrora",
"en-1": "Lexington",
"en-2": "Sandy",
"en-3": "Washington",
"en-4": "Amagi"
},
"ServerPlatform": {
"name": "伺服器平台",
"help": "選擇伺服器平台以啓用伺服器狀態檢測\n當伺服器維護或網路不可用時挂起直到恢複",
"help": "",
"disabled": "不使用",
"cn_android": "國服-安卓端",
"cn_ios": "國服-IOS端",

View File

@ -32,6 +32,25 @@ VALID_CHANNEL_PACKAGE = {
# Tw
'com.hkmanjuu.azurlane.gp.mc': ('tw', 'MyCard'),
}
VALID_SERVER_LIST = {
'cn_android': [
'莱茵演习', '巴巴罗萨', '霸王行动', '冰山行动', '彩虹计划',
'发电机计划', '瞭望台行动', '十字路口行动', '朱诺行动',
'杜立特空袭', '地狱犬行动', '开罗宣言', '奥林匹克行动',
'小王冠行动', '波茨坦公告', '白色方案', '瓦尔基里行动',
'曼哈顿计划', '八月风暴', '秋季旅行', '水星行动', '莱茵河卫兵'
],
'cn_ios': [
'夏威夷', '珊瑚海', '中途岛', '铁底湾', '所罗门', '马里亚纳',
'莱特湾', '硫磺岛', '冲绳岛', '阿留申群岛', '马耳他'
],
'cn_channel': [
'皇家巡游', '大西洋宪章', '十字军行动', '龙骑兵行动'
],
'en': [
'Avrora', 'Lexington', 'Sandy', 'Washington', 'Amagi'
]
}
def set_server(package_or_server: str):

View File

@ -1,39 +1,36 @@
import random
from collections import deque
from json import JSONDecodeError
import requests
from module.base.timer import Timer
from module.config.server import VALID_SERVER_LIST as server_list
from module.exception import ScriptError
from module.logger import logger
class ServerChecker:
def __init__(self, server: str) -> None:
self._base: dict = {
'cn_android': '',
'cn_ios': '',
'cn_channel': '',
'en': '',
'en_channel': '',
'disabled': ''
self._base: str = 'http://43.132.174.132:20002'
self._api: dict = {
'get_state': '/server/get_state', # post
'get_all_state': '/server/get_all_state', # post
'list': '/server/list' # get
}
self._UA: list = [
'Dalvik/2.1.0 (Linux; U; Android 6.0.1; MuMu Build/V417IR)',
]
if server not in self._base:
logger.warning(f'Unsupported server platform "{server}" for server checker.')
logger.warning('Disable server checker by default.')
server = 'disabled'
if server != 'disabled':
server = server.split('-')
server = server_list[server[0]][int(server[-1])]
self._server: str = server
self._state: deque = deque(maxlen=2)
self._reason: str = ''
self._interval: int = 0
self._timer: Timer = Timer(60 * 5) # check per 5 mins
self._timestamp: int = 0
self._expired: int = 0
self._timer: Timer = Timer(0)
# Status flags
self._recover: bool = False
self._maintained: bool = False
self.check_now()
@ -49,41 +46,46 @@ class ServerChecker:
return
try:
resp = requests.get(
# the last '?' will be escaped if use params, don't do so
url=f'{self._base[self._server]}?cmd=load_server?',
headers={
'User-Agent': f'{random.choice(self._UA)}',
'Accept-Encoding': 'gzip',
'Accept': '*/*',
'Connection': 'Keep-Alive',
'X-Unity-Version': '2018.4.34f1',
'Host': f'{self._base[self._server]}'
resp = requests.post(
url=f'{self._base}{self._api["get_state"]}',
params={
'server_name': self._server
},
timeout=3,
timeout=15
)
if resp.ok:
if resp.status_code == 200:
j = resp.json()
server_state = sum([1 if server['state'] == 1 else 0 for server in j])
if server_state / len(j) > 0.5:
self._reason = f'The server "{self._server}" is being maintained. Please wait'
self._state.append(False)
else:
if j['state'] != 1:
self._state.append(True)
else:
self._reason = f'Server "{self._server}" return status code {resp.status_code}'
logger.info(f'Server "{self._server}" is available.')
else:
self._state.append(False)
self._maintained = True
logger.info(f'Server "{self._server}" is under maintenance.')
# Check if API server was died
if j['last_update'] > self._timestamp:
self._timestamp = j['last_update']
self._expired = 0
else:
self._expired += 1
if self._expired > 3:
logger.info(f'Last update timestamp = {self._timestamp}')
raise ScriptError('Timestamp has not been updated for 3 times.')
elif resp.status_code == 404:
self._state.append(False)
raise ScriptError(self._reason)
raise ScriptError(f'Server "{self._server}" does not exist!')
else:
raise ScriptError(f'Get status_code {resp.status_code}. Response is {resp.text}')
except (requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout):
self._reason = 'Unable to connect to the server. Please check your network status'
logger.warning('Unable to connect to the server. Please check your network status.')
self._state.append(False)
except JSONDecodeError:
self._reason = f'Response of "{self._server}" seems not to be a JSON'
self._state.append(False)
raise ScriptError(self._reason)
raise ScriptError(f'Response "{resp.text}" seems not to be a JSON.')
except Exception as e:
self._reason = str(e)
self._state.append(False)
raise e
def wait_until_available(self) -> None:
while not self.is_available():
@ -94,36 +96,41 @@ class ServerChecker:
"""
Ignore timer and get server status immediately.
If server is available, timer will be set to 30 mins.
Otherwise, timer will gradually increases from 1 to 5 min(s).
If server is available, server checker will keep silence.
Otherwise, timer will gradually increases from 2 to 10 min(s).
If a ScriptError occurs, server checker will be temporarily forced off.
"""
try:
self._load_server()
if self._state[-1]:
self._interval = 0
self._timer.limit = 0
# Recover means state[-1] is True and state[0] is False
if not self._state[0]:
self._recover = True
else:
if self._interval < 5:
self._interval += 1
# Only show reason when server is unavailable.
if not self._state[-1]:
if "Unable" in self._reason:
logger.warning(f'{self._reason}. Server checker will retry after {self._interval} mins')
else:
logger.info(f'{self._reason}. Server checker will retry after {self._interval} mins')
except ScriptError as e:
logger.critical(e)
logger.warning('There may be something wrong with server checker.')
logger.warning('Server checker will be temporarily forced off.')
self._server = 'disabled'
self._interval = 0
self._state.clear()
self._state.append(True)
finally:
self._timer.limit = 60 * (30 if self._interval == 0 else self._interval)
if self._timer.limit < 600:
self._timer.limit += 120
logger.info(f'Server checker will retry after {self._timer.limit}s')
self._timer.reset()
except ScriptError as e:
logger.warning(str(e))
logger.warning('There may be something wrong with server checker.')
logger.warning('Please contact the developer to fix it.')
logger.warning('Server checker will be temporarily forced off.')
self.reset()
self._server = 'disabled'
self._recover = True
self._state.append(True)
except Exception as e:
raise e
def reset(self) -> None:
self._timestamp = 0
self._expired = 0
self._timer.limit = 0
self._recover = False
self._maintained = False
def is_available(self) -> bool:
"""
@ -132,7 +139,7 @@ class ServerChecker:
Returns:
bool: True if server is available.
"""
if self._interval != 0 and self._timer.reached():
if self._timer.limit != 0 and self._timer.reached():
self.check_now()
return self._state[-1] # return the latest state
@ -145,23 +152,19 @@ class ServerChecker:
if len(self._state) < 2:
return False
return self._state[0] is False and self._state[-1] is True
if self._recover:
self._recover = False
return True
def is_after_maintenance(self) -> bool:
return False
def is_maintenance_over(self) -> bool:
"""
Reason will only be updated when server is unavailable
Thus, client need to reesart when server recovers
with keyword 'maintained' in self._reason
Returns:
bool: True if server is after maintenance.
bool: True if server maintenance is over.
"""
if self._server == 'disabled':
return False
if not self._state[-1]:
return False
if self._maintained:
self._maintained = False
return True
return 'maintained' in self._reason
def is_enabled(self) -> bool:
return self._server != 'disabled'
return False