2021-09-13 14:21:37 +01:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2021-09-13 20:58:52 +01:00
|
|
|
"fmt"
|
2021-09-13 22:39:09 +01:00
|
|
|
"time"
|
2021-09-13 14:21:37 +01:00
|
|
|
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
|
|
|
|
|
|
"git.ctrlz.es/mgdelacroix/craban/model"
|
2021-09-13 22:39:09 +01:00
|
|
|
"git.ctrlz.es/mgdelacroix/craban/utils"
|
2021-09-13 14:21:37 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var gameColumns = []string{"id", "user_id", "name"}
|
2021-09-13 22:39:09 +01:00
|
|
|
var gameMemberColumns = []string{"game_id", "user_id", "role", "lastviewedat"}
|
2021-09-13 14:21:37 +01:00
|
|
|
|
|
|
|
type GameStore struct {
|
|
|
|
Conn *sql.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewGameStore(s *Store) *GameStore {
|
|
|
|
return &GameStore{Conn: s.Conn}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) Q() sq.StatementBuilderType {
|
|
|
|
return sq.StatementBuilder.RunWith(gs.Conn)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) gamesFromRows(rows *sql.Rows) ([]*model.Game, error) {
|
|
|
|
games := []*model.Game{}
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var game model.Game
|
|
|
|
|
|
|
|
err := rows.Scan(
|
|
|
|
&game.ID,
|
|
|
|
&game.UserID,
|
|
|
|
&game.Name,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
games = append(games, &game)
|
|
|
|
}
|
|
|
|
|
|
|
|
return games, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) getGameByCondition(condition sq.Eq) (*model.Game, error) {
|
|
|
|
games, err := gs.getGamesByCondition(condition)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return games[0], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) getGamesByCondition(condition sq.Eq) ([]*model.Game, error) {
|
2021-09-13 20:58:52 +01:00
|
|
|
rows, err := gs.Q().Select(gameColumns...).
|
2021-09-13 14:21:37 +01:00
|
|
|
From("games").
|
|
|
|
Where(condition).
|
|
|
|
Query()
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot get games: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
games, err := gs.gamesFromRows(rows)
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot get games from rows: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(games) == 0 {
|
|
|
|
return nil, sql.ErrNoRows
|
|
|
|
}
|
|
|
|
|
|
|
|
return games, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) GetByID(id int) (*model.Game, error) {
|
|
|
|
return gs.getGameByCondition(sq.Eq{"id": id})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gs *GameStore) Create(name string, userID int) (*model.Game, error) {
|
|
|
|
// ToDo: generate transaction
|
|
|
|
// ToDo: add tests
|
|
|
|
|
|
|
|
res, err := gs.Q().Insert("games").
|
|
|
|
Columns(gameColumns[1:]...).
|
2021-09-13 20:58:52 +01:00
|
|
|
Values(userID, name).
|
2021-09-13 14:21:37 +01:00
|
|
|
Exec()
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot insert game: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
id, err := res.LastInsertId()
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot get last insert id for created game: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
game, err := gs.GetByID(int(id))
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot get game by id: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
|
2021-09-25 16:32:37 +01:00
|
|
|
_, err = gs.Q().Insert("gamemembers").
|
2021-09-13 14:21:37 +01:00
|
|
|
Columns(gameMemberColumns...).
|
2021-09-13 22:39:09 +01:00
|
|
|
Values(game.ID, userID, model.RoleGameMaster, 0).
|
2021-09-13 14:21:37 +01:00
|
|
|
Exec()
|
|
|
|
if err != nil {
|
2021-09-13 20:58:52 +01:00
|
|
|
return nil, fmt.Errorf("cannot insert gamemember for created game: %w", err)
|
2021-09-13 14:21:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return game, nil
|
|
|
|
}
|
2021-09-13 20:58:52 +01:00
|
|
|
|
2021-09-13 22:39:09 +01:00
|
|
|
func (gs *GameStore) UpdateLastViewedAt(gameID, userID int) error {
|
|
|
|
_, err := gs.Q().Update("gamemembers").
|
|
|
|
Set("lastviewedat", utils.Millis(time.Now())).
|
|
|
|
Where(sq.Eq{"game_id": gameID, "user_id": userID}).
|
|
|
|
Exec()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-09-13 20:58:52 +01:00
|
|
|
func (gs *GameStore) gameMembersFromRows(rows *sql.Rows) ([]*model.GameMember, error) {
|
|
|
|
gameMembers := []*model.GameMember{}
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var gameMember model.GameMember
|
|
|
|
|
|
|
|
err := rows.Scan(
|
|
|
|
&gameMember.GameID,
|
|
|
|
&gameMember.UserID,
|
|
|
|
&gameMember.Role,
|
2021-09-13 22:39:09 +01:00
|
|
|
&gameMember.LastViewedAt,
|
2021-09-13 20:58:52 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
gameMembers = append(gameMembers, &gameMember)
|
|
|
|
}
|
|
|
|
|
|
|
|
return gameMembers, nil
|
|
|
|
}
|
|
|
|
|
2021-09-13 21:05:56 +01:00
|
|
|
func (gs *GameStore) GetMembers(gameID int) ([]*model.GameMember, error) {
|
2021-09-13 20:58:52 +01:00
|
|
|
rows, err := gs.Q().Select(gameMemberColumns...).
|
|
|
|
From("gamemembers").
|
|
|
|
Where(sq.Eq{"game_id": gameID}).
|
|
|
|
Query()
|
|
|
|
if err != nil {
|
2021-09-13 21:05:56 +01:00
|
|
|
return nil, fmt.Errorf("cannot get game members: %w", err)
|
2021-09-13 20:58:52 +01:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
gameMembers, err := gs.gameMembersFromRows(rows)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot get game members from rows: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(gameMembers) == 0 {
|
|
|
|
return nil, sql.ErrNoRows
|
|
|
|
}
|
|
|
|
|
|
|
|
return gameMembers, nil
|
|
|
|
}
|
2021-09-13 21:05:56 +01:00
|
|
|
|
|
|
|
func (gs *GameStore) GetMember(gameID, userID int) (*model.GameMember, error) {
|
|
|
|
rows, err := gs.Q().Select(gameMemberColumns...).
|
|
|
|
From("gamemembers").
|
|
|
|
Where(sq.Eq{"game_id": gameID, "user_id": userID}).
|
|
|
|
Query()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot get game member: %w", err)
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
gameMembers, err := gs.gameMembersFromRows(rows)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot get game member from rows: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(gameMembers) == 0 {
|
|
|
|
return nil, sql.ErrNoRows
|
|
|
|
}
|
|
|
|
|
|
|
|
return gameMembers[0], nil
|
|
|
|
}
|
|
|
|
|
2021-09-13 21:13:22 +01:00
|
|
|
func (gs *GameStore) AddMember(gameID, userID int, role string) (*model.GameMember, error) {
|
|
|
|
_, err := gs.Q().Insert("gamemembers").
|
|
|
|
Columns(gameMemberColumns...).
|
2021-09-13 22:39:09 +01:00
|
|
|
Values(gameID, userID, role, 0).
|
2021-09-13 21:13:22 +01:00
|
|
|
Exec()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot insert gamemember: %w", err)
|
|
|
|
}
|
2021-09-13 21:05:56 +01:00
|
|
|
|
2021-09-13 21:13:22 +01:00
|
|
|
return gs.GetMember(gameID, userID)
|
|
|
|
}
|
2021-09-13 21:45:08 +01:00
|
|
|
|
|
|
|
func (gs *GameStore) ListForUser(userID int) ([]*model.Game, error) {
|
|
|
|
return gs.getGamesByCondition(sq.Eq{"user_id": userID})
|
|
|
|
}
|
2021-09-13 21:59:52 +01:00
|
|
|
|
|
|
|
func (gs *GameStore) List() ([]*model.Game, error) {
|
|
|
|
return gs.getGamesByCondition(sq.Eq{})
|
|
|
|
}
|