aboutsummaryrefslogtreecommitdiff
path: root/steam/steam.go
diff options
context:
space:
mode:
Diffstat (limited to 'steam/steam.go')
-rw-r--r--steam/steam.go102
1 files changed, 53 insertions, 49 deletions
diff --git a/steam/steam.go b/steam/steam.go
index ff0ce5a..66ef7f4 100644
--- a/steam/steam.go
+++ b/steam/steam.go
@@ -4,24 +4,31 @@
package steam
import (
- "bufio"
+ "errors"
"fmt"
"io/ioutil"
- "os"
- "path/filepath"
"regexp"
- "strings"
+ "sync"
)
+var E_GameDoesNotExist = errors.New("Game does not exist")
+
// Library is used to represent the steam library, the Games map is populated
// by NewLibrary when called or when ProcessLibrary is called directly
+// The key in the map is the same as the Game's `Name` property.
+//
+// Status contains various bits of information about previous jobs
+// and the status of any currently running jobs
type Library struct {
- Folder string
- Games map[string]Game
+ folder string
+ games map[string]*Game
+ status *Jobs
+
+ m sync.Mutex
}
-// Game represents an actual game in the steam Library, allowing you to perform
-// a delete, package, and such.
+// Game represents an actual game in the steam Library. The purpose is only
+// to provide info on a game.
type Game struct {
Name string
LibraryPath string
@@ -39,7 +46,12 @@ func (g Game) Slug() string {
// NewLibrary returns a pointer to a processed library and an error
// if any
func NewLibrary(path string) (*Library, error) {
- l := &Library{}
+ l := &Library{
+ status: &Jobs{
+ running: make([]*Job, 0),
+ previous: make([]*Job, 0),
+ },
+ }
err := l.ProcessLibrary(path)
if err != nil {
return nil, err
@@ -57,73 +69,65 @@ func NewLibraryMust(path string) *Library {
return l
}
+// Games returns a slice of *Game for the current library
+func (l *Library) Games() []*Game {
+ l.m.Lock()
+ out := []*Game{}
+ for _, g := range l.games {
+ out = append(out, g)
+ }
+ l.m.Unlock()
+
+ return out
+}
+
+// Jobs returns the current *Jobs struct which can be used to keep track
+// of any long running operations on the library as well as any errors
+// encountered along the way
+func (l *Library) Status() *Jobs {
+ return l.status
+}
+
// ProcessLibrary Populates the "Folder" and "Games" fields based on the
// provided directory.
+//
func (s *Library) ProcessLibrary(r string) error {
+ if s.status.Running() {
+ return errors.New("Cannot process library with actions running")
+ }
+
if !hasCommon(r) {
return fmt.Errorf("No common directory in: %s", r)
}
- s.Games = make(map[string]Game)
+ s.m.Lock()
+ defer s.m.Unlock()
+ s.games = make(map[string]*Game)
dirs, err := ioutil.ReadDir(r + "/common")
if err != nil {
return err
}
- s.Folder = r
+ s.folder = r
for _, f := range dirs {
if f.IsDir() {
g := &Game{
Name: f.Name(),
LibraryPath: r,
}
- g.setSizeInfo()
+ g.SetSizeInfo()
- s.Games[f.Name()] = *g
+ s.games[f.Name()] = g
}
}
return nil
}
-// FindACF will return the filename of the ACF file for a given `game`
-func FindACF(libraryPath, game string) (string, error) {
- files, err := filepath.Glob(filepath.Join(libraryPath, "*.acf"))
- if err != nil {
- return "", err
- }
- for _, fn := range files {
- info, err := os.Lstat(fn)
- if err != nil {
- return "", err
- }
- // We don't want it if it's a directory
- if info.IsDir() {
- continue
- }
-
- // Open up the file
- f, err := os.Open(fn)
- if err != nil {
- return "", err
- }
- defer f.Close()
-
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- if strings.Contains(scanner.Text(), game) {
- return fn, nil
- }
- }
-
- }
- return "", fmt.Errorf("Couldn't find ACF file related to Game: %s", game)
-}
-
func (s *Library) String() (str string) {
- str = fmt.Sprintf("Library: %s\n", s.Folder)
+ str = fmt.Sprintf("Library: %s\n", s.folder)
str = str + "----\n"
- for _, v := range s.Games {
+ for _, v := range s.games {
str = str + fmt.Sprintf("%s\n", v.Name)
}
return