2022-06-08 23:37:10 +00:00
from argparse import ArgumentParser
from pathlib import Path
from platform import system
from shutil import rmtree , copytree , copyfileobj
from tempfile import TemporaryDirectory , NamedTemporaryFile
from zipfile import ZipFile
from urllib . request import Request , urlopen
2022-06-09 00:08:53 +00:00
from urllib . parse import quote
2022-06-08 23:37:10 +00:00
import logging
import re
HEADERS = {
" User-Agent " : " Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:48.0) Gecko/20100101 Firefox/48.0 "
}
def live_to_esoui ( * , path : Path , esoui_uris : list ) :
live_name , live_version , live_path = live_parse ( path )
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
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
request = Request ( esoui_uri , headers = HEADERS )
response = urlopen ( request )
temp_zip = NamedTemporaryFile ( )
copyfileobj ( response , temp_zip )
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
zip_file = ZipFile ( temp_zip )
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
request = Request ( esoui_dowload_uri , headers = HEADERS )
response = urlopen ( request )
temp_zip = NamedTemporaryFile ( )
copyfileobj ( response , temp_zip )
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
zip_file = ZipFile ( temp_zip )
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+ " )
def esoui_parse ( url : str ) :
addon_name = esoui_prefix . split ( url ) [ 1 ]
addon_name = addon_name . split ( " .html " ) [ 0 ]
request = Request ( url , headers = HEADERS )
response = urlopen ( request )
2022-06-09 00:08:53 +00:00
response_data = response . read ( )
# writworthy has some garbage characters on it's page
response_text = response_data [ : 110000 ] . decode ( " unicode_escape " )
2022-06-08 23:37:10 +00:00
version_line = esoui_version_html . search ( response_text ) . group ( 0 )
2022-06-09 00:31:38 +00:00
version = esoui_version_split . split ( version_line ) [ 1 ]
2022-06-08 23:37:10 +00:00
esoui_page_url = url . replace ( " info " , " download " ) . replace ( " .html " , " " )
request = Request ( esoui_page_url , headers = HEADERS )
response = urlopen ( request )
response_text = response . read ( ) . decode ( " unicode_escape " )
esoui_dowload_uri = esoui_download . search ( response_text ) . group ( 0 )
2022-06-09 00:08:53 +00:00
esoui_dowload_uri = esoui_dowload_uri . split ( " ? " ) [ 0 ]
esoui_dowload_uri = esoui_dowload_uri . split ( " https:// " ) [ 1 ]
esoui_dowload_uri = quote ( esoui_dowload_uri )
esoui_dowload_uri = f " https:// { esoui_dowload_uri } "
2022-06-08 23:37:10 +00:00
head_request = Request ( esoui_dowload_uri , method = " HEAD " , headers = HEADERS )
response = urlopen ( head_request )
response_text = response . read ( ) . decode ( " unicode_escape " )
2022-06-09 00:31:38 +00:00
return addon_name , version , esoui_dowload_uri
2022-06-08 23:37:10 +00:00
def live_parse ( path : Path ) :
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 )
2022-06-09 00:31:38 +00:00
version = " 0 "
2022-06-08 23:37:10 +00:00
if result :
2022-06-09 00:31:38 +00:00
version = result . group ( 0 )
version = live_version_split . split ( version ) [ 1 ]
2022-06-08 23:37:10 +00:00
2022-06-09 00:31:38 +00:00
return addon_name , version , path
2022-06-08 23:37:10 +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
"""
def config_new ( path : Path ) :
path . touch ( exist_ok = True )
with path . open ( " w " ) as file_open :
file_open . write ( config_template )
def periodical_script ( ) :
parser = ArgumentParser (
description = " Visit https://www.esoui.com/ to search for addons and their dependencies URLs. Edit addons.text 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 :
if system ( ) == " Windows " :
args . eso_live_path = Path . home ( ) . joinpath (
" Documents \ Elder Scrolls Online \ live "
)
else :
args . eso_live_path = Path . home ( ) . joinpath (
" .steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/ "
)
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.text " )
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 = file_open . readlines ( )
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 )
esoui_uris . append ( esoui )
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 )
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 :
if system ( ) == " Windows " :
args . eso_live_path = Path . home ( ) . joinpath (
" Documents \ Elder Scrolls Online \ live "
)
else :
args . eso_live_path = Path . home ( ) . joinpath (
" .steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/ "
)
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 ) :
request = Request ( price_table_uri , headers = HEADERS )
response = urlopen ( request )
temp_zip = NamedTemporaryFile ( )
copyfileobj ( response , temp_zip )
temp_dir = TemporaryDirectory ( )
temp_path = Path ( temp_dir . name )
zip_file = ZipFile ( temp_zip )
zip_file . extractall ( temp_path )
live_tamriel_trade_centre = live_path . joinpath ( " TamrielTradeCentre " )
2022-06-09 00:31:38 +00:00
copytree ( temp_path , live_tamriel_trade_centre , 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 ( )