✨ Basically move messages to events
This commit is contained in:
181
pkg/internal/services/events.go
Normal file
181
pkg/internal/services/events.go
Normal file
@ -0,0 +1,181 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CountEvent(channel models.Channel) int64 {
|
||||
var count int64
|
||||
if err := database.C.Where(models.Event{
|
||||
ChannelID: channel.ID,
|
||||
}).Model(&models.Event{}).Count(&count).Error; err != nil {
|
||||
return 0
|
||||
} else {
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
||||
func ListEvent(channel models.Channel, take int, offset int) ([]models.Event, error) {
|
||||
if take > 100 {
|
||||
take = 100
|
||||
}
|
||||
|
||||
var events []models.Event
|
||||
if err := database.C.
|
||||
Where(models.Event{
|
||||
ChannelID: channel.ID,
|
||||
}).Limit(take).Offset(offset).
|
||||
Order("created_at DESC").
|
||||
Preload("Sender").
|
||||
Preload("Sender.Account").
|
||||
Find(&events).Error; err != nil {
|
||||
return events, err
|
||||
} else {
|
||||
return events, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetEvent(channel models.Channel, id uint) (models.Event, error) {
|
||||
var event models.Event
|
||||
if err := database.C.
|
||||
Where(models.Event{
|
||||
BaseModel: models.BaseModel{ID: id},
|
||||
ChannelID: channel.ID,
|
||||
}).
|
||||
Preload("Sender").
|
||||
Preload("Sender.Account").
|
||||
First(&event).Error; err != nil {
|
||||
return event, err
|
||||
} else {
|
||||
return event, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetEventWithSender(channel models.Channel, member models.ChannelMember, id uint) (models.Event, error) {
|
||||
var event models.Event
|
||||
if err := database.C.Where(models.Event{
|
||||
BaseModel: models.BaseModel{ID: id},
|
||||
ChannelID: channel.ID,
|
||||
SenderID: member.ID,
|
||||
}).First(&event).Error; err != nil {
|
||||
return event, err
|
||||
} else {
|
||||
return event, nil
|
||||
}
|
||||
}
|
||||
|
||||
func NewEvent(event models.Event) (models.Event, error) {
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Save(&event).Error; err != nil {
|
||||
return event, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: event.ChannelID,
|
||||
}).Preload("Account").Find(&members).Error; err != nil {
|
||||
// Couldn't get channel members, skip notifying
|
||||
return event, nil
|
||||
}
|
||||
|
||||
event, _ = GetEvent(event.Channel, event.ID)
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "events.new",
|
||||
Payload: event,
|
||||
})
|
||||
}
|
||||
|
||||
if strings.HasPrefix(event.Type, "messages") {
|
||||
NotifyMessageEvent(members, event)
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func NotifyMessageEvent(members []models.ChannelMember, event models.Event) {
|
||||
var body models.EventMessageBody
|
||||
raw, _ := jsoniter.Marshal(event.Body)
|
||||
_ = jsoniter.Unmarshal(raw, &body)
|
||||
|
||||
for _, member := range members {
|
||||
if member.ID != event.SenderID {
|
||||
switch member.Notify {
|
||||
case models.NotifyLevelNone:
|
||||
continue
|
||||
case models.NotifyLevelMentioned:
|
||||
if len(body.RelatedUsers) == 0 || !lo.Contains(body.RelatedUsers, member.AccountID) {
|
||||
continue
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
var displayText string
|
||||
if body.Algorithm == "plain" {
|
||||
displayText = body.Text
|
||||
}
|
||||
|
||||
if len(displayText) == 0 {
|
||||
displayText = fmt.Sprintf("%d attachment(s)", len(body.Attachments))
|
||||
}
|
||||
|
||||
err := NotifyAccountMessager(member.Account,
|
||||
"incomingMessage",
|
||||
fmt.Sprintf("%s in #%s", event.Sender.Account.Nick, event.Channel.Alias),
|
||||
fmt.Sprintf("%s", displayText),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("An error occurred when trying notify user.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func EditEvent(event models.Event) (models.Event, error) {
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Save(&event).Error; err != nil {
|
||||
return event, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: event.ChannelID,
|
||||
}).Find(&members).Error; err == nil {
|
||||
event, _ = GetEvent(models.Channel{
|
||||
BaseModel: models.BaseModel{ID: event.Channel.ID},
|
||||
}, event.ID)
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "events.update",
|
||||
Payload: event,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func DeleteEvent(event models.Event) (models.Event, error) {
|
||||
prev, _ := GetEvent(models.Channel{
|
||||
BaseModel: models.BaseModel{ID: event.Channel.ID},
|
||||
}, event.ID)
|
||||
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Delete(&event).Error; err != nil {
|
||||
return event, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: event.ChannelID,
|
||||
}).Find(&members).Error; err == nil {
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "events.burnt",
|
||||
Payload: prev,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
@ -1,181 +1,60 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
"github.com/google/uuid"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func CountMessage(channel models.Channel) int64 {
|
||||
var count int64
|
||||
if err := database.C.Where(models.Message{
|
||||
ChannelID: channel.ID,
|
||||
}).Model(&models.Message{}).Count(&count).Error; err != nil {
|
||||
return 0
|
||||
} else {
|
||||
return count
|
||||
}
|
||||
func EncodeMessageBody(body models.EventMessageBody) map[string]any {
|
||||
var parsed map[string]any
|
||||
raw, _ := jsoniter.Marshal(body)
|
||||
_ = jsoniter.Unmarshal(raw, &parsed)
|
||||
return parsed
|
||||
}
|
||||
|
||||
func ListMessage(channel models.Channel, take int, offset int) ([]models.Message, error) {
|
||||
if take > 100 {
|
||||
take = 100
|
||||
func EditMessage(event models.Event, body models.EventMessageBody) (models.Event, error) {
|
||||
event.Body = EncodeMessageBody(body)
|
||||
event, err := EditEvent(event)
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
body.RelatedEvent = event.ID
|
||||
_, err = NewEvent(models.Event{
|
||||
Uuid: uuid.NewString(),
|
||||
Body: EncodeMessageBody(body),
|
||||
Type: models.EventMessageEdit,
|
||||
Channel: event.Channel,
|
||||
Sender: event.Sender,
|
||||
ChannelID: event.ChannelID,
|
||||
SenderID: event.SenderID,
|
||||
})
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
|
||||
var messages []models.Message
|
||||
if err := database.C.
|
||||
Where(models.Message{
|
||||
ChannelID: channel.ID,
|
||||
}).Limit(take).Offset(offset).
|
||||
Order("created_at DESC").
|
||||
Preload("ReplyTo").
|
||||
Preload("ReplyTo.Sender").
|
||||
Preload("ReplyTo.Sender.Account").
|
||||
Preload("Sender").
|
||||
Preload("Sender.Account").
|
||||
Find(&messages).Error; err != nil {
|
||||
return messages, err
|
||||
} else {
|
||||
return messages, nil
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func GetMessage(channel models.Channel, id uint) (models.Message, error) {
|
||||
var message models.Message
|
||||
if err := database.C.
|
||||
Where(models.Message{
|
||||
BaseModel: models.BaseModel{ID: id},
|
||||
ChannelID: channel.ID,
|
||||
}).
|
||||
Preload("ReplyTo").
|
||||
Preload("ReplyTo.Sender").
|
||||
Preload("ReplyTo.Sender.Account").
|
||||
Preload("Sender").
|
||||
Preload("Sender.Account").
|
||||
First(&message).Error; err != nil {
|
||||
return message, err
|
||||
} else {
|
||||
return message, nil
|
||||
func DeleteMessage(event models.Event) (models.Event, error) {
|
||||
_, err := DeleteEvent(event)
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetMessageWithPrincipal(channel models.Channel, member models.ChannelMember, id uint) (models.Message, error) {
|
||||
var message models.Message
|
||||
if err := database.C.Where(models.Message{
|
||||
BaseModel: models.BaseModel{ID: id},
|
||||
ChannelID: channel.ID,
|
||||
SenderID: member.ID,
|
||||
}).First(&message).Error; err != nil {
|
||||
return message, err
|
||||
} else {
|
||||
return message, nil
|
||||
}
|
||||
}
|
||||
|
||||
func NewMessage(message models.Message) (models.Message, error) {
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Save(&message).Error; err != nil {
|
||||
return message, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: message.ChannelID,
|
||||
}).Preload("Account").Find(&members).Error; err == nil {
|
||||
channel := message.Channel
|
||||
message, _ = GetMessage(message.Channel, message.ID)
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "messages.new",
|
||||
Payload: message,
|
||||
})
|
||||
|
||||
if member.ID != message.SenderID {
|
||||
switch member.Notify {
|
||||
case models.NotifyLevelNone:
|
||||
continue
|
||||
case models.NotifyLevelMentioned:
|
||||
if message.ReplyTo != nil && member.ID == message.ReplyTo.SenderID {
|
||||
break
|
||||
}
|
||||
if val, ok := message.Content["mentioned_users"]; ok {
|
||||
if usernames, ok := val.([]string); ok {
|
||||
if lo.Contains(usernames, member.Account.Name) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
var displayText string
|
||||
if message.Content["algorithm"] == "plain" {
|
||||
displayText, _ = message.Content["value"].(string)
|
||||
} else {
|
||||
displayText = "*encrypted message*"
|
||||
}
|
||||
|
||||
if len(displayText) == 0 {
|
||||
displayText = fmt.Sprintf("%d attachment(s)", len(message.Attachments))
|
||||
}
|
||||
|
||||
err = NotifyAccountMessager(member.Account,
|
||||
"incomingMessage",
|
||||
fmt.Sprintf("%s in #%s", message.Sender.Account.Nick, channel.Alias),
|
||||
fmt.Sprintf("%s", displayText),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("An error occurred when trying notify user.")
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = NewEvent(models.Event{
|
||||
Uuid: uuid.NewString(),
|
||||
Body: EncodeMessageBody(models.EventMessageBody{
|
||||
RelatedEvent: event.ID,
|
||||
}),
|
||||
Type: models.EventMessageDelete,
|
||||
Channel: event.Channel,
|
||||
Sender: event.Sender,
|
||||
ChannelID: event.ChannelID,
|
||||
SenderID: event.SenderID,
|
||||
})
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
func EditMessage(message models.Message) (models.Message, error) {
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Save(&message).Error; err != nil {
|
||||
return message, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: message.ChannelID,
|
||||
}).Find(&members).Error; err == nil {
|
||||
message, _ = GetMessage(models.Channel{
|
||||
BaseModel: models.BaseModel{ID: message.Channel.ID},
|
||||
}, message.ID)
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "messages.update",
|
||||
Payload: message,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
func DeleteMessage(message models.Message) (models.Message, error) {
|
||||
prev, _ := GetMessage(models.Channel{
|
||||
BaseModel: models.BaseModel{ID: message.Channel.ID},
|
||||
}, message.ID)
|
||||
|
||||
var members []models.ChannelMember
|
||||
if err := database.C.Delete(&message).Error; err != nil {
|
||||
return message, err
|
||||
} else if err = database.C.Where(models.ChannelMember{
|
||||
ChannelID: message.ChannelID,
|
||||
}).Find(&members).Error; err == nil {
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, models.UnifiedCommand{
|
||||
Action: "messages.burnt",
|
||||
Payload: prev,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return message, nil
|
||||
return event, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user