plugin_repo/generate_pluginmaster.py

119 lines
3.3 KiB
Python

import yaml
import json
import os
from datetime import datetime
from time import time
from sys import argv
from os.path import getmtime
from zipfile import ZipFile, ZIP_DEFLATED
DEFAULTS = {
'IsHide': False,
'IsTestingExclusive': False,
'ApplicableVersion': 'any',
}
DUPLICATES = {
'DownloadLinkInstall': ['DownloadLinkTesting', 'DownloadLinkUpdate'],
}
TRIMMED_KEYS = [
'Author',
'Name',
'Description',
'InternalName',
'AssemblyVersion',
'RepoUrl',
'ApplicableVersion',
'Tags',
'DalamudApiLevel',
'Punchline',
'IconUrl',
'ImageUrls',
]
def main():
plugins_dir = argv[1] if len(argv) > 1 else 'plugins'
master_name = 'pluginmaster.json' if plugins_dir == 'plugins' else f'{plugins_dir}.json'
info = {
'plugins_dir': plugins_dir,
'master_name': master_name,
}
# extract the manifests from inside the zip files
master = extract_manifests(info)
# trim the manifests
master = [trim_manifest(manifest) for manifest in master]
# convert the list of manifests into a master list
add_extra_fields(info, master)
# write the master
write_master(info, master)
# update the LastUpdate field in master
last_update(info)
def extract_manifests(info):
manifests = []
for dirpath, dirnames, filenames in os.walk(f'./{info["plugins_dir"]}'):
if len(filenames) == 0 or 'latest.zip' not in filenames:
continue
plugin_name = dirpath.split('/')[-1]
latest_zip = f'{dirpath}/latest.zip'
with ZipFile(latest_zip) as z:
manifest = json.loads(z.read(f'{plugin_name}.json').decode('utf-8'))
manifests.append(manifest)
return manifests
def add_extra_fields(info, manifests):
for manifest in manifests:
# generate the download link from the internal assembly name
manifest['DownloadLinkInstall'] = f'https://git.anna.lgbt/anna/plugin_repo/raw/branch/main/{info["plugins_dir"]}/{manifest["InternalName"]}/latest.zip'
# add default values if missing
for k, v in DEFAULTS.items():
if k not in manifest:
manifest[k] = v
# duplicate keys as specified in DUPLICATES
for source, keys in DUPLICATES.items():
for k in keys:
if k not in manifest:
manifest[k] = manifest[source]
def write_master(info, master):
# write as pretty json
with open(info['master_name'], 'w') as f:
json.dump(master, f, indent=4)
def trim_manifest(plugin):
return {k: plugin[k] for k in TRIMMED_KEYS if k in plugin}
def last_update(info):
with open(info['master_name']) as f:
master = json.load(f)
for plugin in master:
latest = f'{info["plugins_dir"]}/{plugin["InternalName"]}/latest.zip'
modified = 0
with ZipFile(latest) as z:
for zip_info in z.infolist():
info_mod = datetime(*zip_info.date_time).timestamp()
if info_mod > modified:
modified = int(info_mod)
if modified == 0:
modified = int(getmtime(latest))
if 'LastUpdate' not in plugin or modified != int(plugin['LastUpdate']):
plugin['LastUpdate'] = str(modified)
with open(info['master_name'], 'w') as f:
json.dump(master, f, indent=4)
if __name__ == '__main__':
main()