diff --git a/guildService.go b/guildService.go index 9550db7..ae662cd 100644 --- a/guildService.go +++ b/guildService.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" ) type GuildService struct { @@ -39,6 +40,7 @@ func (gs *GuildService) Query(query GuildServiceQuery) ([]Guild, error) { } 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 { @@ -49,6 +51,7 @@ func (gs *GuildService) Create(name string) (Guild, error) { 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 { @@ -64,14 +67,17 @@ func (gs *GuildService) Create(name string) (Guild, error) { func (gs *GuildService) GetOrCreate(name string) (Guild, error) { guild := Guild{} guilds, err := gs.Query(GuildServiceQuery{Name: &name}) - if err != nil { - if len(guilds) > 1 { - return guild, fmt.Errorf("more than one guild found for name %s", 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 } diff --git a/main.go b/main.go index a994005..40762b8 100644 --- a/main.go +++ b/main.go @@ -6,9 +6,6 @@ import ( "io" "log" "os" - "regexp" - "strings" - "time" ) var Error *log.Logger @@ -36,6 +33,7 @@ var db DB var gs GuildService var ps PlayerService var ns NoteService +var as AssociationService func main() { inputFile := flag.String("if", "input", "Input file") @@ -55,6 +53,7 @@ func main() { gs = GuildService{db: &db} ps = PlayerService{db: &db} ns = NoteService{db: &db} + as = AssociationService{db: &db} inputData, err := os.ReadFile(*inputFile) if err != nil { @@ -68,44 +67,12 @@ func main() { Error.Printf("Failed parsing note: %v", err) return } - log.Printf("%#v", note) -} -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) - } + dbnote, ass, err := PersistNoteData(note) + if err != nil { + Error.Printf("Failed persisting note: %v", err) + return } - 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 + log.Printf("%#v", dbnote) + log.Printf("%#v", ass) } diff --git a/noteService.go b/noteService.go index fd7c644..327243e 100644 --- a/noteService.go +++ b/noteService.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" "time" ) @@ -30,10 +31,15 @@ func (ns *NoteService) Query(query NoteServiceQuery) ([]Note, error) { for rows.Next() { note := Note{} - err := rows.Scan(¬e.ID, ¬e.Content, ¬e.Timestamp, ¬e.Player.ID) + 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) } @@ -41,8 +47,9 @@ func (ns *NoteService) Query(query NoteServiceQuery) ([]Note, error) { } 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, player.ID) + 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) } @@ -51,6 +58,7 @@ func (ns *NoteService) Create(content string, timestamp time.Time, player Player 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 { diff --git a/playerService.go b/playerService.go index e6f45d7..8051a5e 100644 --- a/playerService.go +++ b/playerService.go @@ -1,6 +1,9 @@ package main -import "fmt" +import ( + "fmt" + "log" +) type PlayerService struct { db *DB @@ -37,6 +40,7 @@ func (ps *PlayerService) Query(query PlayerServiceQuery) ([]Player, error) { } 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 { @@ -47,6 +51,7 @@ func (ps *PlayerService) Create(name string, guild Guild) (Player, error) { 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 { @@ -62,14 +67,17 @@ func (ps *PlayerService) Create(name string, guild Guild) (Player, error) { func (ps *PlayerService) GetOrCreate(name string, guild Guild) (Player, error) { player := Player{} players, err := ps.Query(PlayerServiceQuery{Name: &name}) - if err != nil { - if len(players) > 1 { - return player, fmt.Errorf("more than one player found for name %s", 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 } diff --git a/utils.go b/utils.go index 39c3b85..d899878 100644 --- a/utils.go +++ b/utils.go @@ -3,7 +3,9 @@ package main import ( "fmt" "reflect" + "regexp" "strings" + "time" ) func BuildWhereQuery(params interface{}) string { @@ -35,3 +37,80 @@ func BuildWhereQuery(params interface{}) string { } 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 +} \ No newline at end of file