Implement greet inbox and outbox
- Add user_greet model and startup table sync - Implement /greet/user and /greet/delete handlers - Implement noticeFriendGreeting inbox and noticeUserGreetingHistory outbox - Return peer profile and center unit info for greeting notices - Update login topInfo friend greet counters from unread inbox messages Signed-off-by: Sean Du <do4suki@gmail.com>
This commit is contained in:
@@ -30,13 +30,23 @@ func loginTopInfo(ctx *gin.Context) (res any, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friendGreetCnt64, err := ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("receiver_id = ?", ss.UserID).
|
||||||
|
Where("deleted_from_receiver = ?", false).
|
||||||
|
Where("readed = ?", false).
|
||||||
|
Count()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
friendsRequestCnt := int(friendsRequestCnt64)
|
friendsRequestCnt := int(friendsRequestCnt64)
|
||||||
friendsApprovalWaitCnt := int(friendsApprovalWaitCnt64)
|
friendsApprovalWaitCnt := int(friendsApprovalWaitCnt64)
|
||||||
|
friendGreetCnt := int(friendGreetCnt64)
|
||||||
|
|
||||||
res = loginapischema.TopInfoResp{
|
res = loginapischema.TopInfoResp{
|
||||||
Result: loginapischema.TopInfoData{
|
Result: loginapischema.TopInfoData{
|
||||||
FriendActionCnt: 0,
|
FriendActionCnt: friendGreetCnt,
|
||||||
FriendGreetCnt: 0,
|
FriendGreetCnt: friendGreetCnt,
|
||||||
FriendVarietyCnt: 0,
|
FriendVarietyCnt: 0,
|
||||||
FriendNewCnt: friendsRequestCnt + friendsApprovalWaitCnt,
|
FriendNewCnt: friendsRequestCnt + friendsApprovalWaitCnt,
|
||||||
PresentCnt: 0,
|
PresentCnt: 0,
|
||||||
@@ -44,7 +54,7 @@ func loginTopInfo(ctx *gin.Context) (res any, err error) {
|
|||||||
ServerDatetime: now.Format("2006-01-02 15:04:05"),
|
ServerDatetime: now.Format("2006-01-02 15:04:05"),
|
||||||
ServerTimestamp: now.Unix(),
|
ServerTimestamp: now.Unix(),
|
||||||
NoticeFriendDatetime: now.Format("2006-01-02 15:04:05"),
|
NoticeFriendDatetime: now.Format("2006-01-02 15:04:05"),
|
||||||
NoticeMailDatetime: "2000-01-01 12:00:00",
|
NoticeMailDatetime: now.Format("2006-01-02 15:04:05"),
|
||||||
FriendsApprovalWaitCnt: friendsApprovalWaitCnt,
|
FriendsApprovalWaitCnt: friendsApprovalWaitCnt,
|
||||||
FriendsRequestCnt: friendsRequestCnt,
|
FriendsRequestCnt: friendsRequestCnt,
|
||||||
IsTodayBirthday: false,
|
IsTodayBirthday: false,
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package greet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
|
"honoka-chan/internal/session"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resolveGreetingUserID(ss *session.Session, requestedUserID int) (int, error) {
|
||||||
|
if requestedUserID <= 0 {
|
||||||
|
return 0, errors.New("invalid user_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
pref := usermodel.UserPref{}
|
||||||
|
has, err := ss.UserEng.Table(new(usermodel.UserPref)).
|
||||||
|
Where("invite_code = ?", strconv.Itoa(requestedUserID)).
|
||||||
|
Cols("user_id").
|
||||||
|
Get(&pref)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if has && pref.UserID > 0 {
|
||||||
|
return pref.UserID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user := usermodel.Users{}
|
||||||
|
has, err = ss.UserEng.Table(new(usermodel.Users)).
|
||||||
|
Where("user_id = ?", requestedUserID).
|
||||||
|
Cols("user_id").
|
||||||
|
Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if !has || user.UserID <= 0 {
|
||||||
|
return 0, errors.New("user not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.UserID, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package greet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"honoka-chan/internal/middleware"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
|
"honoka-chan/internal/router"
|
||||||
|
greetschema "honoka-chan/internal/schema/greet"
|
||||||
|
"honoka-chan/internal/session"
|
||||||
|
honokautils "honoka-chan/internal/utils"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deleteMail(ctx *gin.Context) {
|
||||||
|
ss := session.Get(ctx)
|
||||||
|
defer ss.Finalize()
|
||||||
|
|
||||||
|
req := greetschema.DeleteReq{}
|
||||||
|
err := honokautils.ParseRequestData(ctx, &req)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
notice := usermodel.UserGreet{}
|
||||||
|
has, err := ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("notice_id = ?", req.MailNoticeID).
|
||||||
|
Get(¬ice)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
ss.CheckErr(errors.New("notice not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case req.IsSendMail && notice.AffectorID == ss.UserID:
|
||||||
|
_, err = ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("notice_id = ?", req.MailNoticeID).
|
||||||
|
Cols("deleted_from_affector").
|
||||||
|
Update(&usermodel.UserGreet{DeletedFromAffector: true})
|
||||||
|
case !req.IsSendMail && notice.ReceiverID == ss.UserID:
|
||||||
|
_, err = ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("notice_id = ?", req.MailNoticeID).
|
||||||
|
Cols("deleted_from_receiver").
|
||||||
|
Update(&usermodel.UserGreet{DeletedFromReceiver: true})
|
||||||
|
default:
|
||||||
|
ss.CheckErr(errors.New("cannot delete this notice"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ss.Respond(greetschema.EmptyResp{
|
||||||
|
ResponseData: []any{},
|
||||||
|
ReleaseInfo: []any{},
|
||||||
|
StatusCode: 200,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
router.AddHandler("main.php", "POST", "/greet/delete", middleware.Common, deleteMail)
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package greet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"honoka-chan/internal/middleware"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
|
"honoka-chan/internal/router"
|
||||||
|
greetschema "honoka-chan/internal/schema/greet"
|
||||||
|
"honoka-chan/internal/session"
|
||||||
|
honokautils "honoka-chan/internal/utils"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func user(ctx *gin.Context) {
|
||||||
|
ss := session.Get(ctx)
|
||||||
|
defer ss.Finalize()
|
||||||
|
|
||||||
|
req := greetschema.UserReq{}
|
||||||
|
err := honokautils.ParseRequestData(ctx, &req)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
message := strings.TrimSpace(req.Message)
|
||||||
|
if message == "" {
|
||||||
|
ss.CheckErr(errors.New("message is required"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len([]rune(message)) > 200 {
|
||||||
|
ss.CheckErr(errors.New("message too long"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
targetUserID, err := resolveGreetingUserID(ss, req.ToUserID)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if targetUserID == ss.UserID {
|
||||||
|
ss.CheckErr(errors.New("cannot greet self"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
replyFlag := false
|
||||||
|
if req.RepliedNoticeID > 0 {
|
||||||
|
exists, err := ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("notice_id = ?", req.RepliedNoticeID).
|
||||||
|
Exist()
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
ss.CheckErr(errors.New("replied notice not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
replyFlag = true
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ss.UserEng.Table(new(usermodel.UserGreet)).Insert(&usermodel.UserGreet{
|
||||||
|
AffectorID: ss.UserID,
|
||||||
|
ReceiverID: targetUserID,
|
||||||
|
Message: message,
|
||||||
|
Reply: replyFlag,
|
||||||
|
Readed: false,
|
||||||
|
DeletedFromAffector: false,
|
||||||
|
DeletedFromReceiver: false,
|
||||||
|
InsertDate: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ss.Respond(greetschema.EmptyResp{
|
||||||
|
ResponseData: []any{},
|
||||||
|
ReleaseInfo: []any{},
|
||||||
|
StatusCode: 200,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
router.AddHandler("main.php", "POST", "/greet/user", middleware.Common, user)
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
_ "honoka-chan/internal/handler/friend"
|
_ "honoka-chan/internal/handler/friend"
|
||||||
_ "honoka-chan/internal/handler/gdpr"
|
_ "honoka-chan/internal/handler/gdpr"
|
||||||
_ "honoka-chan/internal/handler/ghome"
|
_ "honoka-chan/internal/handler/ghome"
|
||||||
|
_ "honoka-chan/internal/handler/greet"
|
||||||
_ "honoka-chan/internal/handler/lbonus"
|
_ "honoka-chan/internal/handler/lbonus"
|
||||||
_ "honoka-chan/internal/handler/live"
|
_ "honoka-chan/internal/handler/live"
|
||||||
_ "honoka-chan/internal/handler/login"
|
_ "honoka-chan/internal/handler/login"
|
||||||
|
|||||||
@@ -0,0 +1,180 @@
|
|||||||
|
package notice
|
||||||
|
|
||||||
|
import (
|
||||||
|
unitmodel "honoka-chan/internal/model/unit"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
|
noticeschema "honoka-chan/internal/schema/notice"
|
||||||
|
"honoka-chan/internal/session"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type greetingPeerRow struct {
|
||||||
|
UserID int `xorm:"user_id"`
|
||||||
|
UserName string `xorm:"user_name"`
|
||||||
|
UserLevel int `xorm:"user_level"`
|
||||||
|
AwardID int `xorm:"award_id"`
|
||||||
|
CenterUnitOwningUserID int `xorm:"center_unit_owning_user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGreetingPeer(ss *session.Session, userID int) (noticeschema.GreetingPeer, error) {
|
||||||
|
row := greetingPeerRow{}
|
||||||
|
has, err := ss.UserEng.Table(new(usermodel.UserPref)).Alias("up").
|
||||||
|
Join("LEFT", "user_deck ud", "ud.user_id = up.user_id AND ud.main_flag = 1").
|
||||||
|
Join("LEFT", "user_deck_unit udu", "udu.user_deck_id = ud.id AND udu.position = 5").
|
||||||
|
Select(`
|
||||||
|
up.user_id,
|
||||||
|
up.user_name,
|
||||||
|
up.user_level,
|
||||||
|
up.award_id,
|
||||||
|
COALESCE(udu.unit_owning_user_id, up.unit_owning_user_id) AS center_unit_owning_user_id
|
||||||
|
`).
|
||||||
|
Where("up.user_id = ?", userID).
|
||||||
|
Get(&row)
|
||||||
|
if err != nil {
|
||||||
|
return noticeschema.GreetingPeer{}, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return noticeschema.GreetingPeer{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
centerUnitInfo, err := buildGreetingCenterUnitInfo(ss, userID, row.CenterUnitOwningUserID, row.AwardID)
|
||||||
|
if err != nil {
|
||||||
|
return noticeschema.GreetingPeer{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return noticeschema.GreetingPeer{
|
||||||
|
UserData: noticeschema.GreetingUserData{
|
||||||
|
UserID: row.UserID,
|
||||||
|
Name: row.UserName,
|
||||||
|
Level: row.UserLevel,
|
||||||
|
},
|
||||||
|
CenterUnitInfo: centerUnitInfo,
|
||||||
|
SettingAwardID: row.AwardID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildGreetingCenterUnitInfo(ss *session.Session, userID, unitOwningUserID, awardID int) (noticeschema.GreetingCenterUnitInfo, error) {
|
||||||
|
info := noticeschema.GreetingCenterUnitInfo{
|
||||||
|
SettingAwardID: awardID,
|
||||||
|
RemovableSkillIds: []int{},
|
||||||
|
}
|
||||||
|
if unitOwningUserID <= 0 {
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
unitData := unitmodel.UnitDataMap{}
|
||||||
|
has, err := ss.GetBasicUnitInfo().
|
||||||
|
Where("a.user_id = ?", userID).
|
||||||
|
Where("a.unit_owning_user_id = ?", unitOwningUserID).
|
||||||
|
Get(&unitData)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
accessoryInfo, err := getGreetingAccessoryInfo(ss, userID, unitOwningUserID)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
removableSkillIDs := []int{}
|
||||||
|
err = ss.UserEng.Table(new(usermodel.UserUnitSkillEquip)).
|
||||||
|
Where("user_id = ? AND unit_owning_user_id = ?", userID, unitOwningUserID).
|
||||||
|
Cols("unit_removable_skill_id").
|
||||||
|
Find(&removableSkillIDs)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return noticeschema.GreetingCenterUnitInfo{
|
||||||
|
UnitOwningUserID: int64(unitData.UnitOwningUserID),
|
||||||
|
UnitID: unitData.UnitID,
|
||||||
|
Exp: unitData.Exp,
|
||||||
|
NextExp: 0,
|
||||||
|
Level: unitData.Level,
|
||||||
|
LevelLimitID: unitData.LevelLimitID,
|
||||||
|
MaxLevel: unitData.MaxLevel,
|
||||||
|
Rank: unitData.Rank,
|
||||||
|
MaxRank: unitData.MaxRank,
|
||||||
|
Love: unitData.Love,
|
||||||
|
MaxLove: unitData.MaxLove,
|
||||||
|
UnitSkillLevel: unitData.UnitSkillLevel,
|
||||||
|
MaxHp: unitData.MaxHp,
|
||||||
|
FavoriteFlag: unitData.FavoriteFlag,
|
||||||
|
DisplayRank: unitData.DisplayRank,
|
||||||
|
UnitSkillExp: unitData.UnitSkillExp,
|
||||||
|
UnitRemovableSkillCapacity: unitData.UnitRemovableSkillCapacity,
|
||||||
|
Attribute: unitData.Attribute,
|
||||||
|
Smile: unitData.Smile,
|
||||||
|
Cute: unitData.Cute,
|
||||||
|
Cool: unitData.Cool,
|
||||||
|
IsLoveMax: unitData.IsLoveMax,
|
||||||
|
IsLevelMax: unitData.IsLevelMax,
|
||||||
|
IsRankMax: unitData.IsRankMax,
|
||||||
|
IsSigned: unitData.IsSigned,
|
||||||
|
IsSkillLevelMax: unitData.IsSkillLevelMax,
|
||||||
|
SettingAwardID: awardID,
|
||||||
|
RemovableSkillIds: removableSkillIDs,
|
||||||
|
AccessoryInfo: accessoryInfo,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGreetingAccessoryInfo(ss *session.Session, userID, unitOwningUserID int) (*noticeschema.GreetingAccessoryInfo, error) {
|
||||||
|
accessoryWear := usermodel.UserAccessoryWear{}
|
||||||
|
has, err := ss.UserEng.Table(new(usermodel.UserAccessoryWear)).
|
||||||
|
Where("user_id = ? AND unit_owning_user_id = ?", userID, unitOwningUserID).
|
||||||
|
Get(&accessoryWear)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !has || accessoryWear.AccessoryOwningUserID <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
accessoryData := struct {
|
||||||
|
AccessoryID int `xorm:"accessory_id"`
|
||||||
|
Exp int `xorm:"exp"`
|
||||||
|
}{}
|
||||||
|
has, err = ss.MainEng.Table("common_accessory_m").
|
||||||
|
Where("accessory_owning_user_id = ?", accessoryWear.AccessoryOwningUserID).
|
||||||
|
Cols("accessory_id,exp").
|
||||||
|
Get(&accessoryData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ¬iceschema.GreetingAccessoryInfo{
|
||||||
|
AccessoryOwningUserID: accessoryWear.AccessoryOwningUserID,
|
||||||
|
AccessoryID: accessoryData.AccessoryID,
|
||||||
|
Exp: accessoryData.Exp,
|
||||||
|
NextExp: 0,
|
||||||
|
Level: 8,
|
||||||
|
MaxLevel: 8,
|
||||||
|
RankUpCount: 4,
|
||||||
|
FavoriteFlag: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatGreetingElapsedTime(ts int64) string {
|
||||||
|
if ts <= 0 {
|
||||||
|
return "刚刚"
|
||||||
|
}
|
||||||
|
|
||||||
|
delta := time.Since(time.Unix(ts, 0))
|
||||||
|
if delta < time.Minute {
|
||||||
|
return "刚刚"
|
||||||
|
}
|
||||||
|
if delta < time.Hour {
|
||||||
|
return strconv.Itoa(int(delta.Minutes())) + "分钟前"
|
||||||
|
}
|
||||||
|
if delta < 24*time.Hour {
|
||||||
|
return strconv.Itoa(int(delta.Hours())) + "小时前"
|
||||||
|
}
|
||||||
|
return strconv.Itoa(int(delta.Hours())/24) + "天前"
|
||||||
|
}
|
||||||
@@ -2,9 +2,11 @@ package notice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"honoka-chan/internal/middleware"
|
"honoka-chan/internal/middleware"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
"honoka-chan/internal/router"
|
"honoka-chan/internal/router"
|
||||||
noticeschema "honoka-chan/internal/schema/notice"
|
noticeschema "honoka-chan/internal/schema/notice"
|
||||||
"honoka-chan/internal/session"
|
"honoka-chan/internal/session"
|
||||||
|
honokautils "honoka-chan/internal/utils"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -14,10 +16,67 @@ func friendGreeting(ctx *gin.Context) {
|
|||||||
ss := session.Get(ctx)
|
ss := session.Get(ctx)
|
||||||
defer ss.Finalize()
|
defer ss.Finalize()
|
||||||
|
|
||||||
|
req := noticeschema.GreetingNoticeReq{}
|
||||||
|
err := honokautils.ParseRequestData(ctx, &req)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query := ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("receiver_id = ?", ss.UserID).
|
||||||
|
Where("deleted_from_receiver = ?", false)
|
||||||
|
if req.NextID > 0 {
|
||||||
|
query = query.Where("notice_id < ?", req.NextID)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []usermodel.UserGreet{}
|
||||||
|
err = query.
|
||||||
|
OrderBy("notice_id DESC").
|
||||||
|
Limit(usermodel.GreetingPageSize).
|
||||||
|
Find(&rows)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
noticeList := make([]noticeschema.FriendGreetingNotice, 0, len(rows))
|
||||||
|
nextID := 0
|
||||||
|
for _, row := range rows {
|
||||||
|
affector, err := getGreetingPeer(ss, row.AffectorID)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
noticeList = append(noticeList, noticeschema.FriendGreetingNotice{
|
||||||
|
NoticeID: row.NoticeID,
|
||||||
|
NewFlag: true,
|
||||||
|
ReferenceTable: 6,
|
||||||
|
Message: row.Message,
|
||||||
|
ListMessage: row.Message,
|
||||||
|
Readed: true,
|
||||||
|
InsertDate: formatGreetingElapsedTime(row.InsertDate),
|
||||||
|
Affector: affector,
|
||||||
|
ReplyFlag: row.Reply,
|
||||||
|
})
|
||||||
|
nextID = row.NoticeID
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rows) < usermodel.GreetingPageSize {
|
||||||
|
nextID = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("receiver_id = ?", ss.UserID).
|
||||||
|
Where("readed = ?", false).
|
||||||
|
Cols("readed").
|
||||||
|
Update(&usermodel.UserGreet{Readed: true})
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ss.Respond(noticeschema.FriendGreetingResp{
|
ss.Respond(noticeschema.FriendGreetingResp{
|
||||||
ResponseData: noticeschema.FriendGreetingData{
|
ResponseData: noticeschema.FriendGreetingData{
|
||||||
NextId: 0,
|
NextId: nextID,
|
||||||
NoticeList: []any{},
|
NoticeList: noticeList,
|
||||||
ServerTimestamp: time.Now().Unix(),
|
ServerTimestamp: time.Now().Unix(),
|
||||||
},
|
},
|
||||||
ReleaseInfo: []any{},
|
ReleaseInfo: []any{},
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package notice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"honoka-chan/internal/middleware"
|
"honoka-chan/internal/middleware"
|
||||||
|
usermodel "honoka-chan/internal/model/user"
|
||||||
"honoka-chan/internal/router"
|
"honoka-chan/internal/router"
|
||||||
noticeschema "honoka-chan/internal/schema/notice"
|
noticeschema "honoka-chan/internal/schema/notice"
|
||||||
"honoka-chan/internal/session"
|
"honoka-chan/internal/session"
|
||||||
|
honokautils "honoka-chan/internal/utils"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -14,11 +16,55 @@ func userGreetingHistory(ctx *gin.Context) {
|
|||||||
ss := session.Get(ctx)
|
ss := session.Get(ctx)
|
||||||
defer ss.Finalize()
|
defer ss.Finalize()
|
||||||
|
|
||||||
|
req := noticeschema.GreetingNoticeReq{}
|
||||||
|
err := honokautils.ParseRequestData(ctx, &req)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCount, err := ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("affector_id = ?", ss.UserID).
|
||||||
|
Where("deleted_from_affector = ?", false).
|
||||||
|
Count()
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []usermodel.UserGreet{}
|
||||||
|
err = ss.UserEng.Table(new(usermodel.UserGreet)).
|
||||||
|
Where("affector_id = ?", ss.UserID).
|
||||||
|
Where("deleted_from_affector = ?", false).
|
||||||
|
OrderBy("notice_id DESC").
|
||||||
|
Limit(usermodel.GreetingPageSize).
|
||||||
|
Find(&rows)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
noticeList := make([]noticeschema.UserGreetingNotice, 0, len(rows))
|
||||||
|
for _, row := range rows {
|
||||||
|
receiver, err := getGreetingPeer(ss, row.ReceiverID)
|
||||||
|
if ss.CheckErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
noticeList = append(noticeList, noticeschema.UserGreetingNotice{
|
||||||
|
NoticeID: row.NoticeID,
|
||||||
|
ReferenceTable: 6,
|
||||||
|
Message: row.Message,
|
||||||
|
ListMessage: row.Message,
|
||||||
|
InsertDate: formatGreetingElapsedTime(row.InsertDate),
|
||||||
|
Receiver: receiver,
|
||||||
|
ReplyFlag: row.Reply,
|
||||||
|
Readed: row.Readed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ss.Respond(noticeschema.UserGreetingResp{
|
ss.Respond(noticeschema.UserGreetingResp{
|
||||||
ResponseData: noticeschema.UserGreetingData{
|
ResponseData: noticeschema.UserGreetingData{
|
||||||
ItemCount: 0,
|
ItemCount: int(totalCount),
|
||||||
HasNext: false,
|
HasNext: totalCount > int64(len(rows)),
|
||||||
NoticeList: []any{},
|
NoticeList: noticeList,
|
||||||
ServerTimestamp: time.Now().Unix(),
|
ServerTimestamp: time.Now().Unix(),
|
||||||
},
|
},
|
||||||
ReleaseInfo: []any{},
|
ReleaseInfo: []any{},
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package usermodel
|
||||||
|
|
||||||
|
const GreetingPageSize = 40
|
||||||
|
|
||||||
|
type UserGreet struct {
|
||||||
|
NoticeID int `xorm:"notice_id pk autoincr"`
|
||||||
|
AffectorID int `xorm:"affector_id index"`
|
||||||
|
ReceiverID int `xorm:"receiver_id index"`
|
||||||
|
Message string `xorm:"message text"`
|
||||||
|
Reply bool `xorm:"reply"`
|
||||||
|
Readed bool `xorm:"readed"`
|
||||||
|
DeletedFromAffector bool `xorm:"deleted_from_affector"`
|
||||||
|
DeletedFromReceiver bool `xorm:"deleted_from_receiver"`
|
||||||
|
InsertDate int64 `xorm:"insert_date index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UserGreet) TableName() string {
|
||||||
|
return "user_greet"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package greetschema
|
||||||
|
|
||||||
|
type EmptyResp struct {
|
||||||
|
ResponseData []any `json:"response_data"`
|
||||||
|
ReleaseInfo []any `json:"release_info"`
|
||||||
|
StatusCode int `json:"status_code"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package greetschema
|
||||||
|
|
||||||
|
type DeleteReq struct {
|
||||||
|
Module string `json:"module"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
Mgd int `json:"mgd"`
|
||||||
|
IsSendMail bool `json:"is_send_mail"`
|
||||||
|
MailNoticeID int `json:"mail_notice_id"`
|
||||||
|
CommandNum string `json:"commandNum"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package greetschema
|
||||||
|
|
||||||
|
type UserReq struct {
|
||||||
|
Module string `json:"module"`
|
||||||
|
Mgd int `json:"mgd"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
ToUserID int `json:"to_user_id"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
RepliedNoticeID int `json:"replied_notice_id"`
|
||||||
|
CommandNum string `json:"commandNum"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package noticeschema
|
||||||
|
|
||||||
|
type GreetingNoticeReq struct {
|
||||||
|
Module string `json:"module"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
Mgd int `json:"mgd"`
|
||||||
|
NextID int `json:"next_id"`
|
||||||
|
IsPrevious bool `json:"is_previous"`
|
||||||
|
CommandNum string `json:"commandNum"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GreetingUserData struct {
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GreetingAccessoryInfo struct {
|
||||||
|
AccessoryOwningUserID int `json:"accessory_owning_user_id"`
|
||||||
|
AccessoryID int `json:"accessory_id"`
|
||||||
|
Exp int `json:"exp"`
|
||||||
|
NextExp int `json:"next_exp"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
MaxLevel int `json:"max_level"`
|
||||||
|
RankUpCount int `json:"rank_up_count"`
|
||||||
|
FavoriteFlag bool `json:"favorite_flag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GreetingCenterUnitInfo struct {
|
||||||
|
UnitOwningUserID int64 `json:"unit_owning_user_id"`
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
Exp int `json:"exp"`
|
||||||
|
NextExp int `json:"next_exp"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
LevelLimitID int `json:"level_limit_id"`
|
||||||
|
MaxLevel int `json:"max_level"`
|
||||||
|
Rank int `json:"rank"`
|
||||||
|
MaxRank int `json:"max_rank"`
|
||||||
|
Love int `json:"love"`
|
||||||
|
MaxLove int `json:"max_love"`
|
||||||
|
UnitSkillLevel int `json:"unit_skill_level"`
|
||||||
|
MaxHp int `json:"max_hp"`
|
||||||
|
FavoriteFlag bool `json:"favorite_flag"`
|
||||||
|
DisplayRank int `json:"display_rank"`
|
||||||
|
UnitSkillExp int `json:"unit_skill_exp"`
|
||||||
|
UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"`
|
||||||
|
Attribute int `json:"attribute"`
|
||||||
|
Smile int `json:"smile"`
|
||||||
|
Cute int `json:"cute"`
|
||||||
|
Cool int `json:"cool"`
|
||||||
|
IsLoveMax bool `json:"is_love_max"`
|
||||||
|
IsLevelMax bool `json:"is_level_max"`
|
||||||
|
IsRankMax bool `json:"is_rank_max"`
|
||||||
|
IsSigned bool `json:"is_signed"`
|
||||||
|
IsSkillLevelMax bool `json:"is_skill_level_max"`
|
||||||
|
SettingAwardID int `json:"setting_award_id"`
|
||||||
|
RemovableSkillIds []int `json:"removable_skill_ids"`
|
||||||
|
AccessoryInfo *GreetingAccessoryInfo `json:"accessory_info,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GreetingPeer struct {
|
||||||
|
UserData GreetingUserData `json:"user_data"`
|
||||||
|
CenterUnitInfo GreetingCenterUnitInfo `json:"center_unit_info"`
|
||||||
|
SettingAwardID int `json:"setting_award_id"`
|
||||||
|
}
|
||||||
@@ -1,9 +1,21 @@
|
|||||||
package noticeschema
|
package noticeschema
|
||||||
|
|
||||||
type FriendGreetingData struct {
|
type FriendGreetingData struct {
|
||||||
NextId int `json:"next_id"`
|
NextId int `json:"next_id"`
|
||||||
NoticeList []any `json:"notice_list"`
|
NoticeList []FriendGreetingNotice `json:"notice_list"`
|
||||||
ServerTimestamp int64 `json:"server_timestamp"`
|
ServerTimestamp int64 `json:"server_timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FriendGreetingNotice struct {
|
||||||
|
NoticeID int `json:"notice_id"`
|
||||||
|
NewFlag bool `json:"new_flag"`
|
||||||
|
ReferenceTable int `json:"reference_table"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
ListMessage string `json:"list_message"`
|
||||||
|
Readed bool `json:"readed"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
Affector GreetingPeer `json:"affector"`
|
||||||
|
ReplyFlag bool `json:"reply_flag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FriendGreetingResp struct {
|
type FriendGreetingResp struct {
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
package noticeschema
|
package noticeschema
|
||||||
|
|
||||||
type UserGreetingData struct {
|
type UserGreetingData struct {
|
||||||
ItemCount int `json:"item_count"`
|
ItemCount int `json:"item_count"`
|
||||||
HasNext bool `json:"has_next"`
|
HasNext bool `json:"has_next"`
|
||||||
NoticeList []any `json:"notice_list"`
|
NoticeList []UserGreetingNotice `json:"notice_list"`
|
||||||
ServerTimestamp int64 `json:"server_timestamp"`
|
ServerTimestamp int64 `json:"server_timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserGreetingNotice struct {
|
||||||
|
NoticeID int `json:"notice_id"`
|
||||||
|
ReferenceTable int `json:"reference_table"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
ListMessage string `json:"list_message"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
Receiver GreetingPeer `json:"receiver"`
|
||||||
|
ReplyFlag bool `json:"reply_flag"`
|
||||||
|
Readed bool `json:"readed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserGreetingResp struct {
|
type UserGreetingResp struct {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ func CreateTables() {
|
|||||||
db.UserEng.Sync2(new(usermodel.UserLiveInProgress))
|
db.UserEng.Sync2(new(usermodel.UserLiveInProgress))
|
||||||
db.UserEng.Sync2(new(usermodel.UserLiveRecord))
|
db.UserEng.Sync2(new(usermodel.UserLiveRecord))
|
||||||
db.UserEng.Sync2(new(usermodel.UserFriend))
|
db.UserEng.Sync2(new(usermodel.UserFriend))
|
||||||
|
db.UserEng.Sync2(new(usermodel.UserGreet))
|
||||||
db.UserEng.Sync2(new(usermodel.UserPref))
|
db.UserEng.Sync2(new(usermodel.UserPref))
|
||||||
db.UserEng.Sync2(new(usermodel.Users))
|
db.UserEng.Sync2(new(usermodel.Users))
|
||||||
db.UserEng.Sync2(new(usermodel.UserUnit))
|
db.UserEng.Sync2(new(usermodel.UserUnit))
|
||||||
|
|||||||
Reference in New Issue
Block a user