Skip to content

Commit

Permalink
重构大乱斗 BUFF 以及英雄别名资源获取,使其可以进行异常处理 (#401)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zzaphkiel committed Jun 30, 2024
1 parent ee11a47 commit 9129817
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 128 deletions.
7 changes: 2 additions & 5 deletions app/components/profile_level_icon_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from PyQt5.QtWidgets import (QWidget, QApplication, QMainWindow, QHBoxLayout,
QLabel, QVBoxLayout, QGridLayout, QFrame, QGraphicsDropShadowEffect)

from app.lol.aram import AramHome
from app.lol.aram import AramBuff
from app.common.qfluentwidgets import (ProgressRing, ToolTipFilter, ToolTipPosition, isDarkTheme,
themeColor, FlyoutViewBase, TextWrap, FlyoutAnimationType)
from app.components.color_label import ColorLabel
Expand Down Expand Up @@ -85,9 +85,6 @@ def __init__(self,
self.mFlyout = None
self.aramInfo = aramInfo

# Note 如果你希望测试大乱斗的数据弹框, 参考这个 -- By Hpero4
# self.aramInfo = AramHome.getInfoByChampionId("75")

def paintEvent(self, event):
if self.paintXpSinceLastLevel != self.xpSinceLastLevel or self.paintXpUntilNextLevel != self.xpUntilNextLevel or self.callUpdate:
self.progressRing.setVal(self.xpSinceLastLevel * 100 //
Expand Down Expand Up @@ -139,7 +136,7 @@ def updateIcon(self, icon: str, xpSinceLastLevel=None, xpUntilNextLevel=None, te
def updateAramInfo(self, info):
self.aramInfo = info

if not self.mFlyout:
if not self.mFlyout or not info:
return

self.mFlyout.updateInfo(info)
Expand Down
167 changes: 66 additions & 101 deletions app/lol/aram.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,149 +3,114 @@
import re
from functools import lru_cache, wraps

import requests
import aiohttp

from app.common.config import cfg, LOCAL_PATH
from app.common.logger import logger
from app.common.util import getLolClientVersion


class AramHome:
class AramBuff:
"""
#### 数据使用已获得授权
Powered by: 大乱斗之家
Site: http://www.jddld.com
"""
ARAM_CFG_PATH = f"{LOCAL_PATH}/AramBuff.json"
URL = "http://www.jddld.com"
TAG = "AramHome"
TAG = "AramBuff"
APPID = 1
APP_SECRET = "PHPCMFBBC77AF8E8FA5"
data = None

@staticmethod
def needData(func):
"""
TODO 如何优雅地使用它? -- By Hpero4
"""
@wraps(func)
def wrapper(*args, **kwargs):
if AramHome.data is None:
m = AramHome()
m.__loadData()
return func(*args, **kwargs)

return wrapper

@classmethod
async def checkAndUpdate(cls):
m = cls()
if m.__checkUpdate():
if m.__needUpdate():
await m.__update()

@classmethod
def getInfoByChampionId(cls, championId: str):
return cls.getInfoByField("heroid", championId)

@classmethod
def getInfoByChampionName(cls, name: str):
return cls.getInfoByField("name", name)
def __needUpdate(self):
"""
检查缓存的数据与当前版本是否匹配, 若不匹配尝试更新
@classmethod
def getInfoByCatName(cls, name: str):
return cls.getInfoByField("catname", name)
尽可能在游戏启动后再调用, 否则当存在多个客户端时, `cfg.lolFolder` 不一定是准确的
(外服国服可能版本不同)
@classmethod
def getInfoByCatNameLoose(cls, name: str):
return cls.getInfoByFieldLoose("catname", name)
@return :
- `True` -> 需要更新
- `False` -> 无需更新
@classmethod
# @needData
@lru_cache(maxsize=None)
def getInfoByField(cls, field: str, val: str):
TODO: 暂未提供历史版本数据查询接口
"""
通过字段值匹配一个item
try:
lolVersion = getLolClientVersion()
except:
return True

找不到返回 None
"""
if cls.data is None:
m = cls()
m.__loadData()
for item in cls.data.values():
if item[field] == val:
return item
return None
if not os.path.exists(self.ARAM_CFG_PATH):
return True

@classmethod
# @needData
@lru_cache(maxsize=None)
def getInfoByFieldLoose(cls, field: str, val: str):
"""
通过字段值匹配一个item
with open(self.ARAM_CFG_PATH, 'r') as f:
try:
AramBuff.data = json.loads(f.read())
except:
return True

宽松匹配, 只要val在field内都认为找到
return AramBuff.getDataVersion() != lolVersion

找不到返回 None
"""
if cls.data is None:
m = cls()
m.__loadData()
for item in cls.data.values():
if val in item[field]:
return item
return None

def __loadData(self):
with open(self.ARAM_CFG_PATH, 'r') as f:
AramHome.data = json.loads(f.read())
@classmethod
def getDataVersion(cls):
return AramBuff.data.get("version")

async def __update(self):
logger.info("update info", self.TAG)
url = f"{self.URL}/index.php"
url = f'{self.URL}/index.php'
params = {
'appid': self.APPID,
'appsecret': self.APP_SECRET,
's': 'news',
'c': 'search',
'api_call_function': 'module_list',
'pagesize': '200' # FIXME 超过200个英雄会拿不完 -- By Hpero4
'pagesize': '200'
}
data = requests.get(url, params=params, proxies=None,
verify=False).json() # 它不需要代理
if data.get("code") == 1:
with open(self.ARAM_CFG_PATH, "w") as f:
data = data.get("data")
json.dump(data, f)
AramHome.data = data
else:
logger.warning(f"update err: {data}", self.TAG)

def __checkUpdate(self):
"""
检查缓存的数据与当前版本是否匹配, 若不匹配尝试更新

尽可能在游戏启动后再调用, 否则当存在多个客户端时, cfg.lolFolder不一定是准确的(外服国服可能版本不同)
@return :
True -> 需要更新
False -> 无需更新
try:
async with aiohttp.ClientSession() as session:
res = await session.get(url, params=params, proxy=None, ssl=False)
data = await res.json()
except:
logger.warning(f"Getting Aram buff failed, data: {data}", self.TAG)
return

TODO: 暂未提供历史版本数据查询接口
"""
if data.get('code') != 1:
logger.warning(f"Update Aram buff failed, data: {data}", self.TAG)
return

try:
lolVersion = getLolClientVersion()
data: dict = data['data']

version = data.pop('banben')
champions = {item['heroid']: item for item in data.values()}

AramBuff.data = {
'champions': champions,
'version': version
}

with open(self.ARAM_CFG_PATH, 'w') as f:
json.dump(AramBuff.data, f)

except:
return True
logger.warning(f"Parse Aram buff failed, data: {data}", self.TAG)
return

@classmethod
def isAvailable(cls) -> bool:
return AramBuff.data != None

@classmethod
@lru_cache(maxsize=None)
def getInfoByChampionId(cls, championId):
if not AramBuff.isAvailable():
return None

# 检查一下版本号是否相同, 如果一样, 就不更新了
if os.path.exists(self.ARAM_CFG_PATH):
with open(self.ARAM_CFG_PATH, "r") as f:
data = json.loads(f.read())
AramHome.data = data
dataVer = re.search(
r"\d+\.\d+", data.get("banben", "")).group(0)
if dataVer and dataVer == lolVersion:
return False

return True
return AramBuff.data['champions'].get(str(championId))
23 changes: 19 additions & 4 deletions app/lol/champions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import re
from functools import lru_cache, wraps

import requests
import aiohttp

from app.common.config import cfg, LOCAL_PATH
from app.common.logger import logger
Expand All @@ -29,7 +29,15 @@ async def __update(self):
logger.info("Update champions alias", self.TAG)

try:
res = requests.get(self.URL).json()
async with aiohttp.ClientSession() as session:
res = await session.get(self.URL, proxy=None, ssl=False)

# 不知道为什么这样子不行:
# res = await res.json()

s = str(await res.read(), encoding='utf-8')
res = json.loads(s)

champions = {}

for champion in res['hero']:
Expand Down Expand Up @@ -61,9 +69,12 @@ def __needUpdate(self):
return True

with open(self.CHAMPION_CFG_PATH, 'r') as f:
ChampionAlias.data = json.loads(f.read())
try:
ChampionAlias.data = json.loads(f.read())
except:
return True

return ChampionAlias.data.get('version') != lolVersion
return ChampionAlias.getDataVersion() != lolVersion

@classmethod
def getChampionsAlias(cls) -> dict:
Expand All @@ -73,6 +84,10 @@ def getChampionsAlias(cls) -> dict:
def isAvailable(cls) -> bool:
return ChampionAlias.data != None

@classmethod
def getDataVersion(cls) -> str:
return ChampionAlias.data.get("version")

@classmethod
def getChampionIdsByAliasFuzzily(cls, alias):
data = ChampionAlias.getChampionsAlias()
Expand Down
8 changes: 4 additions & 4 deletions app/view/game_info_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from app.components.animation_frame import CardWidget, ColorAnimationFrame
from app.lol.tools import parseSummonerOrder
from app.lol.connector import connector
from app.lol.aram import AramHome
from app.lol.aram import AramBuff
from app.components.seraphine_interface import SeraphineInterface


Expand Down Expand Up @@ -132,7 +132,7 @@ async def updateAllyIcon(self, team):
view.updateIcon(icon)
if self.isAram:
view.updateAramInfo(
AramHome.getInfoByChampionId(str(newChampionId)))
AramBuff.getInfoByChampionId(newChampionId))

async def clear(self):
self.allyChampions = {}
Expand Down Expand Up @@ -280,8 +280,8 @@ def updateSummoners(self, summoners, isAram=False):
continue

if isAram and summoner["championId"]:
aramInfo = AramHome.getInfoByChampionId(
str(summoner["championId"]))
aramInfo = AramBuff.getInfoByChampionId(
summoner["championId"])
else:
aramInfo = None

Expand Down
12 changes: 7 additions & 5 deletions app/view/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
getAllyOrderByGameRole, getTeamColor, autoBan, autoPick, autoComplete,
autoSwap, autoTrade, autoSelectSkinRandom, ChampionSelection, SERVERS_NAME,
SERVERS_SUBSET)
from app.lol.aram import AramHome
from app.lol.aram import AramBuff
from app.lol.champions import ChampionAlias

import threading
Expand Down Expand Up @@ -473,7 +473,7 @@ async def __onLolClientStarted(self, pid):
self.auxiliaryFuncInterface.lockConfigCard.loadNowMode()

# 加载大乱斗buff -- By Hpero4
aramInitT = asyncio.create_task(AramHome.checkAndUpdate())
aramInitT = asyncio.create_task(AramBuff.checkAndUpdate())
championsInit = asyncio.create_task(ChampionAlias.checkAndUpdate())

# ---- 240413 ---- By Hpero4
Expand Down Expand Up @@ -502,10 +502,12 @@ async def __onLolClientStarted(self, pid):
# 这可能导致性能或是其他不可预期的问题, 这是只是一个例子;
# ---- 240413 ---- By Hpero4

t = self.__onGameStatusChanged(status)
self.__unlockInterface()
await asyncio.gather(aramInitT, championsInit)
await t
await asyncio.gather(championsInit, aramInitT)
await self.__onGameStatusChanged(status)

# Note 如果你希望测试大乱斗的数据弹框, 参考这个 -- By Hpero4
# self.careerInterface.icon.aramInfo = AramBuff.getInfoByChampionId(75)

async def __startConnector(self, pid):
try:
Expand Down
4 changes: 3 additions & 1 deletion app/view/search_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,9 @@ async def __loadGames(self, puuid):
endIdx = 29

# NOTE 换了查询目标, 若之前正在查, 先等 task 被 release 掉 -- By Hpero4
while self.gameLoadingTask and not self.gameLoadingTask.done() and puuid != self.puuid:
while self.gameLoadingTask \
and not self.gameLoadingTask.done() \
and puuid != self.puuid:
await asyncio.sleep(.2)

# 连续查多个人时, 将前面正在查的task给release掉
Expand Down
8 changes: 0 additions & 8 deletions app/view/setting_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,6 @@ def __init__(self, parent=None):
self.lolFolderCard.button.setStyleSheet(
"QPushButton {padding-left: 0; padding-right: 0;}")

self.gameStartMinimizeCard = SwitchSettingCard(
Icon.PAGE, self.tr("Minimize windows during game activities"),
self.tr(
"Reduce CPU usage for rendering UI during gaming"),
cfg.enableGameStartMinimize
)

self.logLevelCard = ComboBoxSettingCard(
cfg.logLevel,
Icon.LOG,
Expand Down Expand Up @@ -303,7 +296,6 @@ def __showUpdatedSuccessfullyToolTip(self):
parent=self)

def __onDeleteButtonClicked(self):

folders = [
'champion icons', 'item icons', 'profile icons', 'rune icons',
'summoner spell icons'
Expand Down

0 comments on commit 9129817

Please sign in to comment.