11import json
2+ import os .path
23
34import aiohttp
45from aiocache import cached
@@ -22,12 +23,12 @@ class Enka:
2223 _URL = "https://enka.network/u/{uid}/__data.json"
2324 # https://github.com/theBowja/GenshinData-1
2425 # https://raw.githubusercontent.com/GrownNed/Homework/master
25- _REPO_BASE = 'https://gitlab.com/Dimbreath/gamedata/-/raw/main/ '
26- _LANG_URL = _REPO_BASE + '/TextMap/TextMap{lang}.json'
27- _AVATAR_URL = _REPO_BASE + '/ExcelBinOutput/AvatarExcelConfigData.json'
28- _TALENT_URL = _REPO_BASE + '/ExcelBinOutput/AvatarTalentExcelConfigData.json'
29- _SKILL_DEPOT_URL = _REPO_BASE + '/ExcelBinOutput/AvatarSkillDepotExcelConfigData.json'
30- _SKILL_URL = _REPO_BASE + '/ExcelBinOutput/AvatarSkillExcelConfigData.json'
26+ _REPO_BASE = 'https://gitlab.com/Dimbreath/gamedata/-/raw/main'
27+ _LANG_URL = _REPO_BASE + '/TextMap/TextMap{lang}.json?inline=false '
28+ _AVATAR_URL = _REPO_BASE + '/ExcelBinOutput/AvatarExcelConfigData.json?inline=false '
29+ _TALENT_URL = _REPO_BASE + '/ExcelBinOutput/AvatarTalentExcelConfigData.json?inline=false '
30+ _SKILL_DEPOT_URL = _REPO_BASE + '/ExcelBinOutput/AvatarSkillDepotExcelConfigData.json?inline=false '
31+ _SKILL_URL = _REPO_BASE + '/ExcelBinOutput/AvatarSkillExcelConfigData.json?inline=false '
3132 USER_AGENT = "Mozilla/5.0"
3233 timeout = 30
3334 """Http connection timeout"""
@@ -45,32 +46,120 @@ class Enka:
4546 """Internal skill data"""
4647 lang = 'en'
4748 """Language for text hash resolve"""
49+ _cache = 'cache'
50+ """Cache folder name"""
4851
49- async def load_lang (self , lang = 'en' ):
52+ def _cache_exists (self , name ):
5053 """
51- Load language data from Dimbreath repo
54+ Check if cache file exists and return full cache file path
55+ :param name: cache name
56+ :return: full cache file path
57+ """
58+ package_path = os .path .dirname (os .path .realpath (__file__ ))
59+ cache_path = os .path .join (package_path , self ._cache )
60+ cache_file_path = os .path .join (cache_path , name )
61+
62+ if not os .path .exists (cache_path ):
63+ try :
64+ os .mkdir (cache_path )
65+ except OSError :
66+ pass
67+ return ''
68+ if not os .path .isdir (cache_path ):
69+ try :
70+ os .remove (cache_path )
71+ except OSError :
72+ pass
73+ return ''
74+ if os .path .exists (cache_file_path ):
75+ return cache_file_path
76+ else :
77+ return ''
78+
79+ async def _process_cache (self , client : aiohttp .ClientSession , url , cache_file , force_cache = False ,
80+ force_update = False ):
81+ """
82+ Process cache
83+ :param client: aiohttp client
84+ :param url: git url
85+ :param cache_file: cache file name
86+ :param force_cache: ignore git update, force using cache file
87+ :param force_update: force update from git repo
88+ :return: cache file path
89+ """
90+ cache_file_path = self ._cache_exists (cache_file )
91+ if cache_file_path and not force_update :
92+ stat = os .stat (cache_file_path )
93+ file_size = stat .st_size
94+ if not force_cache :
95+ resp = await client .head (url , proxy = self .proxy )
96+ cl = int (resp .headers ['Content-Length' ])
97+ if cl != file_size :
98+ resp = await client .get (url , proxy = self .proxy )
99+ with open (cache_file_path , 'wb' ) as f :
100+ f .write (await resp .read ())
101+ else :
102+ package_path = os .path .dirname (os .path .realpath (__file__ ))
103+ cache_path = os .path .join (package_path , self ._cache )
104+ cache_file_path = os .path .join (cache_path , cache_file )
105+ resp = await client .get (url , proxy = self .proxy )
106+ with open (cache_file_path , 'wb' ) as f :
107+ f .write (await resp .read ())
108+ return cache_file_path
109+
110+ async def load_lang (self , lang = 'en' , force_cache = False , force_update = False ):
111+ """
112+ Load language data from cache or Dimbreath repo
52113 :param lang: language you want to load, default 'en'
114+ :param force_cache: Do not check repo update if cache file exists
115+ :param force_update: force update from git repo
53116 """
117+
54118 async with aiohttp .ClientSession (headers = {"User-Agent" : self .USER_AGENT }) as client :
55119 if lang not in self ._lang_data :
56- resp = await client .get (self ._LANG_URL .format (lang = lang .upper ()), proxy = self .proxy )
57- self ._lang_data [lang ] = await resp .json (content_type = None )
120+ cache_file_path = await self ._process_cache (client ,
121+ self ._LANG_URL .format (lang = lang .upper ()),
122+ 'lang.json' ,
123+ force_cache ,
124+ force_update )
125+ with open (cache_file_path , 'rb' ) as f :
126+ self ._lang_data [lang ] = json .load (f )
58127 if not self ._avatar_data :
59- resp = await client .get (self ._AVATAR_URL , proxy = self .proxy )
60- for x in await resp .json (content_type = None ):
61- self ._avatar_data [x ['id' ]] = x
128+ cache_file_path = await self ._process_cache (client ,
129+ self ._AVATAR_URL ,
130+ 'avatar.json' ,
131+ force_cache ,
132+ force_update )
133+ with open (cache_file_path , 'rb' ) as f :
134+ for x in json .load (f ):
135+ self ._avatar_data [x ['id' ]] = x
62136 if not self ._skill_depot_data :
63- resp = await client .get (self ._SKILL_DEPOT_URL , proxy = self .proxy )
64- for x in await resp .json (content_type = None ):
65- self ._skill_depot_data [x ['id' ]] = x
137+ cache_file_path = await self ._process_cache (client ,
138+ self ._SKILL_DEPOT_URL ,
139+ 'skill_depot.json' ,
140+ force_cache ,
141+ force_update )
142+ with open (cache_file_path , 'rb' ) as f :
143+ for x in json .load (f ):
144+ self ._skill_depot_data [x ['id' ]] = x
66145 if not self ._skill_data :
67- resp = await client .get (self ._SKILL_URL , proxy = self .proxy )
68- for x in await resp .json (content_type = None ):
69- self ._skill_data [x ['id' ]] = x
146+ cache_file_path = await self ._process_cache (client ,
147+ self ._SKILL_URL ,
148+ 'skill.json' ,
149+ force_cache ,
150+ force_update )
151+ with open (cache_file_path , 'rb' ) as f :
152+ for x in json .load (f ):
153+ self ._skill_data [x ['id' ]] = x
70154 if not self ._talent_data :
71- resp = await client .get (self ._TALENT_URL , proxy = self .proxy )
72- for x in await resp .json (content_type = None ):
73- self ._talent_data [x ['talentId' ]] = x
155+ cache_file_path = await self ._process_cache (client ,
156+ self ._TALENT_URL ,
157+ 'talent.json' ,
158+ force_cache ,
159+ force_update )
160+ with open (cache_file_path , 'rb' ) as f :
161+ for x in json .load (f ):
162+ self ._talent_data [x ['talentId' ]] = x
74163
75164 async def resolve_text_hash (self , text_hash , lang = 'en' ):
76165 """
@@ -121,14 +210,15 @@ async def fetch_user(self, uid: int) -> EnkaData:
121210 for character in obj .characters :
122211 if character .skill_depot_id in self ._skill_depot_data :
123212 depot = self ._skill_depot_data [character .skill_depot_id ]
124- burst_id = depot ['energySkill' ]
125- if burst_id in self ._skill_data :
126- cs = CharacterSkill ()
127- cs .id = burst_id
128- cs .type = CharacterSkillType .ElementalBurst
129- cs .name_hash = self ._skill_data [burst_id ]['nameTextMapHash' ]
130- cs .icon = self ._skill_data [burst_id ]['skillIcon' ]
131- character .skills .append (cs )
213+ if 'energySkill' in depot :
214+ burst_id = depot ['energySkill' ]
215+ if burst_id in self ._skill_data :
216+ cs = CharacterSkill ()
217+ cs .id = burst_id
218+ cs .type = CharacterSkillType .ElementalBurst
219+ cs .name_hash = self ._skill_data [burst_id ]['nameTextMapHash' ]
220+ cs .icon = self ._skill_data [burst_id ]['skillIcon' ]
221+ character .skills .append (cs )
132222 for skill_id in depot ['skills' ]:
133223 if skill_id and skill_id in self ._skill_data :
134224 skill_info = self ._skill_data [skill_id ]
0 commit comments