201 lines
5.3 KiB
Go
201 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
)
|
|
|
|
type PlayerService struct {
|
|
db *DB
|
|
}
|
|
type PlayerServiceQuery struct {
|
|
Name *string `db:"name"`
|
|
ID *int64 `db:"id"`
|
|
}
|
|
|
|
func (ps *PlayerService) Query(query PlayerServiceQuery) ([]Player, error) {
|
|
res := []Player{}
|
|
sqlQuery := "SELECT id, name, guild FROM player"
|
|
whereQuery := BuildWhereQuery(query)
|
|
if whereQuery != "" {
|
|
sqlQuery += " " + whereQuery
|
|
}
|
|
|
|
rows, err := ps.db.readConn.Query(sqlQuery)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed getting players for query %q: %v", sqlQuery, err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
player := Player{}
|
|
err := rows.Scan(&player.ID, &player.Name, &player.Guild.ID)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed scanning player: %v", err)
|
|
}
|
|
res = append(res, player)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (ps *PlayerService) Save(player Player) (Player, error) {
|
|
log.Printf("Saving player %s", player.Name)
|
|
res, err := ps.db.writeConn.Exec("insert into player (name, guild) values (?, ?) on conflict (name) do update set guild = ?", player.Name, player.Guild.ID, player.Guild.ID)
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed to update player: %v", err)
|
|
}
|
|
|
|
id := player.ID
|
|
if id == 0 {
|
|
id, err = res.LastInsertId()
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed to get last insert id: %v", err)
|
|
}
|
|
}
|
|
log.Printf("Updated player %s with id %d", player.Name, id)
|
|
|
|
qres, err := ps.Query(PlayerServiceQuery{ID: &id})
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed getting player for id %d: %v", id, err)
|
|
}
|
|
if len(qres) > 1 {
|
|
return player, fmt.Errorf("more than one player found for id %d", id)
|
|
}
|
|
if len(qres) == 0 {
|
|
return player, fmt.Errorf("no player found for id %d", id)
|
|
}
|
|
|
|
return qres[0], nil
|
|
}
|
|
|
|
func (ps *PlayerService) Create(name string, guild Guild) (Player, error) {
|
|
log.Printf("Creating player %s in guild %s", name, guild.Name)
|
|
player := Player{}
|
|
res, err := ps.db.writeConn.Exec("insert into player (name, guild) values (?, ?)", name, guild.ID)
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed to insert player: %v", err)
|
|
}
|
|
|
|
id, err := res.LastInsertId()
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed to get last insert id: %v", err)
|
|
}
|
|
log.Printf("Created player %s in guild %s with id %d", name, guild.Name, id)
|
|
|
|
qres, err := ps.Query(PlayerServiceQuery{ID: &id})
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed getting player for id %d: %v", id, err)
|
|
}
|
|
if len(qres) > 1 {
|
|
return player, fmt.Errorf("more than one player found for id %d", id)
|
|
}
|
|
|
|
return qres[0], nil
|
|
}
|
|
|
|
func (ps *PlayerService) GetOrCreate(name string, guild Guild) (Player, error) {
|
|
player := Player{}
|
|
players, err := ps.Query(PlayerServiceQuery{Name: &name})
|
|
if len(players) > 1 {
|
|
return player, fmt.Errorf("more than one player found for name %s", name)
|
|
}
|
|
if err != nil || len(players) == 0 {
|
|
player, err = ps.Create(name, guild)
|
|
if err != nil {
|
|
return player, fmt.Errorf("failed creating player: %v", err)
|
|
}
|
|
}
|
|
if len(players) == 1 {
|
|
player = players[0]
|
|
}
|
|
return player, nil
|
|
}
|
|
|
|
type (
|
|
FullPlayer struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Guild struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
} `json:"guild"`
|
|
Associations []FullPlayerAssociation `json:"associations"`
|
|
Notes []FullPlayerNote `json:"notes"`
|
|
}
|
|
|
|
FullPlayerAssociation struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Note string `json:"note"`
|
|
}
|
|
|
|
FullPlayerNote struct {
|
|
ID int64 `json:"id"`
|
|
Content string `json:"content"`
|
|
Timestamp string `json:"timestamp"`
|
|
}
|
|
)
|
|
|
|
func (ps *PlayerService) GetAllPlayerInfo(name string, nnotes int) (FullPlayer, error) {
|
|
res := FullPlayer{}
|
|
|
|
err := ps.db.readConn.QueryRow(selectPlayer, name).Scan(&res.ID, &res.Name, &res.Guild.ID, &res.Guild.Name)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed getting player info: %v", err)
|
|
}
|
|
|
|
rows, err := ps.db.readConn.Query(selectAssociation, res.ID)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed getting player associations: %v", err)
|
|
}
|
|
|
|
for rows.Next() {
|
|
assoc := FullPlayerAssociation{}
|
|
err := rows.Scan(&assoc.ID, &assoc.Name, &assoc.Note)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed scanning association: %v", err)
|
|
}
|
|
res.Associations = append(res.Associations, assoc)
|
|
}
|
|
rows.Close()
|
|
|
|
rows, err = ps.db.readConn.Query(selectNotes, res.ID, nnotes)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed getting player notes: %v", err)
|
|
}
|
|
|
|
for rows.Next() {
|
|
note := FullPlayerNote{}
|
|
err := rows.Scan(¬e.ID, ¬e.Content, ¬e.Timestamp)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed scanning note: %v", err)
|
|
}
|
|
res.Notes = append(res.Notes, note)
|
|
}
|
|
rows.Close()
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (ps *PlayerService) GetAllPlayers() ([]Player, error) {
|
|
res := []Player{}
|
|
|
|
rows, err := ps.db.readConn.Query(selectPlayers)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed getting players: %v", err)
|
|
}
|
|
|
|
for rows.Next() {
|
|
player := Player{}
|
|
err := rows.Scan(&player.ID, &player.Name, &player.Guild.ID, &player.Guild.Name, &player.Notes, &player.Associations)
|
|
if err != nil {
|
|
return res, fmt.Errorf("failed scanning player: %v", err)
|
|
}
|
|
res = append(res, player)
|
|
}
|
|
rows.Close()
|
|
|
|
return res, nil
|
|
}
|