aboutsummaryrefslogtreecommitdiff
path: root/cmd/web
diff options
context:
space:
mode:
authorMitch Riedstra <mitch@riedstra.us>2021-03-04 18:50:47 -0500
committerMitch Riedstra <mitch@riedstra.us>2021-03-04 18:50:47 -0500
commit3b6f5647b0689abf04be73c3cf00297051753435 (patch)
tree3de6871abf37849c1e9f86dfc90ee2b3ed74c66e /cmd/web
parenteaf02771d767e4745572d9b00e71e138ee030e60 (diff)
downloadsteam-export-3b6f5647b0689abf04be73c3cf00297051753435.tar.gz
steam-export-3b6f5647b0689abf04be73c3cf00297051753435.tar.xz
Refactor. Pull most of the functions into methods off of an App struct.
Kill most global variables.
Diffstat (limited to 'cmd/web')
-rw-r--r--cmd/web/delete.go10
-rw-r--r--cmd/web/download.go8
-rw-r--r--cmd/web/index.go25
-rw-r--r--cmd/web/install.go89
-rw-r--r--cmd/web/main.go125
-rw-r--r--cmd/web/serve-self.go2
-rw-r--r--cmd/web/unix.go1
-rw-r--r--cmd/web/windows.go3
8 files changed, 124 insertions, 139 deletions
diff --git a/cmd/web/delete.go b/cmd/web/delete.go
index 49a1326..7fa003e 100644
--- a/cmd/web/delete.go
+++ b/cmd/web/delete.go
@@ -5,7 +5,7 @@ import (
"net/http"
)
-func gameDelete(w http.ResponseWriter, r *http.Request) {
+func (a App) HandleDelete(w http.ResponseWriter, r *http.Request) {
if unauthorizedIfNotLocal(w, r) {
return
}
@@ -25,9 +25,9 @@ func gameDelete(w http.ResponseWriter, r *http.Request) {
return
}
- Lib.Lock()
- g, ok := Lib.Games[game]
- Lib.Unlock()
+ a.Library.Lock()
+ g, ok := a.Library.Games[game]
+ a.Library.Unlock()
if !ok {
Logger.Printf("Missing: %s", game)
http.Error(w, "Game is missing", 404)
@@ -42,6 +42,6 @@ func gameDelete(w http.ResponseWriter, r *http.Request) {
}
Logger.Printf("Removed game: %s", game)
- reloadLib()
+ a.LibraryReload()
http.Redirect(w, r, "/", 302)
}
diff --git a/cmd/web/download.go b/cmd/web/download.go
index f8ba057..0238c8c 100644
--- a/cmd/web/download.go
+++ b/cmd/web/download.go
@@ -9,13 +9,13 @@ import (
"github.com/gorilla/mux"
)
-func gameDownloader(w http.ResponseWriter, r *http.Request) {
+func (a *App) HandleDownload(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
game := vars["game"]
- Lib.Lock()
- g, ok := Lib.Games[game]
- Lib.Unlock()
+ a.Library.Lock()
+ g, ok := a.Library.Games[game]
+ a.Library.Unlock()
if !ok {
Logger.Printf("Missing: %s", game)
http.Error(w, "Game is missing", 404)
diff --git a/cmd/web/index.go b/cmd/web/index.go
index b90faf8..7291af0 100644
--- a/cmd/web/index.go
+++ b/cmd/web/index.go
@@ -1,31 +1,22 @@
package main
import (
- "html/template"
"net/http"
- _ "embed"
"riedstra.dev/mitch/steam-export/steam"
)
-var (
- //go:embed templates/index.html
- indexTemplate string
-
- Templ = template.Must(template.New("index").Parse(indexTemplate))
-)
-
-func index(w http.ResponseWriter, r *http.Request) {
+func (a *App) HandleIndex(w http.ResponseWriter, r *http.Request) {
// During rendering of the template I believe it's
// mutating during the sort of keys, so Lib no longer
// is an RWMutex and we're just locking this as if
// we're writing to it
- Lib.Lock()
- defer Lib.Unlock()
- status.Lock()
- defer status.Unlock()
+ a.Library.Lock()
+ defer a.Library.Unlock()
+ a.Status.Lock()
+ defer a.Status.Unlock()
- err := Templ.ExecuteTemplate(w, "index",
+ err := a.Templates.ExecuteTemplate(w, "index",
struct {
Lib *steam.Library
Info *statusInfo
@@ -34,8 +25,8 @@ func index(w http.ResponseWriter, r *http.Request) {
Port string
Version string
}{
- &Lib.Library,
- status,
+ &a.Library.Library,
+ a.Status,
isLocal(r.RemoteAddr),
getHostIP(),
getPort(),
diff --git a/cmd/web/install.go b/cmd/web/install.go
index fa1ea7a..ce8aa8d 100644
--- a/cmd/web/install.go
+++ b/cmd/web/install.go
@@ -9,44 +9,25 @@ import (
"os"
"strconv"
"strings"
- "sync"
"time"
)
-type statusInfo struct {
- sync.RWMutex
- Running bool
- Error error
- Url string
- Transferred int64
- Size int64
- Start *time.Time
-}
-
-var (
- status = &statusInfo{
- Running: false,
- }
-
- getPath = make(chan string)
-)
-
-func statsHandler(w http.ResponseWriter, r *http.Request) {
- status.RLock()
- defer status.RUnlock()
+func (a *App) HandleStats(w http.ResponseWriter, r *http.Request) {
+ a.Status.RLock()
+ defer a.Status.RUnlock()
w.Header().Add("Content-type", "application/json")
enc := json.NewEncoder(w)
- err := enc.Encode(status)
+ err := enc.Encode(a.Status)
if err != nil {
- Logger.Println("While encoding status: ", err)
+ Logger.Println("While encoding Status: ", err)
}
return
}
-func installHttp(u string) error {
+func (a *App) installHttp(u string) error {
Logger.Println("Installer: loading from url")
resp, err := http.Get(u)
if err != nil {
@@ -58,14 +39,14 @@ func installHttp(u string) error {
return fmt.Errorf("Failed to convert estimated size header: %w", err)
}
- status.Lock()
- status.Size = estSize
- status.Unlock()
+ a.Status.Lock()
+ a.Status.Size = estSize
+ a.Status.Unlock()
rdr, wrtr := io.Pipe()
go func() {
- err = Lib.Extract(rdr)
+ err = a.Library.Extract(rdr)
if err != nil {
Logger.Printf("Installer: extracting %s", err)
}
@@ -74,9 +55,9 @@ func installHttp(u string) error {
var total int64
start := time.Now()
- status.Lock()
- status.Start = &start
- status.Unlock()
+ a.Status.Lock()
+ a.Status.Start = &start
+ a.Status.Unlock()
for {
var n int64
n, err = io.CopyN(wrtr, resp.Body, 100*1024*1024)
@@ -94,9 +75,9 @@ func installHttp(u string) error {
Logger.Printf("Downloading from %s, Size: %s, %0.1f%% Done, Rate: %.2f mb/s",
u, formatBytes(estSize), float64(total)/float64(estSize)*100, rate)
- status.Lock()
- status.Transferred = total
- status.Unlock()
+ a.Status.Lock()
+ a.Status.Transferred = total
+ a.Status.Unlock()
}
if err == io.EOF {
@@ -106,14 +87,14 @@ func installHttp(u string) error {
return err
}
-func installPath(p string) error {
+func (a *App) installPath(p string) error {
Logger.Println("Installer: loading from filesystem")
fh, err := os.Open(p)
if err != nil {
return fmt.Errorf("Installer: opening %w", err)
}
- err = Lib.Extract(fh)
+ err = a.Library.Extract(fh)
if err != nil {
return fmt.Errorf("Installer: opening %w", err)
}
@@ -121,34 +102,34 @@ func installPath(p string) error {
return nil
}
-// installer handles installing games either from a local path or a
-// remote URL
-func installer(urls <-chan string) {
+// installer runs in the background installing games either from a local path or
+// a remote URL
+func (a *App) installer() {
var err error
- for u := range urls {
- status.Lock()
+ for u := range a.download {
+ a.Status.Lock()
Logger.Printf("Installer: running for URI: %s", u)
- status.Running = true
- status.Url = u
- status.Unlock()
+ a.Status.Running = true
+ a.Status.Url = u
+ a.Status.Unlock()
if strings.HasPrefix(u, "http") {
- err = installHttp(u)
+ err = a.installHttp(u)
} else {
- err = installPath(u)
+ err = a.installPath(u)
}
- status.Lock()
- status.Running = false
- status.Error = err
+ a.Status.Lock()
+ a.Status.Running = false
+ a.Status.Error = err
Logger.Printf("Installer: Completed request %s Errors: %s", u, err)
- status.Unlock()
+ a.Status.Unlock()
- reloadLib()
+ a.LibraryReload()
}
}
-func gameInstaller(w http.ResponseWriter, r *http.Request) {
+func (a *App) HandleInstall(w http.ResponseWriter, r *http.Request) {
if unauthorizedIfNotLocal(w, r) {
return
}
@@ -179,7 +160,7 @@ func gameInstaller(w http.ResponseWriter, r *http.Request) {
}
Logger.Printf("Installer: Sending request for: %s to channel", uri)
- getPath <- uri
+ a.download <- uri
http.Redirect(w, r, "/", 302)
}
diff --git a/cmd/web/main.go b/cmd/web/main.go
index 091d22f..f0c7489 100644
--- a/cmd/web/main.go
+++ b/cmd/web/main.go
@@ -1,9 +1,10 @@
package main
import (
+ "embed"
"flag"
- "io"
"fmt"
+ "html/template"
"log"
"math/rand"
"net"
@@ -12,17 +13,55 @@ import (
"strings"
"sync"
"time"
- "embed"
"github.com/gorilla/mux"
"riedstra.dev/mitch/steam-export/steam"
)
+type App struct {
+ Library *steamLib
+ Status *statusInfo
+
+ Templates *template.Template
+
+ // Sending to this channel triggers the downloader in the background
+ download chan string
+}
+
+func NewApp(libPath string) (*App, error) {
+ lib, err := steam.NewLibrary(libPath)
+ if err != nil {
+ return nil, err
+ }
+
+ a := &App{
+ Library: &steamLib{},
+ Status: &statusInfo{},
+ download: make(chan string),
+ }
+
+ a.Library.Library = *lib
+
+ a.Templates = template.Must(template.New("index").Parse(indexTemplate))
+
+ return a, nil
+}
+
type steamLib struct {
steam.Library
sync.Mutex
}
+type statusInfo struct {
+ sync.RWMutex
+ Running bool
+ Error error
+ Url string
+ Transferred int64
+ Size int64
+ Start *time.Time
+}
+
var (
Version = "Development"
Logger = log.New(os.Stderr, "", log.LstdFlags)
@@ -30,25 +69,31 @@ var (
//go:embed static/*
embeddedStatic embed.FS
-
- Lib steamLib
+ //go:embed templates/index.html
+ indexTemplate string
)
-func reloadLib() {
+func (a *App) LibrarySet(path string) {
Logger.Println("Starting library reload")
- Lib.Lock()
- defer Lib.Unlock()
+ a.Library.Lock()
+ defer a.Library.Unlock()
var err error
- l2, err := steam.NewLibrary(DefaultLib)
+ l2, err := steam.NewLibrary(path)
if err != nil {
- Logger.Printf("Error reopening library: %s", err)
+ Logger.Printf("Error reopening lib: %s", err)
return
}
- Lib.Library = *l2
- Logger.Println("Done reloading library")
+ a.Library.Library = *l2
+ Logger.Println("Done reloading lib")
}
-func setLibHandler(w http.ResponseWriter, r *http.Request) {
+func (a *App) LibraryReload() {
+ cur := a.Library.Folder
+ a.LibrarySet(cur)
+ return
+}
+
+func (a *App) HandleSetLib(w http.ResponseWriter, r *http.Request) {
if unauthorizedIfNotLocal(w, r) {
return
}
@@ -60,39 +105,12 @@ func setLibHandler(w http.ResponseWriter, r *http.Request) {
return
}
- DefaultLib = r.Form.Get("path")
- reloadLib()
- http.Redirect(w, r, "/", 302)
-}
-
-func staticHandler(w http.ResponseWriter, r *http.Request){
- /*
- vars := mux.Vars(r)
-
- fn, ok := vars["fn"]
- if !ok {
- http.Error(w, "Not found", http.StatusNotFound)
- return
- }
- */
-
- fn := r.URL.Path
-
- fh, err := embeddedStatic.Open(fn)
- if err != nil {
- Logger.Printf("While reading embedded file: %s", err)
- http.Error(w, "Not found", http.StatusNotFound)
- return
- }
- defer fh.Close()
+ a.LibrarySet(r.Form.Get("path"))
- _, err = io.Copy(w, fh)
- if err != nil {
- Logger.Printf("While sending static file: %s", err)
- }
+ http.Redirect(w, r, "/", 302)
}
-func quitHandler(w http.ResponseWriter, r *http.Request) {
+func (a *App) HandleQuit(w http.ResponseWriter, r *http.Request) {
if unauthorizedIfNotLocal(w, r) {
return
}
@@ -176,28 +194,25 @@ func main() {
Logger.SetFlags(log.LstdFlags | log.Llongfile)
}
- var err error
- var l *steam.Library
- l, err = steam.NewLibrary(DefaultLib)
+ a, err := NewApp(DefaultLib)
if err != nil {
- Logger.Fatalf("While opening library path: %s", err)
+ Logger.Fatal(err)
}
- Lib.Library = *l
- go installer(getPath)
+ go a.installer()
r := mux.NewRouter()
- r.HandleFunc("/quit", quitHandler)
- r.HandleFunc("/setLib", setLibHandler)
- r.HandleFunc("/delete", gameDelete)
- r.HandleFunc("/install", gameInstaller)
+ r.HandleFunc("/quit", a.HandleQuit)
+ r.HandleFunc("/setLib", a.HandleSetLib)
+ r.HandleFunc("/delete", a.HandleDelete)
+ r.HandleFunc("/install", a.HandleInstall)
r.HandleFunc("/steam-export-web.exe", serveSelf)
- r.HandleFunc("/download/{game}", gameDownloader)
- r.HandleFunc("/status", statsHandler)
+ r.HandleFunc("/download/{game}", a.HandleDownload)
+ r.HandleFunc("/status", a.HandleStats)
r.PathPrefix("/static").Handler(
http.FileServer(http.FS(embeddedStatic)))
- r.HandleFunc("/", index)
+ r.HandleFunc("/", a.HandleIndex)
s := http.Server{
Handler: r,
diff --git a/cmd/web/serve-self.go b/cmd/web/serve-self.go
index 103fbf1..8abb830 100644
--- a/cmd/web/serve-self.go
+++ b/cmd/web/serve-self.go
@@ -2,8 +2,8 @@ package main
import (
"io"
- "os"
"net/http"
+ "os"
)
func serveSelf(w http.ResponseWriter, r *http.Request) {
diff --git a/cmd/web/unix.go b/cmd/web/unix.go
index bbe6087..ba028ab 100644
--- a/cmd/web/unix.go
+++ b/cmd/web/unix.go
@@ -13,4 +13,3 @@ var DefaultLib string = filepath.Join(os.Getenv("HOME"), ".steam/steam/steamapps
func startBrowser() {
return
}
-
diff --git a/cmd/web/windows.go b/cmd/web/windows.go
index 034e347..f59761a 100644
--- a/cmd/web/windows.go
+++ b/cmd/web/windows.go
@@ -10,8 +10,7 @@ import (
var DefaultLib string = `C:\Program Files (x86)\Steam\steamapps`
func startBrowser() {
- time.Sleep(time.Second*3)
+ time.Sleep(time.Second * 3)
c := exec.Command("cmd", "/c", "start", "http://127.0.0.1"+Listen)
Logger.Printf("Running command: %s", c.Run())
}
-