Compare commits

...

64 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
JoYo b66d606920 disabled old addon cleanup 2023-07-15 18:00:50 -04:00
JoYo 68ad8fe0dd fix for LibAddonMenu using stupid versioning 2023-07-15 17:46:26 -04:00
JoYo a2825684f7 added popos flatpack path 2022-10-29 04:09:53 +00:00
JoYo c9ff88e45f Update 'README.mdown'
minor syntax
2022-10-17 23:40:57 +00:00
JoYo 4568309d83 Update 'README.mdown'
extended Steam Deck instructions
2022-10-17 23:02:25 +00:00
JoYo 58c30996cd minor doc 2022-06-19 16:06:57 -04:00
JoYo 86c75e60f4 minor doc 2022-06-19 16:05:38 -04:00
JoYo c860ad42bd minor doc 2022-06-19 16:02:26 -04:00
JoYo 62d9433bb0 updated instructions 2022-06-19 15:48:34 -04:00
JoYo 330c416071 reverted back to using requests, im not decoding non utf-8 2022-06-19 15:18:59 -04:00
JoYo d6aef160af timers start services 2022-06-08 21:22:38 -04:00
JoYo 773d17346b full path to python3 2022-06-08 21:06:38 -04:00
JoYo 30228ec14f systemd timer 2022-06-08 20:56:10 -04:00
JoYo df5e66aab1 removed modules unavailable on steam deck 2022-06-08 20:31:38 -04:00
JoYo d8ef990292 html parsing fixes, i hate you writworthy 2022-06-08 20:08:53 -04:00
JoYo 4841d68816 install from script file 2022-06-08 19:38:54 -04:00
JoYo 2668573716 combined into single for to make deployment on steam deck easier 2022-06-08 19:37:10 -04:00
JoYo 44a0046211 minor doc 2022-01-11 18:34:34 +00:00
JoYo 766275c40d time in nonverbose logging 2022-01-05 19:27:31 -05:00
JoYo 94774b3f26 log store true 2022-01-05 19:25:49 -05:00
JoYo e496d7d52b log param 2022-01-05 19:24:26 -05:00
JoYo 205025e7ba python installer to PATH 2022-01-05 19:13:51 -05:00
JoYo c0b488ea94 usage instructions 2022-01-05 18:58:44 -05:00
JoYo 56c18d5048 minor format 2022-01-05 18:45:46 -05:00
JoYo b9d0b58b4e schedule removal instructions 2022-01-05 18:45:02 -05:00
JoYo 23967a8ee7 remove unused files 2022-01-05 18:37:40 -05:00
JoYo 5c0494be70 linux scheduling 2022-01-05 18:36:05 -05:00
JoYo 9f8da90c64 minor doc 2022-01-05 18:24:56 -05:00
JoYo 79f1145098 reordered instructions 2022-01-05 18:23:54 -05:00
JoYo d19f1c9eaa resolve command for scheduled task 2022-01-05 18:20:32 -05:00
JoYo 8571b71298 windows scheduled task instructions and logging 2022-01-05 17:48:39 -05:00
JoYo 4d81453236 Merge branch 'master' of git.thejoyo.com:eso/banana 2022-01-05 15:41:15 -05:00
JoYo db3806e78f tcc cli script 2022-01-05 15:40:58 -05:00
JoYo be36bdf213 Update 'README.mdown' 2021-12-28 20:43:39 +00:00
JoYo ca76d4c605 ttc index updater 2021-12-23 19:06:18 -05:00
JoYo 432f4128c9 live version parsing fixes 2021-12-23 18:33:50 -05:00
JoYo 435230aa6e install new addons func 2021-12-22 18:11:29 -05:00
JoYo 21bbc6c6b2 update live addons 2021-12-15 18:06:20 -05:00
JoYo a5daac007d live addon parsing 2021-12-14 19:01:38 -05:00
JoYo 368413bb51 simplified parsing loop 2021-12-14 18:07:10 -05:00
JoYo f43fb6c80c esoui parse function 2021-12-14 17:55:04 -05:00
JoYo e491ce5319 minor var naming 2021-12-14 17:44:00 -05:00
JoYo 6e64eadc27 get version from esoui 2021-12-14 17:21:42 -05:00
JoYo 1884f8df7b poetry still doesn't support no-deps 2021-12-14 15:25:21 -05:00
JoYo 9b61c1b3c7 arg type check 2021-12-07 18:35:52 -05:00
JoYo fa927f40b8 simplified to a single parameter 2021-12-07 18:33:22 -05:00
JoYo 843ade66ac yaml safe load 2021-12-07 17:24:52 -05:00
JoYo c937dae3b4 initial config 2021-12-07 17:00:56 -05:00
JoYo 30cfbd2157 dev env 2021-12-05 15:09:32 -05:00
12 changed files with 555 additions and 30 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.elf
*.exe
*.sum
live/
*.list
*.zip

