Messages CRUD

This commit is contained in:
LittleSheep 2024-03-30 18:40:21 +08:00
parent 8e31675317
commit 729409618b
5 changed files with 134 additions and 33 deletions

View File

@ -17,6 +17,8 @@ type Message struct {
Metadata datatypes.JSONMap `json:"metadata"` Metadata datatypes.JSONMap `json:"metadata"`
Type MessageType `json:"type"` Type MessageType `json:"type"`
Attachments []Attachment `json:"attachments"` Attachments []Attachment `json:"attachments"`
Channel Channel `json:"channel"`
Sender Account `json:"sender"`
ChannelID uint `json:"channel_id"` ChannelID uint `json:"channel_id"`
SenderID uint `json:"sender_id"` SenderID uint `json:"sender_id"`
} }

View File

@ -6,7 +6,7 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func getMessageHistory(c *fiber.Ctx) error { func listMessage(c *fiber.Ctx) error {
take := c.QueryInt("take", 0) take := c.QueryInt("take", 0)
offset := c.QueryInt("offset", 0) offset := c.QueryInt("offset", 0)
alias := c.Params("channel") alias := c.Params("channel")
@ -50,3 +50,55 @@ func newTextMessage(c *fiber.Ctx) error {
return c.JSON(message) return c.JSON(message)
} }
func editMessage(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")
messageId, _ := c.ParamsInt("messageId", 0)
var data struct {
Content string `json:"content" validate:"required"`
Attachments []models.Attachment `json:"attachments"`
}
if err := BindAndValidate(c, &data); err != nil {
return err
}
var message models.Message
if channel, member, err := services.GetAvailableChannelWithAlias(alias, user); err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
} else if message, err = services.GetMessageWithPrincipal(channel, member, uint(messageId)); err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
message.Content = data.Content
message.Attachments = data.Attachments
message, err := services.EditMessage(message)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
return c.JSON(message)
}
func deleteMessage(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")
messageId, _ := c.ParamsInt("messageId", 0)
var message models.Message
if channel, member, err := services.GetAvailableChannelWithAlias(alias, user); err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
} else if message, err = services.GetMessageWithPrincipal(channel, member, uint(messageId)); err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
message, err := services.DeleteMessage(message)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
return c.JSON(message)
}

View File

@ -77,17 +77,22 @@ func NewServer() {
channels := api.Group("/channels").Name("Channels API") channels := api.Group("/channels").Name("Channels API")
{ {
channels.Get("/", listChannel) channels.Get("/", listChannel)
channels.Get("/:channel", getChannel)
channels.Get("/me", authMiddleware, listOwnedChannel) channels.Get("/me", authMiddleware, listOwnedChannel)
channels.Get("/me/available", authMiddleware, listAvailableChannel) channels.Get("/me/available", authMiddleware, listAvailableChannel)
channels.Get("/:channel", getChannel)
channels.Get("/:channel/messages", getMessageHistory)
channels.Get("/:channelId/members", listChannelMembers)
channels.Post("/", authMiddleware, createChannel) channels.Post("/", authMiddleware, createChannel)
channels.Post("/:channel/messages", authMiddleware, newTextMessage)
channels.Post("/:channelId/invite", authMiddleware, inviteChannel)
channels.Post("/:channelId/kick", authMiddleware, kickChannel)
channels.Put("/:channelId", authMiddleware, editChannel) channels.Put("/:channelId", authMiddleware, editChannel)
channels.Delete("/:channelId", authMiddleware, deleteChannel) channels.Delete("/:channelId", authMiddleware, deleteChannel)
channels.Get("/:channelId/members", listChannelMembers)
channels.Post("/:channelId/invite", authMiddleware, inviteChannel)
channels.Post("/:channelId/kick", authMiddleware, kickChannel)
channels.Get("/:channel/messages", listMessage)
channels.Post("/:channel/messages", authMiddleware, newTextMessage)
channels.Put("/:channel/messages/:messageId", authMiddleware, editMessage)
channels.Delete("/:channel/messages/:messageId", authMiddleware, deleteMessage)
} }
api.Get("/unified", authMiddleware, websocket.New(unifiedGateway)) api.Get("/unified", authMiddleware, websocket.New(unifiedGateway))

View File

@ -3,7 +3,6 @@ package services
import ( import (
"git.solsynth.dev/hydrogen/messaging/pkg/models" "git.solsynth.dev/hydrogen/messaging/pkg/models"
"github.com/gofiber/contrib/websocket" "github.com/gofiber/contrib/websocket"
"github.com/samber/lo"
) )
var WsConn = make(map[uint][]*websocket.Conn) var WsConn = make(map[uint][]*websocket.Conn)
@ -20,28 +19,6 @@ func PushCommand(userId uint, task models.UnifiedCommand) {
func DealCommand(task models.UnifiedCommand, user models.Account) *models.UnifiedCommand { func DealCommand(task models.UnifiedCommand, user models.Account) *models.UnifiedCommand {
switch task.Action { switch task.Action {
case "messages.send.text":
var req struct {
ChannelID uint `json:"channel_id"`
Content string `json:"content"`
Attachments []models.Attachment `json:"attachments"`
}
models.FitStruct(task.Payload, &req)
if len(req.Content) == 0 {
return &models.UnifiedCommand{
Action: "error",
Message: "content cannot be empty",
}
}
if channel, member, err := GetAvailableChannel(req.ChannelID, user); err != nil {
return lo.ToPtr(models.UnifiedCommandFromError(err))
} else if _, err = NewTextMessage(req.Content, member, channel); err != nil {
return lo.ToPtr(models.UnifiedCommandFromError(err))
} else {
return nil
}
default: default:
return &models.UnifiedCommand{ return &models.UnifiedCommand{
Action: "error", Action: "error",

View File

@ -22,15 +22,44 @@ func ListMessage(channel models.Channel, take int, offset int) ([]models.Message
} }
var messages []models.Message var messages []models.Message
if err := database.C.Where(models.Message{ if err := database.C.
Where(models.Message{
ChannelID: channel.ID, ChannelID: channel.ID,
}).Limit(take).Offset(offset).Find(&messages).Error; err != nil { }).Limit(take).Offset(offset).
Order("created_at DESC").
Preload("Sender").
Find(&messages).Error; err != nil {
return messages, err return messages, err
} else { } else {
return messages, nil return messages, 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,
}).First(&message).Error; err != nil {
return message, err
} else {
return message, nil
}
}
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 NewTextMessage(content string, sender models.ChannelMember, channel models.Channel, attachments ...models.Attachment) (models.Message, error) { func NewTextMessage(content string, sender models.ChannelMember, channel models.Channel, attachments ...models.Attachment) (models.Message, error) {
message := models.Message{ message := models.Message{
Content: content, Content: content,
@ -57,3 +86,39 @@ func NewTextMessage(content string, sender models.ChannelMember, channel models.
return message, nil 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 {
for _, member := range members {
PushCommand(member.ID, models.UnifiedCommand{
Action: "messages.update",
Payload: message,
})
}
}
return message, nil
}
func DeleteMessage(message models.Message) (models.Message, error) {
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.ID, models.UnifiedCommand{
Action: "messages.burnt",
Payload: message,
})
}
}
return message, nil
}