Compare commits

...

15 Commits

Author SHA1 Message Date
JoYo a5b4585a44 ignore missing esoui info 2024-06-07 21:19:30 -04:00
JoYo 25dd9f17b0 removed unused const 2024-06-07 19:37:35 -04:00
JoYo ef348159c7 minor doc 2024-06-07 19:16:17 -04:00
JoYo 6f2a9ccf06 added makefile command to install on steamos 2024-06-07 19:10:13 -04:00
JoYo d25d6d1f78 minor doc 2024-06-07 18:37:10 -04:00
JoYo 4acfe44e7c remove python and instructions 2024-06-07 18:31:48 -04:00
JoYo 619d9fcea2 Ignore empty addons, minor log messeges 2024-06-07 17:52:03 -04:00
JoYo 0ef489faa7 update ttc price tables 2024-06-07 17:44:31 -04:00
JoYo f5ff1fdbce downloads and extracts all listed addons 2024-06-07 17:17:54 -04:00
JoYo 35b9852487 print live addon stats 2024-06-07 02:15:14 -04:00
JoYo cf5443ca40 remove unlisted addons 2024-06-07 01:26:49 -04:00
JoYo 8c9c5d732d fixed html regexp 2024-06-06 11:12:07 -04:00
JoYo 62308eed08 esoui addon page get 2024-06-06 00:50:42 -04:00
JoYo 8cbd7b31fc arg names and help 2024-06-05 01:26:03 -04:00
JoYo da8e7ef375 initial go rewrite 2024-06-05 01:01:15 -04:00
8 changed files with 438 additions and 492 deletions

10
.gitignore vendored
View File

@ -1,4 +1,6 @@
__pycache__/
.vscode/
*.egg-info/
build/
*.elf
*.exe
*.sum
live/
*.list
*.zip

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
EXEs=banana.elf banana.exe
all: tidy clean ${EXEs}
tidy:
go mod tidy
banana.elf:
go build -o banana.elf banana.go
banana.exe:
GOOS=windows go build -o banana.exe banana.go
clean:
go clean
-rm ${EXEs}
run:
go run banana.go -i live/addons.list -o live/AddOns/
install:
GOBIN=~/.local/bin/ go install banana.go
install-steamos: banana.elf
cp banana.elf /usr/bin/banana
cp banana.timer banana.service /etc/systemd/system/
systemctl enable banana.timer
systemctl enable banana.service

View File

