mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
237 lines
5.2 KiB
Go
237 lines
5.2 KiB
Go
package service
|
|
|
|
import (
|
|
"database/sql"
|
|
"erupe-ce/internal/constant"
|
|
"erupe-ce/network/binpacket"
|
|
"erupe-ce/network/mhfpacket"
|
|
"erupe-ce/utils/byteframe"
|
|
"erupe-ce/utils/database"
|
|
|
|
"erupe-ce/utils/logger"
|
|
"fmt"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type Mail struct {
|
|
ID int `db:"id"`
|
|
SenderID uint32 `db:"sender_id"`
|
|
RecipientID uint32 `db:"recipient_id"`
|
|
Subject string `db:"subject"`
|
|
Body string `db:"body"`
|
|
Read bool `db:"read"`
|
|
Deleted bool `db:"deleted"`
|
|
Locked bool `db:"locked"`
|
|
AttachedItemReceived bool `db:"attached_item_received"`
|
|
AttachedItemID uint16 `db:"attached_item"`
|
|
AttachedItemAmount uint16 `db:"attached_item_amount"`
|
|
CreatedAt time.Time `db:"created_at"`
|
|
IsGuildInvite bool `db:"is_guild_invite"`
|
|
IsSystemMessage bool `db:"is_sys_message"`
|
|
SenderName string `db:"sender_name"`
|
|
}
|
|
|
|
func (m *Mail) Send(transaction *sql.Tx) error {
|
|
db, err := database.GetDB()
|
|
logger := logger.Get()
|
|
|
|
if err != nil {
|
|
logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
|
}
|
|
query := `
|
|
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite, is_sys_message)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
`
|
|
|
|
if transaction == nil {
|
|
_, err = db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
|
} else {
|
|
_, err = transaction.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Error(
|
|
"failed to send mail",
|
|
zap.Error(err),
|
|
zap.Uint32("senderID", m.SenderID),
|
|
zap.Uint32("recipientID", m.RecipientID),
|
|
zap.String("subject", m.Subject),
|
|
zap.String("body", m.Body),
|
|
zap.Uint16("itemID", m.AttachedItemID),
|
|
zap.Uint16("itemAmount", m.AttachedItemAmount),
|
|
zap.Bool("isGuildInvite", m.IsGuildInvite),
|
|
zap.Bool("isSystemMessage", m.IsSystemMessage),
|
|
)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Mail) MarkRead() error {
|
|
db, err := database.GetDB()
|
|
logger := logger.Get()
|
|
if err != nil {
|
|
logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
|
}
|
|
_, err = db.Exec(`
|
|
UPDATE mail SET read = true WHERE id = $1
|
|
`, m.ID)
|
|
|
|
if err != nil {
|
|
logger.Error(
|
|
"failed to mark mail as read",
|
|
zap.Error(err),
|
|
zap.Int("mailID", m.ID),
|
|
)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetMailListForCharacter(charID uint32) ([]Mail, error) {
|
|
db, err := database.GetDB()
|
|
logger := logger.Get()
|
|
if err != nil {
|
|
logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
|
}
|
|
rows, err := db.Queryx(`
|
|
SELECT
|
|
m.id,
|
|
m.sender_id,
|
|
m.recipient_id,
|
|
m.subject,
|
|
m.read,
|
|
m.attached_item_received,
|
|
m.attached_item,
|
|
m.attached_item_amount,
|
|
m.created_at,
|
|
m.is_guild_invite,
|
|
m.is_sys_message,
|
|
m.deleted,
|
|
m.locked,
|
|
c.name as sender_name
|
|
FROM mail m
|
|
JOIN characters c ON c.id = m.sender_id
|
|
WHERE recipient_id = $1 AND m.deleted = false
|
|
ORDER BY m.created_at DESC, id DESC
|
|
LIMIT 32
|
|
`, charID)
|
|
|
|
if err != nil {
|
|
logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID))
|
|
return nil, err
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
allMail := make([]Mail, 0)
|
|
|
|
for rows.Next() {
|
|
mail := Mail{}
|
|
|
|
err := rows.StructScan(&mail)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
allMail = append(allMail, mail)
|
|
}
|
|
|
|
return allMail, nil
|
|
}
|
|
|
|
func GetMailByID(ID int) (*Mail, error) {
|
|
db, err := database.GetDB()
|
|
logger := logger.Get()
|
|
|
|
if err != nil {
|
|
logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
|
}
|
|
row := db.QueryRowx(`
|
|
SELECT
|
|
m.id,
|
|
m.sender_id,
|
|
m.recipient_id,
|
|
m.subject,
|
|
m.read,
|
|
m.body,
|
|
m.attached_item_received,
|
|
m.attached_item,
|
|
m.attached_item_amount,
|
|
m.created_at,
|
|
m.is_guild_invite,
|
|
m.is_sys_message,
|
|
m.deleted,
|
|
m.locked,
|
|
c.name as sender_name
|
|
FROM mail m
|
|
JOIN characters c ON c.id = m.sender_id
|
|
WHERE m.id = $1
|
|
LIMIT 1
|
|
`, ID)
|
|
|
|
mail := &Mail{}
|
|
|
|
err = row.StructScan(mail)
|
|
|
|
if err != nil {
|
|
logger.Error(
|
|
"failed to retrieve mail",
|
|
zap.Error(err),
|
|
zap.Int("mailID", ID),
|
|
)
|
|
return nil, err
|
|
}
|
|
|
|
return mail, nil
|
|
}
|
|
|
|
type SessionMail interface {
|
|
QueueSendMHFLazy(packet mhfpacket.MHFPacket)
|
|
}
|
|
|
|
func SendMailNotification(m *Mail, recipient SessionMail) {
|
|
bf := byteframe.NewByteFrame()
|
|
|
|
notification := &binpacket.MsgBinMailNotify{
|
|
SenderName: getCharacterName(m.SenderID),
|
|
}
|
|
|
|
notification.Build(bf)
|
|
|
|
castedBinary := &mhfpacket.MsgSysCastedBinary{
|
|
CharID: m.SenderID,
|
|
BroadcastType: 0x00,
|
|
MessageType: constant.BinaryMessageTypeMailNotify,
|
|
RawDataPayload: bf.Data(),
|
|
}
|
|
|
|
castedBinary.Build(bf)
|
|
|
|
recipient.QueueSendMHFLazy(castedBinary)
|
|
}
|
|
|
|
func getCharacterName(charID uint32) string {
|
|
db, err := database.GetDB()
|
|
logger := logger.Get()
|
|
|
|
if err != nil {
|
|
logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
|
}
|
|
row := db.QueryRow("SELECT name FROM characters WHERE id = $1", charID)
|
|
|
|
charName := ""
|
|
|
|
err = row.Scan(&charName)
|
|
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return charName
|
|
}
|