Open FriendsOfGalaxy opened 4 years ago
I've wrote a quick parser for you. And I will pass to current achievements definition to GOG myself.
It will be useful next time if there will be more new achievements. Ideally this could be deployed on some server like Mixail has done for GW2 but as far as I know GOG still utilize it manually from time to time (or from request to request...)
import requests
import time
import json
GAME_ID = 'final_fantasy_xiv_shadowbringers' # gameId is used in the plugin
XIVAPI_URL = 'https://xivapi.com'
SKIP_DESCR_WORDS = ['<Emphasis>', '</Emphasis>']
START_FROM = 1
def get_json(url):
print('getting', url)
r = requests.get(url)
print(r.status_code)
if r.status_code == 429: # to many requests
time.sleep(60)
return get_json(url)
return r.json()
def parse_description(descr: str):
for w in SKIP_DESCR_WORDS:
descr.replace(w, '')
return descr
def parse_achievement(info: dict, details: dict):
assert info['Name']
assert info['ID']
return {
"name": info['Name'],
"description": parse_description(details['Description']), # Galaxy has no localization so far
"api_key": str(info['ID']),
"image_url_unlocked": XIVAPI_URL + info['Icon'],
"image_url_locked": "" # use default Galaxy icon
}
if __name__ == "__main__":
achievements = []
# check number of pages
base = get_json(XIVAPI_URL + '/Achievement')
page_total = base['Pagination']['PageTotal']
for i in range(START_FROM, page_total + 1):
result = get_json(XIVAPI_URL + f'/Achievement?page={i}')
for info in result['Results']:
details = get_json(XIVAPI_URL + info['Url'])
try:
achievements.append(parse_achievement(info, details))
except AssertionError: # not valid/empty achievement
print(f'invalid achievement: {info}. Skipping')
time.sleep(0.1) # avoid API limits
with open('achievements_data.json', 'w') as f:
data = {
"release_per_platform_id": f"ffxiv_{GAME_ID}",
"achievements": achievements
}
json.dump(data, f, indent=4)
It should also be noted that XIVAPI maintains this data in a CSV format in xivapi/ffxiv-datamining, so you could also possibly watch the achievement.csv file for changes and parse it to Galaxy's JSON format, if that works better?
I didn't know about this project. Yes, this is basically the same data.
OK, I plugged this together based on the above code during 5.21 maintenance, which added and changed a few achievements. If you feed it an achievement.csv
file from the datamining repository, it will produce a JSON file with the achievement data for Galaxy.
import csv
import json
from itertools import islice
import urllib.request
import codecs
GAME_ID = 'final_fantasy_xiv_shadowbringers' # gameId is used in the plugin
XIVAPI_URL = 'https://xivapi.com'
def parse_achievement(id, name, description, icon):
assert id
assert name
return {
'name': name,
'description': description,
'api_key': str(id),
'image_url_unlocked': get_icon_url(icon) if icon else '',
'image_url_locked': ''
}
def get_icon_url(icon):
# XIVAPI folder structure details: https://xivapi.com/docs/Icons
if len(icon) >= 6:
icon = str.rjust(icon, 5, "0")
else:
icon = f'0{str.rjust(icon, 5, "0")}'
if len(icon) >= 6:
folder = f'{icon[0]}{icon[1]}{icon[2]}000'
else:
folder = f'0{icon[1]}{icon[2]}000'
return f'{XIVAPI_URL}/i/{folder}/{icon}.png'
if __name__ == '__main__':
achievements = []
url = 'https://raw.githubusercontent.com/xivapi/ffxiv-datamining/master/csv/Achievement.csv'
stream = urllib.request.urlopen(url)
csvdata = codecs.iterdecode(stream, 'utf-8')
# We don't care about the first line in the file, skip it
next(csvdata)
reader = csv.DictReader(csvdata)
# We also don't care about the 3rd line in the file, which deals with datatypes
next(reader)
for line in reader:
try:
achievements.append(parse_achievement(line['#'], line['Name'], line['Description'], line['Icon']))
except AssertionError:
pass
with open('achievement_data.json', 'w', encoding='utf-8') as j:
data = {
'release_per_platform_id': f'ffxiv_{GAME_ID}',
'achievements': achievements
}
json.dump(data, j, indent=4)
@UmbyUmbreon
I've run both and compared results. Those changes are:
\r\n
windows eol from API vs \n\n
from csvhttps://xivapi.com/i/000000/000000.png
,
; your code gives https://xivapi.com
. Both should gives empty string, or even better: None.To sum up direct call to API lasts longer, but is more reliable. csv may be outdated. Icon should be probably None instead of empty transparent 40x40 png in https://xivapi.com/i/000000/000000.png
@FriendsOfGalaxy, I haven't given the code a look but the README states that achievement support is waiting on "platform support" which I assume means GOG needs to achievement definitions. Has there been any progress in that regard?
@FriendsOfGalaxy, I haven't given the code a look but the README states that achievement support is waiting on "platform support" which I assume means GOG needs to achievement definitions. Has there been any progress in that regard?
Honestly since the plugin did not even add Endwalker yet, there will probably be a bunch of problems with Achievement integration anyway? But yes im curious as well.
Hey, it would be cool to add real achievement support. See this similar topic for details: https://github.com/Mixaill/galaxy-integration-gw2/issues/4#issuecomment-541588150