Files
Erupe/server/channelserver/handlers_guild_board.go
Houmgaor d2a9b0ba5c refactor(channelserver): migrate remaining guild SQL into GuildRepository
Move ~39 inline SQL queries from six handler files into repo_guild.go,
consolidating all guild-related DB access (posts, alliances, adventures,
treasure hunts, meals, kill logs, scouts) behind GuildRepository methods.

Handler files now contain only packet serialization, business logic, and
ACK responses with no direct database calls.
2026-02-20 22:14:48 +01:00

115 lines
3.8 KiB
Go

package channelserver
import (
"time"
"erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket"
"go.uber.org/zap"
)
// MessageBoardPost represents a guild message board post.
type MessageBoardPost struct {
ID uint32 `db:"id"`
StampID uint32 `db:"stamp_id"`
Title string `db:"title"`
Body string `db:"body"`
AuthorID uint32 `db:"author_id"`
Timestamp time.Time `db:"created_at"`
LikedBy string `db:"liked_by"`
}
func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMessageBoard)
guild, _ := s.server.guildRepo.GetByCharID(s.charID)
if pkt.BoardType == 1 {
pkt.MaxPosts = 4
}
posts, err := s.server.guildRepo.ListPosts(guild.ID, int(pkt.BoardType))
if err != nil {
s.logger.Error("Failed to get guild messages from db", zap.Error(err))
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
if err := s.server.charRepo.UpdateGuildPostChecked(s.charID); err != nil {
s.logger.Error("Failed to update guild post checked time", zap.Error(err))
}
bf := byteframe.NewByteFrame()
for _, postData := range posts {
bf.WriteUint32(postData.ID)
bf.WriteUint32(postData.AuthorID)
bf.WriteUint32(0)
bf.WriteUint32(uint32(postData.Timestamp.Unix()))
bf.WriteUint32(uint32(stringsupport.CSVLength(postData.LikedBy)))
bf.WriteBool(stringsupport.CSVContains(postData.LikedBy, int(s.charID)))
bf.WriteUint32(postData.StampID)
ps.Uint32(bf, postData.Title, true)
ps.Uint32(bf, postData.Body, true)
}
data := byteframe.NewByteFrame()
data.WriteUint32(uint32(len(posts)))
data.WriteBytes(bf.Data())
doAckBufSucceed(s, pkt.AckHandle, data.Data())
}
func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateGuildMessageBoard)
guild, err := s.server.guildRepo.GetByCharID(s.charID)
applicant := false
if guild != nil {
applicant, _ = s.server.guildRepo.HasApplication(guild.ID, s.charID)
}
if err != nil || guild == nil || applicant {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
switch pkt.MessageOp {
case 0: // Create message
maxPosts := 100
if pkt.PostType == 1 {
maxPosts = 4
}
if err := s.server.guildRepo.CreatePost(guild.ID, s.charID, pkt.StampID, int(pkt.PostType), pkt.Title, pkt.Body, maxPosts); err != nil {
s.logger.Error("Failed to create guild post", zap.Error(err))
}
case 1: // Delete message
if err := s.server.guildRepo.DeletePost(pkt.PostID); err != nil {
s.logger.Error("Failed to soft-delete guild post", zap.Error(err))
}
case 2: // Update message
if err := s.server.guildRepo.UpdatePost(pkt.PostID, pkt.Title, pkt.Body); err != nil {
s.logger.Error("Failed to update guild post", zap.Error(err))
}
case 3: // Update stamp
if err := s.server.guildRepo.UpdatePostStamp(pkt.PostID, pkt.StampID); err != nil {
s.logger.Error("Failed to update guild post stamp", zap.Error(err))
}
case 4: // Like message
likedBy, err := s.server.guildRepo.GetPostLikedBy(pkt.PostID)
if err != nil {
s.logger.Error("Failed to get guild message like data from db", zap.Error(err))
} else {
if pkt.LikeState {
likedBy = stringsupport.CSVAdd(likedBy, int(s.charID))
} else {
likedBy = stringsupport.CSVRemove(likedBy, int(s.charID))
}
if err := s.server.guildRepo.SetPostLikedBy(pkt.PostID, likedBy); err != nil {
s.logger.Error("Failed to update guild post likes", zap.Error(err))
}
}
case 5: // Check for new messages
timeChecked, err := s.server.charRepo.ReadGuildPostChecked(s.charID)
if err == nil {
newPosts, _ := s.server.guildRepo.CountNewPosts(guild.ID, timeChecked)
if newPosts > 0 {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
return
}
}
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}