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:
@@ -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 (
|
||||
"honoka-chan/internal/middleware"
|
||||
usermodel "honoka-chan/internal/model/user"
|
||||
"honoka-chan/internal/router"
|
||||
noticeschema "honoka-chan/internal/schema/notice"
|
||||
"honoka-chan/internal/session"
|
||||
honokautils "honoka-chan/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -14,10 +16,67 @@ func friendGreeting(ctx *gin.Context) {
|
||||
ss := session.Get(ctx)
|
||||
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{
|
||||
ResponseData: noticeschema.FriendGreetingData{
|
||||
NextId: 0,
|
||||
NoticeList: []any{},
|
||||
NextId: nextID,
|
||||
NoticeList: noticeList,
|
||||
ServerTimestamp: time.Now().Unix(),
|
||||
},
|
||||
ReleaseInfo: []any{},
|
||||
|
||||
@@ -2,9 +2,11 @@ package notice
|
||||
|
||||
import (
|
||||
"honoka-chan/internal/middleware"
|
||||
usermodel "honoka-chan/internal/model/user"
|
||||
"honoka-chan/internal/router"
|
||||
noticeschema "honoka-chan/internal/schema/notice"
|
||||
"honoka-chan/internal/session"
|
||||
honokautils "honoka-chan/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -14,11 +16,55 @@ func userGreetingHistory(ctx *gin.Context) {
|
||||
ss := session.Get(ctx)
|
||||
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{
|
||||
ResponseData: noticeschema.UserGreetingData{
|
||||
ItemCount: 0,
|
||||
HasNext: false,
|
||||
NoticeList: []any{},
|
||||
ItemCount: int(totalCount),
|
||||
HasNext: totalCount > int64(len(rows)),
|
||||
NoticeList: noticeList,
|
||||
ServerTimestamp: time.Now().Unix(),
|
||||
},
|
||||
ReleaseInfo: []any{},
|
||||
|
||||
Reference in New Issue
Block a user