@ -4,7 +4,7 @@ Elder Scrolls Online addon manager and a Tamriel Trade Centre price table update
[MIT License](LICENSE)
It is recommended that you back up your ESO live profile before using `eso-banana` in case you want to revert back.
It is recommended that you back up your ESO live profile before using `banana` in case you want to revert back.
On Windows, press `Windows Key + e` to open a file explorer and enter the following path in the address bar:
@ -25,7 +25,7 @@ Make a copy of the `live` folder and rename it to something meaningful like `old
Follow the installation instructions for your `platform`:
- [Windows](#windows-installation)
- [Linux](#linux-installation)
- [SteamOS](#steamos-installation)
On first run, the `addons.list` file will be created in your ESO live directory.
It will look similar to the following:
@ -41,27 +41,18 @@ Make sure to include the `www.` indicator that ESOUI requires for some stupid re
# Windows Installation
Install the latest Python 3 using the installer provided by [python.org](https://www.python.org/downloads/windows/).
When the python installer asks, [add python to PATH](https://docs.python.org/3/using/windows.html#installation-steps).
0. Download the latest `banana.exe` release for [Windows](https://git.joyo.dev/eso/banana/releases/).
Open [Windows Terminal](https://www.microsoft.com/en-US/p/windows-terminal/9n0dx20hk701) or any windows command prompt and navigate to this project.
Use the Python package manager PIP to install `eso-banana`.
1. Add the executable to the [user's path](https://www.wikihow.com/Change-the-PATH-Environment-Variable-on-Windows) or replace "banana.exe" with the full path to where the executable is stored.
2. Run the executable from the commandline `banana.exe` for a default AddOn update or with `banana.exe -h` for usage.
# Windows Optional
To schedule a periodic background run of `banana`, open Powershell as a user and enter the following commands.
```powershell
cd .\banana\
pip install .
```
Once the project is installed to python's packages you may invoke the addon script with the following command:
```powershell
eso-banana-script.exe
```
To schedule a periodic background run of `eso-banana`, open Powershell as a user and enter the following commands.
```powershell
$Command = (Get-Command "eso-banana-script.exe").Source
$Command = (Get-Command "banana.exe").Source
$Action = New-ScheduledTaskAction -Execute $Command -Argument "--log"
$Trigger = New-ScheduledTaskTrigger -Daily -At 11am
$Settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -StartWhenAvailable -RunOnlyIfIdle
@ -76,7 +67,7 @@ TaskPath TaskName State
\ eso-banana Ready
```
# Windows Unschedule
## Windows Unschedule
Only run the following command if you wish to remove scheduled run of `eso-banana`.
@ -88,7 +79,7 @@ Unregister-ScheduledTask eso-banana
Press enter to confirm removal.
# Steam Deck Installation
# SteamOS Installation
The following instructions are for arch linux system installed with the Steam Deck.
@ -96,103 +87,57 @@ The following instructions are for arch linux system installed with the Steam De
> From the STEAM menu, select Power, then Switch to Desktop
1. Once you've become familiar with desktop mode, open a terminal and enter the following commands to install python.
1. Download the latest `banana.elf` release for [SteamOS](https://git.joyo.dev/eso/banana/releases/).
```
sudo btrfs property set -ts / ro false
sudo pacman-key --init
sudo pacman-key --populate archlinux
sudo pacman -S python-pip
```
2. Set executable with `chmod +x banana.elf` and add the executable to `~/.local/bin/` or any directory in the user's $PATH environment.
2. Run the following commands to download this project and install the scheduled service.
- optionally replace "banana.elf" with the full path to where the executable is stored.
```
wget https://joyo.dev/eso/banana/archive/master.tar.gz -O banana.tgz
tar xvf banana.tgz
cd ./banana/
pip install .
cp banana.timer banana.service /etc/systemd/system/
sudo systemctl enable banana.timer
sudo systemctl enable banana.service
```
2. Run the executable from the commandline `banana.elf` for a default AddOn update or with `banana.elf -h` for usage.
3. Now that `eso-banana-script` has been installed, run it once to create the `addons.list` file.
If the mentioned command is missing your may need to restart the TTY.
Note: banana will create and `addons.list` file which can be edited to include additional adddon URLs at the following path:
4. The created file can be edited with vim to include additional adddon URLs at the following path.
`$EDITOR "~/.steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/addons.list"`
`vim "~/.steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/addons.list"`
It will look similar to the following:
```
https://www.esoui.com/downloads/info7-LibAddonMenu.html
https://www.esoui.com/downloads/info1245-TamrielTradeCentre.html
https://www.esoui.com/downloads/info1146-LibCustomMenu.html
```
Add the ESOUI url for each additional addon you wish to keep updated.
Make sure to include the `www.` indicator that ESOUI requires for some stupid reason.
5. Run `eso-banana-script` once more to download and install the additional addons.
6. To return to [Gaming Mode](https://help.steampowered.com/en/faqs/view/671A-4453-E8D2-323C):
5. To return to [Gaming Mode](https://help.steampowered.com/en/faqs/view/671A-4453-E8D2-323C):
> ...there's a shortcut link to 'Return to Gaming Mode'.
> Select that to get back to standard Steam Deck UI.
> You can also go through the system menus to Log Off to get back.
# Steam Deck Unschedule
Only run the following command if you wish to remove scheduled run of `eso-banana`.
```
systemctl list-timers --all
sudo systemctl disable banana.timer
```
# Linux Installation
The following instructions are for any linux system using systemd.
Using your distros package management system, install python3-pip.
```
sudo apt install python3-pip
```
# SteamOS Optional
Because systemd is cancer you will need to edit the `banana.service` file to include your user's home path.
In the unlikely event that the script is not installed to `~/.local/bin/eso-banana-script`, open a new terminal and use the results from `which eso-banana-script`.
If `banana` is not installed to `~/.local/bin/banana.elf`, open a new terminal and use the results from `which banana.elf`.
```
[Unit]
Description=Run banana daily and on boot.
Description="Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater."
Wants=banana.timer
[Service]
Type=oneshot
ExecStart=/home/user_name_here/.local/bin/eso-banana-script
ExecStart=/home/<user_name_here>/.local/bin/banana.elf
User=deck
[Install]
WantedBy=multi-user.target
```
Finally, install `eso-banana` using pip and install the systemd timer and service to run `eso-banana` everyday.
Finally, install the systemd timer and service to run `banana` everyday.
```
cd ./banana/
pip install .
cp banana.timer banana.service /etc/systemd/system/
sudo systemctl enable banana.timer
sudo systemctl enable banana.service
```
# Linux Unschedule
## SteamOS Unschedule
Only run the following command if you wish to remove scheduled run of `eso-banana`.
Only run the following command if you wish to remove scheduled run of `banana`.
```
systemctl list-timers --all
sudo systemctl disable banana.timer
```
```

