package storage import ( "database/sql" "errors" "strings" "time" ) const logHeaderInsert = "INSERT INTO `logheader` (id,channel,time,status,status_time,title,tag,description) VALUES (?, ?, ?, ?, ?, ?, ?, ?);" const logHeaderUpdate = "UPDATE `logheader` SET channel=?,time=?,status=?,status_time=?,title=?,tag=?,description=? WHERE id=?;" const logNicksInsert = "INSERT INTO `lognicks` (log_id,nick) VALUES (?, ?);" const logNicksDelete = "DELETE FROM `lognicks` WHERE log_id=? AND nick=?;" // LogHeader is the struct type LogHeader struct { ID string `json:"id"` Channel string `json:"channel"` Time time.Time `json:"time"` Status string `json:"status"` StatusTime time.Time `json:"statusTime"` Title string `json:"title"` Tag string `json:"tag"` Description string `json:"description"` Nicks []string `json:"nicks"` nicksAdded []string nicksRemoved []string } // SetStatus changes the value of header.Status and updates // header.StatusTime. func (header *LogHeader) SetStatus(value string) { header.Status = strings.ToLower(value) header.StatusTime = time.Now() } // HasNick returns whether a nick exists func (header *LogHeader) HasNick(nick string) bool { for _, existingNick := range header.Nicks { if existingNick == nick { return true } } return false } // AddNick adds a nick to the Nicks array, recording the // change. If the nick exists, it will not be added, though // it won't throw an error. func (header *LogHeader) AddNick(nick string) { if !header.HasNick(nick) { header.Nicks = append(header.Nicks, nick) header.nicksAdded = append(header.nicksAdded, nick) } } // RemoveNick removes a nick from the Nicks array, recording // the change. func (header *LogHeader) RemoveNick(nick string) { for i, existingNick := range header.Nicks { if existingNick == nick { header.Nicks = append(header.Nicks[:i], header.Nicks[i+1:]...) header.nicksRemoved = append(header.nicksRemoved, nick) return } } } // Insert inserts the LogHeader into the database, as well as all nicks func (header *LogHeader) Insert(db *sql.DB) error { // Insert the header result, err := db.Exec(logHeaderInsert, header.ID, header.Channel, header.Time, header.Status, header.StatusTime, header.Title, header.Tag, header.Description) if err != nil { return err } // Check if it was actually inserted rows, err := result.RowsAffected() if err != nil { return err } if rows != 1 { return errors.New("storage: No LogHeader inserted") } // Insert all lognicks for _, nick := range header.Nicks { _, err := db.Exec(logNicksInsert, header.ID, nick) if err != nil { return err } } // Clear the nicksAdded and nicksRemoved lists header.nicksAdded = nil header.nicksRemoved = nil // Success return nil } // Save updates the logheader func (header *LogHeader) Save(db *sql.DB) error { // Insert the header _, err := db.Exec(logHeaderUpdate, header.Channel, header.Time, header.Status, header.StatusTime, header.Title, header.Tag, header.Description, header.ID) if err != nil { return err } // Delete all removed lognicks for _, nick := range header.nicksRemoved { _, err := db.Exec(logNicksDelete, header.ID, nick) if err != nil { return err } } // Insert all new lognicks for _, nick := range header.nicksAdded { _, err := db.Exec(logNicksInsert, header.ID, nick) if err != nil { return err } } // Clear the nicksAdded and nicksRemoved lists header.nicksAdded = nil header.nicksRemoved = nil // Success return nil } // NewLogHeader creates a new LogHeader with an ID based the time and channel // value. It also sets StatusTime to the current time. It leaves // Title, Tag and Nicks blank. func NewLogHeader(logTime time.Time, channel, status string) *LogHeader { header := new(LogHeader) header.ID = logTime.Format("2006-01-02_150405999_") + channel[1:] header.Channel = channel header.Time = logTime header.Status = status header.StatusTime = time.Now() return header }