2022-09-28 09:01:17 +02:00
|
|
|
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 {
|
2022-10-02 22:09:02 +02:00
|
|
|
UID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false" json:"UID,omitempty" yaml:"UID,omitempty"`
|
2022-10-02 11:38:30 +02:00
|
|
|
UserUID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false" json:"UserUID,omitempty" yaml:"UserUID,omitempty"`
|
2022-09-28 09:01:17 +02:00
|
|
|
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 {
|
2022-10-02 22:09:02 +02:00
|
|
|
return "reactions"
|
2022-09-28 09:01:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewReaction creates a new Reaction struct.
|
2022-10-02 22:09:02 +02:00
|
|
|
func NewReaction(uid, userUid string) *Reaction {
|
2022-09-28 09:01:17 +02:00
|
|
|
return &Reaction{
|
2022-10-02 22:09:02 +02:00
|
|
|
UID: uid,
|
|
|
|
UserUID: userUid,
|
2022-09-28 09:01:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindReaction returns the matching Reaction record or nil if it was not found.
|
2022-10-02 22:09:02 +02:00
|
|
|
func FindReaction(uid, userUid string) (m *Reaction) {
|
|
|
|
if uid == "" || userUid == "" {
|
2022-09-28 09:01:17 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
m = &Reaction{}
|
|
|
|
|
2022-10-02 22:09:02 +02:00
|
|
|
if Db().First(m, "uid = ? AND user_uid = ?", uid, userUid).RecordNotFound() {
|
2022-09-28 09:01:17 +02:00
|
|
|
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 {
|
2022-10-02 22:09:02 +02:00
|
|
|
return m.UID == "" || m.UserUID == ""
|
2022-09-28 09:01:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2022-10-02 11:38:30 +02:00
|
|
|
// Save updates the record in the database or inserts a new record if it does not already exist.
|
2022-09-28 09:01:17 +02:00
|
|
|
func (m *Reaction) Save() (err error) {
|
|
|
|
if m.Unknown() {
|
|
|
|
return fmt.Errorf("unknown reaction")
|
|
|
|
}
|
|
|
|
|
|
|
|
if m.ReactedAt == nil {
|
|
|
|
return m.Create()
|
|
|
|
}
|
|
|
|
|
|
|
|
reactedAt := TimePointer()
|
|
|
|
|
2022-10-02 11:38:30 +02:00
|
|
|
values := Values{"reaction": m.Reaction, "reacted": gorm.Expr("reacted + 1"), "reacted_at": reactedAt}
|
2022-09-28 09:01:17 +02:00
|
|
|
|
|
|
|
if err = Db().Model(Reaction{}).
|
2022-10-02 22:09:02 +02:00
|
|
|
Where("uid = ? AND user_uid = ?", m.UID, m.UserUID).
|
2022-10-02 11:38:30 +02:00
|
|
|
UpdateColumns(values).Error; err == nil {
|
2022-09-28 09:01:17 +02:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2022-10-02 22:09:02 +02:00
|
|
|
r := &Reaction{UID: m.UID, UserUID: m.UserUID, Reaction: m.Reaction, Reacted: m.Reacted, ReactedAt: TimePointer()}
|
2022-09-28 09:01:17 +02:00
|
|
|
|
|
|
|
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.
|
2022-10-02 22:09:02 +02:00
|
|
|
err := Db().Delete(m, "uid = ? AND user_uid = ?", m.UID, m.UserUID).Error
|
2022-09-28 09:01:17 +02:00
|
|
|
|
|
|
|
// Ok?
|
|
|
|
if err == nil {
|
|
|
|
m.ReactedAt = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|