photoprism/internal/entity/reaction.go
Michael Mayer e7d862d07a Albums: Improve database error handling #3320
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-04-02 10:27:57 +02:00

135 lines
3.2 KiB
Go

package entity
import (
"fmt"
"time"
"github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/pkg/react"
)
// Reaction represents a human response to content such as photos and albums.
type Reaction struct {
UID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false" json:"UID,omitempty" yaml:"UID,omitempty"`
UserUID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
Reaction string `gorm:"type:VARBINARY(64);primary_key;auto_increment:false" json:"Reaction,omitempty" yaml:"Reaction,omitempty"`
Reacted int `json:"Reacted,omitempty" yaml:"Reacted,omitempty"`
ReactedAt *time.Time `sql:"index" json:"ReactedAt,omitempty" yaml:"ReactedAt,omitempty"`
}
// TableName returns the entity table name.
func (Reaction) TableName() string {
return "reactions"
}
// NewReaction creates a new Reaction struct.
func NewReaction(uid, userUid string) *Reaction {
return &Reaction{
UID: uid,
UserUID: userUid,
}
}
// FindReaction returns the matching Reaction record or nil if it was not found.
func FindReaction(uid, userUid string) (m *Reaction) {
if uid == "" || userUid == "" {
return nil
}
m = &Reaction{}
if Db().First(m, "uid = ? AND user_uid = ?", uid, userUid).Error != nil {
return nil
}
return m
}
// React adds a react.Emoji reaction.
func (m *Reaction) React(emo react.Emoji) *Reaction {
m.Reaction = emo.String()
m.Reacted += 1
return m
}
// Emoji returns the reaction Emoji.
func (m *Reaction) Emoji() react.Emoji {
return react.Emoji(m.Reaction)
}
// String returns the user reaction as string.
func (m *Reaction) String() string {
return m.Reaction
}
// InvalidUID checks if the entity or user uid are missing or incorrect.
func (m *Reaction) InvalidUID() bool {
return m.UID == "" || m.UserUID == ""
}
// Unknown checks if the reaction data is missing or incorrect.
func (m *Reaction) Unknown() bool {
if m.InvalidUID() {
return true
}
return len(m.Reaction) == 0
}
// Save updates the record in the database or inserts a new record if it does not already exist.
func (m *Reaction) Save() (err error) {
if m.Unknown() {
return fmt.Errorf("unknown reaction")
}
if m.ReactedAt == nil {
return m.Create()
}
reactedAt := TimePointer()
values := Values{"reaction": m.Reaction, "reacted": gorm.Expr("reacted + 1"), "reacted_at": reactedAt}
if err = Db().Model(Reaction{}).
Where("uid = ? AND user_uid = ?", m.UID, m.UserUID).
UpdateColumns(values).Error; err == nil {
m.Reacted += 1
m.ReactedAt = reactedAt
}
return err
}
// Create inserts a new Reaction.
func (m *Reaction) Create() (err error) {
if m.Unknown() {
return fmt.Errorf("reaction invalid")
}
r := &Reaction{UID: m.UID, UserUID: m.UserUID, Reaction: m.Reaction, Reacted: m.Reacted, ReactedAt: TimePointer()}
if err = Db().Create(r).Error; err == nil {
m.ReactedAt = r.ReactedAt
}
return err
}
// Delete deletes the Reaction.
func (m *Reaction) Delete() error {
if m.InvalidUID() {
return fmt.Errorf("reaction invalid")
}
// Delete record.
err := Db().Delete(m, "uid = ? AND user_uid = ?", m.UID, m.UserUID).Error
// Ok?
if err == nil {
m.ReactedAt = nil
}
return err
}