diff options
Diffstat (limited to 'cmd/web')
| -rw-r--r-- | cmd/web/delete.go | 42 | ||||
| -rw-r--r-- | cmd/web/download.go | 31 | ||||
| -rw-r--r-- | cmd/web/flagSliceString.go | 12 | ||||
| -rw-r--r-- | cmd/web/index.go | 52 | ||||
| -rw-r--r-- | cmd/web/install.go | 116 | ||||
| -rw-r--r-- | cmd/web/main.go | 71 | ||||
| -rw-r--r-- | cmd/web/unix.go | 6 | ||||
| -rw-r--r-- | cmd/web/windows.go | 12 |
8 files changed, 290 insertions, 52 deletions
diff --git a/cmd/web/delete.go b/cmd/web/delete.go new file mode 100644 index 0000000..7188b45 --- /dev/null +++ b/cmd/web/delete.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "net/http" +) + +func gameDelete(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + Logger.Printf("Installer: While parsing form: %s", err) + http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) + return + } + + game := r.PostForm.Get("name") + + if game == "" { + Logger.Println("Deleter: No game specified") + http.Error(w, "Game param required", 400) + return + } + + libMu.RLock() + g, ok := Lib.Games[game] + libMu.RUnlock() + if !ok { + Logger.Printf("Missing: %s", game) + http.Error(w, "Game is missing", 404) + return + } + + err = g.Delete() + if err != nil { + Logger.Printf("Error removing game: %s", err) + http.Error(w, fmt.Sprintf("Error removing game: %s", err), 500) + return + } + + reloadLib() + http.Redirect(w, r, "/", 302) +} diff --git a/cmd/web/download.go b/cmd/web/download.go new file mode 100644 index 0000000..a640ea2 --- /dev/null +++ b/cmd/web/download.go @@ -0,0 +1,31 @@ +package main + +import ( + "net/http" + + "github.com/gorilla/mux" +) + +func gameDownloader(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + game := vars["game"] + + libMu.RLock() + g, ok := Lib.Games[game] + libMu.RUnlock() + if !ok { + Logger.Printf("Missing: %s", game) + http.Error(w, "Game is missing", 404) + return + } + + w.Header().Add("Content-type", "application/tar") + + err := g.Package(w) + if err != nil { + Logger.Printf("Error Sending game: %s", err) + // Headers already sent, don't bother sending an error + } + +} + diff --git a/cmd/web/flagSliceString.go b/cmd/web/flagSliceString.go new file mode 100644 index 0000000..ec06966 --- /dev/null +++ b/cmd/web/flagSliceString.go @@ -0,0 +1,12 @@ +package main + +type FlagSliceString []string + +func (f *FlagSliceString) String() string { + return "" +} + +func (f *FlagSliceString) Set(val string) error { + *f = append(*f, val) + return nil +} diff --git a/cmd/web/index.go b/cmd/web/index.go index 1a2c344..2dfe20e 100644 --- a/cmd/web/index.go +++ b/cmd/web/index.go @@ -1,8 +1,10 @@ package main import ( - "net/http" "html/template" + "net/http" + + "riedstra.dev/mitch/steam-export/steam" ) var ( @@ -23,33 +25,71 @@ var ( </div> </nav> -<h2>Library: {{.Folder}}</h2> +<h2>Library: {{.Lib.Folder}}</h2> + +{{ if .Info.Running }} +<pre><code> +Currently Downloading from: {{.Info.Url}} +</pre></code> +{{ end }} + +{{ if .Info.Error }} +<pre><code> +Error {{.Info.Error}} Downloading from: {{.Info.Url}} +{{ end }} +</pre></code> <p> Installed games: + +Tip: You can right click and save link as to specify a save location, e.g. +an external hard drive </p> <ul> -{{ range $key, $val := .Games }} +{{ range $key, $val := .Lib.Games }} <li> <a href="/download/{{$key}}">{{$key}}</a> </li> {{ end }} </ul> -Install a game from a URL: +Delete a game: ( Type out exact name, case sensitive ) + +<form action="/delete" method="POST"> + <input type="text" name="name" /> + <input type="submit" value="Delete"> +</form> + +Install a game from a URL or local file path: <form action="/install" method="GET"> - <input type="text" name="url" /> + <input type="text" name="uri" /> <input type="submit" value="Install"> </form> +<p> +Note that You can also give someone a URL to install a game if they're running +this program, e.g. <br /> +http://127.0.0.1:8899/install?uri=http://my-server-ip-or-hostname/download/My Game +</p> + + </body> `)) ) func index(w http.ResponseWriter, r *http.Request) { - err := Templ.ExecuteTemplate(w, "index", Lib) + libMu.RLock() + defer libMu.RUnlock() + status.m.RLock() + defer status.m.RUnlock() + + err := Templ.ExecuteTemplate(w, "index", + struct { + Lib *steam.Library + Info *statusInfo + }{Lib, status.s}) if err != nil { Logger.Printf("While Rendering template: %s", err) } diff --git a/cmd/web/install.go b/cmd/web/install.go new file mode 100644 index 0000000..cd2f03a --- /dev/null +++ b/cmd/web/install.go @@ -0,0 +1,116 @@ +package main + +import ( + "net/url" + "os" + "strings" + "fmt" + "net/http" + "sync" +) + +type statusInfo struct { + Running bool + Error error + Url string +} + +var ( + status = struct { + m *sync.RWMutex + s *statusInfo + }{ + m: &sync.RWMutex{}, + s: &statusInfo{Running: false}, + } + + getPath = make(chan string) +) + +func installHttp(u string) error { + resp, err := http.Get(u) + if err != nil { + return fmt.Errorf("Installer: getting %w", err) + } + + err = Lib.Extract(resp.Body) + if err != nil { + return fmt.Errorf("Installer: extracting %w", err) + } + resp.Body.Close() + return nil +} + +func installPath(p string) error { + fh, err := os.Open(p) + if err != nil { + return fmt.Errorf("Installer: opening %w", err) + } + + err = Lib.Extract(fh) + if err != nil { + return fmt.Errorf("Installer: opening %w", err) + } + fh.Close() + return nil +} + +func installer(urls <-chan string) { + var err error + for u := range urls { + status.m.Lock() + status.s.Running = true + status.s.Url = u + status.m.Unlock() + + if strings.HasPrefix(u, "http") { + err = installHttp(u) + } else { + err = installPath(u) + } + + status.m.Lock() + status.s.Running = false + status.s.Error = err + status.m.Unlock() + + reloadLib() + } +} + +func gameInstaller(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + Logger.Printf("Installer: While parsing form: %s", err) + http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) + return + } + + uri := r.Form.Get("uri") + + if strings.HasPrefix(uri, "http") { + _, err := url.Parse(uri) + if err != nil { + Logger.Printf("Installer: While parsing url: %s", err) + http.Error(w, fmt.Sprintf("Invalid url: %s", err), 400) + return + } + } else { + fi, err := os.Stat(uri) + if err != nil { + Logger.Printf("Installer: While parsing url: %s", err) + http.Error(w, fmt.Sprintf("Invalid uri/path: %s", err), 400) + return + } + + if !fi.Mode().IsRegular() { + Logger.Printf("Installer: While parsing url: %s", err) + http.Error(w, fmt.Sprintf("Invalid uri/path: %s", err), 400) + return + } + } + + getPath <- uri + + http.Redirect(w, r, "/", 302) +} diff --git a/cmd/web/main.go b/cmd/web/main.go index 93025e5..64321da 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -5,7 +5,7 @@ import ( "log" "net/http" "os" - "path/filepath" + "sync" "github.com/gorilla/mux" "riedstra.dev/mitch/steam-export/steam" @@ -15,75 +15,54 @@ var ( Logger = log.New(os.Stderr, "", log.LstdFlags) Listen = ":8899" - Lib = steam.NewLibraryMust(DefaultLib) + libMu = &sync.RWMutex{} + Lib *steam.Library ) -//size, err := estimateSize(g.LibraryPath + "common/" + g.Name) -//if err != nil { -// http.Error(w, "Encountered:"+err, 500) -// return -//} -func estimateSize(pth string) (int64, error) { - var size int64 = 0 - - err := filepath.Walk(pth, func(path string, info os.FileInfo, err error) error { - - if err != nil { - return err - } - - if info.Mode().IsRegular() { - size = size + info.Size() - } - - return nil - }) - - return size, err - -} - -func gameDownloader(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - game := vars["game"] - - g, ok := Lib.Games[game] - if !ok { - Logger.Printf("Missing: %s", game) - http.Error(w, "Game is missing", 404) - return - } - - w.Header().Add("Content-type", "application/tar") - - err := g.Package(w) +func reloadLib() { + libMu.Lock() + defer libMu.Unlock() + var err error + Lib, err = steam.NewLibrary(DefaultLib) if err != nil { - Logger.Printf("Error Sending game: %s", err) - // Headers already sent, don't bother sending an error + Logger.Printf("Error reopening library: %s", err) + return } - } func main() { fl := flag.NewFlagSet("steam-export", flag.ExitOnError) debug := fl.Bool("d", false, "Print line numbers in log") - listen := fl.String("l", Listen, "What address do we listen on?") + fl.StringVar(&Listen, "l", Listen, "What address do we listen on?") + fl.StringVar(&DefaultLib, "L", DefaultLib, "Full path to default library") fl.Parse(os.Args[1:]) if *debug { Logger.SetFlags(log.LstdFlags | log.Llongfile) } + var err error + Lib, err = steam.NewLibrary(DefaultLib) + if err != nil { + Logger.Fatalf("While opening library path: %s", err) + } + + go installer(getPath) + r := mux.NewRouter() + r.HandleFunc("/delete", gameDelete) + r.HandleFunc("/install", gameInstaller) r.HandleFunc("/download/{game}", gameDownloader) r.HandleFunc("/style.css", cssHandler) r.HandleFunc("/", index) s := http.Server{ Handler: r, - Addr: *listen, + Addr: Listen, } + go startBrowser() + Logger.Fatal(s.ListenAndServe()) } diff --git a/cmd/web/unix.go b/cmd/web/unix.go index 6b1b1ae..bbe6087 100644 --- a/cmd/web/unix.go +++ b/cmd/web/unix.go @@ -8,3 +8,9 @@ import ( ) var DefaultLib string = filepath.Join(os.Getenv("HOME"), ".steam/steam/steamapps") + +// TODO +func startBrowser() { + return +} + diff --git a/cmd/web/windows.go b/cmd/web/windows.go index 2effa08..9fe8ab6 100644 --- a/cmd/web/windows.go +++ b/cmd/web/windows.go @@ -2,4 +2,16 @@ package main +import ( + "os/exec" + "time" +) + var DefaultLib string = `C:\Program Files (x86)\Steam\steamapps` + +func startBrowser() { + time.Sleep(time.Second*3) + c := exec.Command("cmd", "/c", "start", "http://127.0.0.1"+Listen) + Logger.Println(c.Run()) +} + |