367
banana.go Normal file
View File

@ -0,0 +1,367 @@
package main
import (
"github.com/alexflint/go-arg"
"archive/zip"
"bufio"
"bytes"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
)
var args struct {
Addon_list_path string `arg:"-i,--addon-list" help:"path to addon list file"`
Out_dir string `arg:"-o,--live-dir" help:"path to eso live directory"`
Ttc bool `arg:"-t,--ttc" help:"only update tamriel trade centre db"`
}
func main() {
arg.MustParse(&args)
eso_live_path := eso_live_path_get()
if args.Addon_list_path == "" {
args.Addon_list_path = filepath.Join(eso_live_path, "addons.list")
}
if args.Out_dir == "" {
args.Out_dir = filepath.Join(eso_live_path, "AddOns")
}
fmt.Println("args", args)
_, error := os.Stat(args.Addon_list_path)
if errors.Is(error, os.ErrNotExist) {
error = addon_list_create(args.Addon_list_path)
if error != nil {
panic(error)
}
}
addon_urls, error := addon_list_read(args.Addon_list_path)
if error != nil {
panic(error)
}
error = ttc_update(filepath.Join(args.Out_dir, "TamrielTradeCentre"))
if error != nil {
panic(error)
}
fmt.Println("Updated,", TCC_PRICE_TABLE_URI)
if args.Ttc {
return
}
addon_paths, error := os.ReadDir(args.Out_dir)
if error != nil {
panic(error)
}
var eso_live_addon_names []string
for _, path := range addon_paths {
if path.IsDir() {
eso_live_addon_names = append(eso_live_addon_names, path.Name())
}
}
var eso_ui_list []EsoAddon
for _, url := range addon_urls {
eso_ui, error := eso_ui_stat_init(url)
if error != nil {
panic(error)
}
eso_ui_list = append(eso_ui_list, eso_ui)
}
var eso_live_list []EsoAddon
for _, eso_live_name := range eso_live_addon_names {
eso_live, error := eso_live_stat_init(eso_live_name)
if error != nil {
continue
}
matching := ""
for _, eso_ui := range eso_ui_list {
if strings.Contains(eso_live_name, eso_ui.name) {
matching = eso_live_name
}
}
if matching == "" {
fmt.Println("Removed,", eso_live.path)
os.RemoveAll(eso_live.path)
continue
}
eso_live_list = append(eso_live_list, eso_live)
}
for _, eso_live := range eso_live_list {
fmt.Printf("Live, %s, %s\n", eso_live.name, eso_live.version)
}
for _, eso_ui := range eso_ui_list {
fmt.Printf("Updated, %s, %s\n", eso_ui.name, eso_ui.version)
error = eso_ui_get_unzip(eso_ui.path, args.Out_dir)
if error != nil {
panic(error)
}
}
}
const (
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
`
ESO_LIVE_PATH_WINDOWS = `Documents\Elder Scrolls Online\live`
ESO_LIVE_PATH_STEAMOS = ".steam/steam/steamapps/compatdata/306130/pfx/drive_c/users/steamuser/Documents/Elder Scrolls Online/live/"
TCC_PRICE_TABLE_URI = "https://us.tamrieltradecentre.com/download/PriceTable"
)
var (
ESOUI_NAME = regexp.MustCompile(`(?:https://www.esoui.com/downloads/info[0-9]+\-)([A-Za-z]+)(?:\.html)`)
ESOUI_VERSION = regexp.MustCompile(`(?:<div\s+id="version">Version:\s+)(.*)(?:</div>)`)
ESOUI_DOWNLOAD = regexp.MustCompile(`https://cdn.esoui.com/downloads/file[^"]*`)
LIVE_VERSION = regexp.MustCompile(`(?:##\s+Version:\s+)(.*)(?:\n)`)
)
func eso_live_path_get() string {
home_path, error := os.UserHomeDir()
if error != nil {
panic(error)
}
if runtime.GOOS == "windows" {
return filepath.Join(home_path, ESO_LIVE_PATH_WINDOWS)
} else {
return filepath.Join(home_path, ESO_LIVE_PATH_STEAMOS)
}
}
func addon_list_create(addon_list_path string) error {
file_open, error := os.Create(addon_list_path)
if error != nil {
return error
}
defer file_open.Close()
_, error = file_open.Write([]byte(CONFIG_TEMPLATE))
if error != nil {
return error
}
return nil
}
func addon_list_read(addon_list_path string) ([]string, error) {
file_open, error := os.OpenFile(addon_list_path, os.O_RDONLY, 0644)
defer file_open.Close()
if error != nil {
return nil, error
}
file_scanner := bufio.NewScanner(file_open)
lines := []string{}
for file_scanner.Scan() {
line := file_scanner.Text()
switch {
case line == "":
continue
case strings.HasPrefix(line, "#"):
continue
case strings.HasPrefix(line, "//"):
continue
case strings.HasPrefix(line, "-"):
continue
}
lines = append(lines, line)
}
return lines, nil
}
type EsoAddon struct {
name string
version string
path string
}
func eso_ui_stat_init(addon_url string) (EsoAddon, error) {
addon_resp, error := http.Get(addon_url)
if error != nil {
return EsoAddon{}, error
}
defer addon_resp.Body.Close()
if addon_resp.StatusCode == http.StatusNotFound {
return EsoAddon{}, errors.New(http.StatusText(addon_resp.StatusCode))
}
addon_body, error := io.ReadAll(addon_resp.Body)
if error != nil {
return EsoAddon{}, error
}
download_page_url := strings.Replace(addon_url, "info", "download", -1)
download_resp, error := http.Get(download_page_url)
if error != nil {
return EsoAddon{}, error
}
defer download_resp.Body.Close()
if download_resp.StatusCode == http.StatusNotFound {
return EsoAddon{}, errors.New(http.StatusText(download_resp.StatusCode))
}
download_body, error := io.ReadAll(download_resp.Body)
if error != nil {
return EsoAddon{}, error
}
var name string
names := ESOUI_NAME.FindStringSubmatch(addon_url)
if len(names) > 1 {
name = names[1]
} else {
name = ""
}
var version string
versions := ESOUI_VERSION.FindStringSubmatch(string(addon_body))
if len(versions) > 1 {
version = versions[1]
} else {
version = ""
}
path := string(ESOUI_DOWNLOAD.Find(download_body))
if path == "" {
return EsoAddon{}, errors.New("Download URI missing " + addon_url)
}
return EsoAddon{name, version, path}, nil
}
func eso_live_stat_init(eso_live_name string) (EsoAddon, error) {
path := filepath.Join(args.Out_dir, eso_live_name)
content, error := os.ReadFile(filepath.Join(path, eso_live_name+".txt"))
if error != nil {
return EsoAddon{}, error
}
var version string
versions := LIVE_VERSION.FindStringSubmatch(string(content))
if len(versions) > 1 {
version = versions[1]
} else {
version = ""
}
return EsoAddon{eso_live_name, version, path}, nil
}
func eso_ui_get_unzip(esoui_url string, out_dir string) error {
response, error := http.Get(esoui_url)
if error != nil {
return error
}
defer response.Body.Close()
if response.StatusCode == http.StatusNotFound {
return errors.New(http.StatusText(response.StatusCode))
}
body, error := io.ReadAll(response.Body)
if error != nil {
return error
}
reader := bytes.NewReader(body)
zip_reader, error := zip.NewReader(reader, int64(len(body)))
if error != nil {
return error
}
for _, zipped_file := range zip_reader.File {
if zipped_file.Mode().IsDir() {
continue
}
zipped_file_open, error := zipped_file.Open()
if error != nil {
return error
}
name := filepath.Join(out_dir, zipped_file.Name)
os.MkdirAll(filepath.Dir(name), os.ModePerm)
create, error := os.Create(name)
if error != nil {
return error
}
defer create.Close()
create.ReadFrom(zipped_file_open)
}
return nil
}
func ttc_update(out_path string) error {
response, error := http.Get(TCC_PRICE_TABLE_URI)
if error != nil {
return error
}
defer response.Body.Close()
if response.StatusCode == http.StatusNotFound {
return errors.New(http.StatusText(response.StatusCode))
}
body, error := io.ReadAll(response.Body)
if error != nil {
return error
}
reader := bytes.NewReader(body)
zip_reader, error := zip.NewReader(reader, int64(len(body)))
if error != nil {
return error
}
for _, zipped_file := range zip_reader.File {
if zipped_file.Mode().IsDir() {
continue
}
zipped_file_open, error := zipped_file.Open()
if error != nil {
return error
}
name := filepath.Join(out_path, zipped_file.Name)
os.MkdirAll(filepath.Dir(name), os.ModePerm)
create, error := os.Create(name)
if error != nil {
return error
}
defer create.Close()
create.ReadFrom(zipped_file_open)
}
return nil
}

388
banana.py
View File

@ -1,388 +0,0 @@
from argparse import ArgumentParser
from io import BytesIO
from packaging import version
from pathlib import Path
from pathlib import Path
from platform import system
from shutil import rmtree, copytree
from tempfile import TemporaryDirectory
from typing import Tuple
from zipfile import ZipFile
import logging
import re
import requests
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 live_to_esoui(*, path: Path, esoui_uris: list):
live_name, live_version, live_path = parsing_live(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
response = requests.get(esoui_uri)
response.raise_for_status()
temp_dir = TemporaryDirectory()
temp_path = Path(temp_dir.name)
zip_file = ZipFile(BytesIO(response.content))
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
response = requests.get(esoui_dowload_uri)
response.raise_for_status()
temp_dir = TemporaryDirectory()
temp_path = Path(temp_dir.name)
zip_file = ZipFile(BytesIO(response.content))
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) -> Tuple[str, version.Version, str]:
addon_name = esoui_prefix.split(url)[1]
addon_name = addon_name.split(".html")[0]
response = requests.get(url)
response.raise_for_status()
version_line = esoui_version_html.search(response.text).group(0)
_version = esoui_version_split.split(version_line)[1]
try:
_version = version.parse(_version)
except version.InvalidVersion:
_version = version.parse("1")
esoui_page_url = url.replace("info", "download").replace(".html", "")
response = requests.get(esoui_page_url)
response.raise_for_status()
esoui_dowload_uri = esoui_download.search(response.text).group(0)
response = requests.head(esoui_dowload_uri)
response.raise_for_status()
return addon_name, _version, esoui_dowload_uri
def parsing_live(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)
if result:
_version = result.group(0)
_version = live_version_split.split(_version)[1]
try:
_version = version.parse(_version)
except version.InvalidVersion:
_version = version.parse("0")
else:
_version = version.parse("0")
return addon_name, _version, path
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.")
def unlisted_remove():
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)
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 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)
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:
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)
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):
response = requests.get(price_table_uri)
response.raise_for_status()
temp_dir = TemporaryDirectory()
temp_path = Path(temp_dir.name)
zip_file = ZipFile(BytesIO(response.content))
zip_file.extractall(temp_path)
live_tamriel_trade_centre = live_path.joinpath("TamrielTradeCentre")
copytree(temp_path.absolute(), live_tamriel_trade_centre.absolute(), dirs_exist_ok=True)
logging.info(
f"tamriel trade centre price table updated: {live_tamriel_trade_centre}"
)
if __name__ == "__main__":
periodical_script()

View File

@ -1,10 +1,10 @@
[Unit]
Description=Run banana daily and on boot.
Description="Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater."
Wants=banana.timer
[Service]
Type=oneshot
ExecStart=/home/deck/.local/bin/eso-banana-script
ExecStart=/usr/bin/banana
User=deck
[Install]

7
go.mod Normal file
View File

@ -0,0 +1,7 @@
module banana
go 1.22.3
require github.com/alexflint/go-arg v1.5.0
require github.com/alexflint/go-scalar v1.2.0 // indirect

View File

@ -1,15 +0,0 @@
from setuptools import setup
setup(
name="eso-banana",
version="0.0.2",
scripts=["banana.py"],
entry_points={
"console_scripts": [
"eso-banana-script = banana:periodical_script",
"eso-ttc = banana:ttc",
],
},
install_requires=["packaging", "requests"],
python_requires=">3",
)