2022-06-08 23:37:10 +00:00
from argparse import ArgumentParser
2022-06-19 19:18:59 +00:00
from io import BytesIO
from packaging import version
from pathlib import Path
2022-06-08 23:37:10 +00:00
from pathlib import Path
from platform import system
2022-06-19 19:18:59 +00:00
from shutil import rmtree , copytree
from tempfile import TemporaryDirectory
2023-07-15 21:46:26 +00:00
from typing import Tuple
2022-06-08 23:37:10 +00:00
from zipfile import ZipFile
import logging
import re
2022-06-19 19:18:59 +00:00
import requests
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
config_template = """ https://www.esoui.com/downloads/info7-LibAddonMenu.html
https : / / www . esoui . com / downloads / info1245 - TamrielTradeCentre . html
https : / / www . esoui . com / downloads / info1146 - LibCustomMenu . html
"""
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
def config_new ( path : Path ) :
path . touch ( exist_ok = True )
with path . open ( " w " ) as file_open :
file_open . write ( config_template )
2022-06-08 23:37:10 +00:00
def live_to_esoui ( * , path : Path , esoui_uris : list ) :
2022-06-19 19:18:59 +00:00
live_name , live_version , live_path = parsing_live ( path )
2022-06-08 23:37:10 +00:00
if not live_path :
return
esoui_name , esoui_version , esoui_uri = None , None , None
for _name , _version , _uri in esoui_uris :
if _name in live_name :
esoui_name , esoui_version , esoui_uri = _name , _version , _uri
break
if live_name in _name :
esoui_name , esoui_version , esoui_uri = _name , _version , _uri
break
2023-07-15 21:46:26 +00:00
2022-06-08 23:37:10 +00:00
if not esoui_name :
rmtree ( live_path )
logging . info ( f " { live_name } addon removed from: { live_path } " )
return
if esoui_version == live_version :
logging . info ( f " { live_name } is already up to date. " )
return
2022-06-19 19:18:59 +00:00
response = requests . get ( esoui_uri )
response . raise_for_status ( )
2022-06-08 23:37:10 +00:00
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
2022-06-19 19:18:59 +00:00
zip_file = ZipFile ( BytesIO ( response . content ) )
2022-06-08 23:37:10 +00:00
zip_file . extractall ( temp_path )
rmtree ( live_path )
for each in temp_path . iterdir ( ) :
copytree ( each , live_path )
logging . info (
f " { live_name } updated from { live_version } to { esoui_version } at { live_path } "
)
def esoui_to_live ( * , esoui_uris : list , live_path : Path ) :
for addon_name , addon_version , esoui_dowload_uri in esoui_uris :
match = None
for each in live_path . iterdir ( ) :
if addon_name in each . name :
match = each
break
if each . name in addon_name :
match = each
break
if match :
logging . debug ( f " { addon_name } already installed. " )
continue
2022-06-19 19:18:59 +00:00
response = requests . get ( esoui_dowload_uri )
response . raise_for_status ( )
2022-06-08 23:37:10 +00:00
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
2022-06-19 19:18:59 +00:00
zip_file = ZipFile ( BytesIO ( response . content ) )
2022-06-08 23:37:10 +00:00
zip_file . extractall ( temp_path )
for each in temp_path . iterdir ( ) :
live_dest = live_path . joinpath ( each . name )
if live_dest . exists ( ) :
continue
copytree ( each , live_dest )
logging . info ( f " { addon_name } installed { addon_version } at { live_dest } " )
esoui_prefix = re . compile ( " https://www.esoui.com/downloads/info[0-9]+ \ - " )
esoui_version_html = re . compile ( ' <div \ s+id= " version " >Version: \ s+[^<]+ ' )
esoui_version_split = re . compile ( ' <div \ s+id= " version " >Version: \ s+ ' )
esoui_download = re . compile ( ' https://cdn.esoui.com/downloads/file[^ " ]* ' )
live_version = re . compile ( " ## \ s+Version: \ s+.* " )
live_version_split = re . compile ( " ## \ s+Version: \ s+ " )
2023-07-15 21:46:26 +00:00
def esoui_parse ( url : str ) - > Tuple [ str , version . Version , str ] :
2022-06-08 23:37:10 +00:00
addon_name = esoui_prefix . split ( url ) [ 1 ]
addon_name = addon_name . split ( " .html " ) [ 0 ]
2022-06-19 19:18:59 +00:00
response = requests . get ( url )
response . raise_for_status ( )
2022-06-09 00:08:53 +00:00
2022-06-19 19:18:59 +00:00
version_line = esoui_version_html . search ( response . text ) . group ( 0 )
_version = esoui_version_split . split ( version_line ) [ 1 ]
2023-07-15 21:46:26 +00:00
try :
_version = version . parse ( _version )
except version . InvalidVersion :
_version = version . parse ( " 1 " )
2022-06-08 23:37:10 +00:00
esoui_page_url = url . replace ( " info " , " download " ) . replace ( " .html " , " " )
2022-06-19 19:18:59 +00:00
response = requests . get ( esoui_page_url )
response . raise_for_status ( )
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
esoui_dowload_uri = esoui_download . search ( response . text ) . group ( 0 )
response = requests . head ( esoui_dowload_uri )
response . raise_for_status ( )
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
return addon_name , _version , esoui_dowload_uri
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
def parsing_live ( path : Path ) :
2022-06-08 23:37:10 +00:00
if not path . is_dir ( ) :
logging . error ( f " unexpected file object { path } , ignoring " )
return
meta_file = path . joinpath ( f " { path . stem } .txt " )
if not meta_file . exists ( ) :
for meta_file in path . glob ( " *.txt " ) :
if not meta_file . stem in path . stem :
continue
try :
with meta_file . open ( " r " ) as file_open :
meta_data = file_open . read ( )
except UnicodeDecodeError :
with meta_file . open ( " r " , encoding = " latin-1 " ) as file_open :
meta_data = file_open . read ( )
addon_name = meta_file . stem
result = live_version . search ( meta_data )
if result :
2022-06-19 19:18:59 +00:00
_version = result . group ( 0 )
_version = live_version_split . split ( _version ) [ 1 ]
2023-07-15 21:46:26 +00:00
try :
_version = version . parse ( _version )
except version . InvalidVersion :
_version = version . parse ( " 0 " )
2022-06-19 19:18:59 +00:00
else :
_version = version . parse ( " 0 " )
2022-06-08 23:37:10 +00:00
2022-06-19 19:18:59 +00:00
return addon_name , _version , path
2022-06-08 23:37:10 +00:00
2022-10-29 04:09:53 +00:00
def eso_live_path_get ( ) :
if system ( ) == " Windows " :
eso_live_path = Path . home ( ) . joinpath (
" Documents \ Elder Scrolls Online \ live "
)
if eso_live_path . exists :
return eso_live_path
else :
eso_live_path = Path . home ( ) . joinpath (
" .steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/ "
)
if eso_live_path . exists ( ) :
return eso_live_path
eso_live_path = Path . home ( ) . joinpath (
" .var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live "
)
if eso_live_path . exists ( ) :
return eso_live_path
raise Exception ( " Unable to find `steamuser/Documents/Elder Scrolls Online/live`, specify the full path and contact maintainer to see if they ' ll add it. " )
2022-06-08 23:37:10 +00:00
2023-07-15 22:00:50 +00:00
def unlisted_remove ( ) :
2022-06-08 23:37:10 +00:00
parser = ArgumentParser (
2022-06-19 19:18:59 +00:00
description = " Visit https://www.esoui.com/ to search for addons and their dependencies URLs. Edit addons.yaml in the ESO live path and add the URL for each addon for installation. "
2022-06-08 23:37:10 +00:00
)
parser . add_argument ( " -v " , " --verbose " , action = " count " , help = " verbose logging " )
parser . add_argument ( " -l " , " --log " , action = " store_true " )
parser . add_argument ( " -p " , " --eso_live_path " )
args = parser . parse_args ( )
if args . eso_live_path :
args . eso_live_path = Path ( args . eso_live_path )
else :
2022-10-29 04:09:53 +00:00
args . eso_live_path = eso_live_path_get ( )
2022-06-08 23:37:10 +00:00
if args . verbose :
level = logging . DEBUG
format = " %(asctime)s %(filename)s : %(lineno)d %(message)s "
else :
level = logging . INFO
format = " %(asctime)s %(message)s "
if args . log :
logging . basicConfig (
level = level ,
format = format ,
filename = args . eso_live_path . joinpath ( " banana.log " ) ,
)
else :
logging . basicConfig (
level = level ,
format = format ,
)
logging . info ( args )
2022-06-19 19:18:59 +00:00
2023-07-15 21:46:26 +00:00
config_path = Path ( args . eso_live_path ) . joinpath ( " addons.list " )
2022-06-08 23:37:10 +00:00
if not config_path . exists ( ) :
config_new ( config_path )
logging . info ( f ' addons list created at " { config_path } " ' )
with config_path . open ( " r " ) as file_open :
2022-06-19 19:18:59 +00:00
config_current = [ line . rstrip ( ' \n ' ) for line in file_open ]
2022-06-08 23:37:10 +00:00
config_current = filter ( None , config_current )
live_path = args . eso_live_path . joinpath ( " AddOns " )
live_path . mkdir ( parents = True , exist_ok = True )
esoui_uris = list ( )
for url in config_current :
esoui = esoui_parse ( url )
2023-07-15 21:46:26 +00:00
if esoui :
esoui_uris . append ( esoui )
2022-06-08 23:37:10 +00:00
for child in live_path . iterdir ( ) :
live_to_esoui ( path = child , esoui_uris = esoui_uris )
esoui_to_live ( esoui_uris = esoui_uris , live_path = live_path )
ttc_update ( live_path = live_path )
2023-07-15 22:00:50 +00:00
def periodical_script ( ) :
parser = ArgumentParser (
description = " Visit https://www.esoui.com/ to search for addons and their dependencies URLs. Edit addons.yaml in the ESO live path and add the URL for each addon for installation. "
)
parser . add_argument ( " -v " , " --verbose " , action = " count " , help = " verbose logging " )
parser . add_argument ( " -l " , " --log " , action = " store_true " )
parser . add_argument ( " -p " , " --eso_live_path " )
args = parser . parse_args ( )
if args . eso_live_path :
args . eso_live_path = Path ( args . eso_live_path )
else :
args . eso_live_path = eso_live_path_get ( )
if args . verbose :
level = logging . DEBUG
format = " %(asctime)s %(filename)s : %(lineno)d %(message)s "
else :
level = logging . INFO
format = " %(asctime)s %(message)s "
if args . log :
logging . basicConfig (
level = level ,
format = format ,
filename = args . eso_live_path . joinpath ( " banana.log " ) ,
)
else :
logging . basicConfig (
level = level ,
format = format ,
)
logging . info ( args )
config_path = Path ( args . eso_live_path ) . joinpath ( " addons.list " )
if not config_path . exists ( ) :
config_new ( config_path )
logging . info ( f ' addons list created at " { config_path } " ' )
with config_path . open ( " r " ) as file_open :
config_current = [ line . rstrip ( ' \n ' ) for line in file_open ]
config_current = filter ( None , config_current )
live_path = args . eso_live_path . joinpath ( " AddOns " )
live_path . mkdir ( parents = True , exist_ok = True )
esoui_uris = list ( )
for url in config_current :
esoui = esoui_parse ( url )
if esoui :
esoui_uris . append ( esoui )
esoui_to_live ( esoui_uris = esoui_uris , live_path = live_path )
ttc_update ( live_path = live_path )
2022-06-08 23:37:10 +00:00
def ttc ( ) :
parser = ArgumentParser ( description = " Tamriel Trade Centre price table updater. " )
parser . add_argument ( " -v " , " --verbose " , action = " count " , help = " verbose logging " )
parser . add_argument ( " -l " , " --log " , action = " store_true " )
parser . add_argument ( " -p " , " --eso_live_path " )
args = parser . parse_args ( )
if args . eso_live_path :
args . eso_live_path = Path ( args . eso_live_path )
else :
2022-10-29 04:09:53 +00:00
args . eso_live_path = eso_live_path_get ( )
2022-06-08 23:37:10 +00:00
if args . verbose :
level = logging . DEBUG
format = " %(asctime)s %(filename)s : %(lineno)d %(message)s "
else :
level = logging . INFO
format = " %(asctime)s %(message)s "
if args . log :
logging . basicConfig (
level = level ,
format = format ,
filename = args . eso_live_path . joinpath ( " banana.log " ) ,
)
else :
logging . basicConfig (
level = level ,
format = format ,
)
logging . info ( args )
live_path = Path ( args . eso_live_path ) . joinpath ( " AddOns " )
if not live_path . is_dir ( ) :
logging . error ( f " eso_live_path_invalid_dir { live_path } " )
return
ttc_update ( live_path = live_path )
price_table_uri = " https://us.tamrieltradecentre.com/download/PriceTable "
price_table_name = " TamrielTradeCentre "
def ttc_update ( live_path : Path ) :
2022-06-19 19:18:59 +00:00
response = requests . get ( price_table_uri )
response . raise_for_status ( )
2022-06-08 23:37:10 +00:00
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
2022-06-19 19:18:59 +00:00
zip_file = ZipFile ( BytesIO ( response . content ) )
2022-06-08 23:37:10 +00:00
zip_file . extractall ( temp_path )
live_tamriel_trade_centre = live_path . joinpath ( " TamrielTradeCentre " )
2022-06-19 19:18:59 +00:00
copytree ( temp_path . absolute ( ) , live_tamriel_trade_centre . absolute ( ) , dirs_exist_ok = True )
2022-06-08 23:37:10 +00:00
logging . info (
f " tamriel trade centre price table updated: { live_tamriel_trade_centre } "
)
if __name__ == " __main__ " :
periodical_script ( )