Move everything to backend
This commit is contained in:
66
backend/associationService.go
Normal file
66
backend/associationService.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
type AssociationService struct {
|
||||
db *DB
|
||||
}
|
||||
type AssociationServiceQuery struct {
|
||||
LHSID *int64 `db:"lhs"`
|
||||
RHSID *int64 `db:"rhs"`
|
||||
NoteID *int64 `db:"note"`
|
||||
ID *int64 `db:"id"`
|
||||
}
|
||||
|
||||
func (as *AssociationService) Query(query AssociationServiceQuery) ([]Association, error) {
|
||||
res := []Association{}
|
||||
sqlQuery := "SELECT id, lhs, rhs, note FROM association"
|
||||
whereQuery := BuildWhereQuery(query)
|
||||
if whereQuery != "" {
|
||||
sqlQuery += " " + whereQuery
|
||||
}
|
||||
|
||||
rows, err := as.db.readConn.Query(sqlQuery)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed getting associations for query %q: %v", sqlQuery, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
association := Association{}
|
||||
err := rows.Scan(&association.ID, &association.LHS.ID, &association.RHS.ID, &association.Note)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed scanning association: %v", err)
|
||||
}
|
||||
res = append(res, association)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (as *AssociationService) Create(lhs Player, rhs Player, note string) (Association, error) {
|
||||
log.Printf("Creating association between %d and %d with note %s", lhs.ID, rhs.ID, note)
|
||||
association := Association{}
|
||||
res, err := as.db.writeConn.Exec("insert into association (lhs, rhs, note) values (?, ?, ?)", lhs.ID, rhs.ID, note)
|
||||
if err != nil {
|
||||
return association, fmt.Errorf("failed to insert association: %v", err)
|
||||
}
|
||||
|
||||
id, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return association, fmt.Errorf("failed to get last insert id: %v", err)
|
||||
}
|
||||
log.Printf("Created association between %d and %d with note %s with id %d", lhs.ID, rhs.ID, note, id)
|
||||
|
||||
qres, err := as.Query(AssociationServiceQuery{ID: &id})
|
||||
if err != nil {
|
||||
return association, fmt.Errorf("failed getting association for id %d: %v", id, err)
|
||||
}
|
||||
if len(qres) > 1 {
|
||||
return association, fmt.Errorf("more than one association found for id %d", id)
|
||||
}
|
||||
return qres[0], nil
|
||||
}
|
84
backend/db.go
Normal file
84
backend/db.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
Ready bool
|
||||
path string
|
||||
readConn *sql.DB
|
||||
writeConn *sql.DB
|
||||
}
|
||||
|
||||
func (db *DB) Open() error {
|
||||
if db.path == "" {
|
||||
return fmt.Errorf("database path not set")
|
||||
}
|
||||
|
||||
file, err := os.Open(db.path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
log.Printf("Database file does not exist at %s, creating", db.path)
|
||||
file, err := os.Create(db.path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create database file: %v", err)
|
||||
}
|
||||
log.Printf("Database created at %s", db.path)
|
||||
file.Close()
|
||||
} else {
|
||||
return fmt.Errorf("failed to open database file: %v", err)
|
||||
}
|
||||
}
|
||||
file.Close()
|
||||
|
||||
writeConn, err := sql.Open("sqlite3", db.path+"?_journal=WAL&_synchronous=NORMAL")
|
||||
if err != nil {
|
||||
Error.Printf("%++v", err)
|
||||
return err
|
||||
}
|
||||
writeConn.SetMaxOpenConns(1)
|
||||
writeConn.SetConnMaxIdleTime(30 * time.Second)
|
||||
writeConn.SetConnMaxLifetime(30 * time.Second)
|
||||
db.writeConn = writeConn
|
||||
|
||||
readConn, err := sql.Open("sqlite3", db.path+"?mode=ro&_journal=WAL&_synchronous=NORMAL&_mode=ro")
|
||||
if err != nil {
|
||||
Error.Printf("%++v", err)
|
||||
return err
|
||||
}
|
||||
readConn.SetMaxOpenConns(4)
|
||||
readConn.SetConnMaxIdleTime(30 * time.Second)
|
||||
readConn.SetConnMaxLifetime(30 * time.Second)
|
||||
db.readConn = readConn
|
||||
|
||||
db.Ready = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) Init(ddl string) error {
|
||||
if !db.Ready {
|
||||
return fmt.Errorf("database not ready")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
err := db.writeConn.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.readConn.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
27
backend/ddl.sql
Normal file
27
backend/ddl.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
create table guild (
|
||||
id integer primary key,
|
||||
name text
|
||||
);
|
||||
create unique index idx_guild_name on guild(name);
|
||||
|
||||
create table player (
|
||||
id integer primary key,
|
||||
name text,
|
||||
guild integer references guild(id)
|
||||
);
|
||||
create unique index idx_player_name on player(name);
|
||||
|
||||
create table association (
|
||||
id integer primary key,
|
||||
lhs integer references player(id),
|
||||
rhs integer references player(id),
|
||||
note text
|
||||
);
|
||||
|
||||
create table note (
|
||||
id integer primary key,
|
||||
content text,
|
||||
timestamp string,
|
||||
player integer references player(id)
|
||||
);
|
||||
create unique index idx_note_content on note(timestamp, player);
|
5
backend/go.mod
Normal file
5
backend/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module stinkinator
|
||||
|
||||
go 1.23.2
|
||||
|
||||
require github.com/mattn/go-sqlite3 v1.14.24
|
2
backend/go.sum
Normal file
2
backend/go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
83
backend/guildService.go
Normal file
83
backend/guildService.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
type GuildService struct {
|
||||
db *DB
|
||||
}
|
||||
type GuildServiceQuery struct {
|
||||
Name *string `db:"name"`
|
||||
ID *int64 `db:"id"`
|
||||
}
|
||||
|
||||
func (gs *GuildService) Query(query GuildServiceQuery) ([]Guild, error) {
|
||||
res := []Guild{}
|
||||
sqlQuery := "SELECT id, name FROM guild"
|
||||
whereQuery := BuildWhereQuery(query)
|
||||
if whereQuery != "" {
|
||||
sqlQuery += " " + whereQuery
|
||||
}
|
||||
|
||||
rows, err := gs.db.readConn.Query(sqlQuery)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed getting guilds for query %q: %v", sqlQuery, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
guild := Guild{}
|
||||
err := rows.Scan(&guild.ID, &guild.Name)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed scanning guild: %v", err)
|
||||
}
|
||||
res = append(res, guild)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (gs *GuildService) Create(name string) (Guild, error) {
|
||||
log.Printf("Creating guild %s", name)
|
||||
guild := Guild{}
|
||||
res, err := gs.db.writeConn.Exec("insert into guild (name) values (?)", name)
|
||||
if err != nil {
|
||||
return guild, fmt.Errorf("failed to insert guild: %v", err)
|
||||
}
|
||||
|
||||
id, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return guild, fmt.Errorf("failed to get last insert id: %v", err)
|
||||
}
|
||||
log.Printf("Created guild %s with id %d", name, id)
|
||||
|
||||
qres, err := gs.Query(GuildServiceQuery{ID: &id})
|
||||
if err != nil {
|
||||
return guild, fmt.Errorf("failed getting guild for id %d: %v", id, err)
|
||||
}
|
||||
if len(qres) > 1 {
|
||||
return guild, fmt.Errorf("more than one guild found for id %d", id)
|
||||
}
|
||||
|
||||
return qres[0], nil
|
||||
}
|
||||
|
||||
func (gs *GuildService) GetOrCreate(name string) (Guild, error) {
|
||||
guild := Guild{}
|
||||
guilds, err := gs.Query(GuildServiceQuery{Name: &name})
|
||||
if len(guilds) > 1 {
|
||||
return guild, fmt.Errorf("more than one guild found for name %s", name)
|
||||
}
|
||||
if err != nil || len(guilds) == 0 {
|
||||
guild, err = gs.Create(name)
|
||||
if err != nil {
|
||||
return guild, fmt.Errorf("failed creating guild: %v", err)
|
||||
}
|
||||
}
|
||||
if len(guilds) == 1 {
|
||||
guild = guilds[0]
|
||||
}
|
||||
return guild, nil
|
||||
}
|
78
backend/main.go
Normal file
78
backend/main.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Error *log.Logger
|
||||
var Warning *log.Logger
|
||||
|
||||
func init() {
|
||||
log.SetFlags(log.Lmicroseconds | log.Lshortfile)
|
||||
logFile, err := os.Create("main.log")
|
||||
if err != nil {
|
||||
log.Printf("Error creating log file: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
logger := io.MultiWriter(os.Stdout, logFile)
|
||||
log.SetOutput(logger)
|
||||
|
||||
Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout),
|
||||
fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"),
|
||||
log.Lmicroseconds|log.Lshortfile)
|
||||
Warning = log.New(io.MultiWriter(logFile, os.Stdout),
|
||||
fmt.Sprintf("%sWarning:%s ", "\033[0;93m", "\033[0m"),
|
||||
log.Lmicroseconds|log.Lshortfile)
|
||||
}
|
||||
|
||||
var db DB
|
||||
var gs GuildService
|
||||
var ps PlayerService
|
||||
var ns NoteService
|
||||
var as AssociationService
|
||||
|
||||
func main() {
|
||||
inputFile := flag.String("if", "input", "Input file")
|
||||
flag.Parse()
|
||||
log.Printf("Input file: %s", *inputFile)
|
||||
|
||||
db = DB{
|
||||
path: "data/db.db",
|
||||
}
|
||||
err := db.Open()
|
||||
if err != nil {
|
||||
Error.Printf("Failed opening database: %v", err)
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
gs = GuildService{db: &db}
|
||||
ps = PlayerService{db: &db}
|
||||
ns = NoteService{db: &db}
|
||||
as = AssociationService{db: &db}
|
||||
|
||||
inputData, err := os.ReadFile(*inputFile)
|
||||
if err != nil {
|
||||
Error.Printf("Failed reading input file: %v", err)
|
||||
return
|
||||
}
|
||||
log.Printf("%#v", string(inputData))
|
||||
|
||||
note, err := ParseNote(string(inputData))
|
||||
if err != nil {
|
||||
Error.Printf("Failed parsing note: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
dbnote, ass, err := PersistNoteData(note)
|
||||
if err != nil {
|
||||
Error.Printf("Failed persisting note: %v", err)
|
||||
return
|
||||
}
|
||||
log.Printf("%#v", dbnote)
|
||||
log.Printf("%#v", ass)
|
||||
}
|
72
backend/noteService.go
Normal file
72
backend/noteService.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NoteService struct {
|
||||
db *DB
|
||||
}
|
||||
type NoteServiceQuery struct {
|
||||
Timestamp *string `db:"timestamp"`
|
||||
PlayerID *int64 `db:"player"`
|
||||
ID *int64 `db:"id"`
|
||||
}
|
||||
|
||||
func (ns *NoteService) Query(query NoteServiceQuery) ([]Note, error) {
|
||||
res := []Note{}
|
||||
sqlQuery := "SELECT id, content, timestamp, player FROM note"
|
||||
whereQuery := BuildWhereQuery(query)
|
||||
if whereQuery != "" {
|
||||
sqlQuery += " " + whereQuery
|
||||
}
|
||||
|
||||
rows, err := ns.db.readConn.Query(sqlQuery)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed getting notes for query %q: %v", sqlQuery, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
note := Note{}
|
||||
var ts string
|
||||
err := rows.Scan(¬e.ID, ¬e.Content, &ts, ¬e.Player.ID)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed scanning note: %v", err)
|
||||
}
|
||||
note.Timestamp, err = time.Parse(time.RFC3339, ts)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed parsing timestamp: %v", err)
|
||||
}
|
||||
res = append(res, note)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ns *NoteService) Create(content string, timestamp time.Time, player Player) (Note, error) {
|
||||
log.Printf("Creating note %q with timestamp %s and player %d", content, timestamp, player.ID)
|
||||
note := Note{}
|
||||
res, err := ns.db.writeConn.Exec("insert into note (content, timestamp, player) values (?, ?, ?)", content, timestamp.Format(time.RFC3339), player.ID)
|
||||
if err != nil {
|
||||
return note, fmt.Errorf("failed to insert note: %v", err)
|
||||
}
|
||||
|
||||
id, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return note, fmt.Errorf("failed to get last insert id: %v", err)
|
||||
}
|
||||
log.Printf("Created note %q with timestamp %s and player %d with id %d", content, timestamp, player.ID, id)
|
||||
|
||||
qres, err := ns.Query(NoteServiceQuery{ID: &id})
|
||||
if err != nil {
|
||||
return note, fmt.Errorf("failed getting note for id %d: %v", id, err)
|
||||
}
|
||||
if len(qres) > 1 {
|
||||
return note, fmt.Errorf("more than one note found for id %d", id)
|
||||
}
|
||||
|
||||
return qres[0], nil
|
||||
}
|
83
backend/playerService.go
Normal file
83
backend/playerService.go
Normal file
@@ -0,0 +1,83 @@
|
||||
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) 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
|
||||
}
|
39
backend/types.go
Normal file
39
backend/types.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
Guild struct {
|
||||
ID int64
|
||||
Name string `json:"name"`
|
||||
}
|
||||
Player struct {
|
||||
ID int64
|
||||
Name string `json:"name"`
|
||||
Guild Guild `json:"guild"`
|
||||
}
|
||||
Association struct {
|
||||
ID int64
|
||||
LHS Player
|
||||
RHS Player
|
||||
Note string
|
||||
}
|
||||
Note struct {
|
||||
ID int64
|
||||
Content string
|
||||
Timestamp time.Time
|
||||
Player Player
|
||||
}
|
||||
)
|
||||
|
||||
type NoteData struct {
|
||||
Player string
|
||||
Date time.Time
|
||||
Guild string
|
||||
Note string
|
||||
Associations []NoteAssociationData
|
||||
}
|
||||
type NoteAssociationData struct {
|
||||
Player string
|
||||
Note string
|
||||
}
|
116
backend/utils.go
Normal file
116
backend/utils.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func BuildWhereQuery(params interface{}) string {
|
||||
conditions := []string{}
|
||||
v := reflect.ValueOf(params)
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
if field.Kind() == reflect.Ptr && !field.IsNil() {
|
||||
dbTag := t.Field(i).Tag.Get("db")
|
||||
if dbTag != "" {
|
||||
switch field.Elem().Kind() {
|
||||
case reflect.String:
|
||||
conditions = append(conditions, fmt.Sprintf("%s = '%s'", dbTag, field.Elem().String()))
|
||||
case reflect.Bool:
|
||||
conditions = append(conditions, fmt.Sprintf("%s = %t", dbTag, field.Elem().Bool()))
|
||||
case reflect.Int:
|
||||
conditions = append(conditions, fmt.Sprintf("%s = %d", dbTag, field.Elem().Int()))
|
||||
case reflect.Int64:
|
||||
conditions = append(conditions, fmt.Sprintf("%s = %d", dbTag, field.Elem().Int()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(conditions) > 0 {
|
||||
return "WHERE " + strings.Join(conditions, " AND ")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var associationRe = regexp.MustCompile(`r:(\w+)(?:\(([^)]+)\))?`)
|
||||
func ParseNote(data string) (NoteData, error) {
|
||||
res := NoteData{}
|
||||
lines := strings.Split(data, "\n")
|
||||
note := []string{}
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(line, ":")
|
||||
switch parts[0] {
|
||||
case "p":
|
||||
res.Player = parts[1]
|
||||
case "d":
|
||||
var err error
|
||||
res.Date, err = time.Parse(time.DateOnly, parts[1])
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("failed to parse date: %v", err)
|
||||
}
|
||||
case "g":
|
||||
res.Guild = parts[1]
|
||||
default:
|
||||
note = append(note, line)
|
||||
}
|
||||
}
|
||||
res.Note = strings.Join(note, "\n")
|
||||
|
||||
matches := associationRe.FindAllStringSubmatch(res.Note, -1)
|
||||
for _, match := range matches {
|
||||
res.Associations = append(res.Associations, NoteAssociationData{
|
||||
Player: match[1],
|
||||
Note: match[2],
|
||||
})
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func PersistNoteData(note NoteData) (Note, []Association, error) {
|
||||
res := Note{}
|
||||
ass := []Association{}
|
||||
|
||||
res.Content = note.Note
|
||||
res.Timestamp = note.Date
|
||||
guild, err := gs.GetOrCreate(note.Guild)
|
||||
if err != nil {
|
||||
return res, ass, fmt.Errorf("failed getting guild for %s: %v", note.Guild, err)
|
||||
}
|
||||
|
||||
player, err := ps.GetOrCreate(note.Player, guild)
|
||||
if err != nil {
|
||||
return res, ass, fmt.Errorf("failed getting player for %s: %v", note.Player, err)
|
||||
}
|
||||
res.Player = player
|
||||
player.Guild = guild
|
||||
|
||||
for _, assoc := range note.Associations {
|
||||
assocPlayer, err := ps.GetOrCreate(assoc.Player, guild)
|
||||
if err != nil {
|
||||
return res, ass, fmt.Errorf("failed getting player for %s: %v", assoc.Player, err)
|
||||
}
|
||||
association, err := as.Create(player, assocPlayer, assoc.Note)
|
||||
if err != nil {
|
||||
return res, ass, fmt.Errorf("failed creating association: %v", err)
|
||||
}
|
||||
ass = append(ass, association)
|
||||
}
|
||||
|
||||
res, err = ns.Create(res.Content, res.Timestamp, res.Player)
|
||||
if err != nil {
|
||||
return res, ass, fmt.Errorf("failed creating note: %v", err)
|
||||
}
|
||||
|
||||
return res, ass, nil
|
||||
}
|
Reference in New Issue
Block a user