Guild Post JP Shift-JIS Support

This commit is contained in:
Malckyor
2022-06-16 01:07:34 +09:00
committed by GitHub
parent f05391ecba
commit 33bb960e55

View File

@@ -1,6 +1,7 @@
package channelserver package channelserver
import ( import (
"bytes"
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/binary" "encoding/binary"
@@ -8,10 +9,13 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"io/ioutil"
"log"
"sort" "sort"
"time"
"strings"
"strconv" "strconv"
"strings"
"time"
"github.com/Andoryuuta/byteframe" "github.com/Andoryuuta/byteframe"
"github.com/Solenataris/Erupe/common/bfutil" "github.com/Solenataris/Erupe/common/bfutil"
@@ -19,6 +23,8 @@ import (
"github.com/Solenataris/Erupe/network/mhfpacket" "github.com/Solenataris/Erupe/network/mhfpacket"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
) )
type FestivalColour string type FestivalColour string
@@ -1515,7 +1521,13 @@ func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) {
// uint32 expiration timestamp // uint32 expiration timestamp
// encourage food // encourage food
data := []byte{0x00, 0x01, 0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x5F, 0xFC, 0x0B, 0x51} data := []byte{0x00, 0x06,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFC, 0x0B, 0x51,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0x9c, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFC, 0x0B, 0x52,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFC, 0x0B, 0x51,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFD, 0x0B, 0x51,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFC, 0x0B, 0x51,
0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x03, 0xF3, 0xFC, 0x0B, 0x51}
doAckBufSucceed(s, pkt.AckHandle, data) doAckBufSucceed(s, pkt.AckHandle, data)
//data := []byte{0x00, 0x01, 0x1C, 0x72, 0x54, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5F, 0xF8, 0x2F, 0xE1} //data := []byte{0x00, 0x01, 0x1C, 0x72, 0x54, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5F, 0xF8, 0x2F, 0xE1}
//doAckBufSucceed(s, pkt.AckHandle, data) //doAckBufSucceed(s, pkt.AckHandle, data)
@@ -1566,7 +1578,7 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
msgs, err := s.server.db.Queryx("SELECT post_type, stamp_id, title, body, author_id, (EXTRACT(epoch FROM created_at)::int) as created_at, liked_by FROM guild_posts WHERE guild_id = $1 AND post_type = $2 ORDER BY created_at DESC", guild.ID, int(pkt.BoardType)) msgs, err := s.server.db.Queryx("SELECT post_type, stamp_id, title, body, author_id, (EXTRACT(epoch FROM created_at)::int) as created_at, liked_by FROM guild_posts WHERE guild_id = $1 AND post_type = $2 ORDER BY created_at DESC", guild.ID, int(pkt.BoardType))
if err != nil { if err != nil {
s.logger.Fatal("Failed to get guild messages from db", zap.Error(err)) log.Println("Failed to get guild messages from db", zap.Error(err))
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -1575,22 +1587,38 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
for msgs.Next() { for msgs.Next() {
noMsgs = false noMsgs = false
postCount++ postCount++
var str_title, str_body string
var timestampst, timecomp uint64
timestampst = 32400
postData := &MessageBoardPost{} postData := &MessageBoardPost{}
err = msgs.StructScan(&postData) err = msgs.StructScan(&postData)
if err != nil { if err != nil {
s.logger.Error("Failed to read guild message board post") log.Println("Failed to get guild messages from db", zap.Error(err))
} }
t := japanese.ShiftJIS.NewEncoder()
str_title, _, err := transform.String(t, postData.Title)
if err != nil {
log.Println(err)
}
str_body, _, err = transform.String(t, postData.Body)
if err != nil {
log.Println(err)
}
timecomp = postData.Timestamp - timestampst
bf.WriteUint32(postData.Type) bf.WriteUint32(postData.Type)
bf.WriteUint32(postData.AuthorID) bf.WriteUint32(postData.AuthorID)
bf.WriteUint64(postData.Timestamp) bf.WriteUint64(timecomp)
liked := false liked := false
likedBySlice := strings.Split(postData.LikedBy, ",") likedBySlice := strings.Split(postData.LikedBy, ",")
for i := 0; i < len(likedBySlice); i++ { for i := 0; i < len(likedBySlice); i++ {
j, _ := strconv.ParseInt(likedBySlice[i], 10, 64) j, _ := strconv.ParseInt(likedBySlice[i], 10, 64)
if int(j) == int(s.charID) { if int(j) == int(s.charID) {
liked = true; break liked = true
break
} }
} }
if likedBySlice[0] == "" { if likedBySlice[0] == "" {
@@ -1598,12 +1626,13 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
bf.WriteUint32(uint32(len(likedBySlice))) bf.WriteUint32(uint32(len(likedBySlice)))
} }
bf.WriteBool(liked) bf.WriteBool(liked)
bf.WriteUint32(postData.StampID) bf.WriteUint32(postData.StampID)
bf.WriteUint32(uint32(len(postData.Title))) bf.WriteUint32(uint32(len(str_title)))
bf.WriteBytes([]byte(postData.Title)) bf.WriteBytes([]byte(str_title))
bf.WriteUint32(uint32(len(postData.Body))) bf.WriteUint32(uint32(len(str_body)))
bf.WriteBytes([]byte(postData.Body)) bf.WriteBytes([]byte(str_body))
} }
if noMsgs { if noMsgs {
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
@@ -1615,6 +1644,19 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} }
} }
func transformEncoding(rawReader io.Reader, trans transform.Transformer) (string, error) {
ret, err := ioutil.ReadAll(transform.NewReader(rawReader, trans))
if err == nil {
return string(ret), nil
} else {
return "", err
}
}
func BytesFromShiftJIS(b []byte) (string, error) {
return transformEncoding(bytes.NewReader(b), japanese.ShiftJIS.NewDecoder())
}
func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateGuildMessageBoard) pkt := p.(*mhfpacket.MsgMhfUpdateGuildMessageBoard)
bf := byteframe.NewByteFrameFromBytes(pkt.Request) bf := byteframe.NewByteFrameFromBytes(pkt.Request)
@@ -1623,57 +1665,109 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
return return
} }
switch pkt.MessageOp { switch pkt.MessageOp {
case 0: // Create message case 0: // Create message
var title_str, body_str string
postType := bf.ReadUint32() // 0 = message, 1 = news postType := bf.ReadUint32() // 0 = message, 1 = news
stampId := bf.ReadUint32() stampId := bf.ReadUint32()
titleLength := bf.ReadUint32() titleLength := bf.ReadUint32()
bodyLength := bf.ReadUint32() bodyLength := bf.ReadUint32()
title := bf.ReadBytes(uint(titleLength)) title := bf.ReadBytes(uint(titleLength))
body := bf.ReadBytes(uint(bodyLength)) body := bf.ReadBytes(uint(bodyLength))
_, err := s.server.db.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.charID, int(stampId), int(postType), string(title), string(body))
title_str, err := BytesFromShiftJIS(title)
if err != nil { if err != nil {
s.logger.Fatal("Failed to add new guild message to db", zap.Error(err)) log.Println(err)
}
fmt.Println(title_str)
body_str, err = BytesFromShiftJIS(body)
if err != nil {
log.Println(err)
}
fmt.Println(body_str)
_, err = s.server.db.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.charID, int(stampId), int(postType), string(title_str), string(body_str))
if err != nil {
log.Println("Failed to add new guild message to db", zap.Error(err))
} }
// TODO: if there are too many messages, purge excess // TODO: if there are too many messages, purge excess
_, err = s.server.db.Exec("") _, err = s.server.db.Exec("")
if err != nil { if err != nil {
s.logger.Fatal("Failed to remove excess guild messages from db", zap.Error(err)) log.Println("Failed to remove excess guild messages from db", zap.Error(err))
} }
case 1: // Delete message case 1: // Delete message
var timestampst, timecomp uint64
timestampst = 32400
postType := bf.ReadUint32() postType := bf.ReadUint32()
timestamp := bf.ReadUint64() timestamp := bf.ReadUint64()
_, err := s.server.db.Exec("DELETE FROM guild_posts WHERE post_type = $1 AND (EXTRACT(epoch FROM created_at)::int) = $2 AND guild_id = $3", int(postType), int(timestamp), guild.ID)
timecomp = timestamp + timestampst
_, err := s.server.db.Exec("DELETE FROM guild_posts WHERE post_type = $1 AND (EXTRACT(epoch FROM created_at)::int) = $2 AND guild_id = $3", int(postType), int(timecomp), guild.ID)
if err != nil { if err != nil {
s.logger.Fatal("Failed to delete guild message from db", zap.Error(err)) log.Println("Failed to delete guild message from db", zap.Error(err))
} }
case 2: // Update message case 2: // Update message
var title_str, body_str string
var timestampst, timecomp uint64
timestampst = 32400
postType := bf.ReadUint32() postType := bf.ReadUint32()
timestamp := bf.ReadUint64() timestamp := bf.ReadUint64()
titleLength := bf.ReadUint32() titleLength := bf.ReadUint32()
bodyLength := bf.ReadUint32() bodyLength := bf.ReadUint32()
title := bf.ReadBytes(uint(titleLength)) title := bf.ReadBytes(uint(titleLength))
body := bf.ReadBytes(uint(bodyLength)) body := bf.ReadBytes(uint(bodyLength))
_, err := s.server.db.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE post_type = $3 AND (EXTRACT(epoch FROM created_at)::int) = $4 AND guild_id = $5", string(title), string(body), int(postType), int(timestamp), guild.ID)
title_str, err := BytesFromShiftJIS(title)
if err != nil { if err != nil {
s.logger.Fatal("Failed to update guild message in db", zap.Error(err)) log.Println(err)
}
fmt.Println(title_str)
body_str, err = BytesFromShiftJIS(body)
if err != nil {
log.Println(err)
}
fmt.Println(body_str)
timecomp = timestamp + timestampst
_, err = s.server.db.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE post_type = $3 AND (EXTRACT(epoch FROM created_at)::int) = $4 AND guild_id = $5", string(title_str), string(body_str), int(postType), int(timecomp), guild.ID)
if err != nil {
log.Println("Failed to update guild message in db", zap.Error(err))
} }
case 3: // Update stamp case 3: // Update stamp
var timestampst, timecomp uint64
timestampst = 32400
postType := bf.ReadUint32() postType := bf.ReadUint32()
timestamp := bf.ReadUint64() timestamp := bf.ReadUint64()
stampId := bf.ReadUint32() stampId := bf.ReadUint32()
_, err := s.server.db.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", int(stampId), int(postType), int(timestamp), guild.ID)
timecomp = timestamp + timestampst
_, err := s.server.db.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", int(stampId), int(postType), int(timecomp), guild.ID)
if err != nil { if err != nil {
s.logger.Fatal("Failed to update guild message stamp in db", zap.Error(err)) log.Println("Failed to update guild message stamp in db", zap.Error(err))
} }
case 4: // Like message case 4: // Like message
var timestampst, timecomp uint64
timestampst = 32400
postType := bf.ReadUint32() postType := bf.ReadUint32()
timestamp := bf.ReadUint64() timestamp := bf.ReadUint64()
likeState := bf.ReadBool() likeState := bf.ReadBool()
timecomp = timestamp + timestampst
var likedBy string var likedBy string
err := s.server.db.QueryRow("SELECT liked_by FROM guild_posts WHERE post_type = $1 AND (EXTRACT(epoch FROM created_at)::int) = $2 AND guild_id = $3", int(postType), int(timestamp), guild.ID).Scan(&likedBy) err := s.server.db.QueryRow("SELECT liked_by FROM guild_posts WHERE post_type = $1 AND (EXTRACT(epoch FROM created_at)::int) = $2 AND guild_id = $3", int(postType), int(timecomp), guild.ID).Scan(&likedBy)
if err != nil { if err != nil {
s.logger.Fatal("Failed to get guild message like data from db", zap.Error(err)) log.Println("Failed to get guild message like data from db", zap.Error(err))
} else { } else {
if likeState { if likeState {
if len(likedBy) == 0 { if len(likedBy) == 0 {
@@ -1681,9 +1775,9 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
likedBy += "," + strconv.Itoa(int(s.charID)) likedBy += "," + strconv.Itoa(int(s.charID))
} }
_, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", likedBy, int(postType), int(timestamp), guild.ID) _, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", likedBy, int(postType), int(timecomp), guild.ID)
if err != nil { if err != nil {
s.logger.Fatal("Failed to like guild message in db", zap.Error(err)) log.Println("Failed to like guild message in db", zap.Error(err))
} }
} else { } else {
likedBySlice := strings.Split(likedBy, ",") likedBySlice := strings.Split(likedBy, ",")
@@ -1694,9 +1788,9 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} }
} }
likedBy = strings.Join(likedBySlice, ",") likedBy = strings.Join(likedBySlice, ",")
_, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", likedBy, int(postType), int(timestamp), guild.ID) _, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE post_type = $2 AND (EXTRACT(epoch FROM created_at)::int) = $3 AND guild_id = $4", likedBy, int(postType), int(timecomp), guild.ID)
if err != nil { if err != nil {
s.logger.Fatal("Failed to unlike guild message in db", zap.Error(err)) log.Println("Failed to unlike guild message in db", zap.Error(err))
} }
} }
} }
@@ -1705,15 +1799,15 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
var newPosts int var newPosts int
err := s.server.db.QueryRow("SELECT (EXTRACT(epoch FROM guild_post_checked)::int) FROM characters WHERE id = $1", s.charID).Scan(&timeChecked) err := s.server.db.QueryRow("SELECT (EXTRACT(epoch FROM guild_post_checked)::int) FROM characters WHERE id = $1", s.charID).Scan(&timeChecked)
if err != nil { if err != nil {
s.logger.Fatal("Failed to get last guild post check timestamp from db", zap.Error(err)) log.Println("Failed to get last guild post check timestamp from db", zap.Error(err))
} else { } else {
_, err = s.server.db.Exec("UPDATE characters SET guild_post_checked = $1 WHERE id = $2", time.Now(), s.charID) _, err = s.server.db.Exec("UPDATE characters SET guild_post_checked = $1 WHERE id = $2", time.Now(), s.charID)
if err != nil { if err != nil {
s.logger.Fatal("Failed to update guild post check timestamp in db", zap.Error(err)) log.Println("Failed to update guild post check timestamp in db", zap.Error(err))
} else { } else {
err = s.server.db.QueryRow("SELECT COUNT(*) FROM guild_posts WHERE guild_id = $1 AND (EXTRACT(epoch FROM created_at)::int) > $2", guild.ID, timeChecked).Scan(&newPosts) err = s.server.db.QueryRow("SELECT COUNT(*) FROM guild_posts WHERE guild_id = $1 AND (EXTRACT(epoch FROM created_at)::int) > $2", guild.ID, timeChecked).Scan(&newPosts)
if err != nil { if err != nil {
s.logger.Fatal("Failed to check for new guild posts in db", zap.Error(err)) log.Println("Failed to check for new guild posts in db", zap.Error(err))
} else { } else {
if newPosts > 0 { if newPosts > 0 {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})