...
 
Commits (72)
package cp_e
type CpAchievement int
const (
CpAchievementLevel CpAchievement = 1 // 等级
CpAchievementVisitors CpAchievement = 2 // 空间访问人数
CpAchievementMonthRank CpAchievement = 3 // 月榜最高
CpAchievementWeekRank CpAchievement = 4 // 周榜最高
CpAchievementDayRank CpAchievement = 5 // 日榜最高
)
package cp_e
type AnniversaryItemType int
const (
AnniversaryItemTypeNormal AnniversaryItemType = 0 // 普通类型
AnniversaryItemTypeAvatar AnniversaryItemType = 1 // 头像类型
AnniversaryItemTypeAnniversary AnniversaryItemType = 2 // 纪念日类型(一年一度,如生日/结婚纪念日)
)
package cp_e
import "git.hilo.cn/hilo-common/resource/mysql"
const (
EffectDays = 30 // 30天有效期
)
type CpLevel int
const (
CpLevel0 CpLevel = 0 // 无称号
CpLevel1 CpLevel = 1 // 恋爱CP
CpLevel2 CpLevel = 2 // 甜蜜CP
CpLevel3 CpLevel = 3 // 忠诚CP
CpLevel4 CpLevel = 4 // 炽热CP
CpLevel5 CpLevel = 5 // 荣耀CP
CpLevelMax = CpLevel5
)
var (
// cp等级积分
CpLevelPoints = map[CpLevel]mysql.Num{
CpLevel0: 0,
CpLevel1: 200000,
CpLevel2: 800000,
CpLevel3: 1000000,
CpLevel4: 3000000,
CpLevel5: 10000000,
}
// cp等级icon // todo ui
CpLevelIcon = map[CpLevel]string{
CpLevel0: "icon0.png",
CpLevel1: "icon1.png",
CpLevel2: "icon2.png",
CpLevel3: "icon3.png",
CpLevel4: "icon4.png",
CpLevel5: "icon5.png",
}
// cp等级称号
CpLevelTitle = map[CpLevel]uint{
CpLevel1: 252,
CpLevel2: 253,
CpLevel3: 254,
CpLevel4: 255,
CpLevel5: 256,
}
// cp特权名称
CpPrivilegeNameMsgId = map[CpPrivilege]uint{
CpPrivilegeSpace: 234,
CpPrivilegeBanner: 235,
CpPrivilegeMedal: 236,
CpPrivilegeCert: 237,
CpPrivilegeRoomEffect: 238,
CpPrivilegeHeadwear: 239,
CpPrivilegeActiveProfile: 240,
CpPrivilegeMicEffect: 241,
}
// cp特权描述
CpPrivilegeDescMsgId = map[CpPrivilege]uint{
CpPrivilegeSpace: 264,
CpPrivilegeBanner: 265,
CpPrivilegeMedal: 266,
CpPrivilegeCert: 267,
CpPrivilegeRoomEffect: 268,
CpPrivilegeHeadwear: 269,
CpPrivilegeActiveProfile: 270,
CpPrivilegeMicEffect: 271,
}
// cp特权icon // todo ui
CpPrivilegeIcon = map[CpPrivilege]string{
CpPrivilegeSpace: "icon_p_1.png",
CpPrivilegeBanner: "icon_p_2.png",
CpPrivilegeMedal: "icon_p_3.png",
CpPrivilegeCert: "icon_p_4.png",
CpPrivilegeRoomEffect: "icon_p_5.png",
CpPrivilegeHeadwear: "icon_p_6.png",
CpPrivilegeActiveProfile: "icon_p_7.png",
CpPrivilegeMicEffect: "icon_p_8.png",
}
)
type CpPrivilege int
const (
CpPrivilegeSpace CpPrivilege = 1 // 空间
CpPrivilegeBanner CpPrivilege = 2 // 横幅
CpPrivilegeMedal CpPrivilege = 3 // 等级勋章
CpPrivilegeCert CpPrivilege = 4 // 证书
CpPrivilegeRoomEffect CpPrivilege = 5 // 进场特效
CpPrivilegeHeadwear CpPrivilege = 6 // 头像头饰
CpPrivilegeActiveProfile CpPrivilege = 7 // 动态资料卡
CpPrivilegeMicEffect CpPrivilege = 8 // 麦位特效
)
package gift_e
import "git.hilo.cn/hilo-common/resource/mysql"
type GiftOperateSceneType mysql.Type
const (
//匹配声网中场景
MatchVedioSceneType GiftOperateSceneType = 1
// 私聊
PriveChatSceneType GiftOperateSceneType = 2
//1对1视频
VideoSceneType GiftOperateSceneType = 3
//群组
GroupSceneType GiftOperateSceneType = 4
)
type ResGiftAvatarType = mysql.Type
const (
SendGiftCpGiftAvatarType ResGiftAvatarType = 1 //周CP
MonthlyWealthGiftAvatarType ResGiftAvatarType = 2 //月冠财富榜
MonthlyCharmGiftAvatarType ResGiftAvatarType = 3 //月冠魅力榜
MonthlyPayGiftAvatarType ResGiftAvatarType = 4 //月冠充值榜
WeekStarGiftAvatarType ResGiftAvatarType = 5 //周星榜
CountryStarGiftAvatarType ResGiftAvatarType = 6 // 国家之星
)
type GiftPrivateRecordType = mysql.Type
const (
PrivateRecord GiftPrivateRecordType = 1
VideoTradeUnion GiftPrivateRecordType = 2
PrivateRecordBag GiftPrivateRecordType = 3
)
type GiftColumnType = uint16
const (
GiftColumnGift GiftColumnType = 1 // 礼物
GiftColumnRomance GiftColumnType = 2 // 浪漫
GiftColumnCountry GiftColumnType = 3 // 国家
GiftColumnCustom GiftColumnType = 4 // 定制
)
type GiftTagType = uint16
const (
GiftTagMedal GiftTagType = 1 // 勋章礼物
GiftTagWeeklyStar GiftTagType = 2 // 周星礼物
)
type GiftEntryType = uint16
const (
GiftEntryWeeklyStar GiftEntryType = 1 // 周星活动入口
GiftEntryWeeklyCp GiftEntryType = 2 // 周CP活动入口
GiftEntryMedal GiftEntryType = 3 // 勋章激活动入口
GiftEntryCountryStar GiftEntryType = 4 // 国家之星活动入口
)
...@@ -5,55 +5,16 @@ import "git.hilo.cn/hilo-common/resource/mysql" ...@@ -5,55 +5,16 @@ import "git.hilo.cn/hilo-common/resource/mysql"
type MsgIdType = uint type MsgIdType = uint
const ( const (
DEFAULT_LANG = "en" DefaultLang = "en"
) )
type ResMedalType = mysql.Type type ResMedalType = mysql.Type
const (
Wealth ResMedalType = 1
Charm ResMedalType = 2
LoveForAll ResMedalType = 3
StartForAll ResMedalType = 4
MoonForAll ResMedalType = 5
MarryMe ResMedalType = 6
RoomRocket ResMedalType = 7
Actity ResMedalType = 8
FruitKing ResMedalType = 9
BoxKing ResMedalType = 10
Helicopter ResMedalType = 11
Roadster ResMedalType = 12
Watermelon ResMedalType = 13
Kiss ResMedalType = 14
Love ResMedalType = 15
Chick ResMedalType = 16
SportsCar ResMedalType = 17
Rocket ResMedalType = 18
Tower ResMedalType = 19
Eagle ResMedalType = 20
Lion ResMedalType = 21
Vacation ResMedalType = 22
RomanticNight ResMedalType = 23
SweetCouple ResMedalType = 24
Castle ResMedalType = 25
WeddingCar ResMedalType = 26
VideoChat ResMedalType = 27
)
type ResMedalScope = mysql.Type type ResMedalScope = mysql.Type
const (
//私有,只能时管理人发放
Private ResMedalScope = 1
//公有,自己获取
Public ResMedalScope = 2
)
type ResNameplateType = mysql.Type type ResNameplateType = mysql.Type
type ResNameplateObtainType = mysql.Type type ResNameplateObtainType = mysql.Type
type ResNameplateScope = mysql.Type type ResNameplateScope = mysql.Type
type ResUserBag = mysql.Type type ResUserBag = mysql.Type
type ResPropertyAvatarType = mysql.Type
const ( const (
ResUserBagGift ResUserBag = 1 // 背包道具-礼物 ResUserBagGift ResUserBag = 1 // 背包道具-礼物
......
package cp_cron
import (
"git.hilo.cn/hilo-common/_const/enum/msg_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/msg_m"
)
// 纪念日
type CpAnniversaryNoticeMsg struct {
Identifier string `json:"identifier"`
Content string `json:"content"`
Timestamp int64 `json:"timestamp"`
}
func CpAnniversaryNotice() {
c := cron.New()
// 1小时操作一次
spec := "0 0 */1 * * ?"
if !config.AppIsRelease() {
// 测服1分钟
spec = "0 * * * * ?"
}
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
anniversary := cp_m.GetNeedRemindCpAnniversary(model)
for _, v := range anniversary {
var userIds []uint64
userIds = append(userIds, v.UserId1, v.UserId2)
record1 := msg_m.NewUserRecord(model, v.UserId1, msg_e.CpAnniversaryNotice, v.Content, 0, "", "", "", "", "")
record2 := msg_m.NewUserRecord(model, v.UserId2, msg_e.CpAnniversaryNotice, v.Content, 0, "", "", "", "", "")
err1, err2 := record1.Persistent(), record2.Persistent()
if err1 != nil || err2 != nil {
model.Log.Errorf("NewUserRecord fail:%v-%v", err1, err2)
return
}
//if err := tencentyun.BatchSendCustomMsg(model, 1, users[0].ExternalId, []string{users[1].ExternalId}, string(data), "cp纪念日"); err != nil {
// model.Log.Errorf("BatchSendCustomMsg fail:%v", err)
//}
//if err := tencentyun.BatchSendCustomMsg(model, 1, users[1].ExternalId, []string{users[0].ExternalId}, string(data), "cp纪念日"); err != nil {
// model.Log.Errorf("BatchSendCustomMsg fail:%v", err)
//}
if err := cp_m.UpdateCpAnniversaryReminded(model, v.ID); err != nil {
model.Log.Errorf("UpdateCpAnniversaryReminded fail:%v", err)
}
}
})
c.Start()
}
package cp_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-user/domain/model/cp_m"
)
func ClearCpExpire() {
c := cron.New()
spec := "0 0 */1 * * ?"
if !config.AppIsRelease() {
spec = "* * * * * ?"
}
// 1小时清理一次
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
if err := cp_m.ClearExpireCpPoints(model); err != nil {
model.Log.Errorf("ClearExpireCpPoints fail:%v", err)
}
})
c.Start()
}
package cron
import (
"git.hilo.cn/hilo-common/resource/config"
"hilo-user/cron/cp_cron"
"hilo-user/cron/gift_cron"
)
func Init() {
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
cp_cron.ClearCpExpire() // 清理过期cp
cp_cron.CpAnniversaryNotice() // cp纪念日
}
package gift_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-user/domain/model/event_m"
)
// 补偿检查mark=2
func GiftRemark() {
c := cron.New()
// 每5分钟
spec := "0 */5 * * * ?"
if !config.AppIsRelease() {
spec = "0 * * * * ?" // 测服1分钟
}
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
unmarks, err := event_m.FetchUnMarkEvents(model, 10)
if err != nil {
model.Log.Errorf("FetchUnMarkEvents fail:%v", err)
return
}
for _, unmark := range unmarks {
model.Log.Infof("FetchUnMarkEvent start:%v", unmark.ID)
// 重新入库
if err := event_m.AddUnMarkEvent(model, &event_m.EventGiftSend{
Proto: unmark.Proto,
Payload: unmark.Payload,
MarkHiloGroup: unmark.MarkHiloGroup,
MarkHiloUser: unmark.MarkHiloUser,
Mark: unmark.Mark, // 不能影响别的服务的mark状态
}); err != nil {
model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err)
continue
}
// 旧的标记已处理
unmark.Model = model
if err := unmark.MarkDone(); err != nil {
model.Log.Errorf("FetchUnMarkEvent mark fail:%v", err)
}
model.Log.Infof("FetchUnMarkEvent success:%v", unmark.ID)
}
})
c.Start()
}
package gift_cron
import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"hilo-user/domain/service/event_s"
"time"
)
// 送礼事件
func SendGiftEventInit() {
mylogrus.MyLog.Infof("SendGiftEventInit")
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
//start := time.Now()
myCtx := mycontext.CreateMyContext(nil)
// 消费送礼事件
if err := event_s.NewGiftSendEventService(myCtx).Consume(); err != nil {
myCtx.Log.Errorf("eventServcie consume fail:%v", err)
} else {
//myCtx.Log.Infof("eventServcie consume success,cost:%v", time.Now().Sub(start))
}
}
}
}()
}
package cp_cv
import (
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/user_cv"
)
// cp信息
type CvCpBase struct {
UserInfo user_cv.UserTiny `json:"userInfo"` // 用户信息
CpUserInfo user_cv.UserTiny `json:"cpUserInfo,omitempty"` // cp用户信息
}
type CvCpAnniversary struct {
Type cp_e.AnniversaryItemType `json:"type"` // 列表类型 0:普通 1:头像
CpInfo *CvCpBase `json:"cpInfo,omitempty"` // cp信息,type=1(头像)时候用到
Id uint64 `json:"id"` // 记录id
Content string `json:"content"` // 纪念日内容
OriginTimestamp int64 `json:"originTimestamp"` // 纪念日的时间
Timestamp int64 `json:"timestamp"` // 下次纪念日时间戳
IsRemind bool `json:"isRemind"` // 是否提醒
CanDel bool `json:"canDel"` // 能否删除
IsTop bool `json:"isTop"` // 是否置顶
}
package cp_cv
import "hilo-user/cv/user_cv"
// cp信息
type CvCp struct {
CpUserInfo *user_cv.CvUserBase `json:"cpUserInfo"` // cp用户信息
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
MyPrivilegeList []CvPrivilege `json:"myPrivilegeList"` // 等级特权
}
// cp关系
type CvCpRelation struct {
CpId uint64 `json:"cpId"`
UserId uint64 `json:"userId"`
CpUserId uint64 `json:"cpUserId"`
CpUserAvatar string `json:"cpUserAvatar,omitempty"`
}
package cp_cv
import (
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/user_cv"
)
type CvCpRank struct {
CpId uint64 `json:"cpId"` // cpId
User1 *user_cv.CvUserBase `json:"user1"` // user1
User2 *user_cv.CvUserBase `json:"user2,omitempty"` // user2
Score uint32 `json:"score"` // 分值
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
Ranking string `json:"ranking"` // 排名
}
type CvCpAchievement struct {
CpId uint64 `json:"cpId"` // cpId
User1 *user_cv.UserTiny `json:"user1"` // user1
User2 *user_cv.UserTiny `json:"user2"` // user2
Type cp_e.CpAchievement `json:"type"` // 成就类型 1:等级 2:空间访问人数 3:月榜最高 4:周榜最高 5:日榜最高
TypeDesc string `json:"typeDesc"` // 成就类型翻译
Score uint32 `json:"score"` // 分值
TimeUnix int64 `json:"timeUnix"` // 达成成就时间戳
}
type CpTops struct {
Day []CvCpRank `json:"day"`
Week []CvCpRank `json:"week"`
}
package cp_cv
import (
"fmt"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/res_m"
"time"
)
// cp信息
type CvCpInfo struct {
UserInfo *user_cv.UserTiny `json:"userInfo"` // 用户信息
CpUserInfo *user_cv.UserTiny `json:"cpUserInfo,omitempty"` // cp用户信息
CpDays int `json:"cpDays"` // cp天数
VisitTimes int64 `json:"visitTimes"` // 空间访问量
ApplyToUnbind bool `json:"applyToUnbind"` // 是否申请撤销cp
}
// cp等级
type CvCpLevel struct {
Level cp_e.CpLevel `json:"level"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP
Points uint32 `json:"points"` // CP值
StartPoints uint32 `json:"startPoints,omitempty"` // 上个等级所需CP值
EndPoints uint32 `json:"endPoints,omitempty"` // 下个等级所需CP值
ExpireAtUnix int64 `json:"expireAtUnix,omitempty"` // 有效期,时间戳
SettlementDate string `json:"settlementDate"` // 等级过期时间
MaxLevel cp_e.CpLevel `json:"maxLevel"` // cp最大的等级
Title string `json:"title,omitempty"` // 称号翻译
}
// 资源等级
type CvResLevel struct {
Level cp_e.CpLevel `json:"level"` // 等级
Icon string `json:"icon"` // 等级icon图
StartPoints uint32 `json:"startPoints"` // 上个等级所需CP值
EndPoints uint32 `json:"endPoints,omitempty"` // 下个等级所需CP值
}
// 特权信息
type CvPrivilege struct {
Type cp_e.CpPrivilege `json:"type"` // 特权id 1:空间 2:横幅 3:等级勋章 4:证书 5:进场特效 6:头像头饰 7:动态资料卡 8:麦位特效
NameMsgId uint `json:"-"` // 名称-翻译id
Name string `json:"name"` // 名称
DescMsgId uint `json:"-"` // 描述-翻译id
Desc string `json:"desc"`
Icon string `json:"icon"` // 图标
CanSwitch bool `json:"canSwitch"` // 能否开关
UserSwitch bool `json:"userSwitch"` // 用户开关
LevelList []cp_e.CpLevel `json:"levelList"` // 特权->level的反向索引
}
// cp空间页
type CvSpace struct {
CpInfo CvCpInfo `json:"cpInfo"` // cp信息
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
ResLevelList []CvResLevel `json:"resLevelList"` // 资源等级列表,无称号/恋爱CP/甜蜜CP/忠诚CP/炽热CP/荣耀CP
PrivilegeList [][]CvPrivilege `json:"privilegeList"` // 等级特权
CpAnniversary []CvCpAnniversary `json:"cpAnniversary"` // 提醒的纪念日
}
var CvResLevelList = []CvResLevel{
{cp_e.CpLevel0, cp_e.CpLevelIcon[cp_e.CpLevel0], cp_e.CpLevelPoints[cp_e.CpLevel0], cp_e.CpLevelPoints[cp_e.CpLevel1]},
{cp_e.CpLevel1, cp_e.CpLevelIcon[cp_e.CpLevel1], cp_e.CpLevelPoints[cp_e.CpLevel1], cp_e.CpLevelPoints[cp_e.CpLevel2]},
{cp_e.CpLevel2, cp_e.CpLevelIcon[cp_e.CpLevel2], cp_e.CpLevelPoints[cp_e.CpLevel2], cp_e.CpLevelPoints[cp_e.CpLevel3]},
{cp_e.CpLevel3, cp_e.CpLevelIcon[cp_e.CpLevel3], cp_e.CpLevelPoints[cp_e.CpLevel3], cp_e.CpLevelPoints[cp_e.CpLevel4]},
{cp_e.CpLevel4, cp_e.CpLevelIcon[cp_e.CpLevel4], cp_e.CpLevelPoints[cp_e.CpLevel4], cp_e.CpLevelPoints[cp_e.CpLevel5]},
{cp_e.CpLevel5, cp_e.CpLevelIcon[cp_e.CpLevel5], cp_e.CpLevelPoints[cp_e.CpLevel5], cp_e.CpLevelPoints[cp_e.CpLevelMax]},
}
var (
CvPrivilege1 = CvPrivilege{cp_e.CpPrivilegeSpace, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeSpace], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeSpace], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeSpace]}
CvPrivilege2 = CvPrivilege{cp_e.CpPrivilegeBanner, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeBanner], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeBanner], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeBanner]}
CvPrivilege3 = CvPrivilege{cp_e.CpPrivilegeMedal, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeMedal], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMedal], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeMedal]}
CvPrivilege4 = CvPrivilege{cp_e.CpPrivilegeCert, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeCert], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeCert], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeCert], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeCert]}
CvPrivilege5 = CvPrivilege{cp_e.CpPrivilegeRoomEffect, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeRoomEffect], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeRoomEffect], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeRoomEffect], true, false, CpPrivilegeLevelList[cp_e.CpPrivilegeRoomEffect]}
CvPrivilege6 = CvPrivilege{cp_e.CpPrivilegeHeadwear, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeHeadwear], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeHeadwear], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeHeadwear], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeHeadwear]}
CvPrivilege7 = CvPrivilege{cp_e.CpPrivilegeActiveProfile, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeActiveProfile], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeActiveProfile], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeActiveProfile], true, false, CpPrivilegeLevelList[cp_e.CpPrivilegeActiveProfile]}
CvPrivilege8 = CvPrivilege{cp_e.CpPrivilegeMicEffect, cp_e.CpPrivilegeNameMsgId[cp_e.CpPrivilegeMicEffect], "", cp_e.CpPrivilegeDescMsgId[cp_e.CpPrivilegeMicEffect], "", cp_e.CpPrivilegeIcon[cp_e.CpPrivilegeMicEffect], false, false, CpPrivilegeLevelList[cp_e.CpPrivilegeMicEffect]}
)
var CpLevelPrivilegeList = map[cp_e.CpLevel][]CvPrivilege{
cp_e.CpLevel0: {CvPrivilege1},
cp_e.CpLevel1: {CvPrivilege1, CvPrivilege2, CvPrivilege3, CvPrivilege4},
cp_e.CpLevel2: {CvPrivilege1, CvPrivilege2, CvPrivilege3, CvPrivilege4, CvPrivilege5},
cp_e.CpLevel3: {CvPrivilege1, CvPrivilege2, CvPrivilege3, CvPrivilege4, CvPrivilege5, CvPrivilege6},
cp_e.CpLevel4: {CvPrivilege1, CvPrivilege2, CvPrivilege3, CvPrivilege4, CvPrivilege5, CvPrivilege6, CvPrivilege7},
cp_e.CpLevel5: {CvPrivilege1, CvPrivilege2, CvPrivilege3, CvPrivilege4, CvPrivilege5, CvPrivilege6, CvPrivilege7, CvPrivilege8},
}
var CpPrivilegeLevelList = map[cp_e.CpPrivilege][]cp_e.CpLevel{
cp_e.CpPrivilegeSpace: {cp_e.CpLevel0, cp_e.CpLevel1, cp_e.CpLevel2, cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeBanner: {cp_e.CpLevel1, cp_e.CpLevel2, cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeMedal: {cp_e.CpLevel1, cp_e.CpLevel2, cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeCert: {cp_e.CpLevel1, cp_e.CpLevel2, cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeRoomEffect: {cp_e.CpLevel2, cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeHeadwear: {cp_e.CpLevel3, cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeActiveProfile: {cp_e.CpLevel4, cp_e.CpLevel5},
cp_e.CpPrivilegeMicEffect: {cp_e.CpLevel5},
}
func CopyCpLevelPrivilegeList(Level cp_e.CpLevel, lang string) []CvPrivilege {
privileges := make([]CvPrivilege, len(CpLevelPrivilegeList[Level]))
copy(privileges, CpLevelPrivilegeList[Level])
for i, v := range privileges {
privileges[i].Name = GetTranslate(v.NameMsgId, lang)
privileges[i].Desc = GetTranslate(v.DescMsgId, lang)
}
return privileges
}
var translateCache = gcache.New(1000).LRU().Build()
func GetTranslate(msgId uint, lang string) string {
key := fmt.Sprintf("%v-%v", msgId, lang)
if data, err := translateCache.Get(key); err == nil {
return data.(string)
}
if resMul, _ := res_m.GetResMultiTextBy(mysql.Db, msgId, lang); resMul != nil {
_ = translateCache.SetWithExpire(key, resMul.Content, time.Hour)
return resMul.Content
}
return "default"
}
package headwear_cv
import (
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/headwear_e"
"hilo-user/domain/model/res_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr"
"strconv"
"time"
)
type CvHeadwear struct {
Id uint64 `json:"id"`
Using bool `json:"using"`
PicUrl mysql.Str `json:"picUrl"`
EffectUrl mysql.Str `json:"effectUrl"`
TimeLeft int64 `json:"timeLeft"` // 离到期还有多少秒(过期则是负数)
}
type CvHeadwearDiamond struct {
Id uint64 `json:"id"`
PicUrl string `json:"picUrl"`
EffectUrl string `json:"effectUrl"`
DiamondNum uint32 `json:"diamondNum"`
Second uint32 `json:"second"`
Days string `json:"days"`
}
func GetCvHeadwearDiamond(pageSize int, pageIndex int) ([]CvHeadwearDiamond, error) {
headwearDiamonds := []CvHeadwearDiamond{}
if err := mysql.Db.Raw("SELECT d.id, r.pic_url, r.effect_url, d.`second`, d.diamond_num from res_headwear r, res_headwear_diamond d where r.id = d.res_headwear_id and d.`status` = ? ORDER BY d.diamond_num asc LIMIT ?, ?", mysql.USER, (pageIndex-1)*pageSize, pageSize).Scan(&headwearDiamonds).Error; err != nil {
return nil, myerr.WrapErr(err)
}
for i, _ := range headwearDiamonds {
headwearDiamonds[i].Days = strconv.FormatUint(uint64(headwearDiamonds[i].Second/(24*60*60)), 10)
}
return headwearDiamonds, nil
}
func GetHeadwearList(db *gorm.DB, userId uint64) ([]CvHeadwear, error) {
rows := make([]user_m.UserHeadwear, 0)
if err := db.Where(&user_m.UserHeadwear{
UserId: userId,
}).Where("end_time >= ?", time.Now()).Order("`using` DESC, updated_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
resHwMap, err := res_m.GetResHeadwearMap(db)
if err != nil {
return nil, myerr.WrapErr(err)
}
result := make([]CvHeadwear, 0)
now := time.Now()
hasUsing := false
for _, i := range rows {
// TODO: 没过期并且有设置using的,才算是,因为写入方不维护using状态的更新
isUsing := i.Using == headwear_e.YesUsing && i.EndTime.After(now)
result = append(result, CvHeadwear{
Id: i.HeadwearId,
PicUrl: resHwMap[i.HeadwearId].PicUrl,
EffectUrl: resHwMap[i.HeadwearId].EffectUrl,
Using: isUsing,
TimeLeft: i.EndTime.Unix() - now.Unix(),
})
if isUsing {
hasUsing = true
}
}
// 如果没有一个using,则找第一个没过期的充当
if ! hasUsing {
for i, e := range result {
if e.TimeLeft > 0 {
result[i].Using = true
break
}
}
}
return result, nil
}
func GetCvHeadwear(userId uint64) (*CvHeadwear, error) {
userHeadwear := user_m.UserHeadwear{}
if err := mysql.Db.Model(&user_m.UserHeadwear{}).Where(&user_m.UserHeadwear{
UserId: userId,
}).Where("end_time >= ?", time.Now()).Order("`using` DESC, updated_time DESC").First(&userHeadwear).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
resHeadwear := res_m.ResHeadwear{}
if err := mysql.Db.Model(&res_m.ResHeadwear{}).First(&resHeadwear, userHeadwear.HeadwearId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
return &CvHeadwear{
Id: userHeadwear.HeadwearId,
PicUrl: resHeadwear.PicUrl,
EffectUrl: resHeadwear.EffectUrl,
Using: userHeadwear.Using == headwear_e.YesUsing,
}, nil
}
func BatchGetCvHeadwears(userIds []uint64) (map[uint64]CvHeadwear, error) {
if len(userIds) == 0 {
return map[uint64]CvHeadwear{}, nil
}
rows := make([]user_m.UserHeadwear, 0)
//asc 进行覆盖,保证了updated_time 最大的是最后的输出
if err := mysql.Db.Where("user_id IN ?", userIds).Where("end_time >= ?", time.Now()).
Order("`using` ASC, updated_time ASC").Find(&rows).Error; err != nil {
return nil, err
}
//
resHeadwearIds := make([]uint64, 0, len(rows))
for i, _ := range rows {
resHeadwearIds = append(resHeadwearIds, rows[i].HeadwearId)
}
//获取头饰资源,然后转换成map结构
resHeadwearMap := map[uint64]res_m.ResHeadwear{}
resHeadwears := []res_m.ResHeadwear{}
if err := mysql.Db.Where("id IN ?", resHeadwearIds).Find(&resHeadwears).Error; err != nil {
return nil, err
}
for i, _ := range resHeadwears {
resHeadwearMap[resHeadwears[i].ID] = resHeadwears[i]
}
result := make(map[uint64]CvHeadwear, 0)
for _, r := range rows {
headwear, flag := resHeadwearMap[r.HeadwearId]
if flag {
result[r.UserId] = CvHeadwear{
Id: headwear.ID,
PicUrl: headwear.PicUrl,
EffectUrl: headwear.EffectUrl,
Using: r.Using == headwear_e.YesUsing,
}
}
}
return result, nil
}
package medal_cv
import (
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/domain/model/res_m"
"sort"
)
type CvMedal struct {
Id uint32 `json:"id"`
PicUrl mysql.Str `json:"picUrl"`
EffectUrl mysql.Str `json:"effectUrl"`
}
type ReturnGroupMedal struct {
PicUrl string `json:"picUrl"`
SvgaUrl string `json:"svgaUrl"`
}
type PicElement struct {
PicUrl string `json:"picUrl"`
SvgaUrl string `json:"svgaUrl"`
}
func GetMedalInfoMap(db *gorm.DB, medals map[uint64][]uint32) (map[uint64][]uint32, map[uint64][]CvMedal, error) {
resMedals, err := res_m.MedalGetAllMap(db)
if err != nil {
return nil, nil, err
}
medalIds := make(map[uint64][]uint32)
medalMap := make(map[uint64][]CvMedal, 0)
// 只选择合法的勋章
for u, i := range medals {
medalIds[u] = make([]uint32, 0)
medalMap[u] = make([]CvMedal, 0)
for _, j := range i {
if e, ok := resMedals[j]; ok {
medalIds[u] = append(medalIds[u], j)
medalMap[u] = append(medalMap[u], CvMedal{
Id: j,
PicUrl: e.PicUrl,
EffectUrl: e.SvgaUrl,
})
}
}
// 按照勋章排序
sort.Slice(medalIds[u], func(i, j int) bool {
return resMedals[medalIds[u][i]].Sort < resMedals[medalIds[u][j]].Sort
})
sort.Slice(medalMap[u], func(i, j int) bool {
return resMedals[medalMap[u][i].Id].Sort < resMedals[medalMap[u][j].Id].Sort
})
}
return medalIds, medalMap, nil
}
package noble_cv
import (
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/domain/model/noble_m"
"hilo-user/myerr"
"time"
)
type NobleConfig struct {
Level uint16 `json:"level"` // 贵族等级
PurchasePrice uint32 `json:"purchasePrice"` // 购买价格
RenewalPrice uint32 `json:"renewalPrice"` // 续费价格
Duration uint16 `json:"duration"` // 有效期(天)
PicUrl string `json:"picUrl"` // 大图url
DailyGold uint `json:"dailyGold"` // 每日登录领取的金币
RideId uint64 `json:"rideId"` // 赠送的勋章ID
HeaddressId uint64 `json:"headdressId"` // 赠送的头饰ID
Privileges []int `json:"privileges"` // 权益列表
}
type NobleInfo struct {
Level uint16 `json:"level"` // 等级
EndTime int64 `json:"endTime"` // 截止时间
RemainTime int64 `json:"remainTime"` // 还有多久(秒)过期,可以是负数
Price uint32 `json:"price"` // 购买或续费价格
}
type CvNoble struct {
Level uint16 `json:"level"`
EndTime int64 `json:"endTime"`
}
func GetCvNoble(userId uint64) (CvNoble, error) {
userNoble := noble_m.UserNoble{}
if err := mysql.Db.Model(&noble_m.UserNoble{}).Where(&noble_m.UserNoble{
UserId: userId,
}).Where("end_time > ?", time.Now()).Order("level desc").First(&userNoble).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return CvNoble{
Level: 0,
EndTime: 0,
}, nil
} else {
return CvNoble{
Level: 0,
EndTime: 0,
}, myerr.WrapErr(err)
}
} else {
return CvNoble{
Level: userNoble.Level,
EndTime: userNoble.EndTime.Unix(),
}, nil
}
}
func GetCvNobles(userIds []uint64) (map[uint64]CvNoble, error) {
if len(userIds) == 0 {
return map[uint64]CvNoble{}, nil
}
var userNobles []noble_m.UserNoble
if err := mysql.Db.Model(&noble_m.UserNoble{}).Where("user_id in (?)", userIds).Where("end_time > ?", time.Now()).Order("level asc").Find(&userNobles).Error; err != nil {
return nil, err
}
userNobleMap := map[uint64]noble_m.UserNoble{}
for i, _ := range userNobles {
userNobleMap[userNobles[i].UserId] = userNobles[i]
}
result := map[uint64]CvNoble{}
for _, r := range userIds {
userNoble, flag := userNobleMap[r]
if flag {
result[r] = CvNoble{
Level: userNoble.Level,
EndTime: userNoble.EndTime.Unix(),
}
} else {
result[r] = CvNoble{
Level: 0,
EndTime: 0,
}
}
}
return result, nil
}
package property_cv
import (
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/headwear_e"
"hilo-user/domain/model/res_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr"
"strconv"
"time"
)
type CvProperty struct {
Id uint64 `json:"id"`
PicUrl mysql.Str `json:"picUrl"`
EffectUrl mysql.Str `json:"effectUrl"`
Using bool `json:"using"`
TimeLeft int64 `json:"timeLeft"` // 离到期还有多少秒(过期则是负数)
SenderAvatar string `json:"senderAvatar"`
ReceiverAvatar string `json:"receiverAvatar"`
}
type CvPropertyDiamond struct {
Id uint64 `json:"id"`
PicUrl string `json:"picUrl"`
EffectUrl string `json:"effectUrl"`
DiamondNum uint32 `json:"diamondNum"`
Second uint32 `json:"second"`
Days string `json:"days"`
}
func GetCvPropertyDiamond(pageSize int, pageIndex int) ([]CvPropertyDiamond, error) {
propertyDiamonds := []CvPropertyDiamond{}
if err := mysql.Db.Raw("select d.id, r.pic_url, r.effect_url, d.`second`, d.diamond_num from res_property r, res_property_diamond d where r.id = d.res_property_id and d.`status` = ? ORDER BY d.diamond_num ASC LIMIT ?, ?", mysql.USER, (pageIndex-1)*pageSize, pageSize).Scan(&propertyDiamonds).Error; err != nil {
return nil, myerr.WrapErr(err)
}
for i, _ := range propertyDiamonds {
propertyDiamonds[i].Days = strconv.FormatUint(uint64(propertyDiamonds[i].Second/(24*60*60)), 10)
}
return propertyDiamonds, nil
}
func GetPropertyById(resPropertyId mysql.ID) (CvProperty, error) {
resProperty := res_m.ResProperty{}
if err := mysql.Db.Model(&res_m.ResProperty{}).First(&resProperty, resPropertyId).Error; err != nil {
return CvProperty{}, err
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
if err != nil {
return CvProperty{}, err
}
userIds := []uint64{}
for _, value := range propertieAvatarMap {
if value.SendUserId > 0 {
userIds = append(userIds, value.SendUserId)
}
if value.ReceiverUserId > 0 {
userIds = append(userIds, value.ReceiverUserId)
}
}
//获取用户信息
users := []user_m.User{}
if err := mysql.Db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return CvProperty{}, myerr.WrapErr(err)
}
userAvatarMap := map[mysql.ID]string{}
for _, r := range users {
userAvatarMap[r.ID] = r.Avatar
}
var senderAvatar string = ""
var receiverAvatar string = ""
if propertieAvatar, flag := propertieAvatarMap[resProperty.ID]; flag {
if propertieAvatar.SendUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.SendUserId]; flag {
senderAvatar = avatar
}
}
if propertieAvatar.ReceiverUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.ReceiverUserId]; flag {
receiverAvatar = avatar
}
}
}
return CvProperty{
Id: resProperty.ID,
PicUrl: resProperty.PicUrl,
EffectUrl: resProperty.EffectUrl,
SenderAvatar: senderAvatar,
ReceiverAvatar: receiverAvatar,
}, nil
}
func GetPropertyAll(db *gorm.DB) (map[uint64]CvProperty, error) {
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
return nil, err
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
userIds := []uint64{}
for _, value := range propertieAvatarMap {
if value.SendUserId > 0 {
userIds = append(userIds, value.SendUserId)
}
if value.ReceiverUserId > 0 {
userIds = append(userIds, value.ReceiverUserId)
}
}
//获取用户信息
users := []user_m.User{}
if err := db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userAvatarMap := map[mysql.ID]string{}
for _, r := range users {
userAvatarMap[r.ID] = r.Avatar
}
result := map[uint64]CvProperty{}
for _, r := range properties {
var senderAvatar string = ""
var receiverAvatar string = ""
if propertieAvatar, flag := propertieAvatarMap[r.ID]; flag {
if propertieAvatar.SendUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.SendUserId]; flag {
senderAvatar = avatar
}
}
if propertieAvatar.ReceiverUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.ReceiverUserId]; flag {
receiverAvatar = avatar
}
}
}
result[r.ID] = CvProperty{
Id: r.ID,
PicUrl: r.PicUrl,
EffectUrl: r.EffectUrl,
SenderAvatar: senderAvatar,
ReceiverAvatar: receiverAvatar,
}
}
return result, nil
}
func GetPropertyList(db *gorm.DB, userId uint64) ([]CvProperty, error) {
rows := make([]user_m.UserProperty, 0)
if err := db.Where(&user_m.UserProperty{
UserId: userId,
}).Order("`using` DESC, updated_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
return nil, err
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
userIds := []uint64{}
for _, value := range propertieAvatarMap {
if value.SendUserId > 0 {
userIds = append(userIds, value.SendUserId)
}
if value.ReceiverUserId > 0 {
userIds = append(userIds, value.ReceiverUserId)
}
}
//获取用户信息
users := []user_m.User{}
if err := db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userAvatarMap := map[mysql.ID]string{}
for _, r := range users {
userAvatarMap[r.ID] = r.Avatar
}
result := make([]CvProperty, 0)
now := time.Now()
hasUsing := false
for _, i := range rows {
// TODO: 没过期并且有设置using的,才算是,因为写入方不维护using状态的更新
isUsing := i.Using == headwear_e.YesUsing && i.EndTime.After(now)
var senderAvatar string = ""
var receiverAvatar string = ""
if propertieAvatar, flag := propertieAvatarMap[i.PropertyId]; flag {
if propertieAvatar.SendUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.SendUserId]; flag {
senderAvatar = avatar
}
}
if propertieAvatar.ReceiverUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.ReceiverUserId]; flag {
receiverAvatar = avatar
}
}
}
result = append(result, CvProperty{
Id: i.PropertyId,
PicUrl: properties[i.PropertyId].PicUrl,
EffectUrl: properties[i.PropertyId].EffectUrl,
Using: isUsing,
TimeLeft: i.EndTime.Unix() - now.Unix(),
SenderAvatar: senderAvatar,
ReceiverAvatar: receiverAvatar,
})
if isUsing {
hasUsing = true
}
}
// 如果没有一个using,则找第一个没过期的充当
if !hasUsing {
for i, e := range result {
if e.TimeLeft > 0 {
result[i].Using = true
break
}
}
}
return result, nil
}
type PropertyExt struct {
Id uint64
PicUrl mysql.Str
EffectUrl mysql.Str
Using bool
TimeLeft int64 // 离到期还有多少秒(过期则是负数)
SenderAvatar string
ReceiverAvatar string
}
func GetExtendedProperty(db *gorm.DB) (map[uint64]PropertyExt, error) {
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
return nil, err
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
userIds := []uint64{}
for _, value := range propertieAvatarMap {
if value.SendUserId > 0 {
userIds = append(userIds, value.SendUserId)
}
if value.ReceiverUserId > 0 {
userIds = append(userIds, value.ReceiverUserId)
}
}
//获取用户信息
users := []user_m.User{}
if err := db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userAvatarMap := map[mysql.ID]string{}
for _, r := range users {
userAvatarMap[r.ID] = r.Avatar
}
result := map[uint64]PropertyExt{}
for _, r := range properties {
var senderAvatar string = ""
var receiverAvatar string = ""
if propertieAvatar, flag := propertieAvatarMap[r.ID]; flag {
if propertieAvatar.SendUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.SendUserId]; flag {
senderAvatar = avatar
}
}
if propertieAvatar.ReceiverUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.ReceiverUserId]; flag {
receiverAvatar = avatar
}
}
}
result[r.ID] = PropertyExt{
Id: r.ID,
PicUrl: r.PicUrl,
EffectUrl: r.EffectUrl,
SenderAvatar: senderAvatar,
ReceiverAvatar: receiverAvatar,
}
}
return result, nil
}
This diff is collapsed.
package user_cv
import (
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/cv/headwear_cv"
"hilo-user/cv/medal_cv"
"hilo-user/cv/property_cv"
"time"
)
//空字符串转成nil
func StrNil(msg string) *string {
if msg == "" {
return nil
}
return &msg
}
func TypeToUint8(t *mysql.Type) *uint8 {
if *t == 0 {
return nil
} else {
return (*uint8)(t)
}
}
func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 {
if *birthday == 0 {
return nil
}
return (*uint64)(birthday)
}
func NumToUint32(num *mysql.Num) *uint32 {
return (*uint32)(num)
}
func TimeToUint64(t *time.Time) *uint64 {
a := uint64(t.Unix())
return &a
}
func StrToString(str *mysql.Str) *string {
return (*string)(str)
}
func IndexToUint16(i *mysql.Index) *uint16 {
return (*uint16)(i)
}
func IdToUint64(id *mysql.ID) *uint64 {
return (*uint64)(id)
}
func IsInStringList(str string, list []string) bool {
for _, v := range list {
if str == v {
return true
}
}
return false
}
func IfLogoutStr(condition bool, trueVal, falseVal string) string {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutNick(condition bool, code string, nick string) string {
if condition {
return "Hilo No." + code
}
return nick
}
func IfLogout(logoutTime int64) bool {
return logoutTime > 0 && time.Now().Unix() > logoutTime
}
func IfLogoutMedalInfo(condition bool, trueVal, falseVal []medal_cv.CvMedal) []medal_cv.CvMedal {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutRide(condition bool, trueVal, falseVal property_cv.CvProperty) property_cv.CvProperty {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutHeadwear(condition bool, trueVal, falseVal *headwear_cv.CvHeadwear) *headwear_cv.CvHeadwear {
if condition {
return trueVal
}
return falseVal
}
package cp_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
//注册监听
var spaceVisitListen = new(domain.EventBase)
type SpaceVisitEvent struct {
UserId mysql.ID
CpId mysql.ID
UserId1, UserId2 mysql.ID
}
//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。
func AddCpSpaceVisitSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(spaceVisitListen, callback)
}
//加入到异步操作中
func AddCpSpaceVisitAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(spaceVisitListen, callback)
}
//领域事件发布
func PublishCpSpaceVisit(model *domain.Model, event interface{}) error {
return domain.PublishEvent(spaceVisitListen, model, event)
}
package gift_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/_const/enum/gift_e"
)
var sendGiftListen = new(domain.EventBase)
// 送礼事件
type SendGiftEvent struct {
SendUserId mysql.ID
ReceiveUserIds []mysql.ID
ResGift EventResGift
GiftOperateIds []mysql.ID
GiftN mysql.Num
SceneType gift_e.GiftOperateSceneType
SceneUid mysql.Str
NoDiamondConsume bool // 不要消费钻石
TotalConsume uint64 // 房间的总消费额
}
type EventResGift struct {
ID mysql.ID
Name mysql.Str
IconUrl mysql.Str
SvgaUrl mysql.Str
MusicUrl mysql.Str
DiamondNum mysql.Num
BeanNum mysql.Num
ReceiveDiamondNum mysql.Num
Second mysql.Num
N mysql.Num
GroupBroadcast bool
Cp bool
Together bool
Status mysql.UserYesNo
GiftType mysql.Type
}
func AddSendGiftEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(sendGiftListen, callback)
}
func AddSendGiftEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(sendGiftListen, callback)
}
func PublishSendGiftEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(sendGiftListen, model, event)
}
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/cp_e"
"time"
)
type CpAchievement struct {
CpId mysql.ID
UserId1 mysql.ID
UserId2 mysql.ID
Type cp_e.CpAchievement
Score mysql.Num
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 更新cp成就
// 单进程操作,先create,后update
func UpdateCpAchievement(model *domain.Model, cpId, userId1, userId2 mysql.ID, Type cp_e.CpAchievement, score mysql.Num) error {
var cpAchievement CpAchievement
if err := model.DB().Model(CpAchievement{}).Where("cp_id = ? AND `type` = ?", cpId, Type).First(&cpAchievement).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
return err
}
// gorm.ErrRecordNotFound
cpAchievement = CpAchievement{
CpId: cpId,
UserId1: userId1,
UserId2: userId2,
Type: Type,
Score: score,
}
return model.DB().Model(CpAchievement{}).Create(&cpAchievement).Error
}
// update if less than
return model.DB().Model(CpAchievement{}).Where("cp_id = ? AND `type` = ?", cpId, Type).Where("score < ?", score).UpdateColumn("score", score).Error
}
// 获取cp成就
func GetCpAchievements(model *domain.Model) []CpAchievement {
var achievements []CpAchievement
subQuery := model.DB().Table("cp_achievement a").Joins("JOIN cp_relation r ON a.cp_id = r.id").Select("type,MAX(score) AS max_score").Group("type")
if err := model.DB().Model(CpAchievement{}).Where("(type, score) IN (?)", subQuery).Find(&achievements).Error; err != nil {
model.Log.Errorf("GetAchievements fail:%v", err)
}
return achievements
}
package cp_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"hilo-user/_const/enum/cp_e"
"hilo-user/domain/model/res_m"
"hilo-user/domain/model/user_m"
"time"
)
// CpAnniversary cp纪念日
type CpAnniversary struct {
mysql.Entity
Type cp_e.AnniversaryItemType
CpId mysql.ID
UserId1 mysql.ID
UserId2 mysql.ID
Content string
Timestamp int64
IsRemind bool
LastRemindTime int64
Sort int
}
// 初始化6个cp纪念日
// 1)我们在一起;2)XXX的生日;3)XXX的生日;4)第一次说我爱你;5)第一次亲吻;6)结婚纪念日
func InitCpAnniversary(model *domain.Model, cp CpRelationTmp, lang string) error {
users, err := user_m.GetUserMapByIds(model, []uint64{cp.UserId1, cp.UserId2})
if err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeNormal, cp, GetTranslate(259, lang), time.Now().Unix(), true, 100); err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeAnniversary, cp, fmt.Sprintf(GetTranslate(260, lang), users[cp.UserId1].Nick), 0, true, 0); err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeAnniversary, cp, fmt.Sprintf(GetTranslate(260, lang), users[cp.UserId2].Nick), 0, true, 0); err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeNormal, cp, GetTranslate(261, lang), 0, false, 0); err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeNormal, cp, GetTranslate(262, lang), 0, false, 0); err != nil {
return err
}
if err := AddCpAnniversary(model, cp_e.AnniversaryItemTypeAnniversary, cp, GetTranslate(263, lang), 0, false, 0); err != nil {
return err
}
return nil
}
var translateCache = gcache.New(1000).LRU().Build()
func GetTranslate(msgId uint, lang string) string {
key := fmt.Sprintf("%v-%v", msgId, lang)
if data, err := translateCache.Get(key); err == nil {
return data.(string)
}
if resMul, _ := res_m.GetResMultiTextBy(mysql.Db, msgId, lang); resMul != nil {
_ = translateCache.SetWithExpire(key, resMul.Content, time.Hour)
return resMul.Content
}
return "default"
}
// 添加cp纪念日
func AddCpAnniversary(model *domain.Model, Type cp_e.AnniversaryItemType, cp CpRelationTmp, content string, ts int64, isRemind bool, sort int) error {
return model.DB().Model(CpAnniversary{}).Create(&CpAnniversary{
CpId: cp.ID,
Type: Type,
UserId1: cp.UserId1,
UserId2: cp.UserId2,
Content: content,
Timestamp: ts,
IsRemind: isRemind,
LastRemindTime: 0,
Sort: sort,
}).Error
}
// 更新cp纪念日
func UpdateCpAnniversary(model *domain.Model, id mysql.ID, content string, ts int64, isRemind bool) error {
updates := map[string]interface{}{
"content": content,
"timestamp": ts,
"is_remind": isRemind,
}
return model.DB().Model(CpAnniversary{}).Where("id = ?", id).Updates(updates).Error
}
func DelCpAnniversary(model *domain.Model, id mysql.ID) error {
return model.DB().Model(CpAnniversary{}).Where("id = ? ", id).Delete(&CpAnniversary{}).Error
}
// 根据用户id获取所有纪念日
func GetAllCpAnniversary(model *domain.Model, userId mysql.ID) []CpAnniversary {
var res []CpAnniversary
relation, exists := GetCpRelation(model, userId)
if !exists {
return res
}
if err := model.DB().Model(CpAnniversary{}).Where("cp_id = ?", relation.ID).Order("`sort` DESC,updated_time DESC,id ASC").Find(&res).Error; err != nil {
model.Log.Errorf("GetAllCpAnniversary fail:%v", err)
}
return res
}
// 获取所有需要提醒的纪念日
func GetNeedRemindCpAnniversary(model *domain.Model) []CpAnniversary {
var res []CpAnniversary
if err := model.DB().Model(CpAnniversary{}).
Where("`timestamp` >= ?", time.Now().Unix()-86400).
Where("`timestamp` < ?", time.Now().Unix()).
Where("is_remind = 1").
Where("last_remind_time < ?", time.Now().AddDate(-1, 0, 0).Unix()). // 一年前提醒过
Find(&res).Error; err != nil {
model.Log.Errorf("GetNeedRemindCpAnniversary fail:%v", err)
}
return res
}
// 获取cp当天需要提醒的纪念日
func GetUserTodayCpAnniversary(model *domain.Model, cpId mysql.ID) []CpAnniversary {
var res []CpAnniversary
if err := model.DB().Model(CpAnniversary{}).
Where("`timestamp` >= ?", time.Now().Unix()-86400).
Where("`timestamp` < ?", time.Now().Unix()).
Where("is_remind = 1").
Where("cp_id = ?", cpId).
Find(&res).Error; err != nil {
model.Log.Errorf("GetUserTodayCpAnniversary fail:%v", err)
}
return res
}
func UpdateCpAnniversaryReminded(model *domain.Model, id mysql.ID) error {
return model.DB().Model(CpAnniversary{}).Where("id = ?", id).Update("last_remind_time", time.Now().Unix()).Error
}
This diff is collapsed.
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/cp_e"
)
// svip特权
type CpPrivilege struct {
mysql.Entity
UserId mysql.ID
Type cp_e.CpPrivilege
OpenClose mysql.OpenClose
}
// 开关用于svip特权
func OpenCLoseUserSvipPrivilege(model *domain.Model, userId mysql.ID, Type cp_e.CpPrivilege, openClose mysql.OpenClose) error {
var pri CpPrivilege
if err := model.DB().Model(CpPrivilege{}).Where("user_id = ? AND `type` = ?", userId, Type).
First(&pri).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// record not found
return model.DB().Create(&CpPrivilege{
UserId: userId,
Type: Type,
OpenClose: openClose,
}).Error
}
// update
return model.DB().Model(CpPrivilege{}).Where("user_id = ? AND `type` = ?", userId, Type).
UpdateColumn("open_close", openClose).Error
}
// 批量获取用户svip特权开关
// map userId->type->open
func MGetUserSvipPrivilege(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]map[cp_e.CpPrivilege]bool, error) {
res := make(map[mysql.ID]map[cp_e.CpPrivilege]bool)
var privileges []CpPrivilege
if err := model.DB().Model(CpPrivilege{}).Where("user_id in ? AND open_close = ?", userIds, mysql.OPEN).Find(&privileges).Error; err != nil {
return res, err
}
for _, v := range privileges {
if data, ok := res[v.UserId]; ok {
data[v.Type] = true
} else {
res[v.UserId] = make(map[cp_e.CpPrivilege]bool)
res[v.UserId][v.Type] = true
}
}
return res, nil
}
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"time"
)
type CpDayRank struct {
Date string
CpId mysql.ID
UserId1 mysql.ID
UserId2 mysql.ID
Score mysql.Num
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加cp排行榜-天
func AddCpDayRank(model *domain.Model, cpRelation CpRelationTmp, score mysql.Num) (err error) {
date := time.Now().Format("2006-01-02")
rank := &CpDayRank{
Date: date,
CpId: cpRelation.ID,
UserId1: cpRelation.UserId1,
UserId2: cpRelation.UserId2,
Score: score,
}
if err = model.DB().Model(CpDayRank{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "cp_id"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"score": gorm.Expr("score + ?", rank.Score)})}).Create(rank).Error; err != nil {
model.Log.Errorf("AddCpDayRank fail:%v", err)
return err
}
return nil
}
// 分页获取cp排行榜
func PageCpDayRank(model *domain.Model, beginDate, endDate string, offset, limit int) []CpDayRank {
var ranks []CpDayRank
if err := model.DB().Table("cp_day_rank r").Joins("INNER JOIN cp_relation c ON c.id = r.cp_id").
Where("r.date BETWEEN ? AND ?", beginDate, endDate).Group("cp_id").Select("cp_id,r.user_id1,r.user_id2,SUM(r.score) score").
Order("score DESC").Offset(offset).Limit(limit).Find(&ranks).Error; err != nil {
model.Log.Errorf("PageCpDayRank fail:%v", err)
}
return ranks
}
// 获取指定cp排行榜
func GetCpDayRank(model *domain.Model, beginDate, endDate string, cpId mysql.ID) CpDayRank {
var rank CpDayRank
if err := model.DB().Table("cp_day_rank").
Where("date BETWEEN ? AND ?", beginDate, endDate).Where("cp_id = ?", cpId).Select("cp_id,user_id1,user_id2,SUM(score) score").
First(&rank).Error; err != nil {
model.Log.Errorf("GetCpDayRank fail:%v", err)
}
return rank
}
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-user/domain/model"
)
func (p *CpLevel) Persistence(m *domain.Model) error {
return model.Persistent(m.DB(), p)
}
package cp_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"time"
)
type CpVisitor struct {
CpId mysql.ID
UserId1 mysql.ID
UserId2 mysql.ID
Visitor mysql.ID
Times mysql.Num
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 添加cp空间访问量
func AddCpSpaceVisitor(model *domain.Model, cpId, userId1, userId2, visitor mysql.ID) error {
vis := &CpVisitor{
CpId: cpId,
UserId1: userId1,
UserId2: userId2,
Visitor: visitor,
Times: 1,
}
if err := model.DB().Model(CpVisitor{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "cp_id"}, {Name: "visitor"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"times": gorm.Expr("times + ?", 1)})}).Create(vis).Error; err != nil {
model.Log.Errorf("AddCpSpaceVisitor fail:%v", err)
return err
}
return nil
}
// 获取cp空间访问人数
func CountCpSpaceVisitors(model *domain.Model, cpId mysql.ID) int64 {
var cnt int64
if err := model.DB().Model(CpVisitor{}).Where("cp_id = ?", cpId).Count(&cnt).Error; err != nil {
model.Log.Errorf("CountCpSpaceVisitors fail:%v", err)
}
return cnt
}
package event_m
import "hilo-user/domain/model"
func (p *EventGiftSendOffsetHiloUser) Persistence() error {
return model.Persistent(p.Db, p)
}
func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p)
}
package event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/pkg/errors"
"gorm.io/gorm"
"time"
)
// 送礼事件消息
type EventGiftSend struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
MarkHiloUser mysql.YesNo
}
func (EventGiftSend) TableName() string {
return "event_gift_send"
}
// 偏移值
type EventGiftSendOffsetHiloUser struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func Offset(model *domain.Model) (*EventGiftSendOffsetHiloUser, error) {
offset := new(EventGiftSendOffsetHiloUser)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取送礼
func FetchEventGiftSend(model *domain.Model, limit int) ([]*EventGiftSend, *EventGiftSendOffsetHiloUser, error) {
offset, err := Offset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGiftSend
if err := model.Db.WithContext(model).Model(EventGiftSend{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGiftSend fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGiftSend) MarkDone() error {
p.MarkHiloUser = mysql.YES
result := p.Db.WithContext(p.Model).Model(EventGiftSend{}).Where("id = ?", p.ID).Update("mark_hilo_user", p.MarkHiloUser).Limit(1)
if result.Error != nil {
return result.Error
}
if result.RowsAffected <= 0 {
p.Model.Log.Errorf("MarkDone row affeced 0")
return errors.New("row affect 0")
}
return nil
}
// 查询过去1小时-5分钟前未mark的事件
// 用来补偿
// 记得加limit
func FetchUnMarkEvents(model *domain.Model, limit int) ([]*EventGiftSend, error) {
offset, err := Offset(model)
if err != nil {
return nil, err
}
t := time.Now().Add(-time.Minute * 5)
lt := t.Add(-time.Hour)
var events []*EventGiftSend
if err := model.Db.WithContext(model).Model(EventGiftSend{}).
Where("mark_hilo_user = ?", mysql.NO).
Where("id <= ?", offset.MarkOffset).
Where("created_time < ?", t).
Where("created_time > ?", lt).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchUnMarkEvents fail:%v", err)
return nil, err
}
return events, nil
}
// 补偿加上unmark的event
func AddUnMarkEvent(model *domain.Model, event *EventGiftSend) error {
return model.Db.WithContext(model).Create(event).Error
}
...@@ -191,7 +191,7 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) { ...@@ -191,7 +191,7 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
if err == nil { if err == nil {
return r.Lang, nil return r.Lang, nil
} else if err == gorm.ErrRecordNotFound { } else if err == gorm.ErrRecordNotFound {
return res_e.DEFAULT_LANG, nil return res_e.DefaultLang, nil
} else { } else {
return "", myerr.WrapErr(err) return "", myerr.WrapErr(err)
} }
......
...@@ -123,3 +123,15 @@ func CheckHeadwearValidById(model *domain.Model, id mysql.ID) (bool, error) { ...@@ -123,3 +123,15 @@ func CheckHeadwearValidById(model *domain.Model, id mysql.ID) (bool, error) {
return true, nil return true, nil
} }
} }
func GetResHeadwearMap(db *gorm.DB) (map[uint64]ResHeadwear, error) {
rows := make([]ResHeadwear, 0)
if err := db.Model(&ResHeadwear{}).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[uint64]ResHeadwear, 0)
for _, i := range rows {
result[i.ID] = i
}
return result, nil
}
\ No newline at end of file
...@@ -2,8 +2,10 @@ package res_m ...@@ -2,8 +2,10 @@ package res_m
import ( import (
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-user/_const/enum/res_e" "hilo-user/_const/enum/res_e"
"time"
) )
type ResMedal struct { type ResMedal struct {
...@@ -41,3 +43,39 @@ func GetUserMedalLevelMap(db *gorm.DB) (map[uint64]uint8, map[uint8][]uint64, er ...@@ -41,3 +43,39 @@ func GetUserMedalLevelMap(db *gorm.DB) (map[uint64]uint8, map[uint8][]uint64, er
} }
return medalTypes, result, nil return medalTypes, result, nil
} }
var medalCache = gcache.New(1000).LRU().Build()
var medalMapCache = gcache.New(1).LRU().Build()
const medalKey = "MEDAL"
// pprof看到内存分配很多
// 加上15min lru
func MedalGetAll(db *gorm.DB) ([]ResMedal, error) {
if data, err := medalCache.Get(medalKey); err == nil {
return data.([]ResMedal), nil
}
rows := make([]ResMedal, 0)
err := db.Find(&rows).Error
if err != nil {
return nil, err
}
_ = medalCache.SetWithExpire(medalKey, rows, time.Minute*15)
return rows, nil
}
func MedalGetAllMap(db *gorm.DB) (map[uint32]ResMedal, error) {
if data, err := medalMapCache.Get(medalKey); err == nil {
return data.(map[uint32]ResMedal), nil
}
rows, err := MedalGetAll(db)
if err != nil {
return nil, err
}
result := make(map[uint32]ResMedal, 0)
for _, i := range rows {
result[uint32(i.ID)] = i
}
_ = medalMapCache.SetWithExpire(medalKey, result, time.Minute*15)
return result, nil
}
package res_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/res_e"
"hilo-user/myerr"
"hilo-user/myerr/bizerr"
)
type ResProperty struct {
mysql.Entity
*domain.Model `gorm:"-"`
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
}
type ResPropertyDiamond struct {
mysql.Entity
*domain.Model `gorm:"-"`
ResPropertyId mysql.ID
DiamondNum mysql.Num
Second mysql.Num
Status mysql.UserYesNo
}
type ResPropertyAvatar struct {
mysql.Entity
*domain.Model `gorm:"-"`
ResPropertyId mysql.ID
Type res_e.ResPropertyAvatarType
SendUserId mysql.ID
ReceiverUserId mysql.ID
}
func InitResPropertyDiamond(model *domain.Model, resPropertyId mysql.ID, diamondNum mysql.Num, second mysql.Num) *ResPropertyDiamond {
return &ResPropertyDiamond{
Model: model,
ResPropertyId: resPropertyId,
DiamondNum: diamondNum,
Second: second,
Status: mysql.NOUSER,
}
}
//id获取头饰,不存在则抛异常
func GetPropertyById(model *domain.Model, id mysql.ID) (*ResProperty, error) {
resProperty := ResProperty{}
if err := model.Db.Model(&ResProperty{}).First(&resProperty, id).Error; err != nil {
return nil, myerr.WrapErr(err)
} else {
resProperty.Model = model
return &resProperty, nil
}
}
func GetResPropertyDiamond(model *domain.Model, resPropertyDiamondId mysql.ID) (*ResPropertyDiamond, error) {
resPropertyDiamond := ResPropertyDiamond{}
if err := model.Db.Model(&ResPropertyDiamond{}).First(&resPropertyDiamond, resPropertyDiamondId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
if resPropertyDiamond.Status == mysql.NOUSER {
return nil, bizerr.ResPropertyDiamondNoUse
}
return &resPropertyDiamond, nil
}
func GetResPropertyDiamondByPropertyIdOrNil(model *domain.Model, resPropertyId mysql.ID) (*ResPropertyDiamond, error) {
resPropertyDiamond := ResPropertyDiamond{}
if err := model.Db.Model(&ResPropertyDiamond{}).Where(&ResPropertyDiamond{
ResPropertyId: resPropertyId,
}).First(&resPropertyDiamond).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
resPropertyDiamond.Model = model
return &resPropertyDiamond, nil
}
//设置成未使用
func (resPropertyDiamond *ResPropertyDiamond) SetUser() *ResPropertyDiamond {
resPropertyDiamond.Status = mysql.USER
return resPropertyDiamond
}
//设置成未使用
func (resPropertyDiamond *ResPropertyDiamond) SetNoUser() *ResPropertyDiamond {
resPropertyDiamond.Status = mysql.NOUSER
return resPropertyDiamond
}
func (resPropertyDiamond *ResPropertyDiamond) SetDiamondNum(diamondNum uint32) *ResPropertyDiamond {
resPropertyDiamond.DiamondNum = diamondNum
return resPropertyDiamond
}
func (resPropertyDiamond *ResPropertyDiamond) SetSecond(second uint32) *ResPropertyDiamond {
resPropertyDiamond.Second = second
return resPropertyDiamond
}
func AddProperty(model *domain.Model, p *ResProperty) error {
return model.Db.Create(p).Error
}
func EditProperty(model *domain.Model, propertyId uint64, name, picUrl, effectUrl string) error {
activityConfig := ResProperty{Entity: mysql.Entity{ID: propertyId}}
err := model.Db.First(&activityConfig).Error
if err != nil {
return err
}
activityConfig.Name = name
activityConfig.PicUrl = picUrl
activityConfig.EffectUrl = effectUrl
return model.Db.Save(&activityConfig).Error
}
func (p *ResProperty) Get(db *gorm.DB) error {
return db.Where(p).First(p).Error
}
func (p *ResProperty) GetAll(db *gorm.DB) (map[uint64]ResProperty, error) {
rows := make([]ResProperty, 0)
if err := db.Where(p).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[uint64]ResProperty, 0)
for _, i := range rows {
result[i.ID] = i
}
return result, nil
}
func (p *ResPropertyAvatar) GetAll(db *gorm.DB) (map[uint64]ResPropertyAvatar, error) {
rows := make([]ResPropertyAvatar, 0)
if err := db.Where(p).Find(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
result := make(map[uint64]ResPropertyAvatar, 0)
for _, i := range rows {
result[i.ResPropertyId] = i
}
return result, nil
}
...@@ -27,7 +27,7 @@ func GetResMultiTextBy(db *gorm.DB, msgId uint, Language mysql.Str) (*ResMultiTe ...@@ -27,7 +27,7 @@ func GetResMultiTextBy(db *gorm.DB, msgId uint, Language mysql.Str) (*ResMultiTe
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
if err := db.Where(&ResMultiText{ if err := db.Where(&ResMultiText{
MsgId: msgId, MsgId: msgId,
Language: res_e.DEFAULT_LANG, Language: res_e.DefaultLang,
}).First(&r).Error; err != nil { }).First(&r).Error; err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
......
...@@ -89,3 +89,15 @@ func GetUserMedal(db *gorm.DB, userId mysql.ID) ([]uint32, error) { ...@@ -89,3 +89,15 @@ func GetUserMedal(db *gorm.DB, userId mysql.ID) ([]uint32, error) {
} }
return result, nil return result, nil
} }
func BatchGetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userIds []mysql.ID) (map[uint64][]uint32, error) {
result := make(map[uint64][]uint32, 0)
for _, u := range userIds {
a, err := GetUserMedalMerge(logger, db, u)
if err != nil {
return nil, err
}
result[u] = a
}
return result, nil
}
...@@ -109,3 +109,31 @@ type UserPropertyLog struct { ...@@ -109,3 +109,31 @@ type UserPropertyLog struct {
AddSecond *mysql.Num AddSecond *mysql.Num
UpdateEndTime *time.Time UpdateEndTime *time.Time
} }
func (userProperty *UserProperty) BatchGet(db *gorm.DB, userIds []uint64) (map[uint64]uint64, error) {
rows := make([]UserProperty, 0)
if err := db.Model(userProperty).
Where("end_time > NOW() AND user_id IN ?", userIds).Order("id DESC").Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[uint64]uint64, 0)
tmp := make(map[uint64]uint64, 0)
for _, i := range rows {
if _, ok := result[i.UserId]; !ok {
if i.Using == property_e.YesUsing {
// using = true且id最大,就确定是当前使用的
result[i.UserId] = i.PropertyId
} else if _, ok := tmp[i.UserId]; !ok {
// using = false且id最大,先记下,因为不知道还有没有using=true的
tmp[i.UserId] = i.PropertyId
}
}
}
for k, v := range tmp {
// result中没有的,就采用tmp保存的
if _, ok := result[k]; !ok {
result[k] = v
}
}
return result, nil
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/myerr"
"strings"
)
type SuperManager struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
IsAll bool
Countries string
}
func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
var n int64
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).Count(&n).Error; err != nil {
return false, myerr.WrapErr(err)
}
return n > 0, nil
}
// 对某人是否有超管权限
func IsSuperManagerV2(model *domain.Model, userId, targetUserId mysql.ID) (bool, error) {
var man SuperManager
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).First(&man).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsSuperManagerV2 fail:%v", err)
}
return false, nil
}
if man.IsAll {
return true, nil
}
targetUser, err := GetUser(model, targetUserId)
if err != nil {
return false, err
}
countries := strings.Split(man.Countries, ",")
for _, c := range countries {
if c == targetUser.Country {
return true, nil
}
}
return false, nil
}
func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
var superManagers []SuperManager
if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userIds := make([]uint64, 0, len(superManagers))
for i, _ := range superManagers {
userIds = append(userIds, superManagers[i].UserId)
}
return userIds, nil
}
/*
func GetSuperManagerMap(model *domain.Model) (map[uint64]struct{}, error) {
userIds, err := GetSuperManagerAll(model)
if err != nil {
return nil, err
}
userIdMap := map[uint64]struct{}{}
for i, _ := range userIds {
userIdMap[userIds[i]] = struct{}{}
}
return userIdMap, nil
}*/
...@@ -43,3 +43,24 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) { ...@@ -43,3 +43,24 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
} }
return nil, nil return nil, nil
} }
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error
if err != nil {
return nil, err
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds {
result[i] = nil
}
now := time.Now()
for _, i := range rows {
if i.ExpireAt.After(now) {
ts := i.ExpireAt.Unix()
result[i.UserId] = &ts
}
}
return result, nil
}
package event_s
import (
"git.hilo.cn/hilo-common/domain"
"github.com/jinzhu/now"
"hilo-user/_const/enum/cp_e"
"hilo-user/domain/event/gift_ev"
"hilo-user/domain/model/cp_m"
"time"
)
// 送礼增加cp等级
// 送礼增加cp排行榜
func CpGiftEvent() {
gift_ev.AddSendGiftEventSync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil
}
// 只处理cp礼物
if !sendGiftEvent.ResGift.Cp {
return nil
}
for _, receiverUid := range sendGiftEvent.ReceiveUserIds {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
// 有cp关系
if cpRelation, exits := cp_m.GetCpRelationPair(model, sendGiftEvent.SendUserId, receiverUid); exits {
if err := cp_m.AddCpLevelPoints(model, cpRelation, diamonds); err != nil {
model.Log.Errorf("AddCpLevelPoints fail:%v", err)
}
if err := cp_m.AddCpDayRank(model, cpRelation, diamonds); err != nil {
model.Log.Errorf("AddCpDayRank fail:%v", err)
}
// 检查最新的等级
if cpLevel := cp_m.GetCpLevel(model, cpRelation.ID); cpLevel.CpId >= 0 {
points := cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level]
if err := cp_m.UpdateCpAchievement(model, cpLevel.CpId, cpRelation.UserId1, cpRelation.UserId2, cp_e.CpAchievementLevel, points); err != nil {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
}
}
// 检查最高的分数
for _, queryType := range []string{"day", "week", "month"} {
var beginDate, endDate string
var cpAchievementType cp_e.CpAchievement
switch queryType {
case "day":
beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementDayRank
case "week":
beginDate = now.BeginningOfWeek().Format("2006-01-02")
endDate = now.EndOfWeek().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementWeekRank
case "month":
beginDate = now.BeginningOfMonth().Format("2006-01-02")
endDate = now.EndOfMonth().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementMonthRank
}
if data := cp_m.GetCpDayRank(model, beginDate, endDate, cpRelation.ID); data.Score > 0 {
if err := cp_m.UpdateCpAchievement(model, cpRelation.ID, cpRelation.UserId1, cpRelation.UserId2, cpAchievementType, data.Score); err != nil {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
}
}
}
// 检查最新日周月榜单
return nil // 业务场景允许提前break(cp是唯一的)
}
}
return nil
})
}
package event_s
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/_const/enum/cp_e"
"hilo-user/domain/event/cp_ev"
"hilo-user/domain/model/cp_m"
"hilo-user/myerr/bizerr"
)
// cp空间访问
func CpSpaceVisitEvent() {
cp_ev.AddCpSpaceVisitAsync(func(model *domain.Model, event interface{}) error {
e, ok := event.(*cp_ev.SpaceVisitEvent)
if !ok {
return bizerr.InvalidParameter
}
if err := cp_m.AddCpSpaceVisitor(model, e.CpId, e.UserId1, e.UserId2, e.UserId); err != nil {
model.Log.Errorf("AddCpSpaceVisitor fail:%v", err)
}
if cnt := cp_m.CountCpSpaceVisitors(model, e.CpId); cnt > 0 {
if err := cp_m.UpdateCpAchievement(model, e.CpId, e.UserId1, e.UserId2, cp_e.CpAchievementVisitors, mysql.Num(cnt)); err != nil {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
}
}
return nil
})
}
...@@ -14,6 +14,8 @@ import ( ...@@ -14,6 +14,8 @@ import (
func EventInit() { func EventInit() {
UserBagSendEvent() UserBagSendEvent()
CpGiftEvent()
CpSpaceVisitEvent()
} }
func UserBagSendEvent() { func UserBagSendEvent() {
......
package event_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/domain/event/gift_ev"
"hilo-user/domain/model/event_m"
"runtime/debug"
)
// 每次处理500条
const BatchCount = 500
type GiftSendEventService struct {
svc *domain.Service
}
func NewGiftSendEventService(myContext *mycontext.MyContext) *GiftSendEventService {
svc := domain.CreateService(myContext)
return &GiftSendEventService{svc}
}
//
func (s *GiftSendEventService) Consume() error {
defer func() {
if err := recover(); err != nil {
s.svc.Log.Errorf("ExceptionHandle GiftSendEventService Consume SYSTEM ACTION PANIC: %v, stack: %v", err, string(debug.Stack()))
}
}()
var model = domain.CreateModel(s.svc.CtxAndDb)
return model.Transaction(func(model *domain.Model) error {
events, offset, err := event_m.FetchEventGiftSend(model, BatchCount)
if err != nil {
return err
}
for k := range events {
cpEvent := &event_m.EventGiftSend{
Entity: mysql.Entity{
ID: events[k].ID,
CreatedTime: events[k].CreatedTime,
UpdatedTime: events[k].UpdatedTime,
},
Proto: events[k].Proto,
Payload: events[k].Payload,
MarkHiloUser: events[k].MarkHiloUser,
}
if cpEvent.MarkHiloUser == mysql.YES {
model.Log.Warnf("already consume msg :%v", cpEvent)
continue
}
sendGiftEvent := new(gift_ev.SendGiftEvent)
if err := json.Unmarshal(cpEvent.Payload, sendGiftEvent); err != nil {
model.Log.Errorf("json msg fail,event:%v,err:%v", cpEvent, err)
continue
}
// 标记已经处理,mark比publish事件提前,尽量避免异步事件重复执行
cpEvent.Model = model
err = cpEvent.MarkDone()
if err != nil {
model.Log.Errorf("consume msg fail,event:%v,err:%v", cpEvent, err)
return err
}
if err := gift_ev.PublishSendGiftEvent(model, sendGiftEvent); err != nil {
model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", string(cpEvent.Payload), err)
return err
}
}
// 最后一次提交offset
if len(events) > 0 {
offset.MarkOffset = events[len(events)-1].ID
return offset.Persistence()
}
return nil
})
}
...@@ -25,6 +25,7 @@ require ( ...@@ -25,6 +25,7 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.61.1274 // indirect
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/bluele/gcache v0.0.2 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.9.0 // indirect github.com/fatih/color v1.9.0 // indirect
...@@ -63,11 +64,17 @@ require ( ...@@ -63,11 +64,17 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 // indirect
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 // indirect golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect gopkg.in/ini.v1 v1.63.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
......
This diff is collapsed.
...@@ -3,6 +3,7 @@ package main ...@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/resource/consul" "git.hilo.cn/hilo-common/resource/consul"
"hilo-user/cron"
"hilo-user/domain/service/event_s" "hilo-user/domain/service/event_s"
"hilo-user/route" "hilo-user/route"
) )
...@@ -14,7 +15,7 @@ const ( ...@@ -14,7 +15,7 @@ const (
) )
func main() { func main() {
//cron.Init() // 开启定时任务 cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
r := route.InitRouter() // 注册路由 r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册 consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
......
...@@ -20,30 +20,7 @@ var ( ...@@ -20,30 +20,7 @@ var (
DiamondFrequency = myerr.NewBusinessCode(4001, "Diamond operation frequency too high", myerr.BusinessData{}) DiamondFrequency = myerr.NewBusinessCode(4001, "Diamond operation frequency too high", myerr.BusinessData{})
DiamondAccountFrozen = myerr.NewBusinessCode(4004, "Diamond Account Frozen", myerr.BusinessData{}) DiamondAccountFrozen = myerr.NewBusinessCode(4004, "Diamond Account Frozen", myerr.BusinessData{})
// 游戏 ResPropertyDiamondNoUse = myerr.NewBusinessCode(5004, "Property can not buy", myerr.BusinessData{}) //头饰不能买
GameInvalidParameter = myerr.NewGameError(10002, "invalid parameter")
GameTokenInvalid = myerr.NewGameError(1004, "user token invalid")
GameTokenExpire = myerr.NewGameError(1005, "user token expire")
// 群组 CpNotRelation = myerr.NewBusinessCode(6000, "cp not relation", myerr.BusinessData{})
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
// 游戏服务的错误码,6位,50XXX
GameAddNoPermissions = myerr.NewBusinessCode(50100, "Only room administrators can create users", myerr.BusinessData{}) // 权限不足
GameAddNotOnMic = myerr.NewBusinessCode(50101, "Need on mic", myerr.BusinessData{}) // 需要在麦上才能创建、加入游戏
GameHaveNoEnd = myerr.NewBusinessCode(50102, "Group user have no end", myerr.BusinessData{}) // 房间还有未结束的游戏
GameNotFound = myerr.NewBusinessCode(50103, "Game not found", myerr.BusinessData{}) //
GameStart = myerr.NewBusinessCode(50104, "Gaming", myerr.BusinessData{}) //
GameAlreadyJoin = myerr.NewBusinessCode(50105, "Already Joined", myerr.BusinessData{}) // 已经加入了游戏
GameNotJoin = myerr.NewBusinessCode(50106, "Not Join user", myerr.BusinessData{}) // 还未加入游戏
GameCannotClose = myerr.NewBusinessCode(50107, "Have no power to close user", myerr.BusinessData{}) // 没有权限关闭游戏
GameCloseGaming = myerr.NewBusinessCode(50108, "Can't close a user in progress", myerr.BusinessData{}) // 不能关闭进行中的游戏
GamePlayerNumWrong = myerr.NewBusinessCode(50109, "Game player num wrong", myerr.BusinessData{}) // 玩家数量错误
GameHaveNoMyRoom = myerr.NewBusinessCode(50110, "Have no my room", myerr.BusinessData{}) // 自己没有房间
GameHaveNoEndGame = myerr.NewBusinessCode(50111, "The last user is not over yet, cannot create/join a user", myerr.BusinessData{}) // 已经加入了其他房间的游戏
GameExitWrong = myerr.NewBusinessCode(50112, "Can not exit user", myerr.BusinessData{}) // 离开游戏失败
GameDiamondCannotEdit = myerr.NewBusinessCode(50113, "Game diamond can not edit", myerr.BusinessData{}) //
GameSettleWrong = myerr.NewBusinessCode(50114, "Game settle wrong", myerr.BusinessData{}) // 结算修改错误
GameCloseWrong = myerr.NewBusinessCode(50115, "Game close wrong", myerr.BusinessData{}) // 关闭错误
GameJoinFailed = myerr.NewBusinessCode(50116, "Join failed", myerr.BusinessData{}) // 加入失败
) )
...@@ -225,36 +225,3 @@ func WrapErr(err error) error { ...@@ -225,36 +225,3 @@ func WrapErr(err error) error {
return errors.Wrap(err, "") return errors.Wrap(err, "")
} }
} }
func WrapGameErr(err error) error {
if err == nil {
return err
}
if h, ok := err.(*GameError); ok {
return h
}
return NewGameError(500, err.Error())
}
// 系统错误
type GameError struct {
code uint16
message string
err error
}
func (err *GameError) Error() string {
return err.err.Error()
}
func (err *GameError) Code() uint16 {
return err.code
}
func NewGameError(code uint16, msg string) *GameError {
return &GameError{
code: code,
message: msg,
err: errors.New("{code:" + strconv.Itoa(int(code)) + ",message:" + msg + "}"),
}
}
...@@ -10,6 +10,18 @@ import ( ...@@ -10,6 +10,18 @@ import (
"hilo-user/myerr/bizerr" "hilo-user/myerr/bizerr"
) )
// 分页base
type PageReqBase struct {
PageIndex int `form:"pageIndex,default=0"`
PageSize int `form:"pageSize,default=10"`
}
type PageRespBase struct {
NextPageIndex int `json:"nextPageIndex"`
HasNextPage bool `json:"hasNextPage"`
Data interface{} `json:"data"` // 需要具体自定义
}
func GetUserId(c *gin.Context) (mysql.ID, error) { func GetUserId(c *gin.Context) (mysql.ID, error) {
if userIdStr, ok := c.Keys[mycontext.USERID]; ok { if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
userId := userIdStr.(uint64) userId := userIdStr.(uint64)
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-user/myerr" "hilo-user/myerr"
"hilo-user/req"
"net/http" "net/http"
) )
...@@ -42,27 +43,23 @@ func ResponseOk(c *gin.Context, data interface{}) { ...@@ -42,27 +43,23 @@ func ResponseOk(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, response) c.JSON(http.StatusOK, response)
} }
func GameResponseOk(c *gin.Context, data interface{}) { // 分页返回
// always return http.StatusOK // 客户端入参 req.PageReqBase
response := GameResponse{ // 服务端返回 req.PageRespBase
RetCode: 0, func ResponsePageBaseOk(c *gin.Context, data interface{}, nextPageIndex int, hasNextPage bool) {
RetMsg: myerr.GetSuccessMsg(), if data == nil {
SdkErrorCode: 0, data = make([]interface{}, 0)
Data: data,
} }
printResponseBody(c, &response) response := Response{
c.JSON(http.StatusOK, response) Code: myerr.GetSuccessCode(),
} Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
func GameResponseFail(c *gin.Context, err *myerr.GameError) { Data: req.PageRespBase{
// always return http.StatusOK NextPageIndex: nextPageIndex,
response := GameResponse{ HasNextPage: hasNextPage,
RetCode: err.Code(), Data: data,
RetMsg: err.Error(), },
SdkErrorCode: err.Code(),
Data: nil,
} }
printResponseBody(c, &response)
c.JSON(http.StatusOK, response) c.JSON(http.StatusOK, response)
} }
......
package cp_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"github.com/gin-gonic/gin"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr/bizerr"
"hilo-user/req"
"hilo-user/resp"
"strconv"
"time"
)
type PostPutAnniversaryReq struct {
Content string `form:"content" binding:"required"`
Timestamp int64 `form:"timestamp" binding:"required"`
IsRemind bool `form:"isRemind"`
}
// @Tags CP v2
// @Summary 发布纪念日
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param content formData string true "纪念日名称"
// @Param timestamp formData int true "时间戳"
// @Param isRemind formData bool false "是否提醒"
// @Success 200
// @Router /v2/cp/anniversary [post]
func PostAnniversary(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
var param PostPutAnniversaryReq
if err := c.ShouldBind(&param); err != nil {
return myCtx, err
}
model := domain.CreateModelContext(myCtx)
relation, exits := cp_m.GetCpRelation(model, userId)
if !exits {
return myCtx, bizerr.CpNotRelation
} else {
if err := cp_m.AddCpAnniversary(model, cp_e.AnniversaryItemTypeNormal, relation, param.Content, param.Timestamp, param.IsRemind, 0); err != nil {
return myCtx, err
}
}
resp.ResponseOk(c, "")
return myCtx, nil
}
// @Tags CP v2
// @Summary 修改纪念日
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param content formData string true "纪念日名称"
// @Param timestamp formData int true "时间戳"
// @Param isRemind formData bool false "是否提醒"
// @Param id path int true "更新的记录id"
// @Success 200
// @Router /v2/cp/anniversary/{id} [put]
func PutAnniversary(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
var param PostPutAnniversaryReq
if err := c.ShouldBind(&param); err != nil {
return myCtx, err
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
model := domain.CreateModelContext(myCtx)
if err := cp_m.UpdateCpAnniversary(model, id, param.Content, param.Timestamp, param.IsRemind); err != nil {
return myCtx, err
}
resp.ResponseOk(c, "")
return myCtx, nil
}
// @Tags CP v2
// @Summary 获取纪念日
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageIndex query int true "偏移值 默认:1" default(1)
// @Param pageSize query int true "请求数量 默认:10" default(10)
// @Success 200 {object} []cp_cv.CvCpAnniversary
// @Router /v2/cp/anniversary [get]
func PageAnniversary(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
var response = make([]cp_cv.CvCpAnniversary, 0)
model := domain.CreateModelContext(myCtx)
cpRelation, exits := cp_m.GetCpRelation(model, userId)
if exits {
userIds := []uint64{cpRelation.UserId1, cpRelation.UserId2}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
return myCtx, err
}
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
userInfo := user_cv.UserToTiny(users[userId])
cpUserInfo := user_cv.UserToTiny(users[cpUserId])
response = append(response, cp_cv.CvCpAnniversary{
Type: cp_e.AnniversaryItemTypeAvatar,
CpInfo: &cp_cv.CvCpBase{
UserInfo: *userInfo,
CpUserInfo: *cpUserInfo,
},
OriginTimestamp: cpRelation.CreatedTime.Unix(),
Timestamp: cpRelation.CreatedTime.Unix(),
CanDel: false,
})
}
anniversary := cp_m.GetAllCpAnniversary(model, userId)
for _, v := range anniversary {
timestamp := v.Timestamp
if v.Type == cp_e.AnniversaryItemTypeAnniversary && timestamp > 0 {
timestamp = calcNextAnniversary(timestamp)
}
// 客户端只认识0 1
Type := v.Type
if v.Type != cp_e.AnniversaryItemTypeAvatar {
Type = cp_e.AnniversaryItemTypeNormal
}
response = append(response, cp_cv.CvCpAnniversary{
Type: Type,
Id: v.ID,
Content: v.Content,
Timestamp: timestamp,
OriginTimestamp: v.Timestamp,
IsRemind: v.IsRemind,
CanDel: true,
IsTop: v.Sort > 0,
})
}
resp.ResponsePageBaseOk(c, response, 0, false)
return myCtx, nil
}
// 计算下一个纪念日
func calcNextAnniversary(timestamp int64) int64 {
now := time.Now()
// 还没超过一天,不用计算明年的
if now.Unix()-timestamp < 86400 {
return timestamp
}
birthday := time.Unix(timestamp, 0)
// 计算今年的生日日期
thisYearBirthday := time.Date(now.Year(), birthday.Month(), birthday.Day(), birthday.Hour(), birthday.Minute(), birthday.Second(), 0, time.Local)
// 如果今年的生日还未到,则生日日期为今年的生日日期;否则为明年的生日日期
var next time.Time
if thisYearBirthday.After(now) {
next = thisYearBirthday
} else {
next = thisYearBirthday.AddDate(1, 0, 0)
}
// 计算时间戳
nextTimestamp := next.Unix()
return nextTimestamp
}
// @Tags CP v2
// @Summary 获取纪念日
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param id path int true "记录id"
// @Success 200
// @Router /v2/cp/anniversary/:id [delete]
func DelAnniversary(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
model := domain.CreateModelContext(myCtx)
if err := cp_m.DelCpAnniversary(model, id); err != nil {
return myCtx, err
}
resp.ResponseOk(c, "")
return myCtx, nil
}
package cp_r
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr/bizerr"
"hilo-user/req"
"hilo-user/resp"
"time"
)
// @Tags CP v2
// @Summary 排行榜
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageIndex query int true "偏移值 默认:1" default(1)
// @Param pageSize query int true "请求数量 默认:10" default(10)
// @Param queryType path string true "类型:day/week/month"
// @Success 200 {object} []cp_cv.CvCpRank
// @Router /v2/cp/rank/{queryType} [get]
func CpRank(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
pageReq := new(req.PageReqBase)
if err := c.ShouldBindQuery(pageReq); err != nil {
return myCtx, err
}
if pageReq.PageIndex == 0 {
pageReq.PageIndex = 1
}
queryType := c.Param("queryType")
if queryType != "day" && queryType != "week" && queryType != "month" {
return myCtx, bizerr.InvalidParameter
}
var beginDate, endDate string
switch queryType {
case "day":
beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02")
case "week":
beginDate = now.BeginningOfWeek().Format("2006-01-02")
endDate = now.EndOfWeek().Format("2006-01-02")
case "month":
beginDate = now.BeginningOfMonth().Format("2006-01-02")
endDate = now.EndOfMonth().Format("2006-01-02")
}
offset, limit := (pageReq.PageIndex-1)*pageReq.PageSize, pageReq.PageSize
model := domain.CreateModelContext(myCtx)
ranks := cp_m.PageCpDayRank(model, beginDate, endDate, offset, limit)
var response []cp_cv.CvCpRank
var userIds []mysql.ID
var cpIds []mysql.ID
for _, rank := range ranks {
userIds = append(userIds, rank.UserId1)
userIds = append(userIds, rank.UserId2)
cpIds = append(cpIds, rank.CpId)
}
userBase, err := user_cv.GetUserBaseMap(userIds, userId)
if err != nil {
return myCtx, err
}
cpLevels := cp_m.MGetCpLevel(model, cpIds)
for i, rank := range ranks {
response = append(response, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
Level: cpLevels[rank.CpId].Level,
//Points: cp_e.CpLevelPoints[cpLevel] + curPoints,
//EndPoints: nextPoints,
//RemainPoints: remainPoints,
//ExpireAtUnix: expireAtUnix,
},
})
}
resp.ResponsePageBaseOk(c, response, pageReq.PageIndex+1, len(ranks) >= pageReq.PageSize)
return myCtx, nil
}
// @Tags CP v2
// @Summary CP,Top3
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Success 200 {object} cp_cv.CpTops
// @Router /v2/cp/top3 [get]
func CpTop3(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
var response = cp_cv.CpTops{
Day: make([]cp_cv.CvCpRank, 0),
Week: make([]cp_cv.CvCpRank, 0),
}
queryTypes := []string{"day", "week"}
for _, queryType := range queryTypes {
var beginDate, endDate string
switch queryType {
case "day":
beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02")
case "week":
beginDate = now.BeginningOfWeek().Format("2006-01-02")
endDate = now.EndOfWeek().Format("2006-01-02")
}
offset, limit := 0, 3
model := domain.CreateModelContext(myCtx)
ranks := cp_m.PageCpDayRank(model, beginDate, endDate, offset, limit)
var userIds []mysql.ID
var cpIds []mysql.ID
for _, rank := range ranks {
userIds = append(userIds, rank.UserId1)
userIds = append(userIds, rank.UserId2)
cpIds = append(cpIds, rank.CpId)
}
userBase, err := user_cv.GetUserBaseMap(userIds, userId)
if err != nil {
return myCtx, err
}
cpLevels := cp_m.MGetCpLevel(model, cpIds)
for i, rank := range ranks {
if queryType == "day" {
response.Day = append(response.Day, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
Level: cpLevels[rank.CpId].Level,
},
})
} else {
response.Week = append(response.Week, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
Level: cpLevels[rank.CpId].Level,
},
})
}
}
}
resp.ResponseOk(c, response)
return myCtx, nil
}
// @Tags CP v2
// @Summary 我的cp
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param queryType path string true "类型:day/week/month"
// @Success 200 {object} cp_cv.CvCpRank
// @Router /v2/cp/my/{queryType} [get]
func CpMy(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
queryType := c.Param("queryType")
if queryType != "day" && queryType != "week" && queryType != "month" {
return myCtx, bizerr.InvalidParameter
}
var beginDate, endDate string
switch queryType {
case "day":
beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02")
case "week":
beginDate = now.BeginningOfWeek().Format("2006-01-02")
endDate = now.EndOfWeek().Format("2006-01-02")
case "month":
beginDate = now.BeginningOfMonth().Format("2006-01-02")
endDate = now.EndOfMonth().Format("2006-01-02")
}
model := domain.CreateModelContext(myCtx)
relation, exits := cp_m.GetCpRelation(model, userId)
var userIds []mysql.ID
var scores uint32
if exits {
// 保证一下自己是userId1
userIds = append(userIds, userId)
if relation.UserId1 == userId {
userIds = append(userIds, relation.UserId2)
} else {
userIds = append(userIds, relation.UserId1)
}
rank := cp_m.GetCpDayRank(model, beginDate, endDate, relation.ID)
scores = rank.Score
} else {
userIds = append(userIds, userId)
relation.UserId1 = userId
}
userBases, err := user_cv.GetUserBaseMap(userIds, userId)
if err != nil {
return myCtx, err
}
response := cp_cv.CvCpRank{
CpId: relation.ID,
Score: scores,
}
if relation.UserId1 > 0 {
response.User1 = userBases[relation.UserId1]
}
if relation.UserId2 > 0 {
response.User2 = userBases[relation.UserId2]
response.Ranking = "30+"
ranks := cp_m.PageCpDayRank(model, beginDate, endDate, 0, 30)
for i, rank := range ranks {
if relation.ID == rank.CpId {
response.Ranking = fmt.Sprintf("%d", i+1)
break
}
}
}
resp.ResponseOk(c, response)
return myCtx, nil
}
// @Tags CP v2
// @Summary 成就页
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageIndex query int true "偏移值 默认:1" default(1)
// @Param pageSize query int true "请求数量 默认:10" default(10)
// @Success 200 {object} []cp_cv.CvCpAchievement
// @Router /v2/cp/achievement [get]
func CpAchievement(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
model := domain.CreateModelContext(myCtx)
var response = make([]cp_cv.CvCpAchievement, 0)
TypeDescMap := map[cp_e.CpAchievement]string{ // todo 翻译
cp_e.CpAchievementLevel: "等级分值最高",
cp_e.CpAchievementVisitors: "空间访问量最高",
cp_e.CpAchievementMonthRank: "月榜最高",
cp_e.CpAchievementWeekRank: "周榜最高",
cp_e.CpAchievementDayRank: "天榜最高",
}
achievements := cp_m.GetCpAchievements(model)
var userIds []uint64
for _, v := range achievements {
userIds = append(userIds, v.UserId1)
userIds = append(userIds, v.UserId2)
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
return myCtx, err
}
for _, a := range achievements {
response = append(response, cp_cv.CvCpAchievement{
CpId: a.CpId,
User1: user_cv.UserToTiny(users[a.UserId1]),
User2: user_cv.UserToTiny(users[a.UserId2]),
Type: a.Type,
TypeDesc: TypeDescMap[a.Type],
Score: a.Score,
TimeUnix: a.UpdatedTime.Unix(),
})
}
resp.ResponsePageBaseOk(c, response, 0, false)
return myCtx, nil
}
package cp_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/event/cp_ev"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr/bizerr"
"hilo-user/req"
"hilo-user/resp"
"time"
)
// @Tags CP v2
// @Summary cp空间
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param externalId query string true "查看用户的externalId"
// @Success 200 {object} cp_cv.CvSpace
// @Router /v2/cp/space [get]
func CpSpace(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
externalId := c.Query("externalId")
if len(externalId) <= 0 {
return myContext, bizerr.InvalidParameter
}
var model = domain.CreateModelContext(myContext)
userInfo, err := user_m.GetUser(model, userId)
if err != nil {
return myContext, err
}
targetUserInfo, err := user_m.GetUserByExtId(model, externalId)
if err != nil {
return myContext, err
}
var cpUserInfo *user_m.User
expireAtUnix, cpLevel := int64(0), cp_e.CpLevel0
visitTimes := int64(0)
settlementDate, cpDays, applyToUnbind := "", 0, false
nextPoints, curPoints := cp_e.CpLevelPoints[cp_e.CpLevel1], mysql.Num(0)
cpRelation, exists := cp_m.GetCpRelation(model, targetUserInfo.ID)
if exists {
level := cp_m.GetCpLevel(model, cpRelation.ID)
if level.ExpireAt.Before(time.Now()) {
level.ExpireAt = time.Now().AddDate(0, 1, 0)
}
cpLevel, curPoints = level.Level, level.Points
expireAtUnix, settlementDate = level.ExpireAt.Unix(), level.ExpireAt.Format("2006-01-02")
cpDays = int(time.Now().Sub(cpRelation.CreatedTime).Hours()/24) + 1
// cp 存在的时候,发布访问cp空间事件
if err := cp_ev.PublishCpSpaceVisit(model, &cp_ev.SpaceVisitEvent{
UserId: userId,
CpId: cpRelation.ID,
UserId1: cpRelation.UserId1,
UserId2: cpRelation.UserId2,
}); err != nil {
return myContext, err
}
visitTimes = cp_m.CountCpSpaceVisitors(model, cpRelation.ID)
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
cpUserInfo, err = user_m.GetUser(model, cpUserId)
if err != nil {
return myContext, err
}
// 查看别人的cp空间
if userId != cpRelation.UserId1 && userId != cpRelation.UserId2 {
userInfo, err = user_m.GetUser(model, cpRelation.UserId1)
if err != nil {
return myContext, err
}
} else {
// 自己的空间
applyToUnbind = cp_m.GetApplyToUnbind(model, userId, cpUserId)
}
}
if cpLevel != cp_e.CpLevelMax {
nextPoints = cp_e.CpLevelPoints[cpLevel+1]
} else {
nextPoints = cp_e.CpLevelPoints[cp_e.CpLevelMax]
}
userPrivileges, err := cp_m.MGetUserSvipPrivilege(model, []uint64{userId})
if err != nil {
return myContext, err
}
allPrivilegeList := make([][]cp_cv.CvPrivilege, cp_e.CpLevelMax+1)
for level := cp_e.CpLevel0; level <= cp_e.CpLevelMax; level++ {
privilegeList := cp_cv.CopyCpLevelPrivilegeList(level, lang)
for i, v := range privilegeList {
if v.CanSwitch {
privilegeList[i].UserSwitch = userPrivileges[userId][v.Type]
}
}
allPrivilegeList[level] = privilegeList
}
// 返回值
response := cp_cv.CvSpace{
CpLevel: cp_cv.CvCpLevel{
Level: cpLevel,
Points: cp_e.CpLevelPoints[cpLevel] + curPoints,
StartPoints: cp_e.CpLevelPoints[cpLevel],
EndPoints: nextPoints,
ExpireAtUnix: expireAtUnix,
SettlementDate: settlementDate,
MaxLevel: cp_e.CpLevelMax,
},
ResLevelList: cp_cv.CvResLevelList,
PrivilegeList: allPrivilegeList,
}
response.CpInfo = cp_cv.CvCpInfo{
UserInfo: user_cv.UserToTiny(*userInfo),
CpDays: cpDays,
VisitTimes: visitTimes,
ApplyToUnbind: applyToUnbind,
}
if cpUserInfo != nil {
response.CpInfo.CpUserInfo = user_cv.UserToTiny(*cpUserInfo)
}
// 需要提醒的纪念日
if exists && (userId == cpRelation.UserId1 || userId == cpRelation.UserId2) {
anniversary := cp_m.GetUserTodayCpAnniversary(model, cpRelation.ID)
for _, a := range anniversary {
response.CpAnniversary = append(response.CpAnniversary, cp_cv.CvCpAnniversary{
Id: a.ID,
Content: a.Content,
Timestamp: a.Timestamp,
})
}
}
resp.ResponseOk(c, response)
return myContext, nil
}
type CpPrivilegeOpenCloseReq struct {
Type cp_e.CpPrivilege `form:"type" binding:"required"`
OpenClose mysql.OpenClose `form:"openClose" binding:"required"`
}
// @Tags CP v2
// @Summary cp特权开关
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param type formData int true "1.空间 2.横幅 3.等级勋章 4.证书 5.进场特效 6.头像头饰 7.动态资料卡 8.麦位特效"
// @Param openClose formData int true "1:open 2:close"
// @Success 200
// @Router /v2/cp/privilege/openClose [put]
func CpPrivilegeOpenClose(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
var request CpPrivilegeOpenCloseReq
if err := c.ShouldBind(&request); err != nil {
return myCtx, err
}
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
var model = domain.CreateModelContext(myCtx)
if err := cp_m.OpenCLoseUserSvipPrivilege(model, userId, request.Type, request.OpenClose); err != nil {
return myCtx, err
}
resp.ResponseOk(c, "")
return myCtx, nil
}
...@@ -37,9 +37,6 @@ func wrapper(handler HandlerFunc) func(c *gin.Context) { ...@@ -37,9 +37,6 @@ func wrapper(handler HandlerFunc) func(c *gin.Context) {
userId, _ := req.GetUserId(c) userId, _ := req.GetUserId(c)
switch h := err.(type) { switch h := err.(type) {
case *myerr.GameError:
myContext.Log.Warnf("request user err -> url:%v, method:%v, userId:%v, err :%+v\n", reqUri, method, userId, h.Error())
resp.GameResponseFail(c, h)
case *myerr.BusinessError: case *myerr.BusinessError:
myContext.Log.Warnf("request err -> url:%v, method:%v, userId:%v, err :%+v\n", reqUri, method, userId, h.GetErr()) myContext.Log.Warnf("request err -> url:%v, method:%v, userId:%v, err :%+v\n", reqUri, method, userId, h.GetErr())
resp.ResponseBusiness(c, h) resp.ResponseBusiness(c, h)
......
...@@ -102,6 +102,12 @@ func LoggerHandle(c *gin.Context) { ...@@ -102,6 +102,12 @@ func LoggerHandle(c *gin.Context) {
c.Set(mycontext.APP_VERSION, appVersion) c.Set(mycontext.APP_VERSION, appVersion)
c.Set(mycontext.URL, reqUri) c.Set(mycontext.URL, reqUri)
c.Set(mycontext.METHOD, method) c.Set(mycontext.METHOD, method)
lang := header.Get(mycontext.LANGUAGE)
c.Set(mycontext.LANGUAGE, lang)
carrier := header.Get(mycontext.CARRIER)
c.Set(mycontext.CARRIER, carrier)
timezone := header.Get(mycontext.TIMEZONE)
c.Set(mycontext.TIMEZONE, timezone)
userId, _ := req.GetUserId(c) userId, _ := req.GetUserId(c)
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
_ "hilo-user/docs" _ "hilo-user/docs"
"hilo-user/domain/model/msg_m" "hilo-user/domain/model/msg_m"
"hilo-user/resp" "hilo-user/resp"
"hilo-user/route/cp_r"
"hilo-user/route/user_r" "hilo-user/route/user_r"
) )
...@@ -22,17 +23,36 @@ func InitRouter() *gin.Engine { ...@@ -22,17 +23,36 @@ func InitRouter() *gin.Engine {
needLogin := r.Group("") needLogin := r.Group("")
needLogin.Use(ExceptionHandle, LoggerHandle, JWTApiHandle) needLogin.Use(ExceptionHandle, LoggerHandle, JWTApiHandle)
v1 := needLogin.Group("/v1") v1 := needLogin.Group("/v1")
v2 := needLogin.Group("/v2")
user := v1.Group("/user") user := v1.Group("/user")
{ {
user.GET("/nameplate", wrapper(user_r.UserNameplate)) user.GET("/nameplate", wrapper(user_r.UserNameplate))
user.GET("/bag/:resType", wrapper(user_r.UserBag)) user.GET("/bag/:resType", wrapper(user_r.UserBag))
} }
cp := v2.Group("/cp")
{
cp.GET("/space", wrapper(cp_r.CpSpace))
cp.PUT("/privilege/openClose", wrapper(cp_r.CpPrivilegeOpenClose))
cp.GET("/rank/:queryType", wrapper(cp_r.CpRank))
cp.GET("/my/:queryType", wrapper(cp_r.CpMy))
cp.GET("/achievement", wrapper(cp_r.CpAchievement))
cp.GET("/top3", wrapper(cp_r.CpTop3))
cp.POST("/anniversary", wrapper(cp_r.PostAnniversary))
cp.PUT("/anniversary/:id", wrapper(cp_r.PutAnniversary))
cp.GET("/anniversary", wrapper(cp_r.PageAnniversary))
cp.DELETE("/anniversary/:id", wrapper(cp_r.DelAnniversary))
}
inner := r.Group("/inner") inner := r.Group("/inner")
inner.Use(ExceptionHandle, LoggerHandle) inner.Use(ExceptionHandle, LoggerHandle)
innerUser := inner.Group("/user") innerUser := inner.Group("/user")
{ {
innerUser.GET("/levels", wrapper(user_r.MGetUserLevels)) innerUser.GET("/levels", wrapper(user_r.MGetUserLevels))
innerUser.GET("/bag/id", wrapper(user_r.GetUserBagId)) innerUser.GET("/bag/id", wrapper(user_r.GetUserBagId))
innerUser.GET("/cp", wrapper(user_r.GetUserCp))
innerUser.GET("/cpRelation", wrapper(user_r.GetUserCpRelation))
innerUser.GET("/cpRelations", wrapper(user_r.MGetUserCpRelation))
innerUser.GET("/cp/pair", wrapper(user_r.GetUserCpPair))
} }
// 道具相关 // 道具相关
innerProp := inner.Group("/prop") innerProp := inner.Group("/prop")
......
...@@ -5,8 +5,11 @@ import ( ...@@ -5,8 +5,11 @@ import (
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/user_cv" "hilo-user/cv/user_cv"
"hilo-user/domain/model/bag_m" "hilo-user/domain/model/bag_m"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/noble_m" "hilo-user/domain/model/noble_m"
"hilo-user/domain/model/res_m" "hilo-user/domain/model/res_m"
"hilo-user/domain/model/user_m" "hilo-user/domain/model/user_m"
...@@ -90,3 +93,193 @@ func GetUserBagId(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -90,3 +93,193 @@ func GetUserBagId(c *gin.Context) (*mycontext.MyContext, error) {
}) })
return myCtx, nil return myCtx, nil
} }
type GetUserCpReq struct {
Id mysql.ID `form:"id" binding:"required"`
Language string `form:"language"`
}
// @Tags 用户-内部
// @Summary 获取用户cp
// @Param id query int true "用户id"
// @Param language query string true "语言"
// @Success 200 {object} cp_cv.CvCp
// @Router /inner/user/cp [get]
func GetUserCp(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myContext)
var req GetUserCpReq
if err := c.ShouldBindQuery(&req); err != nil {
return myContext, err
}
userId := req.Id
var response cp_cv.CvCp
cpLevel := cp_e.CpLevel0
cpRelation, exists := cp_m.GetCpRelation(model, userId)
if !exists {
resp.ResponseOk(c, response)
return myContext, nil
}
var myPrivilegeList []cp_cv.CvPrivilege
level := cp_m.GetCpLevel(model, cpRelation.ID)
if level.ExpireAt.Before(time.Now()) {
level.ExpireAt = time.Now().AddDate(0, 1, 0)
}
cpLevel = level.Level
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
userPrivileges, err := cp_m.MGetUserSvipPrivilege(model, []uint64{userId})
if err != nil {
return myContext, err
}
privilegeList := cp_cv.CopyCpLevelPrivilegeList(level.Level, "en")
for i, v := range privilegeList {
if v.CanSwitch {
privilegeList[i].UserSwitch = userPrivileges[userId][v.Type]
}
}
// 我的特权,有开关并且打开才返回
for i, v := range privilegeList {
if !v.CanSwitch {
myPrivilegeList = append(myPrivilegeList, privilegeList[i])
} else if v.UserSwitch {
myPrivilegeList = append(myPrivilegeList, privilegeList[i])
}
}
userBases, err := user_cv.GetUserBaseMap([]uint64{cpUserId}, userId)
if err != nil {
return myContext, err
}
// 返回值
title := ""
if msgId, ok := cp_e.CpLevelTitle[level.Level]; ok {
title = cp_cv.GetTranslate(msgId, req.Language)
}
response = cp_cv.CvCp{
CpUserInfo: userBases[cpUserId],
CpLevel: cp_cv.CvCpLevel{
Level: cpLevel,
Points: cp_e.CpLevelPoints[cpLevel] + level.Points,
Title: title,
},
MyPrivilegeList: myPrivilegeList,
}
resp.ResponseOk(c, response)
return myContext, nil
}
// @Tags 用户-内部
// @Summary 获取用户cp关系
// @Param id query int true "用户id"
// @Success 200 {object} cp_cv.CvCpRelation
// @Router /inner/user/cpRelation [get]
func GetUserCpRelation(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myContext)
var req GetUserCpReq
if err := c.ShouldBindQuery(&req); err != nil {
return myContext, err
}
userId := req.Id
var response cp_cv.CvCpRelation
cpRelation, exists := cp_m.GetCpRelation(model, userId)
if !exists {
resp.ResponseOk(c, response)
return myContext, nil
}
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
cpUser, _ := user_m.GetUser(model, cpUserId)
response = cp_cv.CvCpRelation{
CpId: cpRelation.ID,
UserId: userId,
CpUserId: cpUserId,
CpUserAvatar: cpUser.Avatar,
}
resp.ResponseOk(c, response)
return myContext, nil
}
type MGetUserCpRelationReq struct {
Ids []mysql.ID `form:"ids" binding:"required"`
}
// @Tags 用户-内部
// @Summary 批量获取用户cp关系
// @Param ids query int true "用户ids"
// @Success 200 {object} map[uint64]cp_cv.CvCpRelation
// @Router /inner/user/cpRelations [get]
func MGetUserCpRelation(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myContext)
var req MGetUserCpRelationReq
if err := c.ShouldBindQuery(&req); err != nil {
return myContext, err
}
cpRelations := cp_m.MGetCpRelation(model, req.Ids)
var m = make(map[uint64]cp_m.CpRelationTmp)
var userIds []uint64
for i, v := range cpRelations {
m[v.UserId1] = cpRelations[i]
m[v.UserId2] = cpRelations[i]
userIds = append(userIds, v.UserId1)
userIds = append(userIds, v.UserId2)
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
return myContext, err
}
var response = make(map[uint64]cp_cv.CvCpRelation)
for _, uid := range req.Ids {
if cpRelation, ok := m[uid]; ok {
cpUserId := cpRelation.UserId2
if cpUserId == uid {
cpUserId = cpRelation.UserId1
}
response[uid] = cp_cv.CvCpRelation{
CpId: cpRelation.ID,
UserId: uid,
CpUserId: cpUserId,
CpUserAvatar: users[cpUserId].Avatar,
}
}
}
resp.ResponseOk(c, response)
return myContext, nil
}
type GetUserCpPairReq struct {
Ids []mysql.ID `form:"ids" binding:"required"`
}
// @Tags 用户-内部
// @Summary 给出指定uids下的cp对
// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3"
// @Success 200 {object} [][]uint64
// @Router /inner/user/cp/pair [get]
func GetUserCpPair(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myContext)
var req GetUserCpPairReq
if err := c.ShouldBindQuery(&req); err != nil {
return myContext, err
}
userIds := req.Ids
m := make(map[mysql.ID]bool)
for _, uid := range userIds {
m[uid] = true
}
pairs := cp_m.MGetCpRelation(model, userIds)
var response [][2]uint64
for _, pair := range pairs {
if m[pair.UserId1] && m[pair.UserId2] {
response = append(response, [2]mysql.ID{pair.UserId1, pair.UserId2})
}
}
resp.ResponseOk(c, response)
return myContext, nil
}