View File

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

@ -1,9 +1,143 @@
# Elder Scrolls Online Commadline Addon Manager # Elder Scrolls Online Commadline Addon Manager
Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater.
# Dependencies [MIT License](LICENSE)
# Installation 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:
```
%HOME%\Documents\Elder Scrolls Online\
```
or on Windows 11
```
Documents\Elder Scrolls Online\
```
Make a copy of the `live` folder and rename it to something meaningful like `old` or `backup`.
# Usage # Usage
Follow the installation instructions for your `platform`:
- [Windows](#windows-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:
```
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.
# Windows Installation
0. Download the latest `banana.exe` release for [Windows](https://git.joyo.dev/eso/banana/releases/).
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
$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
Register-ScheduledTask -TaskName "eso-banana" -Action $Action -Trigger $Trigger -Settings $Settings -Description "Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater."
```
To check to make sure the task is registered correctly, enter `Get-ScheduledTask` and check that the first entry looks similar:
```
TaskPath TaskName State
-------- -------- -----
\ eso-banana Ready
```
## Windows Unschedule
Only run the following command if you wish to remove scheduled run of `eso-banana`.
To remove the schedule, use the `Unregister-ScheduledTask` command:
```
Unregister-ScheduledTask eso-banana
```
Press enter to confirm removal.
# SteamOS Installation
The following instructions are for arch linux system installed with the Steam Deck.
0. From the [Steam Deck instructions](https://help.steampowered.com/en/faqs/view/671A-4453-E8D2-323C):
> From the STEAM menu, select Power, then Switch to Desktop
1. Download the latest `banana.elf` release for [SteamOS](https://git.joyo.dev/eso/banana/releases/).
2. Set executable with `chmod +x banana.elf` and add the executable to `~/.local/bin/` or any directory in the user's $PATH environment.
- optionally replace "banana.elf" with the full path to where the executable is stored.
2. Run the executable from the commandline `banana.elf` for a default AddOn update or with `banana.elf -h` for usage.
Note: banana will create and `addons.list` file which can be edited 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"`
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.
# SteamOS Optional
Because systemd is cancer you will need to edit the `banana.service` file to include your user's home path.
If `banana` is not installed to `~/.local/bin/banana.elf`, open a new terminal and use the results from `which banana.elf`.
```
[Unit]
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/banana.elf
User=deck
[Install]
WantedBy=multi-user.target
```
Finally, install the systemd timer and service to run `banana` everyday.
```
cd ./banana/
cp banana.timer banana.service /etc/systemd/system/
sudo systemctl enable banana.timer
sudo systemctl enable banana.service
```
## SteamOS Unschedule
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
}

View File

@ -1,9 +1,11 @@
[Unit] [Unit]
Description=run eso-banana addon management Description="Elder Scrolls Online addon manager and a Tamriel Trade Centre price table updater."
Wants=banana.timer
[Service] [Service]
Type=simple Type=oneshot
ExecStart=banana-script ExecStart=/usr/bin/banana
User=deck
[Install] [Install]
WantedBy=default.target WantedBy=multi-user.target

View File

@ -1,9 +1,9 @@
[Unit] [Unit]
Description=Run eso-banana addon management once a day. Description=Run banana daily and on boot.
[Timer] [Timer]
OnUnitActiveSec=12h OnCalendar=daily
Unit=banana.service Persistent=true
[Install] [Install]
WantedBy=multi-user.target WantedBy=timers.target

View File

View File

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

View File

@ -1,19 +0,0 @@
[build-system]
requires = ["poetry"]
build-backend = "poetry.masonry.api"
[tool.poetry]
authors = ["py <py@py>"]
description = ""
license = "MIT"
name = "banana"
version = "0.0.1"
[[tool.poetry.packages]]
include = "banana"
[tool.poetry.scripts]
banana-script = "banana:scripts.periodical_script"
[tool.poetry.dependencies]
requests = ""