diff options
Diffstat (limited to 'golang')
-rw-r--r-- | golang/cmd/spacetraders/main.go | 24 | ||||
-rw-r--r-- | golang/pkg/api/agents.go | 25 | ||||
-rw-r--r-- | golang/pkg/api/api.go | 21 | ||||
-rw-r--r-- | golang/pkg/api/register.go | 27 | ||||
-rw-r--r-- | golang/pkg/api/ships.go | 46 | ||||
-rw-r--r-- | golang/pkg/database/db.go | 19 | ||||
-rw-r--r-- | golang/pkg/database/migrations.go | 16 | ||||
-rw-r--r-- | golang/pkg/database/sql/000_init.sql | 6 | ||||
-rw-r--r-- | golang/pkg/database/tokens.go | 7 | ||||
-rw-r--r-- | golang/pkg/model/agent.go | 10 | ||||
-rw-r--r-- | golang/pkg/model/register.go | 9 |
11 files changed, 104 insertions, 106 deletions
diff --git a/golang/cmd/spacetraders/main.go b/golang/cmd/spacetraders/main.go index 42d43a6..84d34ea 100644 --- a/golang/cmd/spacetraders/main.go +++ b/golang/cmd/spacetraders/main.go @@ -35,8 +35,8 @@ func main() { client := api.NewClient(ctx) defer client.Close() if err := run( - db, client, + db, ); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) if err := db.Close(); err != nil { @@ -47,11 +47,11 @@ func main() { } func run( - db *database.DB, client *api.Client, + db *database.DB, ) error { // ----- Get token or register --------------------------------------------- - r, err := client.Register("COSMIC", "ADYXAX-GO") + register, err := client.Register("COSMIC", "ADYXAX-GO") if err != nil { apiError := &api.APIError{} if errors.As(err, &apiError) { @@ -59,9 +59,14 @@ func run( case 4111: // Agent symbol has already been claimed token, err := db.GetToken() if err != nil || token == "" { - return fmt.Errorf("failed to register and failed to get a token from the database: someone stole are agent's callsign: %w", err) + return fmt.Errorf("failed to register and failed to get a token from the database: someone stole our agent's callsign: %w", err) } client.SetToken(token) + agent, err := client.MyAgent() + if err != nil { + return fmt.Errorf("failed to get agent: %w", err) + } + slog.Info("agent", "agent", agent) default: return fmt.Errorf("failed to register: %w\n", err) } @@ -71,22 +76,19 @@ func run( } else { token, err := db.GetToken() if err != nil || token == "" { - if err := db.AddToken(r.Token); err != nil { + if err := db.AddToken(register.Token); err != nil { return fmt.Errorf("failed to save token: %w", err) } - client.SetToken(r.Token) + client.SetToken(register.Token) } else { return fmt.Errorf("TODO server reset not implemented yet") } } - // ----- Update agent ------------------------------------------------------ - agent, err := client.MyAgent() - slog.Info("agent", "agent", agent, "err", err) // ----- Get ships --------------------------------------------------------- ships, err := client.MyShips() err = client.Dock(&ships[0]) - slog.Info("dock", "ship", ships[0], "err", err) + slog.Info("dock", "ship", ships[0].Nav.Status, "err", err) err = client.Orbit(&ships[0]) - slog.Info("orbit", "ship", ships[0], "err", err) + slog.Info("orbit", "ship", ships[0].Nav.Status, "err", err) return nil } diff --git a/golang/pkg/api/agents.go b/golang/pkg/api/agents.go index db5b7db..a2d5b6a 100644 --- a/golang/pkg/api/agents.go +++ b/golang/pkg/api/agents.go @@ -1,32 +1,17 @@ package api import ( - "encoding/json" - "fmt" "net/url" -) -type AgentMessage struct { - AccountID string `json:"accountId"` - Credits int `json:"credits"` - Headquarters string `json:"headquarters"` - ShipCount int `json:"shipCount"` - StartingFaction string `json:"startingFaction"` - Symbol string `json:"symbol"` -} + "git.adyxax.org/adyxax/spacetraders/v2/pkg/model" +) -func (c *Client) MyAgent() (*AgentMessage, error) { +func (c *Client) MyAgent() (*model.Agent, error) { uriRef := url.URL{Path: "my/agent"} - msg, err := c.Send("GET", &uriRef, nil) + var response model.Agent + err := c.Send("GET", &uriRef, nil, &response) if err != nil { return nil, err } - if msg.Error != nil { - return nil, msg.Error - } - var response AgentMessage - if err := json.Unmarshal(msg.Data, &response); err != nil { - return nil, fmt.Errorf("failed to unmarshal agent data: %w", err) - } return &response, nil } diff --git a/golang/pkg/api/api.go b/golang/pkg/api/api.go index 7aee2fa..472d9e5 100644 --- a/golang/pkg/api/api.go +++ b/golang/pkg/api/api.go @@ -43,7 +43,7 @@ type Response struct { Err error } -func (c *Client) Send(method string, uriRef *url.URL, payload any) (*APIMessage, error) { +func (c *Client) Send(method string, uriRef *url.URL, payload any, response any) error { responseChannel := make(chan *Response) c.requestsChannel <- &Request{ method: method, @@ -53,7 +53,24 @@ func (c *Client) Send(method string, uriRef *url.URL, payload any) (*APIMessage, uri: c.baseURI.ResolveReference(uriRef), } res := <-responseChannel - return res.Message, res.Err + if res.Err != nil { + return res.Err + } + err := res.Message.Error + if err != nil { + switch err.Code { + case 4214: + e := decodeShipInTransitError(err.Data) + time.Sleep(e.SecondsToArrival.Duration() * time.Second) + return c.Send(method, uriRef, payload, response) + default: + return err + } + } + if err := json.Unmarshal(res.Message.Data, &response); err != nil { + return fmt.Errorf("failed to unmarshal message: %w", err) + } + return nil } func queueProcessor(client *Client) { diff --git a/golang/pkg/api/register.go b/golang/pkg/api/register.go index 4f45cd1..d6c185c 100644 --- a/golang/pkg/api/register.go +++ b/golang/pkg/api/register.go @@ -1,38 +1,25 @@ package api import ( - "encoding/json" - "fmt" "net/url" -) -type RegisterMessage struct { - //agent - //contract - //faction - //ship - Token string `json:"token"` -} + "git.adyxax.org/adyxax/spacetraders/v2/pkg/model" +) -func (c *Client) Register(faction, symbol string) (*RegisterMessage, error) { +func (c *Client) Register(faction, symbol string) (*model.Register, error) { type RegisterRequest struct { Faction string `json:"faction"` Symbol string `json:"symbol"` } uriRef := url.URL{Path: "register"} - msg, err := c.Send("POST", &uriRef, RegisterRequest{ + payload := RegisterRequest{ Faction: faction, Symbol: symbol, - }) + } + var response model.Register + err := c.Send("POST", &uriRef, payload, &response) if err != nil { return nil, err } - if msg.Error != nil { - return nil, msg.Error - } - var response RegisterMessage - if err := json.Unmarshal(msg.Data, &response); err != nil { - return nil, fmt.Errorf("failed to unmarshal register data: %w", err) - } return &response, nil } diff --git a/golang/pkg/api/ships.go b/golang/pkg/api/ships.go index afcf530..dc6a27c 100644 --- a/golang/pkg/api/ships.go +++ b/golang/pkg/api/ships.go @@ -1,11 +1,9 @@ package api import ( - "encoding/json" "fmt" "net/url" "path" - "time" "git.adyxax.org/adyxax/spacetraders/v2/pkg/model" ) @@ -18,41 +16,22 @@ func (c *Client) Dock(s *model.Ship) error { Nav model.Nav `json:"nav"` } uriRef := url.URL{Path: path.Join("my/ships", s.Symbol, "dock")} - msg, err := c.Send("POST", &uriRef, nil) + var response DockResponse + err := c.Send("POST", &uriRef, nil, &response) if err != nil { return fmt.Errorf("failed to dock ship %s: %w", s.Symbol, err) } - if msg.Error != nil { - switch msg.Error.Code { - case 4214: - e := decodeShipInTransitError(msg.Error.Data) - time.Sleep(e.SecondsToArrival.Duration() * time.Second) - return c.Dock(s) - default: - return msg.Error - } - } - var response DockResponse - if err := json.Unmarshal(msg.Data, &response); err != nil { - return fmt.Errorf("failed to unmarshal dock data: %w", err) - } s.Nav = response.Nav return nil } func (c *Client) MyShips() ([]model.Ship, error) { uriRef := url.URL{Path: "my/ships"} - msg, err := c.Send("GET", &uriRef, nil) + var response []model.Ship + err := c.Send("GET", &uriRef, nil, &response) if err != nil { return nil, fmt.Errorf("failed to get ships: %w", err) } - if msg.Error != nil { - return nil, fmt.Errorf("failed to get ships: %w", msg.Error) - } - var response []model.Ship - if err := json.Unmarshal(msg.Data, &response); err != nil { - return nil, fmt.Errorf("failed to unmarshal ships data: %w", err) - } return response, nil } @@ -64,24 +43,11 @@ func (c *Client) Orbit(s *model.Ship) error { Nav model.Nav `json:"nav"` } uriRef := url.URL{Path: path.Join("my/ships", s.Symbol, "orbit")} - msg, err := c.Send("POST", &uriRef, nil) + var response OrbitResponse + err := c.Send("POST", &uriRef, nil, &response) if err != nil { return fmt.Errorf("failed to orbit ship %s: %w", s.Symbol, err) } - if msg.Error != nil { - switch msg.Error.Code { - case 4214: - e := decodeShipInTransitError(msg.Error.Data) - time.Sleep(e.SecondsToArrival.Duration() * time.Second) - return c.Orbit(s) - default: - return msg.Error - } - } - var response OrbitResponse - if err := json.Unmarshal(msg.Data, &response); err != nil { - return fmt.Errorf("failed to unmarshal orbit data: %w", err) - } s.Nav = response.Nav return nil } diff --git a/golang/pkg/database/db.go b/golang/pkg/database/db.go new file mode 100644 index 0000000..3e07db3 --- /dev/null +++ b/golang/pkg/database/db.go @@ -0,0 +1,19 @@ +package database + +import ( + "context" + "database/sql" +) + +type DB struct { + ctx context.Context + db *sql.DB +} + +func (db *DB) Exec(query string, args ...any) (sql.Result, error) { + return db.db.ExecContext(db.ctx, query, args...) +} + +func (db *DB) QueryRow(query string, args ...any) *sql.Row { + return db.db.QueryRowContext(db.ctx, query, args...) +} diff --git a/golang/pkg/database/migrations.go b/golang/pkg/database/migrations.go index 94207a5..b167087 100644 --- a/golang/pkg/database/migrations.go +++ b/golang/pkg/database/migrations.go @@ -9,11 +9,6 @@ import ( _ "github.com/mattn/go-sqlite3" ) -type DB struct { - ctx context.Context - db *sql.DB -} - //go:embed sql/*.sql var schemaFiles embed.FS @@ -61,15 +56,22 @@ func DBInit(ctx context.Context, url string) (myDB *DB, err error) { return nil, err } + tx, err := db.Begin() + if err != nil { + return nil, err + } for version < len(statements) { - if _, err = db.ExecContext(ctx, statements[version]); err != nil { + if _, err = tx.ExecContext(ctx, statements[version]); err != nil { + tx.Rollback() return nil, err } version++ } - if _, err = db.ExecContext(ctx, `DELETE FROM schema_version; INSERT INTO schema_version (version) VALUES (?);`, version); err != nil { + if _, err = tx.ExecContext(ctx, `DELETE FROM schema_version; INSERT INTO schema_version (version) VALUES (?);`, version); err != nil { + tx.Rollback() return nil, err } + tx.Commit() return &DB{ctx: ctx, db: db}, nil } diff --git a/golang/pkg/database/sql/000_init.sql b/golang/pkg/database/sql/000_init.sql index c06d2d3..bd92821 100644 --- a/golang/pkg/database/sql/000_init.sql +++ b/golang/pkg/database/sql/000_init.sql @@ -1,7 +1,7 @@ CREATE TABLE schema_version ( - version INTEGER NOT NULL + version INTEGER NOT NULL ); CREATE TABLE tokens ( - id INTEGER PRIMARY KEY, - data TEXT NOT NULL + id INTEGER PRIMARY KEY, + data TEXT NOT NULL ); diff --git a/golang/pkg/database/tokens.go b/golang/pkg/database/tokens.go index 0787b5c..0356cb2 100644 --- a/golang/pkg/database/tokens.go +++ b/golang/pkg/database/tokens.go @@ -1,11 +1,12 @@ package database func (db *DB) AddToken(token string) error { - _, err := db.db.ExecContext(db.ctx, `INSERT INTO tokens(data) VALUES (?);`, token) + _, err := db.Exec(`INSERT INTO tokens(data) VALUES (?);`, token) return err } -func (db *DB) GetToken() (token string, err error) { - err = db.db.QueryRowContext(db.ctx, `SELECT data FROM tokens;`).Scan(&token) +func (db *DB) GetToken() (string, error) { + var token string + err := db.QueryRow(`SELECT data FROM tokens;`).Scan(&token) return token, err } diff --git a/golang/pkg/model/agent.go b/golang/pkg/model/agent.go new file mode 100644 index 0000000..1c2b80b --- /dev/null +++ b/golang/pkg/model/agent.go @@ -0,0 +1,10 @@ +package model + +type Agent struct { + AccountID string `json:"accountId"` + Credits int `json:"credits"` + Headquarters string `json:"headquarters"` + ShipCount int `json:"shipCount"` + StartingFaction string `json:"startingFaction"` + Symbol string `json:"symbol"` +} diff --git a/golang/pkg/model/register.go b/golang/pkg/model/register.go new file mode 100644 index 0000000..cf48b8b --- /dev/null +++ b/golang/pkg/model/register.go @@ -0,0 +1,9 @@ +package model + +type Register struct { + Agent Agent `json:"agent"` + //contract + //faction + Ship Ship `json:"ship"` + Token string `json:"token"` +} |