From 3566534b4cb9a2991e9b297940fd9f800a9f296d Mon Sep 17 00:00:00 2001 From: hujiebin Date: Mon, 20 Mar 2023 10:20:17 +0800 Subject: [PATCH] Feature/3.5 --- _const/enum/country_e/enum.go | 2 +- _const/enum/groupPower_e/enum.go | 11 + _const/enum/groupPower_e/grade.go | 34 + _const/enum/groupPower_e/star.go | 16 + _const/enum/msg_e/msg.go | 2 + common/constDef.go | 208 +++++ common/utils.go | 42 + common/utime/utime.go | 70 ++ cron/cron.go | 8 +- cron/group_cron/group_power_exp.go | 37 + cron/mic_cron/on_mic.go | 45 ++ cv/group_cv/group.go | 214 ++++- cv/group_power_cv/groupPower.go | 74 +- cv/group_power_cv/group_rank.go | 114 +++ cv/user_cv/user.go | 56 +- domain/cache/user_c/user.go | 97 ++- .../group_power_ev/groupPowerExpireNotice.go | 26 + .../event/group_power_ev/groupPowerUpgrade.go | 28 + domain/event/mic_ev/on_mic.go | 29 + domain/model/diamond_m/dealer.go | 211 +++++ domain/model/groupPower_m/family.go | 159 ++++ domain/model/groupPower_m/groupPower.go | 110 ++- domain/model/groupPower_m/group_grade.go | 323 ++++++++ domain/model/groupPower_m/group_info.go | 69 ++ .../model/groupPower_m/group_power_apply.go | 82 ++ .../model/groupPower_m/group_power_invite.go | 50 ++ domain/model/groupPower_m/group_rank.go | 27 + domain/model/groupPower_m/group_star.go | 90 +++ domain/model/group_m/groupInfo.go | 42 +- domain/model/mic_m/mic.go | 86 ++ domain/model/user_m/user.go | 9 + domain/service/diamond_s/diamond.go | 64 ++ domain/service/event_s/event_init.go | 139 +++- domain/service/event_s/send_gift.go | 2 +- domain/service/group_mic_s/group_mic.go | 37 + go.mod | 15 +- go.sum | 65 +- local.ini | 8 +- myerr/bizerr/bizCode.go | 26 +- mysql/3.5.0.sql | 45 ++ route/charge_r/charge.go | 41 + route/group_power_r/group_power.go | 752 +++++++++++++++++- route/group_power_r/group_rank.go | 232 ++++++ route/group_power_r/inner.go | 93 +++ route/group_r/group_info.go | 17 +- route/group_r/group_list.go | 49 +- route/group_r/group_mic.go | 4 +- route/group_r/group_support.go | 4 +- route/mic_r/inner.go | 37 + route/router.go | 35 + test/.env | 1 + test/group_power_test.go | 12 + test/local.ini | 171 ++++ 53 files changed, 4074 insertions(+), 146 deletions(-) create mode 100644 _const/enum/groupPower_e/grade.go create mode 100644 _const/enum/groupPower_e/star.go create mode 100644 common/constDef.go create mode 100755 common/utils.go create mode 100644 common/utime/utime.go create mode 100644 cron/group_cron/group_power_exp.go create mode 100644 cron/mic_cron/on_mic.go create mode 100644 cv/group_power_cv/group_rank.go create mode 100644 domain/event/group_power_ev/groupPowerExpireNotice.go create mode 100644 domain/event/group_power_ev/groupPowerUpgrade.go create mode 100644 domain/event/mic_ev/on_mic.go create mode 100644 domain/model/diamond_m/dealer.go create mode 100644 domain/model/groupPower_m/family.go create mode 100644 domain/model/groupPower_m/group_grade.go create mode 100644 domain/model/groupPower_m/group_info.go create mode 100644 domain/model/groupPower_m/group_power_apply.go create mode 100644 domain/model/groupPower_m/group_power_invite.go create mode 100644 domain/model/groupPower_m/group_rank.go create mode 100644 domain/model/groupPower_m/group_star.go create mode 100644 domain/model/mic_m/mic.go create mode 100644 domain/service/diamond_s/diamond.go create mode 100644 mysql/3.5.0.sql create mode 100644 route/charge_r/charge.go create mode 100644 route/group_power_r/group_rank.go create mode 100644 route/group_power_r/inner.go create mode 100644 route/mic_r/inner.go create mode 100644 test/.env create mode 100644 test/group_power_test.go create mode 100644 test/local.ini diff --git a/_const/enum/country_e/enum.go b/_const/enum/country_e/enum.go index 1f09c39..b7ed2b9 100644 --- a/_const/enum/country_e/enum.go +++ b/_const/enum/country_e/enum.go @@ -3,7 +3,7 @@ package country_e import "git.hilo.cn/hilo-common/resource/mysql" // 国家角色 -type CountryMgrRole mysql.Type +type CountryMgrRole uint8 const ( // 国家管理员 diff --git a/_const/enum/groupPower_e/enum.go b/_const/enum/groupPower_e/enum.go index d074370..a9e4a84 100644 --- a/_const/enum/groupPower_e/enum.go +++ b/_const/enum/groupPower_e/enum.go @@ -22,6 +22,17 @@ const ( GroupPowerUserRoleUser GroupPowerUserRole = 1 //势力主 GroupPowerUserRoleMgr GroupPowerUserRole = 2 + //势力管理员 + GroupPowerUserRoleAdmin GroupPowerUserRole = 3 +) + +//国家势力排行榜类型 +type GroupPowerRankType = mysql.Type + +const ( + GroupPowerRankTypeFamous GroupPowerRankType = 1 + GroupPowerRankTypeActive GroupPowerRankType = 2 + GroupPowerRankTypeCharm GroupPowerRankType = 3 ) //国家势力日志操作类型 diff --git a/_const/enum/groupPower_e/grade.go b/_const/enum/groupPower_e/grade.go new file mode 100644 index 0000000..9879b25 --- /dev/null +++ b/_const/enum/groupPower_e/grade.go @@ -0,0 +1,34 @@ +package groupPower_e + +import "git.hilo.cn/hilo-common/resource/mysql" + +type GroupPowerGrade int + +const ( + GroupPowerGrade0 GroupPowerGrade = 0 // 青铜 + GroupPowerGrade1 GroupPowerGrade = 1 // 白银 + GroupPowerGrade2 GroupPowerGrade = 2 // 黄金 + GroupPowerGrade3 GroupPowerGrade = 3 // 黑金 + + GroupPowerGradeMax = GroupPowerGrade3 +) + +var ( + GroupPowerGradeExp = map[GroupPowerGrade]mysql.Num{ + GroupPowerGrade0: 0, + GroupPowerGrade1: 2500000, + GroupPowerGrade2: 15000000, + GroupPowerGrade3: 60000000, + } +) + +type GroupPowerPrivilege int + +const ( + GroupPowerPrivilegeMemberNum GroupPowerPrivilege = 1 // 成员数 + GroupPowerPrivilegeMgrNum GroupPowerPrivilege = 2 // 管理员数 + GroupPowerPrivilegeNameplate GroupPowerPrivilege = 3 // 家族铭牌 + GroupPowerPrivilegeMedal GroupPowerPrivilege = 4 // 家族徽章装饰 + GroupPowerPrivilegeNameplateEdit GroupPowerPrivilege = 5 // 编辑铭牌 + GroupPowerPrivilegeNameplateHeadwear GroupPowerPrivilege = 6 // 家族头饰 +) diff --git a/_const/enum/groupPower_e/star.go b/_const/enum/groupPower_e/star.go new file mode 100644 index 0000000..09f4c07 --- /dev/null +++ b/_const/enum/groupPower_e/star.go @@ -0,0 +1,16 @@ +package groupPower_e + +type GroupPowerStarType int + +const ( + GroupPowerStarTypeFamous GroupPowerStarType = 1 // 送礼 + GroupPowerStarTypeActive GroupPowerStarType = 2 // 活跃 + GroupPowerStarTypeCharm GroupPowerStarType = 3 // 收礼 +) + +func IsGroupPowerStarType(t GroupPowerStarType) bool { + if t != GroupPowerStarTypeFamous && t != GroupPowerStarTypeActive && t != GroupPowerStarTypeCharm { + return false + } + return true +} diff --git a/_const/enum/msg_e/msg.go b/_const/enum/msg_e/msg.go index a6ed59d..02b9f55 100644 --- a/_const/enum/msg_e/msg.go +++ b/_const/enum/msg_e/msg.go @@ -131,6 +131,8 @@ const ( NewUserRegisterPush2 = 45 // 邀请朋友来Hilo,最高获得100,000钻石奖励! NewUserRegisterPush3 = 46 // 举办首个活动,领取10,000钻石和35%奖杯奖励! ActFruitPutRankAward = 47 // 水果机投入排行榜提醒领奖 + GroupPowerUpgrade = 48 // 家族升级 + GroupPowerExpireNotice = 49 // 家族等级即将过期(每月20日) ) type MsgSysUserType = mysql.Type diff --git a/common/constDef.go b/common/constDef.go new file mode 100644 index 0000000..c487484 --- /dev/null +++ b/common/constDef.go @@ -0,0 +1,208 @@ +package common + +type MsgIdType = uint +type OnlineStatusType = uint +type GroupRoleType = uint16 +type AddGroupResultType = uint + +const ( + APP_KICKOFF_TIME = "2020-12-19" + + DEFAULT_LANG = "en" + DEFAULT_COUNTRY = "KSA" + DEFAULT_NICK = "Hilo No.%s" + DEFAULT_DESCRIPTION = "Welcome to Hilo" + DEFAULT_GROUP_NAME = "Hilo Group NO.%s" + + DefaultAvatarMan = "hilo/manager/ea48b62d54a24a709de3c38702c89995.png" + DefaultAvatarWoman = "hilo/manager/ea48b62d54a24a709de3c38702c89995.png" + // 用户视频最低要求时长 + BASIC_VIDEO_TIME = 1 + + // 公会用户视频最低要求时长 + GUILD_USER_VIDEO_TIME = 15 + + STATUS_IN_USE = 1 + STATUS_UNUSED = 2 + + // 公会用户是否打开通知 + GuildUserNotifyOn = 1 + GuildUserNotifyOff = 2 + + // 平台 + PlatformIOS = 1 + PlatformGOOGLE = 2 + PlatformEggPlant = 3 // 通过starchat回调的茄子充值 + PlatformCheckout = 4 + + // 加、减 + DIRECTION_ADD = 1 + DIRECTION_REDUCE = 2 + + // 操作类型 + //发送礼物 + OPERATE_TYPE_SENDGIFT = 1 + //匹配条件 + OPERATE_TYPE_MATCHCONDITION = 2 + //建立融云会话 + OPERATE_TYPE_SESSIONPAY = 3 + //购买钻石 + OPERATE_TYPE_BUYDIAMOND = 4 + //接受礼物 + OPERATE_TYPE_RECEIVEGIFT = 5 + //注册 + OPERATE_TYPE_REGISTER = 6 + //平台赠送 + OPERATE_TYPE_MGRSEND = 8 + + MATCH_CONFIRM_SUCCESS = 1 + MATCH_CONFIRM_FAIL = 2 + MATCH_CONFIRM_TEMP = 3 + + ACCEPT_MATCH_CONFIRM = 1 + REFUSE_MATCH_CONFIRM = 2 + + // 视频通话是否达标 + VIDEO_EFFECTIVE_YES = 1 + VIDEO_EFFECTIVE_NO = 2 + + // 最大用户相册数 + USER_PHOTO_MAX = 9 + + // 上下架状态 + SWITCH_ON = 1 + SWITH_OFF = 0 + + // 群组角色 + GROUP_VISITOR GroupRoleType = 0 // 游客 + GROUP_MEMBER GroupRoleType = 1 // 成员 + GROUP_ADMIN GroupRoleType = 10 // 管理员 + GROUP_MANAGER GroupRoleType = 50 // 经理 + GROUP_OWNER GroupRoleType = 100 // owner + + ROOM_PASSWORD_LENGTH = 4 + CREATE_GROUP_MAX_ATTEMPT = 10 + + // 在线状态 + IM_STATUS_OFF_LINE OnlineStatusType = 0 + IM_STATUS_PUSH_ON_LINE OnlineStatusType = 1 + IM_STATUS_ON_LINE OnlineStatusType = 2 + + MSG_ID_GROUP_NAME MsgIdType = 101 + MSG_ID_GROUP_INTRODUCTION MsgIdType = 102 + MSG_ID_GROUP_NOTIFICATION MsgIdType = 103 + MSG_ID_GROUP_WELCOME MsgIdType = 104 + MSG_ID_GROUP_INVITE MsgIdType = 105 + MSG_ID_GROUP_LEAVE_POWER MsgIdType = 106 + MSG_ID_ALL_GROUP_ROCKET MsgIdType = 107 + MSG_ID_ROOM_MEADAL MsgIdType = 108 + MSG_ID_VIDEO_PUSH_TITITLE MsgIdType = 109 + MSG_ID_VIDEO_PUSH_CONTENT MsgIdType = 110 + MSG_ID_REPEAT_ACCOUNT MsgIdType = 111 + MSG_ID_USER_TRANSFER MsgIdType = 114 + MSG_ID_NO_POWER_TO_SVIP6 MsgIdType = 115 // 不能对svip6做某些动作 + // ps:116-138 在hilo-finance定义了! + MSG_ID_NOT_FAMILY_MEMBER MsgIdType = 165 // 非家族成员 + MSG_ID_DEALER_CAN_NOT_SOLE MsgIdType = 166 // 此用户已有家族代理,不能出售钻石 + MSG_ID_BUY_FROM_FAMILY MsgIdType = 167 // 请向本家族代理购买钻石 + MSG_ID_NEED_JOIN_FAMILY MsgIdType = 168 // 请加入代理的家族后进行购买 + + ADD_GROUP_FAILED AddGroupResultType = 0 + ADD_GROUP_DONE AddGroupResultType = 1 + ADD_GROUP_DUPLICATE AddGroupResultType = 2 + ADD_GROUP_PENDING AddGroupResultType = 3 + + SETTING_OFFICIAL = 1 + SETTING_CUSTOMIZED = 2 +) + +var USER_QPS_DEFAULT_MAX int64 = 15 +var HEART_VALUE_MAX uint32 = 2000 +var BUILDBOARD_SMALL_SIZE = 30 +var BUILDBOARD_SIZE = 50 + +var GROUP_CREATE_LIMIT = 1 +var GROUP_NAME_LENGTH_LIMIT = 30 +var GROUP_INTRODUCTION_LENGTH_LIMIT = 500 +var GROUP_NOTIFICATION_LENGTH_LIMIT = 150 + +var MAX_BEAUTIFUL_CODE_LENGTH = 8 +var GROUP_DEFAULT_CODE_LENGTH uint16 = 8 +var GROUP_DEFAULT_JOIN_LIMIT uint = 200 +var GROUP_VIP_JOIN_LIMIT uint = 500 +var GROUP_NOBLE4_JOIN_LIMIT uint = 1000 + +var GROUP_MANAGER_LIMIT uint = 30 +var GROUP_ADMIN_LIMIT uint = 50 +var GROUP_ROLE_VIEW_LIMIT = 10 +var GROUP_ROLE_PERSONAL_VIEW_LIMIT = 5 + +var GROUP_RECOMMEND_SIZE = 5 + +var IM_INVALID_USER = "@TLS#NOT_FOUND" + +// TIM相关常量 +const ( + SYNC_TO_SENDER = 1 + NOSYNC_TO_SENDER = 2 + + TAG_PROFILE_IM_LEVEL = "Tag_Profile_IM_Level" + TAG_PROFILE_IM_NICK = "Tag_Profile_IM_Nick" + TAG_PROFILE_IM_IMAGE = "Tag_Profile_IM_Image" + TAG_PROFILE_IM_HILO = "Tag_Profile_Custom_Hilo" +) + +// 群组内游戏相关 +const ( + GROUP_DICE_NUM_DEFAULT = 5 + GROUP_DICE_NUM_MAX = 5 +) + +var PAY_TEST_USERS = []uint64{11, 21, 41, 71, 151, 251, 291, 881, 1041, 4411, 951, 24091} + +var ROCKET_STAGE_NUM uint16 = 3 +var ROCKET_STAGE_CHANGE_THRESHOLD = 10 +var ROCKET_SHOW_DURATION = 10 + +// RocketAwardType +const ( + ROCKET_AWARD_GUEST_DIAMOND = 0 // 观众分到小额钻石 + ROCKET_AWARD_PROPERTY = 1 // TOP6抽到的座驾 + ROCKET_AWARD_HEADDRESS = 2 // TOP6抽到的头饰 + ROCKET_AWARD_DIAMOND = 3 // TOP6抽到的钻石 +) + +const DefaultMinimalVersionAndroid = 100 +const DefaultMinimalVersionIOS = 100 + +const DefaultMsgParallelSize = 20 + +const OldGroupNamePrefix = "@TGS#" +const NewGroupNamePrefix = "HTGS#" +const OverseaGroupNamePrefix = NewGroupNamePrefix + "a" + +const ( + SendSmsCodeIpMaxHourTimes = 20 + SendSmsCodeImeiMaxHourTimes = 10 + SendSmsCodePhoneMaxHourTimes = 5 + SendSmsCodeUserMaxHourTimes = 3 + SendSmsCodeLen = 6 // 验证码长度 + SendSmsCodeMaxCheckTimes = 3 // 验证码最大校验次数 + SendSmsCodeNoUserIdMaxHourTimes = 1000 // 没有传userId调用发短信,5分钟最大次数 + + CallbackCheckoutPaySucceed = "payment_captured" // checkout回调支付成功 + + // ranking + RankingDay = "day" + RankingWeek = "week" + RankingMonth = "month" + RankingAll = "all" + // ranking module + RankingModulePinkDiamond = "pinkDiamond" + + // giftwall 礼物墙 + GiftWallInitNum = 15000 // 礼物墙初始化数量 + GiftWallInitOnceSetNum = 500 // 礼物墙初始化,一次插入的数量 + GiftWallStartReduceNum = 20000 // 礼物墙触发清理逻辑数量 + GiftWallReduceNum = 3000 // 礼物墙触发清理逻辑,清理的数量 +) diff --git a/common/utils.go b/common/utils.go new file mode 100755 index 0000000..d9c0237 --- /dev/null +++ b/common/utils.go @@ -0,0 +1,42 @@ +package common + +import ( + "git.hilo.cn/hilo-common/resource/config" + "strings" +) + +// 去除slice中的重复元素 +func UniqueSliceUInt64(sliceIn []uint64) []uint64 { + sliceOut := make([]uint64, 0, len(sliceIn)) + m := make(map[uint64]struct{}, len(sliceIn)) + for _, i := range sliceIn { + if _, ok := m[i]; !ok { + m[i] = struct{}{} + sliceOut = append(sliceOut, i) + } + } + return sliceOut +} + +// 补全url,区分处理oss和aws两种情况 +func MakeFullUrl(url string) string { + if strings.HasPrefix(url, config.GetConfigOss().OSS_CDN) || strings.HasPrefix(url, config.GetConfigAws().AWS_CDN) { + return url + } else if strings.HasPrefix(url, "nextvideo/") { + return config.GetConfigOss().OSS_CDN + url + } else if strings.HasPrefix(url, config.GetConfigAws().AWS_DIR) { + return config.GetConfigAws().AWS_CDN + url + } else { + return url + } +} + +func PageNext(total int64, pageIndex, pageSize int) (int, bool) { + var nextIdx int + var hasNext bool + if total >= int64(pageIndex+pageSize) { + hasNext = true + nextIdx = pageIndex + pageSize + } + return nextIdx, hasNext +} diff --git a/common/utime/utime.go b/common/utime/utime.go new file mode 100644 index 0000000..68a1676 --- /dev/null +++ b/common/utime/utime.go @@ -0,0 +1,70 @@ +package utime + +import ( + "github.com/jinzhu/now" + "time" +) + +const ( + Day = 86400 + Layout = "2006-01-02 15:04:05" + LayoutDay = "2006-01-02" + LayoutDay2 = "20060102" + LayoutMonth = "2006-01" + LayoutMinute = "2006-01-02 15:04" +) + +// 获取时间所在周的第一天(周一) 00:00:00,和最后一天(周日)23:59:59 +func WeekStartEnd(date time.Time) (start, end time.Time) { + w := 0 + week := date.Weekday() + if week == time.Sunday { + w = 7 + } else { + w = int(week) + } + startTmp := date.AddDate(0, 0, -w+1) + endTmp := date.AddDate(0, 0, 7-w) + + start = time.Date(startTmp.Year(), startTmp.Month(), startTmp.Day(), 0, 0, 0, 0, startTmp.Location()) + end = time.Date(endTmp.Year(), endTmp.Month(), endTmp.Day(), 23, 59, 59, 999, endTmp.Location()) + return +} + +// 当天开始结束 +func DayStartEnd(date time.Time) (start, end time.Time) { + start = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location()) + end = time.Date(date.Year(), date.Month(), date.Day(), 23, 59, 59, 999, date.Location()) + return +} + +// 获取时间所在月的第一天(1号) 00:00:00,和最后一天23:59:59 +func MonthStartEnd(date time.Time) (start, end time.Time) { + start = time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location()) + lastDay := now.New(start).EndOfMonth().Day() + end = time.Date(date.Year(), date.Month(), lastDay, 23, 59, 59, 999999999, date.Location()) + return +} + +// 增加年/月 +// 因为golang原生的Time.AddDate增加月份的时候有bug +func AddDate(t time.Time, years int, months int) time.Time { + year, month, day := t.Date() + hour, min, sec := t.Clock() + + // firstDayOfMonthAfterAddDate: years 年,months 月后的 那个月份的1号 + firstDayOfMonthAfterAddDate := time.Date(year+years, month+time.Month(months), 1, + hour, min, sec, t.Nanosecond(), t.Location()) + // firstDayOfMonthAfterAddDate 月份的最后一天 + lastDay := now.New(firstDayOfMonthAfterAddDate).EndOfMonth().Day() + + // 如果 t 的天 > lastDay,则设置为lastDay + // 如:t 为 2020-03-31 12:00:00 +0800,增加1个月,为4月31号 + // 但是4月没有31号,则设置为4月最后一天lastDay(30号) + if day > lastDay { + day = lastDay + } + + return time.Date(year+years, month+time.Month(months), day, + hour, min, sec, t.Nanosecond(), t.Location()) +} diff --git a/cron/cron.go b/cron/cron.go index c739d21..9fd7f65 100644 --- a/cron/cron.go +++ b/cron/cron.go @@ -3,12 +3,16 @@ package cron import ( "git.hilo.cn/hilo-common/resource/config" "hilo-group/cron/gift_cron" + "hilo-group/cron/group_cron" + "hilo-group/cron/mic_cron" ) func Init() { if !config.IsMaster() { return } - gift_cron.SendGiftEventInit() // 礼物消息 - gift_cron.GiftRemark() // 礼物消息补偿 + gift_cron.SendGiftEventInit() // 礼物消息 + gift_cron.GiftRemark() // 礼物消息补偿 + mic_cron.OnMicCheck() // 检查上麦 + group_cron.GroupPowerExpClear() // 清理家族经验/等级 } diff --git a/cron/group_cron/group_power_exp.go b/cron/group_cron/group_power_exp.go new file mode 100644 index 0000000..b0b7070 --- /dev/null +++ b/cron/group_cron/group_power_exp.go @@ -0,0 +1,37 @@ +package group_cron + +import ( + "git.hilo.cn/hilo-common/domain" + "github.com/robfig/cron" + "hilo-group/domain/event/group_power_ev" + "hilo-group/domain/model/groupPower_m" +) + +// 清理家族经验和等级 +func GroupPowerExpClear() { + c := cron.New() + // 每月1号0:00经验值清零 + spec := "0 0 0 1 * ?" + _ = c.AddFunc(spec, func() { + var model = domain.CreateModelNil() + if err := groupPower_m.ClearGroupPowerExp(model); err != nil { + model.Log.Errorf("ClearGroupPowerExp fail:%v", err) + } + }) + + // 每分钟清理过期家族等级 + spec = "0 * * * * ?" + _ = c.AddFunc(spec, func() { + var model = domain.CreateModelNil() + if err := groupPower_m.ClearGroupPowerGrade(model); err != nil { + model.Log.Errorf("ClearGroupPowerGrade fail:%v", err) + } + }) + // 每月20号发家族即将过期通知 + spec = "0 0 0 20 * ?" + _ = c.AddFunc(spec, func() { + var model = domain.CreateModelNil() + _ = group_power_ev.PublishGroupPowerExpireNotice(model, &group_power_ev.GroupPowerExpireNoticeEvent{}) + }) + c.Start() +} diff --git a/cron/mic_cron/on_mic.go b/cron/mic_cron/on_mic.go new file mode 100644 index 0000000..4e2127c --- /dev/null +++ b/cron/mic_cron/on_mic.go @@ -0,0 +1,45 @@ +package mic_cron + +import ( + "git.hilo.cn/hilo-common/domain" + "github.com/robfig/cron" + "hilo-group/domain/event/mic_ev" + "hilo-group/domain/model/group_m" +) + +func OnMicCheck() { + c := cron.New() + //一分钟执行一次 + spec := "0 */1 * * * ?" + _ = c.AddFunc(spec, func() { + //获取麦上的所有人 + var model = domain.CreateModelNil() + groupIds, err := group_m.GetMicHasInGroups() + if err != nil { + model.Log.Errorf("cron micIn GetMicHasInGroups err:%v", err) + return + } + for _, groupId := range groupIds { + //遍历每个麦位 + for i := 1; i <= 30; i++ { + micUser, err := group_m.GetMicUser(model, groupId, i) + if err != nil { + model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err) + } + if micUser != nil { + if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{ + GroupUuid: micUser.GroupUuid, + I: micUser.I, + ExternalId: micUser.ExternalId, + UserId: micUser.UserId, + Forbid: micUser.Forbid, + Timestamp: micUser.Timestamp, + }); err != nil { + model.Log.Errorf("PublishOnMicEvent fail:%v", err) + } + } + } + } + }) + c.Start() +} diff --git a/cv/group_cv/group.go b/cv/group_cv/group.go index b5b2035..354320b 100644 --- a/cv/group_cv/group.go +++ b/cv/group_cv/group.go @@ -4,6 +4,7 @@ import ( "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/utils" "hilo-group/_const/enum/game_e" + "hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/online_e" "hilo-group/cv/billboard_cv" @@ -43,12 +44,12 @@ type GroupBasicInfo struct { //1:5人 2:10人 MicNumType int `json:"micNumType"` // N天内的进入用户数量(重复进入去重,实时) - GroupInUserDuration int64 `json:"groupInUserDuration"` - GroupMedals []medal_cv.PicElement `json:"groupMedals"` // 群勋章 - TouristMic uint8 `json:"touristMic"` // 游客是否能上麦 - TouristSendMsg uint8 `json:"touristSendMsg"` // 游客是否能发言 - TouristSendPic uint8 `json:"touristSendPic"` // 游客是否能发图片 - MemberFee uint64 `json:"memberFee"` // 加入群组会员需要的黄钻 + GroupInUserDuration int64 `json:"groupInUserDuration"` // 群热度 + GroupMedals []medal_cv.PicElement `json:"groupMedals"` // 群勋章 + TouristMic uint8 `json:"touristMic"` // 游客是否能上麦 + TouristSendMsg uint8 `json:"touristSendMsg"` // 游客是否能发言 + TouristSendPic uint8 `json:"touristSendPic"` // 游客是否能发图片 + MemberFee uint64 `json:"memberFee"` // 加入群组会员需要的黄钻 } type MemberListInfo struct { @@ -60,14 +61,23 @@ type MemberListInfo struct { // AppMemberDefinedData": [ // 群成员自定义字段 【暂时不用】 } +type GroupPower struct { + Id uint64 `json:"id"` // 群主所在的势力ID + Name string `json:"name"` // 群主所在的势力的名称 + Nameplate string `json:"nameplate"` // 势力铭牌 + Grade groupPower_e.GroupPowerGrade `json:"grade"` // 等级 +} + type GroupInfo struct { GroupBasicInfo // hilo业务 - EntryLevel uint32 `json:"entryLevel"` // obsolete - HasOnMic bool `json:"hasOnMic"` // 房间麦上是否有人 - GroupPowerId uint64 `json:"groupPowerId"` // 群主所在的势力ID - GroupPowerName string `json:"groupPowerName"` // 群主所在的势力的名称 + EntryLevel uint32 `json:"entryLevel"` // obsolete + HasOnMic bool `json:"hasOnMic"` // 房间麦上是否有人 + GroupPowerId uint64 `json:"groupPowerId"` // 群主所在的势力ID + GroupPowerName string `json:"groupPowerName"` // 群主所在的势力的名称 + GroupPowerNameplate string `json:"groupPowerNameplate"` // 势力铭牌 + GroupPower GroupPower `json:"groupPower"` // 势力信息 // "AppDefinedData": 群组维度的自定义字段 【暂时不用】 MemberList []MemberListInfo @@ -312,7 +322,7 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [ for _, i := range groupIds { owners = append(owners, groupInfo[i].Owner) } - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return nil, 0, err } @@ -388,9 +398,16 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [ MicNumType: int(g.MicNumType), GroupMedals: medals, }, - HasOnMic: len(micUsers) > 0, - GroupPowerId: powerIds[g.Owner], - GroupPowerName: powerNames[g.Owner], + HasOnMic: len(micUsers) > 0, + GroupPowerId: powerIds[g.Owner], + GroupPowerName: powerNames[g.Owner], + GroupPowerNameplate: powerNameplates[g.Owner], + GroupPower: GroupPower{ + Id: powerIds[g.Owner], + Name: powerNames[g.Owner], + Nameplate: powerNameplates[g.Owner], + Grade: powerGrades[g.Owner], + }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i]), @@ -404,6 +421,175 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [ return result, len(groupInfo), nil } +func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) { + groupIds := make([]string, 0, len(groupInfo)) + for _, v := range groupInfo { + groupIds = append(groupIds, v.ImGroupId) + } + + // roomMicUserMap不影响排序 + roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) + if err != nil { + return nil, err + } + uids := make([]uint64, 0) + micUsersMap := make(map[string][]uint64, 0) + for _, v := range groupInfo { + micUsersMap[v.ImGroupId] = make([]uint64, 0) + + if len(v.Password) <= 0 { + // 密码群不显示麦上头像 + u := roomMicUserMap[v.ImGroupId] + if len(u) >= 4 { + micUsersMap[v.ImGroupId] = u[0:4] + } else if len(u) > 0 { + micUsersMap[v.ImGroupId] = u + } + uids = append(uids, micUsersMap[v.ImGroupId]...) + } + } + + uids = utils.UniqueSliceUInt64(uids) + userTiny, err := user_cv.GetUserTinyMap(uids) + if err != nil { + return nil, err + } + roomCount, err := group_m.BatchGetRoomCount(model, groupIds) + if err != nil { + return nil, err + } + + countryInfo, err := res_c.GetCountryIconMap(model) + if err != nil { + return nil, err + } + + supportLevels, err := group_s.NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap() + if err != nil { + return nil, err + } + + visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds) + if err != nil { + return nil, err + } + + roomEnterTime, err := room_c.GetUserRoomVisit(myUserId) + if err != nil { + return nil, err + } + model.Log.Infof("BuildPopularGroupInfo, roomEnterTime: %v", roomEnterTime) + + // 排序优先级V8.0版本 + sort.Slice(groupIds, func(i, j int) bool { + gi := groupIds[i] + gj := groupIds[j] + return roomEnterTime[gi] > roomEnterTime[gj] || + roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] > visitCount[gj] || + roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] == visitCount[gj] && i >= j + }) + + result := make([]*PopularGroupInfo, 0) + owners := make([]uint64, 0) + for _, v := range groupInfo { + owners = append(owners, v.Owner) + } + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + if err != nil { + return nil, err + } + groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds) + if err != nil { + return nil, err + } + resMedal, err := res_m.MedalGetAllMap(model.Db) + if err != nil { + return nil, err + } + + rr := rocket_m.RocketResult{} + maxStageMap, err := rr.GetMaxStage(model.Db, groupIds) + if err != nil { + return nil, err + } + // 正在进行的游戏 + games := game_m.GetNotEndGamesMap(model) + + for _, v := range groupInfo { + g := v + i := v.ImGroupId + micUsers := make([]user_cv.CvUserTiny, 0) + for _, j := range micUsersMap[i] { + micUsers = append(micUsers, userTiny[j]) + } + + var maxStage *uint16 = nil + if s, ok := maxStageMap[i]; ok { + maxStage = &s + } + + medals := make([]medal_cv.PicElement, 0) + if m, ok := groupMedals[i]; ok { + for _, j := range m { + mId := uint32(j) + if e, ok := resMedal[mId]; ok { + medals = append(medals, medal_cv.PicElement{ + PicUrl: e.PicUrl, + }) + } + } + } + // 补上房间流水勋章 + var pe *medal_cv.PicElement + _, pe, err = medal_cv.GetGroupConsumeMedal(model, i) + if err != nil { + model.Log.Infof("BuildPopularGroupInfo: GetGroupConsumeMedal: %s", err.Error()) + } else if pe != nil { + medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl}) + } + + var password *string = nil + if len(g.Password) > 0 && g.Owner != myUserId { + emptyStr := "" + password = &emptyStr + } + + result = append(result, &PopularGroupInfo{ + GroupInfo: GroupInfo{ + GroupBasicInfo: GroupBasicInfo{ + GroupId: g.TxGroupId, + Name: g.Name, + Notification: g.Notification, + Introduction: g.Introduction, + FaceUrl: g.FaceUrl, + Code: g.Code, + CountryIcon: countryInfo[g.Country], + Password: password, + SupportLevel: supportLevels[i], + GroupInUserDuration: visitCount[i], + MicNumType: int(g.MicNumType), + GroupMedals: medals, + }, + HasOnMic: len(micUsers) > 0, + GroupPowerId: powerIds[g.Owner], + GroupPowerName: powerNames[g.Owner], + GroupPowerNameplate: powerNameplates[g.Owner], + GroupPower: GroupPower{ + Id: powerIds[g.Owner], + Name: powerNames[g.Owner], + Nameplate: powerNameplates[g.Owner], + Grade: powerGrades[g.Owner], + }, + }, + MicUsers: micUsers, + RoomUserCount: uint(roomCount[i]), + MaxStage: maxStage, + GameTypes: games[g.TxGroupId], + }) + } + return result, nil +} + //检查群组中是否有有人在麦上,返回存在的Set[imGroupId] func CheckMicHasUserByGroup(groupIds []string) (map[string]struct{}, error) { groupMap := map[string]struct{}{} diff --git a/cv/group_power_cv/groupPower.go b/cv/group_power_cv/groupPower.go index 6953f63..cf4996d 100644 --- a/cv/group_power_cv/groupPower.go +++ b/cv/group_power_cv/groupPower.go @@ -16,6 +16,7 @@ import ( "hilo-group/cv/user_cv" "hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/group_m" + "hilo-group/domain/model/user_m" "hilo-group/myerr" "sort" "strconv" @@ -232,28 +233,37 @@ func GetCvGroupPowerUsers(groupPowerId uint64) ([]mysql.ID, error) { return usreIds, nil } -func BatchGetGroupPower(db *gorm.DB, userIds []uint64) (map[uint64]uint64, map[uint64]string, error) { +// return userId->powerId userId->powerName userId->powerNameplate +func BatchGetGroupPower(db *gorm.DB, userIds []uint64) (map[uint64]uint64, map[uint64]string, map[uint64]string, map[uint64]groupPower_e.GroupPowerGrade, error) { if len(userIds) <= 0 { - return nil, nil, nil + return nil, nil, nil, nil, nil } groupPowers, err := groupPower_m.GetGroupPowerMap(db, userIds) if err != nil { - return nil, nil, err + return nil, nil, nil, nil, err } gpIds := make([]uint64, 0) for _, i := range groupPowers { gpIds = append(gpIds, i) } - powerNames, err := groupPower_m.GetGroupPowerNames(db, gpIds) + powerNames, powerNameplates, err := groupPower_m.GetGroupPowerNames(db, gpIds) if err != nil { - return nil, nil, err + return nil, nil, nil, nil, err + } + groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(domain.CreateModelNil(), gpIds) + if err != nil { + return nil, nil, nil, nil, err } groupPowerNames := make(map[mysql.ID]string, 0) + groupPowerNameplates := make(map[mysql.ID]string, 0) + groupPowerGrades := make(map[mysql.ID]groupPower_e.GroupPowerGrade, 0) for i, g := range groupPowers { groupPowerNames[i] = powerNames[g] + groupPowerNameplates[i] = powerNameplates[g] + groupPowerGrades[i] = groupPowerGrade[g].Grade } - return groupPowers, groupPowerNames, nil + return groupPowers, groupPowerNames, groupPowerNameplates, groupPowerGrades, nil } //获取国家势力的所有用户数量 @@ -639,3 +649,55 @@ func GetAllPowerDiamond(period string) (map[string]string, error) { key := redis_key.GetPrefixGroupPowerDiamond(period) return redisCli.GetRedis().HGetAll(context.Background(), key).Result() } + +type GroupPowerInfo struct { + Info *GroupPower `json:"info"` + Members []*GroupPowerUser `json:"members"` + Stars []*GroupPowerStar `json:"stars,omitempty"` +} + +type GroupPower struct { + Id uint64 `json:"id"` + Name string `json:"name"` + Nameplate string `json:"nameplate"` // 铭牌 + Declaration string `json:"declaration"` // 宣言 + Icon string `json:"icon"` // 头像 + Grade mysql.Num `json:"grade" gorm:"-"` // 等级 + Exp mysql.Num `json:"exp" gorm:"-"` // 当前经验值 + NextExp mysql.Num `json:"nextExp" gorm:"-"` // 升到下一级需要的经验值 + GradeName mysql.Str `json:"gradeName"` // 等级称号 + GradeMedal mysql.Str `json:"gradeMedal"` // 等级勋章图片 + MemberNum mysql.Num `json:"memberNum" gorm:"-"` // 当前人数 + MemberMax mysql.Num `json:"memberMax" gorm:"-"` // 最大人数 + Role int `json:"role" gorm:"-"` // 我在此家族中的角色 0.路人 1.成员 2.家族长 3.管理员 + IsApply bool `json:"isApply" gorm:"-"` // 最大人数 +} + +type GroupPowerUser struct { + User *user_m.UserTiny `json:"user"` + Role groupPower_e.GroupPowerUserRole `json:"role"` +} + +type GroupPowerStar struct { + User user_cv.CvUserTiny `json:"user"` + RankingType groupPower_e.GroupPowerRankType `json:"rankingType"` +} + +type FamilyMemberDetail struct { + User user_cv.CvUserExtend `json:"user"` + Role groupPower_e.GroupPowerUserRole `json:"role"` +} + +type FamilyApplyList struct { + User *user_m.UserTiny `json:"user"` + Time int64 `json:"time"` + Status int8 `json:"status"` // 0未操作,1已接受,2.已拒绝 + MgrName string `json:"mgrName"` // 管理员名称 +} + +type FamilyQuitList struct { + User *user_m.UserTiny `json:"user"` + Time int64 `json:"time"` + QuitType int8 `json:"quitType"` // 1.主动退出 2.被踢出 + MgrName string `json:"mgrName"` // 管理员名称 +} diff --git a/cv/group_power_cv/group_rank.go b/cv/group_power_cv/group_rank.go new file mode 100644 index 0000000..2432114 --- /dev/null +++ b/cv/group_power_cv/group_rank.go @@ -0,0 +1,114 @@ +package group_power_cv + +import ( + "hilo-group/_const/enum/groupPower_e" + "hilo-group/cv/user_cv" +) + +// 家族信息 +type CvGroupPowerInfo struct { + CvGroupPowerBase `json:",inline"` + CvGroupPowerMember `json:",inline"` + CvGroupPowerGrade `json:",inline"` +} + +// 家族基本信息 +type CvGroupPowerBase struct { + Id uint64 `json:"id"` // 家族id + Icon string `json:"icon"` // 家族图片 + Name string `json:"name"` // 家族名 + Nameplate string `json:"nameplate"` // 铭牌 +} + +// 家族成员 +type CvGroupPowerMember struct { + MemberNum uint32 `json:"memberNum"` // 当前成员数 + MemberMax uint32 `json:"memberMax"` // 成员上限 +} + +// 家族等级 +type CvGroupPowerGrade struct { + Grade groupPower_e.GroupPowerGrade `json:"grade"` // 等级 0:青铜 1:白银 2:黄金 3:黑金 + Exp uint32 `json:"exp"` // 经验值 + NextExp uint32 `json:"nextExp,omitempty"` // 下个等级所需经验值 + ExpireAt string `json:"expireAt,omitempty"` // 有效期 +} + +// 家族榜单 +type CvGroupPowerRank struct { + MyGroupPower *CvGroupPowerRankData `json:"myGroupPower,omitempty"` // 我的家族排名 + Items []CvGroupPowerRankData `json:"items"` // 列表 +} + +type CvGroupPowerRankData struct { + CvGroupPowerBase `json:",inline"` + CvGroupPowerGrade `json:",inline"` + Rank int `json:"rank"` // 排名 +} + +// 家族之星 +type CvGroupPowerStarData struct { + User user_cv.CvUserTiny `json:"user"` + Score uint32 `json:"score"` // 对应分值 +} + +// 资源等级 +type CvResGrade struct { + Grade groupPower_e.GroupPowerGrade `json:"grade"` // 等级 + Icon string `json:"icon"` // 等级icon + BigIcon string `json:"bigIcon"` // 等级大图标 +} + +// 特权信息 +type CvPrivilege struct { + Type groupPower_e.GroupPowerPrivilege `json:"type"` // 特权id 1:成员数 2:管理员数 3:家族铭牌 4:家族徽章装饰 5:编辑铭牌 6:家族头饰 + Num int `json:"num"` // 数目 +} + +// 家族等级页 +type CvGroupPowerGradeDetail struct { + GroupPowerBase CvGroupPowerBase `json:"groupPowerBase"` // 家族基本信息 + GroupPowerGrade CvGroupPowerGrade `json:"groupPowerGrade"` // 家族等级信息 + ResGradeList []CvResGrade `json:"resGradeList"` // 资源等级列表,青铜、白银、黄金、黑金 + PrivilegeList []CvPrivilege `json:"privilegeList"` // 等级特权 + IsMember bool `json:"isMember"` // 是否家族成员 +} + +var CvResGradeList = []CvResGrade{ + {groupPower_e.GroupPowerGrade0, "青铜icon", "青铜bigIcon"}, // todo + {groupPower_e.GroupPowerGrade1, "白银icon", "白银bigIcon"}, // todo + {groupPower_e.GroupPowerGrade2, "黄金icon", "黄金bigIcon"}, // todo + {groupPower_e.GroupPowerGrade3, "黑金icon", "黑金bigIcon"}, // todo +} + +var GroupPowerGradePrivilegeNum = map[groupPower_e.GroupPowerGrade][]CvPrivilege{ + groupPower_e.GroupPowerGrade0: { + {groupPower_e.GroupPowerPrivilegeMemberNum, 300}, + {groupPower_e.GroupPowerPrivilegeMgrNum, 10}, + {groupPower_e.GroupPowerPrivilegeNameplate, 1}, + {groupPower_e.GroupPowerPrivilegeMedal, 1}, + }, + groupPower_e.GroupPowerGrade1: { + {groupPower_e.GroupPowerPrivilegeMemberNum, 500}, + {groupPower_e.GroupPowerPrivilegeMgrNum, 15}, + {groupPower_e.GroupPowerPrivilegeNameplate, 1}, + {groupPower_e.GroupPowerPrivilegeMedal, 1}, + {groupPower_e.GroupPowerPrivilegeNameplateEdit, 1}, + }, + groupPower_e.GroupPowerGrade2: { + {groupPower_e.GroupPowerPrivilegeMemberNum, 800}, + {groupPower_e.GroupPowerPrivilegeMgrNum, 20}, + {groupPower_e.GroupPowerPrivilegeNameplate, 1}, + {groupPower_e.GroupPowerPrivilegeMedal, 1}, + {groupPower_e.GroupPowerPrivilegeNameplateEdit, 1}, + {groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1}, + }, + groupPower_e.GroupPowerGrade3: { + {groupPower_e.GroupPowerPrivilegeMemberNum, 1200}, + {groupPower_e.GroupPowerPrivilegeMgrNum, 25}, + {groupPower_e.GroupPowerPrivilegeNameplate, 1}, + {groupPower_e.GroupPowerPrivilegeMedal, 1}, + {groupPower_e.GroupPowerPrivilegeNameplateEdit, 1}, + {groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1}, + }, +} diff --git a/cv/user_cv/user.go b/cv/user_cv/user.go index 89d2c24..ec58c55 100644 --- a/cv/user_cv/user.go +++ b/cv/user_cv/user.go @@ -7,6 +7,7 @@ import ( "git.hilo.cn/hilo-common/rpc" . "git.hilo.cn/hilo-common/utils" "gorm.io/gorm" + "hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/user_e" "hilo-group/cv/country_cv" @@ -61,12 +62,20 @@ type CvUserDetail struct { CurrentRoom string `json:"currentRoom"` // 当前用户所在房间(产品叫“群组”) MyGroupPower uint64 `json:"myGroupPower"` // 当前用户所在势力 MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称 + GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息 GroupId string `json:"groupId"` // 当前用户拥有的群组id(产品叫“群组”),如果没有则为空,拥有多个,返回第一个 PhoneInfo *user_m.UserPhoneInfo `json:"phoneInfo"` // 用户绑定的手机信息 ThirdList []int8 `json:"thirdList"` // 用户绑定的第三方平台列表;类型 1:phone, 2:google, 3:facebook 4:apple 5:wechat" Enums(1,2,3,4,5) CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员 } +type GroupPower struct { + Id uint64 `json:"id"` // 群主所在的势力ID + Name string `json:"name"` // 群主所在的势力的名称 + Nameplate string `json:"nameplate"` // 势力铭牌 + Grade groupPower_e.GroupPowerGrade `json:"grade"` // 等级 +} + type CvUserTiny struct { Id uint64 `json:"id,omitempty"` ExternalId string `json:"externalId"` @@ -290,6 +299,7 @@ func getUserDetails(model *domain.Model, users []*user_m.User, myUserId mysql.ID } model.Log.Infof("getUserDetails: %+v", rooms) + // userId->groupPowerId groupPowers, err := groupPower_m.GetGroupPowerMap(mysql.Db, userIds) if err != nil { return nil, err @@ -299,13 +309,25 @@ func getUserDetails(model *domain.Model, users []*user_m.User, myUserId mysql.ID for _, i := range groupPowers { gpIds = append(gpIds, i) } - powerNames, err := groupPower_m.GetGroupPowerNames(mysql.Db, gpIds) + powerNames, _, err := groupPower_m.GetGroupPowerNames(mysql.Db, gpIds) + if err != nil { + return nil, err + } + groupPowerInfoMap, err := groupPower_m.MGetGroupPowerInfoMap(model, gpIds) + if err != nil { + return nil, err + } + groupPowerGradeMap, err := groupPower_m.MGetGroupPowerGrade(model, gpIds) if err != nil { return nil, err } groupPowerNames := make(map[mysql.ID]string, 0) - for i, g := range groupPowers { - groupPowerNames[i] = powerNames[g] + groupPowerInfos := make(map[mysql.ID]groupPower_m.GroupPowerInfo) + groupPowerGrades := make(map[mysql.ID]groupPower_m.GroupPowerGrade) + for uid, gid := range groupPowers { + groupPowerNames[uid] = powerNames[gid] + groupPowerInfos[uid] = groupPowerInfoMap[gid] + groupPowerGrades[uid] = groupPowerGradeMap[gid] } up := user_m.UserProperty{} @@ -350,7 +372,7 @@ func getUserDetails(model *domain.Model, users []*user_m.User, myUserId mysql.ID cvUserDetail, err := userToDetail(users[i], myUserId, userTradeUnion, likeMap, likeMeMap, rels, vips[users[i].ID] != nil, vips[users[i].ID], svips[users[i].ID], headwear, ride, - wealthGradeMap, charmGradeMap, activeGradeMap, medals, medalInfo, rooms, groupPowers, groupPowerNames, nobles, superManagerMap) + wealthGradeMap, charmGradeMap, activeGradeMap, medals, medalInfo, rooms, groupPowers, groupPowerNames, groupPowerInfos, groupPowerGrades, nobles, superManagerMap) if err != nil { return nil, err } @@ -370,7 +392,7 @@ func userToDetail(user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.U likeMeMap map[mysql.ID]bool, hvMap map[mysql.ID]Relation, isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGradeMap map[mysql.ID]uint32, charmGradeMap map[mysql.ID]uint32, actityGradeMap map[mysql.ID]uint32, medals map[uint64][]uint32, medalInfo map[uint64][]medal_cv.CvMedal, rooms map[mysql.ID]string, - powers map[mysql.ID]uint64, powerNames map[mysql.ID]string, nobles map[mysql.ID]noble_m.UserNoble, superManagerMap map[uint64]bool) (*CvUserDetail, error) { + powers map[mysql.ID]uint64, powerNames map[mysql.ID]string, groupPowerInfos map[mysql.ID]groupPower_m.GroupPowerInfo, powerGrades map[mysql.ID]groupPower_m.GroupPowerGrade, nobles map[mysql.ID]noble_m.UserNoble, superManagerMap map[uint64]bool) (*CvUserDetail, error) { cvUserDetail := &CvUserDetail{ CvUserBase: CvUserBase{ Id: &user.ID, @@ -510,6 +532,12 @@ func userToDetail(user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.U cvUserDetail.CurrentRoom = rooms[user.ID] cvUserDetail.MyGroupPower = powers[user.ID] cvUserDetail.MyGroupPowerName = powerNames[user.ID] + cvUserDetail.GroupPower = GroupPower{ + Id: groupPowerInfos[user.ID].ID, + Name: groupPowerInfos[user.ID].Name, + Nameplate: groupPowerInfos[user.ID].Nameplate, + Grade: powerGrades[user.ID].Grade, + } if n, ok := nobles[user.ID]; ok && n.Level > 0 { cvUserDetail.Noble = noble_cv.CvNoble{ Level: n.Level, @@ -670,6 +698,8 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv } powers := map[mysql.ID]uint64{userId: groupPowerId} powerNames := map[mysql.ID]string{userId: groupPowerName} + groupPowerInfos, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId}) + groupPowerGrades, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId}) up := user_m.UserProperty{} rides, err := up.BatchGet(mysql.Db, []uint64{userId}) @@ -759,14 +789,14 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv return userToDetailOne(model, &user, myUserId, userTradeUnion, likeN > 0, likeMe > 0, rel, isVip, expireTime, svip, headwear, ride, wealthUserScore.Grade, charmUserScore.Grade, - activityUserScore.Grade, medals[userId], medalInfo[userId], rooms[userId], powers[userId], powerNames[userId], + activityUserScore.Grade, medals[userId], medalInfo[userId], rooms[userId], powers[userId], powerNames[userId], groupPowerInfos[groupPowerId].Nameplate, groupPowerGrades[groupPowerId], noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager) } // 单用户版,简化参数 func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]Relation, isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32, - medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, noble *noble_m.UserNoble, isOfficialStaff bool, + medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, powerNameplate string, grade groupPower_m.GroupPowerGrade, noble *noble_m.UserNoble, isOfficialStaff bool, myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) { room, err := group_m.ToTxGroupId(model, room) @@ -806,9 +836,15 @@ func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, CurrentRoom: room, MyGroupPower: power, MyGroupPowerName: powerName, - PhoneInfo: phoneInfo, - ThirdList: thirdList, - CountryManager: countryManager, + GroupPower: GroupPower{ + Id: power, + Name: powerName, + Nameplate: powerNameplate, + Grade: grade.Grade, + }, + PhoneInfo: phoneInfo, + ThirdList: thirdList, + CountryManager: countryManager, } if noble != nil { cvUserDetail.Noble = noble_cv.CvNoble{ diff --git a/domain/cache/user_c/user.go b/domain/cache/user_c/user.go index 0d784a1..6ffd2b3 100644 --- a/domain/cache/user_c/user.go +++ b/domain/cache/user_c/user.go @@ -6,10 +6,12 @@ import ( redisV8 "github.com/go-redis/redis/v8" "github.com/jinzhu/copier" "hilo-group/_const/redis_key/user_k" + "hilo-group/common" "hilo-group/domain/cache" "hilo-group/domain/model/user_m" "hilo-group/myerr" "hilo-group/myerr/bizerr" + "time" ) // 获取用户简要信息 @@ -96,10 +98,11 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) { // 顺手缓存code->userId // param user: 已经在上层获取的db User结构 func cacheUserTiny(model *domain.Model, user *user_m.User) error { - userTiny := new(user_m.UserTiny) - if err := copier.Copy(userTiny, user); err != nil { - return err - } + userTiny := ToUserTinyBy(user) + //userTiny := new(user_m.UserTiny) + //if err := copier.Copy(userTiny, user); err != nil { + // return err + //} // cache externalId->userId if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil { return err @@ -113,3 +116,89 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error { } return nil } + +// 获取用户简要信息 +// param userIds 用户id列表 +func GetUserTinyMap(model *domain.Model, userIds []mysql.ID, isDefAvatar bool) (map[mysql.ID]*user_m.UserTiny, error) { + redisNoIds := make([]mysql.ID, 0) + res := make(map[mysql.ID]*user_m.UserTiny) + for _, id := range userIds { + userTiny := new(user_m.UserTiny) + key := user_k.GetUserTinyKey(id) + err := cache.GetJSON(model, key, userTiny) + if err != nil && err != redisV8.Nil { + return nil, err + } + if err == redisV8.Nil { + redisNoIds = append(redisNoIds, id) + } else if userTiny.ID > 0 { + res[id] = userTiny + } + } + // 从db中读 + users, err := user_m.GetUsers(model, redisNoIds) + if err != nil { + return nil, err + } + for _, u := range users { + userTiny := ToUserTinyBy(u) + err = cacheUserTiny(model, u) + if err != nil { + return nil, err + } + res[userTiny.ID] = userTiny + } + if isDefAvatar { + for _, v := range res { + if len(v.Avatar) <= 0 { + if v.Sex == mysql.MAN { + v.Avatar = common.MakeFullUrl(common.DefaultAvatarMan) + } else if v.Sex == mysql.WOMAN { + v.Avatar = common.MakeFullUrl(common.DefaultAvatarWoman) + } + } + } + } + return res, nil +} + +func ToUserTinyBy(user *user_m.User) *user_m.UserTiny { + return &user_m.UserTiny{ + ID: user.ID, + Avatar: IfLogoutStr(IfLogout(user.LogoutTime), "", user.Avatar), + ExternalId: user.ExternalId, + Nick: IfLogoutNick(IfLogout(user.LogoutTime), user.Code, user.Nick), + Sex: user.Sex, + Code: user.Code, + Country: user.Country, + CountryIcon: user.CountryIcon, + IsPrettyCode: user.IsPrettyCode(), + IsLogout: IfLogout(user.LogoutTime), + Birthday: BirthdayToUint64(&user.Birthday), + } +} + +func IfLogout(logoutTime int64) bool { + return logoutTime > 0 && time.Now().Unix() > logoutTime +} + +func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 { + if *birthday == 0 { + return nil + } + return (*uint64)(birthday) +} + +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 +} diff --git a/domain/event/group_power_ev/groupPowerExpireNotice.go b/domain/event/group_power_ev/groupPowerExpireNotice.go new file mode 100644 index 0000000..91b81d8 --- /dev/null +++ b/domain/event/group_power_ev/groupPowerExpireNotice.go @@ -0,0 +1,26 @@ +package group_power_ev + +import ( + "git.hilo.cn/hilo-common/domain" +) + +//注册监听 +var groupPowerExpireNoticeListen = new(domain.EventBase) + +type GroupPowerExpireNoticeEvent struct { +} + +//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。 +func AddGroupPowerExpireNoticeSync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventSync(groupPowerExpireNoticeListen, callback) +} + +//加入到异步操作中 +func AddGroupPowerExpireNoticeAsync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventAsync(groupPowerExpireNoticeListen, callback) +} + +//领域事件发布 +func PublishGroupPowerExpireNotice(model *domain.Model, event interface{}) error { + return domain.PublishEvent(groupPowerExpireNoticeListen, model, event) +} diff --git a/domain/event/group_power_ev/groupPowerUpgrade.go b/domain/event/group_power_ev/groupPowerUpgrade.go new file mode 100644 index 0000000..b60d194 --- /dev/null +++ b/domain/event/group_power_ev/groupPowerUpgrade.go @@ -0,0 +1,28 @@ +package group_power_ev + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" +) + +//注册监听 +var groupPowerUpgradeListen = new(domain.EventBase) + +type GroupPowerUpgradeEvent struct { + GroupPowerId mysql.ID +} + +//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。 +func AddGroupPowerUpgradeSync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventSync(groupPowerUpgradeListen, callback) +} + +//加入到异步操作中 +func AddGroupPowerUpgradeAsync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventAsync(groupPowerUpgradeListen, callback) +} + +//领域事件发布 +func PublishGroupPowerUpgrade(model *domain.Model, event interface{}) error { + return domain.PublishEvent(groupPowerUpgradeListen, model, event) +} diff --git a/domain/event/mic_ev/on_mic.go b/domain/event/mic_ev/on_mic.go new file mode 100644 index 0000000..881a20c --- /dev/null +++ b/domain/event/mic_ev/on_mic.go @@ -0,0 +1,29 @@ +package mic_ev + +import ( + "git.hilo.cn/hilo-common/domain" +) + +var onMicListen = new(domain.EventBase) + +// 在麦上事件 +type OnMicEvent struct { + GroupUuid string // 群组uuid + I int // 麦位 + ExternalId string // 麦中的人 + UserId uint64 // 麦中的人 + Forbid bool // 静音 true:静音,false:没有静音 + Timestamp int64 // 上麦的的时间戳 +} + +func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventSync(onMicListen, callback) +} + +func AddOnMicEventAsync(callback func(model *domain.Model, event interface{}) error) { + domain.AddEventAsync(onMicListen, callback) +} + +func PublishOnMicEvent(model *domain.Model, event interface{}) error { + return domain.PublishEvent(onMicListen, model, event) +} diff --git a/domain/model/diamond_m/dealer.go b/domain/model/diamond_m/dealer.go new file mode 100644 index 0000000..a46391b --- /dev/null +++ b/domain/model/diamond_m/dealer.go @@ -0,0 +1,211 @@ +package diamond_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mylogrus" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-group/common" + "hilo-group/myerr" +) + +type DiamondDealer struct { + mysql.Entity + UserId uint64 + Diamond uint32 + Wechat string + Whatsapp string + Contact string + Status int + HasInvite int + IsFamilyAgent int8 +} + +func (dealer *DiamondDealer) Save(db *gorm.DB) error { + if dealer.ID > 0 { + db = db.Omit("diamond", "status") + } else { + dealer.Status = common.SWITCH_ON + } + return db.Save(dealer).Error +} + +func (dealer *DiamondDealer) Get(db *gorm.DB) error { + return db.Where(dealer).First(dealer).Error +} + +func IsDiamondDealer(db *gorm.DB, userId uint64) (bool, error) { + dd := DiamondDealer{UserId: userId, Status: common.SWITCH_ON} + if err := dd.Get(db); err != nil { + if err == gorm.ErrRecordNotFound { + return false, nil + } else { + return false, err + } + } + return true, nil +} + +// 是否是家族代理 +func IsFamilyDiamondDealer(db *gorm.DB, userId uint64) (bool, error) { + dd := DiamondDealer{UserId: userId, Status: common.SWITCH_ON, IsFamilyAgent: 1} + if err := dd.Get(db); err != nil { + if err == gorm.ErrRecordNotFound { + return false, nil + } else { + return false, err + } + } + return true, nil +} + +func GetDiamondDealer(db *gorm.DB, userId uint64) (*DiamondDealer, error) { + dd := &DiamondDealer{UserId: userId, Status: common.SWITCH_ON} + if err := dd.Get(db); err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return dd, nil +} + +func (dealer *DiamondDealer) GetAll(db *gorm.DB, status *uint8) ([]DiamondDealer, error) { + rows := make([]DiamondDealer, 0) + if status == nil { + if err := db.Where(dealer).Find(&rows).Error; err != nil { + return nil, err + } + } else if err := db.Where(dealer).Where("status = ?", *status).Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil +} + +func (dealer *DiamondDealer) Remove(db *gorm.DB) (int64, error) { + result := db.Where(dealer).Delete(&DiamondDealer{}) + return result.RowsAffected, result.Error +} + +func (dealer *DiamondDealer) SafeReduceDiamond(db *gorm.DB, diamond uint32) (int64, error) { + result := db.Model(&DiamondDealer{}).Where(dealer).Where("diamond >= ?", diamond).UpdateColumn("diamond", gorm.Expr("diamond - ?", diamond)) + return result.RowsAffected, result.Error +} + +func (dealer *DiamondDealer) AddDiamond(db *gorm.DB, diamond uint32) (int64, error) { + result := db.Model(&DiamondDealer{}).Where(dealer).Where("status = ?", common.SWITCH_ON).UpdateColumn("diamond", gorm.Expr("diamond + ?", diamond)) + return result.RowsAffected, result.Error +} + +func (dealer *DiamondDealer) SetStatus(db *gorm.DB, status uint8) error { + return db.Model(&DiamondDealer{}).Where(dealer).Update("status", status).Error +} + +type DealerTransferDetail struct { + mysql.Entity + DealerId uint64 + ReceiverId uint64 + Diamond uint32 + Dollar uint +} + +func (dtd *DealerTransferDetail) Create(db *gorm.DB) error { + return db.Create(dtd).Error +} + +func (dfd *DealerTransferDetail) Find(db *gorm.DB, offset, limit int) ([]DealerTransferDetail, error) { + rows := make([]DealerTransferDetail, 0) + if err := db.Where(dfd).Order("created_time DESC").Offset(offset).Limit(limit).Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil +} + +func (dfd *DealerTransferDetail) CountByDealer(db *gorm.DB, dealerIds []uint64) (map[uint64]uint, error) { + type summary struct { + DealerId uint64 + C uint + } + rows := make([]summary, 0) + if err := db.Model(&DealerTransferDetail{}).Where("dealer_id IN ?", dealerIds). + Select("dealer_id, COUNT(0) AS c").Group("dealer_id").Find(&rows).Error; err != nil { + return nil, err + } + result := make(map[uint64]uint, 0) + for _, i := range rows { + result[i.DealerId] = i.C + } + return result, nil +} + +func (dfd *DealerTransferDetail) Sum(db *gorm.DB) (uint, uint32, uint, error) { + type summary struct { + C uint + Diamond uint32 + Dollar uint + } + s := summary{} + if err := db.Model(&DealerTransferDetail{}).Where(dfd). + Select("COUNT(0) AS c, SUM(diamond) AS diamond, SUM(dollar) AS dollar").First(&s).Error; err != nil { + return 0, 0, 0, err + } + return s.C, s.Diamond, s.Dollar, nil +} + +type DealerChargeDetail struct { + mysql.Entity + DealerId uint64 + MgrId uint64 + Diamond uint32 + Dollar uint + PaymentMethod string + Type uint8 + Money float32 `json:"money"` // 支付的货币数值 + Currency string `json:"currency"` // 支付货币 + GoodsId string `json:"goodsId"` // 充值钻石套餐id/商品id +} + +func (dcd *DealerChargeDetail) Create(db *gorm.DB) error { + return db.Create(dcd).Error +} + +type DealerCountry struct { + DealerId uint64 + Country string +} + +func (dc *DealerCountry) Find(db *gorm.DB) ([]DealerCountry, error) { + rows := make([]DealerCountry, 0) + if err := db.Where(dc).Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil +} + +func (dc *DealerCountry) Delete(db *gorm.DB) error { + return db.Where(dc).Delete(&DealerCountry{}).Error +} + +func (dc *DealerCountry) BatchInsert(db *gorm.DB, dealerId uint64, countries []string) error { + rows := make([]DealerCountry, 0) + for _, i := range countries { + rows = append(rows, DealerCountry{ + DealerId: dealerId, + Country: i, + }) + } + return db.Create(&rows).Error +} + +// 活动排行榜黑名单 获取所有已经上架代理币商的群组id +func GetAllValidActivityBlackImGroupIds(model *domain.Model) []mysql.Str { + //return []mysql.Str{"HTGS#a88745892", "@TGS#3UW6RFSIX"} + var imGroupIds []mysql.Str + subQuery := model.Db.WithContext(model).Model(DiamondDealer{}).Where("status = 1").Select("user_id") + if err := model.Db.WithContext(model).Table("group_info").Select("im_group_id").Where("owner in (?)", subQuery).Scan(&imGroupIds).Error; err != nil { + mylogrus.MyLog.Errorf("GetAllValidActivityBlackImGroupIds fail:%v", err) + } + imGroupIds = append(imGroupIds, "HTGS#a88745892", "@TGS#3UW6RFSIX") + return imGroupIds +} diff --git a/domain/model/groupPower_m/family.go b/domain/model/groupPower_m/family.go new file mode 100644 index 0000000..a2a0791 --- /dev/null +++ b/domain/model/groupPower_m/family.go @@ -0,0 +1,159 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-group/_const/enum/groupPower_e" + "hilo-group/common" + "hilo-group/common/utime" + "hilo-group/myerr" + "hilo-group/myerr/bizerr" + "time" +) + +//type GroupPowerGrade struct { +// GroupPowerId uint64 `json:"group_power_id"` +// Exp int64 `json:"exp"` +// Grade int32 `json:"grade"` +// ExpireAt time.Time `json:"expire_at"` +//} + +type GroupPowerQuitLog struct { + Id uint64 `json:"id"` + UserId uint64 `json:"user_id"` + MgrId uint64 `json:"mgr_id"` + CreatedTime time.Time `json:"created_time"` + GroupPowerId uint64 `json:"group_power_id"` +} + +func (this *GroupPower) Get(model *domain.Model) (*GroupPower, error) { + group := new(GroupPower) + err := model.Db.Where(this).First(&group).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, err + } + grade := new(GroupPowerGrade) + err = model.Db.Model(&GroupPowerGrade{}).Where("group_power_id=? and expire_at > ?", this.ID, time.Now().Format(utime.Layout)).First(&grade).Error + if err != nil && err != gorm.ErrRecordNotFound { + return nil, err + } + if grade.GroupPowerId > 0 { + group.Grade = mysql.Num(grade.Grade) + group.Exp = mysql.Num(grade.Exp) + group.NextExp = mysql.Num(grade.Exp) + } + return group, nil +} + +func (gpu *GroupPowerUser) GetBy(model *domain.Model, pageSize, pageIndex int) ([]*GroupPowerUser, int64, int, bool, error) { + rows := make([]*GroupPowerUser, 0) + db := model.Db.Model(GroupPowerUser{}).Where(gpu).Order("field(`role`, 2, 3, 1)") + var count int64 + err := db.Count(&count).Error + if err != nil { + return nil, 0, 0, false, err + } + err = db.Limit(pageSize).Offset(pageIndex).Find(&rows).Error + if err != nil { + return nil, 0, 0, false, err + } + nextPageIndex, hasNextPage := common.PageNext(count, pageIndex, pageSize) + return rows, count, nextPageIndex, hasNextPage, nil +} + +func (gpu *GroupPowerUser) GetGroupPowerUser(model *domain.Model) (*GroupPowerUser, error) { + rows := make([]*GroupPowerUser, 0) + err := model.Db.Where(gpu).Find(&rows).Error + if err != nil { + return nil, err + } + if len(rows) == 0 { + return nil, nil + } + return rows[0], nil +} + +func (gpu *GroupPowerUser) Create(db *gorm.DB) error { + return db.Create(gpu).Error +} + +func QuitFamily(model *domain.Model, userId, mgrId, familyId uint64) error { + err := model.Db.Exec("delete from group_power_user where group_power_id = ? and user_id = ?", familyId, userId).Error + if err != nil { + return err + } + // log + log := &GroupPowerQuitLog{UserId: userId, MgrId: mgrId, GroupPowerId: familyId, CreatedTime: time.Now()} + return model.Db.Create(log).Error +} + +func GroupPowerQuitList(model *domain.Model, familyId uint64, pageSize, pageIndex int) ([]*GroupPowerQuitLog, int, bool, error) { + rows := make([]*GroupPowerQuitLog, 0) + db := model.Db.Model(GroupPowerQuitLog{}).Where("group_power_id = ?", familyId).Order("created_time desc") + var count int64 + err := db.Count(&count).Error + if err != nil { + return nil, 0, false, err + } + err = db.Limit(pageSize).Offset(pageIndex).Find(&rows).Error + if err != nil { + return nil, 0, false, err + } + nextIdx, hasNext := common.PageNext(count, pageIndex, pageSize) + return rows, nextIdx, hasNext, nil +} + +func UpdateFamilyAdmin(model *domain.Model, userId, familyId uint64, role groupPower_e.GroupPowerUserRole) error { + err := model.Db.Exec("update group_power_user set role = ? where group_power_id = ? and user_id = ?", role, familyId, userId).Error + if err != nil { + return err + } + return nil +} + +func UpdateFamily(model *domain.Model, familyId uint64, name, nameplate, declaration, icon string) error { + if familyId == 0 || (name == "" && nameplate == "" && declaration == "" && icon == "") { + return nil + } + db := model.Db.Model(GroupPower{}) + updateMap := make(map[string]interface{}) + if name != "" { + updateMap["name"] = name + } + if nameplate != "" { + updateMap["nameplate"] = nameplate + db = db.Where("not exists (select id from group_power where nameplate = ?)", nameplate) + } + if declaration != "" { + updateMap["declaration"] = declaration + } + if icon != "" { + updateMap["icon"] = icon + } + result := db.Where("id = ?", familyId).Updates(updateMap).Limit(1) + if result.Error != nil { + return myerr.WrapErr(result.Error) + } + if result.RowsAffected <= 0 { + return myerr.WrapErr(bizerr.GroupPowerHaveChangeInfo) + } + + return nil +} + +func IsExistsNameplate(model *domain.Model, nameplate string) bool { + var count int64 + err := model.Db.Model(GroupPower{}).Where("nameplate = ?", nameplate).Count(&count).Error + if err != nil { + model.Log.Errorf("IsExistsNameplate err:%v, nameplate:%s", err, nameplate) + return false + } + if count > 0 { + return true + } + return false +} diff --git a/domain/model/groupPower_m/groupPower.go b/domain/model/groupPower_m/groupPower.go index c0a71a8..19a4cd7 100644 --- a/domain/model/groupPower_m/groupPower.go +++ b/domain/model/groupPower_m/groupPower.go @@ -26,6 +26,14 @@ type GroupPower struct { GroupUid mysql.Str Name mysql.Str Status groupPower_e.GroupPowerStatus + Nameplate mysql.Str // 铭牌 + Declaration mysql.Str // 宣言 + Icon mysql.Str // 头像 + Grade mysql.Num `gorm:"-"` // 等级 + Exp mysql.Num `gorm:"-"` // 当前经验值 + NextExp mysql.Num `gorm:"-"` // 升到下一级需要的经验值 + GradeName mysql.Str // 等级称号 + GradeMedal mysql.Str // 等级勋章图片 } type GroupPowerUser struct { @@ -334,6 +342,34 @@ func GetGroupPowerByGroupOrNil(model *domain.Model, groupUid string) (*GroupPowe return &groupPower, nil } +// 某个势力的势力主是否是代理 +func IsGroupPowerHasMgrDealer(model *domain.Model, groupId mysql.ID) (bool, error) { + var num int64 + if err := model.Db.Raw("select count(1) from (select * from diamond_dealer where user_id in "+ + "(select user_id from group_power_user where group_power_id = ? and role = ?)) a", groupId, groupPower_e.GroupPowerUserRoleMgr). + Scan(&num).Error; err != nil { + return false, myerr.WrapErr(err) + } + if num > 0 { + return true, nil + } + return false, nil +} + +// 某个家族是否有家族代理 +func IsGroupPowerHasFamilyAgent(model *domain.Model, groupId mysql.ID) (bool, error) { + var num int64 + if err := model.Db.Raw("select count(1) from diamond_dealer where status=1 and is_family_agent=1 and user_id in "+ + "(select user_id from group_power_user where group_power_id = ?)", groupId). + Scan(&num).Error; err != nil { + return false, myerr.WrapErr(err) + } + if num > 0 { + return true, nil + } + return false, nil +} + func GetGroupPowerMap(db *gorm.DB, userIds []mysql.ID) (map[mysql.ID]uint64, error) { rows := make([]GroupPowerUser, 0) if len(userIds) > 0 { @@ -348,47 +384,28 @@ func GetGroupPowerMap(db *gorm.DB, userIds []mysql.ID) (map[mysql.ID]uint64, err return result, nil } -func GetGroupPowerNames(db *gorm.DB, ids []mysql.ID) (map[mysql.ID]string, error) { +// return +func GetGroupPowerNames(db *gorm.DB, ids []mysql.ID) (map[mysql.ID]string, map[mysql.ID]string, error) { type record struct { - Id mysql.ID - Name string + Id mysql.ID + Name string + Nameplate string } rows := make([]record, 0) + result := make(map[mysql.ID]string, 0) + result2 := make(map[mysql.ID]string, 0) if len(ids) > 0 { - if err := db.Model(&GroupPower{}).Select("p.id, i.name"). + if err := db.Model(&GroupPower{}).Select("p.id, i.name,p.nameplate"). Joins("AS p INNER JOIN group_info AS i ON p.group_uid = i.im_group_id"). Where("p.id IN ?", ids).Find(&rows).Error; err != nil { - return nil, err + return result, result2, err } } - result := make(map[mysql.ID]string, 0) for _, i := range rows { result[i.Id] = i.Name + result2[i.Id] = i.Nameplate } - return result, nil -} - -type GroupPowerInfo struct { - PowerId mysql.ID - Owner mysql.ID - Name string -} - -func BatchGetGroupPower(db *gorm.DB, ids []mysql.ID) (map[mysql.ID]GroupPowerInfo, error) { - rows := make([]GroupPowerInfo, 0) - if len(ids) > 0 { - if err := db.Model(&GroupPower{}).Select("p.id AS power_id, u.user_id AS owner, p.name"). - Joins("AS p INNER JOIN group_power_user AS u ON p.id = u.group_power_id"). - Where("p.id IN ? AND p.status = ? AND role = ?", ids, groupPower_e.GroupPowerUserHas, groupPower_e.GroupPowerUserRoleMgr). - Find(&rows).Error; err != nil { - return nil, err - } - } - result := make(map[mysql.ID]GroupPowerInfo, 0) - for _, i := range rows { - result[i.PowerId] = i - } - return result, nil + return result, result2, nil } func GetGroupPower(model *domain.Model, id mysql.ID) (*GroupPower, error) { @@ -648,3 +665,36 @@ func GetUserGroupPower(model *domain.Model, userId uint64) (uint64, string, erro } return gpu.GroupPowerId, powerName, nil } + +// 获取势力下的所有群组 +func GetGroupPowerGroups(model *domain.Model, groupPowerId mysql.ID) ([]*group_m.GroupInfo, error) { + var res []*group_m.GroupInfo + var ownerIds []mysql.ID + if err := model.DB().Model(GroupPowerUser{}).Select("user_id").Where("group_power_id = ?", groupPowerId).Scan(&ownerIds).Error; err != nil { + model.Log.Errorf("GetGroupPowerGroups fail:%v", err) + return nil, err + } + if len(ownerIds) <= 0 { + return res, nil + } + if err := model.DB().Model(group_m.GroupInfo{}).Where("owner in ?", ownerIds).Find(&res).Error; err != nil { + model.Log.Errorf("GetGroupPowerGroups fail:%v", err) + return nil, err + } + return res, nil +} + +// 批量获取势力用户 +// return userId->GroupPowerUser +func BatchGetGroupPowerUser(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]GroupPowerUser, error) { + var rows []GroupPowerUser + res := make(map[mysql.ID]GroupPowerUser) + if err := model.Db.Model(GroupPowerUser{}).Where("user_id in ?", userIds).Find(&rows).Error; err != nil { + model.Log.Errorf("BatchGetGroupPowerUser fail:%v", err) + return res, err + } + for i, v := range rows { + res[v.UserId] = rows[i] + } + return res, nil +} diff --git a/domain/model/groupPower_m/group_grade.go b/domain/model/groupPower_m/group_grade.go new file mode 100644 index 0000000..b1d0241 --- /dev/null +++ b/domain/model/groupPower_m/group_grade.go @@ -0,0 +1,323 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/utils" + "github.com/jinzhu/now" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "hilo-group/_const/enum/groupPower_e" + "hilo-group/domain/event/group_power_ev" + "time" +) + +type GroupPowerDayExp struct { + Date string + GroupPowerId mysql.ID + Exp mysql.Num + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +type GroupPowerGrade struct { + GroupPowerId mysql.ID + Exp mysql.Num + Grade groupPower_e.GroupPowerGrade + ExpireAt time.Time + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +type GroupPowerExpDetail struct { + mysql.Entity + GroupPowerId mysql.ID + UserId mysql.ID + Exp mysql.Num + AddReduce mysql.AddReduce + BefNum mysql.Num + AftNum mysql.Num + Remark string +} + +type GroupPowerOnMic struct { + Date string + GroupPowerId mysql.ID + UserId mysql.ID + Seconds int64 + LastCalTs int64 + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +type GroupPowerOnMicDetail struct { + Date string + GroupPowerId mysql.ID + UserId mysql.ID + Minute int + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +// 增加家族经验 +// 达到经验值之后升级 +// 单进程同步执行,不考虑并发 +func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.Num, userId mysql.ID, remark string) error { + var err error + defer func() { + if err != nil { + txModel.Log.Errorf("IncrGroupPowerExp fail,id:%v,exp:%v,err:%v", groupPowerId, exp, err) + } + }() + // 增加家族经验-天 + date := time.Now().Format("2006-01-02") + gpe := &GroupPowerDayExp{ + Date: date, + GroupPowerId: groupPowerId, + Exp: exp, + } + if err = txModel.DB().Model(GroupPowerDayExp{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}}, + DoUpdates: clause.Assignments(map[string]interface{}{ + "exp": gorm.Expr("exp + ?", gpe.Exp)})}).Create(gpe).Error; err != nil { + return err + } + // 增加家族经验-总 + gpg := &GroupPowerGrade{ + GroupPowerId: groupPowerId, + Exp: exp, + Grade: 0, + ExpireAt: time.Time{}, + } + if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}}, + DoUpdates: clause.Assignments(map[string]interface{}{ + "exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil { + return err + } + // 当前写后读 + latestGrade := new(GroupPowerGrade) + if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil { + return err + } + // 记录明细 + detail := &GroupPowerExpDetail{ + GroupPowerId: groupPowerId, + UserId: userId, + Exp: exp, + AddReduce: mysql.ADD, + BefNum: latestGrade.Exp - exp, + AftNum: latestGrade.Exp, + Remark: remark, + } + if err = txModel.DB().Model(GroupPowerExpDetail{}).Create(detail).Error; err != nil { + return err + } + // 达到经验值之后升级 + for grade := groupPower_e.GroupPowerGradeMax; grade >= groupPower_e.GroupPowerGrade0; grade-- { + if latestGrade.Exp > groupPower_e.GroupPowerGradeExp[grade] { + if latestGrade.Grade < grade { // 升级 + expireAt := now.EndOfMonth() + expireAt = utils.AddDate(expireAt, 0, 1) // 等级有效期到下个月月底 + updateAttrs := map[string]interface{}{ + "grade": grade, + "expire_at": expireAt, + } + if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", latestGrade.GroupPowerId).UpdateColumns(updateAttrs).Error; err != nil { + return err + } + // 升级发事件 + _ = group_power_ev.PublishGroupPowerUpgrade(txModel, &group_power_ev.GroupPowerUpgradeEvent{ + GroupPowerId: groupPowerId, + }) + } + break + } + } + return nil +} + +// 获取势力用户上麦加经验记录 +func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) { + var res []*GroupPowerOnMicDetail + date := time.Now().Format("2006-01-02") + if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil { + return res, err + } + return res, nil +} + +// 获取势力用户上麦记录 +func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) { + gpom := new(GroupPowerOnMic) + date := time.Now().Format("2006-01-02") + if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil + } + return nil, err + } + return gpom, nil +} + +const MaxMinuteTimes = 18 + +// 增加势力上麦经验 +// 事务操作 +func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { + return model.Transaction(func(model *domain.Model) error { + // 获取用户上麦奖励历史 + onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId) + if err != nil { + return err + } + numDetails := len(onMicDetails) + if numDetails >= MaxMinuteTimes { + // 上麦经验贡献值最多1800,1分钟100 + return nil + } + onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId) + if err != nil { + return err + } + nowTs := time.Now().Unix() + curTs := joinMicTimestamp + day0Ts := utils.GetZeroTime(time.Now()).Unix() + if joinMicTimestamp < onMic.LastCalTs { + curTs = onMic.LastCalTs + } + // 跨天 + if curTs < day0Ts { + curTs = day0Ts + } + onMicSeconds := nowTs - curTs + var moreDetails []*GroupPowerOnMicDetail + totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数 + if totalMinuteTimes >= MaxMinuteTimes { + totalMinuteTimes = MaxMinuteTimes + } + if totalMinuteTimes > numDetails { + // 续上上一次的时间,从numDetails开始 + for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ { + moreDetails = append(moreDetails, &GroupPowerOnMicDetail{ + Date: time.Now().Format("2006-01-02"), + GroupPowerId: groupPowerId, + UserId: userId, + Minute: mt * 10, // 转换分钟 + }) + } + } + // 有更多麦上10分钟,可以加经验 + if len(moreDetails) > 0 { + for _, detail := range moreDetails { + // 添加明细,避免重复计算 + if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil { + return err + } + // 每10分钟增加100点经验 + if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil { + return err + } + } + // 更新micExp信息 + onMic.Seconds = onMic.Seconds + onMicSeconds + onMic.LastCalTs = nowTs + if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}}, + DoUpdates: clause.Assignments( + map[string]interface{}{ + "seconds": onMic.Seconds, + "last_cal_ts": nowTs, + }, + )}). + Create(onMic).Error; err != nil { + return err + } + } + return nil + }) +} + +// 增加势力上麦时长-家族之星 +// 事务操作 +func IncrGroupPowerStarOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { + return model.Transaction(func(model *domain.Model) error { + // 月统计 + star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive) + curTs := joinMicTimestamp + nowTs := time.Now().Unix() + month0Ts := now.BeginningOfMonth().Unix() + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小 + curTs = star.LastCalTs + } + // 跨月 + if curTs < month0Ts { + curTs = month0Ts + } + score := nowTs - curTs + return IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs) + }) +} + +// 清理所有家族的经验 +func ClearGroupPowerExp(model *domain.Model) error { + var groupPowerGrades []*GroupPowerGrade + if err := model.DB().Model(GroupPowerGrade{}).Where("exp > 0").Find(&groupPowerGrades).Error; err != nil { + return err + } + return model.Transaction(func(model *domain.Model) error { + for _, grade := range groupPowerGrades { + if err := model.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", grade.GroupPowerId).UpdateColumn("exp", 0).Error; err != nil { + return err + } + // 记录明细 + detail := &GroupPowerExpDetail{ + GroupPowerId: grade.GroupPowerId, + UserId: 0, + Exp: 0, + AddReduce: mysql.SET, + BefNum: grade.Exp, + AftNum: 0, + Remark: "每月清零", + } + if err := model.DB().Model(GroupPowerExpDetail{}).Create(detail).Error; err != nil { + return err + } + } + return nil + }) +} + +// 清理过期家族等级 +func ClearGroupPowerGrade(model *domain.Model) error { + var groupPowerGrades []*GroupPowerGrade + if err := model.DB().Model(GroupPowerGrade{}).Where("expire_at < ?", time.Now()).Find(&groupPowerGrades).Error; err != nil { + return err + } + return model.Transaction(func(model *domain.Model) error { + for _, grade := range groupPowerGrades { + updateAttrs := map[string]interface{}{ + "grade": 0, + "expire_at": time.Time{}, + } + if err := model.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", grade.GroupPowerId).Updates(updateAttrs).Error; err != nil { + return err + } + } + return nil + }) +} + +// 批量获取家族等级 +func MGetGroupPowerGrade(model *domain.Model, groupPowerIds []mysql.ID) (map[mysql.ID]GroupPowerGrade, error) { + var rows []GroupPowerGrade + res := make(map[mysql.ID]GroupPowerGrade) + if err := model.DB().Model(GroupPowerGrade{}).Where("group_power_id in ?", groupPowerIds).Find(&rows).Error; err != nil { + model.Log.Errorf("MGetGroupPowerGrade fail:%v", err) + return res, err + } + for i, v := range rows { + res[v.GroupPowerId] = rows[i] + } + return res, nil +} diff --git a/domain/model/groupPower_m/group_info.go b/domain/model/groupPower_m/group_info.go new file mode 100644 index 0000000..aae2b02 --- /dev/null +++ b/domain/model/groupPower_m/group_info.go @@ -0,0 +1,69 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-group/_const/enum/groupPower_e" +) + +type GroupPowerInfo struct { + mysql.Entity + GroupUid string + Name string + Nameplate string + Declaration string + Icon string + Status int +} + +func (GroupPowerInfo) TableName() string { + return "group_power" +} + +// 批量获取家族信息 +func MGetGroupPowerInfoMap(model *domain.Model, groupPowerIds []mysql.ID) (map[mysql.ID]GroupPowerInfo, error) { + var rows []GroupPowerInfo + res := make(map[mysql.ID]GroupPowerInfo) + if err := model.DB().Model(GroupPowerInfo{}).Where("id in ?", groupPowerIds).Find(&rows).Error; err != nil { + model.Log.Errorf("MGetGroupPowerInfo fail:%v", err) + return res, err + } + for i, v := range rows { + res[v.ID] = rows[i] + } + return res, nil +} + +// 批量获取家族成员 +func MGetGroupPowerUsers(model *domain.Model, groupPowerIds []mysql.ID) (map[mysql.ID][]*GroupPowerUser, error) { + var users []*GroupPowerUser + res := make(map[mysql.ID][]*GroupPowerUser) + if err := model.DB().Model(GroupPowerUser{}).Where("group_power_id in ?", groupPowerIds).Find(&users).Error; err != nil { + model.Log.Errorf("MGetGroupPowerUsers fail:%v", err) + return res, err + } + for i, v := range users { + res[v.GroupPowerId] = append(res[v.GroupPowerId], users[i]) + } + return res, nil +} + +// 获取家族成员 +func GetGroupPowerUser(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerUser, error) { + m, err := MGetGroupPowerUsers(model, []mysql.ID{groupPowerId}) + if err != nil { + return nil, err + } + return m[groupPowerId], nil +} + +// 获取所有家族的主 +func GetAllGroupPowerOwners(model *domain.Model) ([]mysql.ID, error) { + var userIds []mysql.ID + if err := model.DB().Model(GroupPowerUser{}).Select("user_id"). + Where("role = ?", groupPower_e.GroupPowerUserRoleMgr).Find(&userIds).Error; err != nil { + model.Log.Errorf("GetAllGroupPowerOwners fail:%v", err) + return userIds, err + } + return userIds, nil +} diff --git a/domain/model/groupPower_m/group_power_apply.go b/domain/model/groupPower_m/group_power_apply.go new file mode 100644 index 0000000..ddd6ee1 --- /dev/null +++ b/domain/model/groupPower_m/group_power_apply.go @@ -0,0 +1,82 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "gorm.io/gorm" + "hilo-group/common" + "hilo-group/myerr" + "hilo-group/myerr/bizerr" + "time" +) + +type GroupPowerApplyJoin struct { + Id uint64 `json:"id"` + UserId uint64 `json:"user_id"` + GroupPowerId uint64 `json:"group_power_id"` + CreatedTime time.Time `json:"created_time"` + UpdatedTime time.Time `json:"updated_time"` + IsAccept int8 `json:"is_accept"` + MgrId uint64 `json:"mgr_id"` +} + +func InsertGroupPowerApplyJoin(model *domain.Model, userId, familyId uint64) error { + sql := "insert into group_power_apply_join(user_id,group_power_id,is_accept) " + + "select ?, ?, ? where not exists (select id from group_power_apply_join where user_id=? and group_power_id=? and is_accept=0)" + result := model.Db.Exec(sql, userId, familyId, 0, userId, familyId) + if result.Error != nil { + return myerr.WrapErr(result.Error) + } + if result.RowsAffected <= 0 { + return myerr.WrapErr(bizerr.GroupPowerHaveAlreadyApply) + } + return nil +} + +func GetGroupPowerApplyJoin(model *domain.Model, userId, familyId uint64, isAccept int) (*GroupPowerApplyJoin, error) { + res := new(GroupPowerApplyJoin) + db := model.Db.Where(GroupPowerApplyJoin{UserId: userId, GroupPowerId: familyId}) + if isAccept != -1 { + db = db.Where("is_accept=?", isAccept) + } + err := db.First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return res, nil +} + +func OptGroupPowerApplyJoinById(model *domain.Model, id, mgrId uint64, optType int) error { + err := model.Db.Exec("update group_power_apply_join set is_accept = ?, mgr_id = ? where id=? and is_accept = 0", optType, mgrId, id).Error + if err != nil { + return myerr.WrapErr(err) + } + return nil +} + +func AcceptGroupPowerApplyJoin(model *domain.Model, userId, familyId uint64) error { + err := model.Db.Exec("update group_power_apply_join set is_accept = 1 where user_id=? and group_power_id=?", userId, familyId).Error + if err != nil { + return myerr.WrapErr(err) + } + return nil +} + +func OptGroupPowerApplyList(model *domain.Model, familyId uint64, pageSize, pageIndex int) ([]*GroupPowerApplyJoin, int, bool, error) { + rows := make([]*GroupPowerApplyJoin, 0) + db := model.Db.Model(GroupPowerApplyJoin{}).Where("group_power_id = ?", familyId).Order("is_accept, created_time desc") + var count int64 + err := db.Count(&count).Error + if err != nil { + return nil, 0, false, err + } + err = db.Limit(pageSize).Offset(pageIndex).Find(&rows).Error + if err != nil { + return nil, 0, false, err + } + nextIdx, hasNext := common.PageNext(count, pageIndex, pageSize) + return rows, nextIdx, hasNext, nil +} diff --git a/domain/model/groupPower_m/group_power_invite.go b/domain/model/groupPower_m/group_power_invite.go new file mode 100644 index 0000000..4c4c040 --- /dev/null +++ b/domain/model/groupPower_m/group_power_invite.go @@ -0,0 +1,50 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "hilo-group/myerr" + "time" +) + +type GroupPowerInviteJoin struct { + Id uint64 `json:"id"` + UserId uint64 `json:"user_id"` + GroupPowerId uint64 `json:"group_power_id"` + CreatedTime time.Time `json:"created_time"` + UpdatedTime time.Time `json:"updated_time"` + InviteUserId uint64 `json:"invite_user_id"` + IsAccept int8 `json:"is_accept"` +} + +func InsertGroupPowerInviteJoin(userId, inviteUserId, familyId uint64) error { + nowTime := time.Now() + sql := "insert into group_power_invite_join(user_id,invite_user_id,group_power_id,is_accept,created_time,updated_time) " + + "value(?,?,?,?,?,?) on duplicate key update is_accept=?,created_time=?,updated_time=?" + err := mysql.Db.Exec(sql, userId, inviteUserId, familyId, 0, nowTime, nowTime, 0, nowTime, nowTime).Error + if err != nil { + return myerr.WrapErr(err) + } + return nil +} + +func GetGroupPowerInviteJoin(userId, familyId uint64) (*GroupPowerInviteJoin, error) { + res := new(GroupPowerInviteJoin) + err := mysql.Db.Where(GroupPowerInviteJoin{UserId: userId, GroupPowerId: familyId}).Where("is_accept=0").First(&res).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } else { + return nil, myerr.WrapErr(err) + } + } + return res, nil +} + +func AcceptGroupPowerInviteJoin(userId, familyId uint64) error { + err := mysql.Db.Exec("update group_power_invite_join set is_accept = 1 where user_id=? and group_power_id=?", userId, familyId).Error + if err != nil { + return myerr.WrapErr(err) + } + return nil +} diff --git a/domain/model/groupPower_m/group_rank.go b/domain/model/groupPower_m/group_rank.go new file mode 100644 index 0000000..9ebcfd5 --- /dev/null +++ b/domain/model/groupPower_m/group_rank.go @@ -0,0 +1,27 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" +) + +type GroupPowerExpRank struct { + GroupPowerId mysql.ID + Exp mysql.Num + Rank int +} + +// 获取家族经验排行榜 +// param limit: 排行榜人数 +func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int) ([]GroupPowerExpRank, error) { + var res []GroupPowerExpRank + if err := model.DB().Table("group_power_day_exp").Select("group_power_id,SUM(exp) as exp"). + Where("date BETWEEN ? AND ?", beginDate, endDate).Group("group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil { + model.Log.Errorf("GetGroupPowerExpRank fail:%v", err) + return res, err + } + for i := range res { + res[i].Rank = i + 1 + } + return res, nil +} diff --git a/domain/model/groupPower_m/group_star.go b/domain/model/groupPower_m/group_star.go new file mode 100644 index 0000000..930a318 --- /dev/null +++ b/domain/model/groupPower_m/group_star.go @@ -0,0 +1,90 @@ +package groupPower_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "hilo-group/_const/enum/groupPower_e" + "time" +) + +// 家族之星 +type GroupPowerMonthStar struct { + Month string + GroupPowerId mysql.ID + UserId mysql.ID + Type groupPower_e.GroupPowerStarType + Score mysql.Num + LastCalTs int64 + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +// 增加家族之星分数 +func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error { + month := time.Now().Format("200601") + star := &GroupPowerMonthStar{ + Month: month, + GroupPowerId: groupPowerId, + UserId: userId, + Type: _type, + Score: score, + LastCalTs: lastCalTs, + } + if err := model.DB().Model(GroupPowerMonthStar{}).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "month"}, {Name: "group_power_id"}, {Name: "user_id"}, {Name: "type"}}, + DoUpdates: clause.Assignments(map[string]interface{}{ + "score": gorm.Expr("score + ?", star.Score), + "last_cal_ts": lastCalTs, + }), + }).Create(star).Error; err != nil { + model.Log.Errorf("IncrGroupPowerMonthStarScore fail:%v", err) + return err + } + return nil +} + +// 获取家族之星分数 +// 允许返回gorm.ErrRecordNotFound +func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) { + res := new(GroupPowerMonthStar) + month := time.Now().Format("200601") + if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil { + return nil, err + } + return res, nil +} + +// 获取家族之星排行 +func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int) ([]*GroupPowerMonthStar, error) { + var res []*GroupPowerMonthStar + month := time.Now().Format("200601") + if err := model.DB().Model(GroupPowerMonthStar{}).Where("month = ? AND group_power_id = ? AND `type` = ?", month, groupPowerId, _type). + Order("score desc").Offset(offset).Limit(limit).Find(&res).Error; err != nil { + model.Log.Errorf("GetGroupPowerMonthStarRank fail:%v", err) + return res, err + } + return res, nil +} + +// 获取家族之星三个排行榜的各自第一名 +func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerMonthStar, error) { + var res []*GroupPowerMonthStar + r1, err := GetGroupPowerMonthStarRank(model, groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1) + if err != nil { + return res, err + } + r2, err := GetGroupPowerMonthStarRank(model, groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1) + if err != nil { + return res, err + } + r3, err := GetGroupPowerMonthStarRank(model, groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1) + if err != nil { + return res, err + } + res = append(res, r1...) + res = append(res, r2...) + res = append(res, r3...) + return res, nil +} diff --git a/domain/model/group_m/groupInfo.go b/domain/model/group_m/groupInfo.go index 94bf11f..0c91c58 100644 --- a/domain/model/group_m/groupInfo.go +++ b/domain/model/group_m/groupInfo.go @@ -8,6 +8,7 @@ import ( "github.com/bluele/gcache" "gorm.io/gorm" "hilo-group/_const/enum/group_e" + "hilo-group/common" "hilo-group/myerr" "hilo-group/myerr/bizerr" "math/rand" @@ -515,29 +516,18 @@ func GetLatestGroupInfos(model *domain.Model, limit, lastId int, groupIds []stri return } -//func init() { -// // 初始化官方群组 -// strGroupIds := strings.Split(config.GetConfigApp().OFFICIAL_GROUP, ",") -// for _, i := range strGroupIds { -// if len(i) > 0 { -// officialGroup = append(officialGroup, i) -// } -// } -// mylogrus.MyLog.Info("Official groups: ", officialGroup) -// -// event.AddUserInfoUpdate(func(model *domain.Model, e interface{}) error { -// event := e.(*event.UserInfoUpdateEvent) -// if event.Country == nil { -// return nil -// } else { -// // v2.3需求:同步更新群组country -// model.Log.Infof("Receive userInfoUpdate: user %d, country %s", event.UserId, *event.Country) -// return UpdateCountryByOwner(model, *event.Country, event.UserId) -// } -// }) -// event.AddMgrUserCountryUpdateAsync(func(model *domain.Model, event *event.MgrUserCountryUpdateEvent) error { -// // v2.3需求:同步更新群组country -// model.Log.Infof("Receive MgrUserCountryUpdate: user %d, from %s to %s", event.UserId, event.OldCountry, event.NewCountry) -// return UpdateCountryByOwner(model, event.NewCountry, event.UserId) -// }) -//} +func GetFamilyRooms(model *domain.Model, familyId uint64, pageSize, pageIndex int) ([]*GroupInfo, int, bool, error) { + rows := make([]*GroupInfo, 0) + db := model.Db.Model(GroupInfo{}).Where("owner in (select user_id from group_power_user where group_power_id=? order by field(`role`, 2, 3, 1))", familyId) + var count int64 + err := db.Count(&count).Error + if err != nil { + return nil, 0, false, err + } + err = db.Limit(pageSize).Offset(pageIndex).Find(&rows).Error + if err != nil { + return nil, 0, false, err + } + nextIdx, hasNext := common.PageNext(count, pageIndex, pageSize) + return rows, nextIdx, hasNext, nil +} diff --git a/domain/model/mic_m/mic.go b/domain/model/mic_m/mic.go new file mode 100644 index 0000000..64b44ef --- /dev/null +++ b/domain/model/mic_m/mic.go @@ -0,0 +1,86 @@ +package mic_m + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/utils" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "time" +) + +// 用户上麦 +type UserOnMic struct { + Date string + UserId mysql.ID + Seconds mysql.Num + LastCalTs int64 + CreatedTime time.Time `gorm:"->"` + UpdatedTime time.Time `gorm:"->"` +} + +// 获取用户当日上麦 +// 允许返回gorm.ErrRecordNotFound +func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) { + res := new(UserOnMic) + day := time.Now().Format("2006-01-02") + if err := model.DB().Where("date = ? AND user_id = ?", day, userId).First(res).Error; err != nil { + return nil, err + } + return res, nil +} + +// 增加用户上麦时长 +// 事务操作 +func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error { + return model.Transaction(func(model *domain.Model) error { + omMic, err := GetUserOnMic(model, userId) + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + curTs := joinMicTimestamp + nowTs := time.Now().Unix() + day0Ts := utils.GetZeroTime(time.Now()).Unix() + if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小 + curTs = omMic.LastCalTs + } + // 跨天 + if curTs < day0Ts { + curTs = day0Ts + } + score := nowTs - curTs + day := time.Now().Format("2006-01-02") + onMicNew := &UserOnMic{ + Date: day, + UserId: userId, + Seconds: mysql.Num(score), + LastCalTs: nowTs, + } + if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}}, + DoUpdates: clause.Assignments(map[string]interface{}{ + "seconds": gorm.Expr("seconds + ?", onMicNew.Seconds), + "last_cal_ts": nowTs, + }), + }).Create(onMicNew).Error; err != nil { + model.Log.Errorf("IncrUserOnMic fail:%v", err) + return err + } + return nil + }) +} + +// 批量获取用户上麦时长 +// @return userId->seconds +func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (map[mysql.ID]mysql.Num, error) { + var rows []UserOnMic + res := make(map[mysql.ID]mysql.Num) + if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND user_id in ?", day, userIds).Find(&rows).Error; err != nil { + model.Log.Errorf("MGetUserOnMic fail:%v", err) + return res, err + } + for _, r := range rows { + res[r.UserId] = r.Seconds + } + return res, nil +} diff --git a/domain/model/user_m/user.go b/domain/model/user_m/user.go index f6c1960..8a0dc8f 100644 --- a/domain/model/user_m/user.go +++ b/domain/model/user_m/user.go @@ -118,3 +118,12 @@ func BatchGetUserByExtIds(model *domain.Model, extIds []string) ([]User, error) } return users, nil } + +//获取用户 +func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) { + res := make([]*User, 0) + if err := model.Db.WithContext(model.Context).Where("id in (?)", ids).Find(&res).Error; err != nil { + return nil, myerr.WrapErr(err) + } + return res, nil +} diff --git a/domain/service/diamond_s/diamond.go b/domain/service/diamond_s/diamond.go new file mode 100644 index 0000000..1b29129 --- /dev/null +++ b/domain/service/diamond_s/diamond.go @@ -0,0 +1,64 @@ +package diamond_s + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/resource/mysql" + "hilo-group/common" + "hilo-group/domain/model/diamond_m" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/res_m" + "hilo-group/myerr" + "hilo-group/myerr/bizerr" +) + +type DiamondService struct { + svc *domain.Service +} + +func NewDiamondService(myContext *mycontext.MyContext) *DiamondService { + svc := domain.CreateService(myContext) + return &DiamondService{svc} +} + +// 币商转账钻石-家族限制检查 +func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint64, lang string) error { + model := domain.CreateModelContext(this.svc.MyContext) + // 代理、用户是否加入了家族 + dealerFamily, err := groupPower_m.GetGroupPowerUserOrNil(model, dealerId) + if err != nil { + return err + } + // 代理是否是家族代理 + isFamilyAgent, err := diamond_m.IsFamilyDiamondDealer(mysql.Db, dealerId) + if err != nil { + return err + } + + userFamily, err := groupPower_m.GetGroupPowerUserOrNil(model, userId) + if err != nil { + return err + } + // 用户的家族是否有家族代理 + var userHasFamilyAgent bool + if userFamily != nil { + userHasFamilyAgent, err = groupPower_m.IsGroupPowerHasFamilyAgent(model, userFamily.GroupPowerId) + if err != nil { + return err + } + } + if dealerFamily != nil && dealerFamily.GroupPowerId > 0 { // 代理加入了家族 + if isFamilyAgent && (userFamily == nil || userFamily.GroupPowerId != dealerFamily.GroupPowerId) { // 是家族代理:只能向本家族成员转移钻石,如果向非家族成员转移钻石,则提示“非家族成员” + return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_NOT_FAMILY_MEMBER, lang, bizerr.GroupPowerDealerNotMember)) + } + if !isFamilyAgent && userHasFamilyAgent { // 不是家族代理:如果用户加入了家族,且家族中有家族代理,那么也不能,“此用户已有家族代理,不能出售钻石” + return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole)) + } + } else { // 代理没有加入家族的 + // 普通代理:不能向已经加入家族的成员(并且家族有家族代理)转移钻石,如果转移则提示“此用户已有家族代理,不能出售钻石” + if userHasFamilyAgent { + return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole)) + } + } + return nil +} diff --git a/domain/service/event_s/event_init.go b/domain/service/event_s/event_init.go index bf2a7f2..c5b1009 100644 --- a/domain/service/event_s/event_init.go +++ b/domain/service/event_s/event_init.go @@ -3,20 +3,25 @@ package event_s import ( "encoding/json" "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/sdk/tencentyun" + "hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/task_e" "hilo-group/domain/event/gift_ev" "hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_power_ev" + "hilo-group/domain/event/mic_ev" "hilo-group/domain/model/diamond_m" "hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/group_m" + "hilo-group/domain/model/mic_m" "hilo-group/domain/model/msg_m" "hilo-group/domain/model/task_m" "hilo-group/domain/model/user_m" + "hilo-group/domain/service/group_mic_s" "hilo-group/myerr" "strconv" "time" @@ -28,7 +33,8 @@ func EventInit() { GroupEvents() GroupImMass() GroupTheme() - SendGift() + SendGift() // 送礼事件 + OnMic() // 在麦上事件 } func GroupSupportEvents() { @@ -101,7 +107,7 @@ func GroupSupportEvents() { } func GroupPowerEvents() { - //加入势力 + // 加入势力 group_power_ev.AddGroupPowerJoinAsync(func(model *domain.Model, e interface{}) error { event, ok := e.(*group_power_ev.GroupPowerJoinEvent) if !ok { @@ -129,7 +135,7 @@ func GroupPowerEvents() { msg_m.SendEmasMsgAssistant(model, mgrUser.ExternalId, mgrUser.DeviceType) return nil }) - //离开势力 + // 离开势力 group_power_ev.AddGroupPowerLeaveAsync(func(model *domain.Model, e interface{}) error { event, ok := e.(*group_power_ev.GroupPowerLeaveEvent) if !ok { @@ -157,6 +163,57 @@ func GroupPowerEvents() { msg_m.SendEmasMsgAssistant(model, mgrUser.ExternalId, mgrUser.DeviceType) return nil }) + // 势力升级 + group_power_ev.AddGroupPowerUpgradeAsync(func(model *domain.Model, e interface{}) error { + event, ok := e.(*group_power_ev.GroupPowerUpgradeEvent) + if !ok { + model.Log.Errorf("AddGroupPowerUpgradeAsync event type err") + return nil + } + model.Log.Infof("msg AddGroupPowerUpgradeAsync GroupPowerId:%v", event.GroupPowerId) + users, err := groupPower_m.GetGroupPowerUser(model, event.GroupPowerId) + if err != nil { + return err + } + var userIds []mysql.ID + for _, u := range users { + userIds = append(userIds, u.UserId) + } + userMaps, err := user_m.GetUserMapByIds(model, userIds) + if err != nil { + return err + } + for uid, u := range userMaps { + if err := msg_m.NewUserRecord(model, uid, msg_e.GroupPowerUpgrade, "", 0, "", "", "", "", "").Persistent(); err != nil { + model.Log.Errorf("msg AddGroupPowerLeaveAsync NewUserRecord err:%v", err) + return nil + } + msg_m.SendEmasMsgAssistant(model, u.ExternalId, u.DeviceType) + } + return nil + }) + + // 势力等级即将过期 + group_power_ev.AddGroupPowerExpireNoticeAsync(func(model *domain.Model, e interface{}) error { + model.Log.Infof("msg AddGroupPowerExpireNoticeAsync") + powerOwners, err := groupPower_m.GetAllGroupPowerOwners(model) + if err != nil { + model.Log.Errorf("AddGroupPowerExpireNoticeAsync fail:%v", err) + return err + } + userMaps, err := user_m.GetUserMapByIds(model, powerOwners) + if err != nil { + return err + } + for uid, u := range userMaps { + if err := msg_m.NewUserRecord(model, uid, msg_e.GroupPowerExpireNotice, "", 0, "", "", "", "", "").Persistent(); err != nil { + model.Log.Errorf("msg AddGroupPowerExpireNoticeAsync NewUserRecord err:%v", err) + return nil + } + msg_m.SendEmasMsgAssistant(model, u.ExternalId, u.DeviceType) + } + return nil + }) } func GroupEvents() { @@ -397,14 +454,86 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, } func SendGift() { - // 送礼事件-火箭 - gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error { + // 送礼事件-势力经验 + 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 } model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent) + exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId) + if err != nil { + model.Log.Infof("CheckGroupPowerUser fail %+v", err) + return err + } + if exist { + exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum + return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼") + } + return nil + }) + // 家族之星-送礼/收礼 + gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error { + sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent) + if !ok { + model.Log.Errorf("AddSendGiftEventAsync event type err") + return nil + } + var userIds = []mysql.ID{sendGiftEvent.SendUserId} + userIds = append(userIds, sendGiftEvent.ReceiveUserIds...) + groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds) + if err != nil { + model.Log.Errorf("AddSendGiftEventAsync fail:%v", err) + return err + } + // 送礼加分 + if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok { + diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) + if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil { + model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err) + } + } + // 收礼加分 + for _, userId := range sendGiftEvent.ReceiveUserIds { + if data, ok := groupPowers[userId]; ok { + diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum + if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { + model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err) + } + } + } + return nil + }) +} + +func OnMic() { + // 上麦经验/上麦时长 + mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error { + event, ok := e.(*mic_ev.OnMicEvent) + if !ok { + model.Log.Errorf("AddOnMicEventSync event type err") + return nil + } + if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(event.GroupUuid, event.UserId, event.Timestamp); err != nil { + model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err) + } else { + model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v", event.GroupUuid, event.UserId) + } + return nil + }) + // 用户上麦时长 + mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error { + event, ok := e.(*mic_ev.OnMicEvent) + if !ok { + model.Log.Errorf("AddOnMicEventSync event type err") + return nil + } + if err := mic_m.IncrUserOnMic(model, event.UserId, event.Timestamp); err != nil { + model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err) + } else { + model.Log.Infof("cron micIn IncrUserOnMic success,userId:%v", event.UserId) + } return nil }) } diff --git a/domain/service/event_s/send_gift.go b/domain/service/event_s/send_gift.go index 159955a..9125763 100644 --- a/domain/service/event_s/send_gift.go +++ b/domain/service/event_s/send_gift.go @@ -57,7 +57,7 @@ func (s *GiftSendEventService) Consume() error { return nil } if err := gift_ev.PublishSendGiftEvent(model, sendGiftEvent); err != nil { - model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", cpEvent, err) + model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", string(cpEvent.Payload), err) return err } // 标记已经处理 diff --git a/domain/service/group_mic_s/group_mic.go b/domain/service/group_mic_s/group_mic.go index f9a54ad..0b8f25c 100644 --- a/domain/service/group_mic_s/group_mic.go +++ b/domain/service/group_mic_s/group_mic.go @@ -10,6 +10,7 @@ import ( "hilo-group/_const/enum/group_e" "hilo-group/_const/redis_key" "hilo-group/domain/event/group_ev" + "hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/group_m" "hilo-group/domain/service/signal_s" "hilo-group/myerr" @@ -287,3 +288,39 @@ func (s *GroupMicService) GroupIMMassByMgr(groupId string, userId uint64, extern }) }) } + +// 增加势力上麦经验/时长 +func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId uint64, joinMicTimestamp int64) error { + var model = domain.CreateModelContext(s.svc.MyContext) + exists, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, userId) + if err != nil { + return err + } + if !exists { + return nil + } + // 获取势力下所有群组 + groups, err := groupPower_m.GetGroupPowerGroups(model, groupPowerId) + if err != nil { + return err + } + inGroup := false + for _, group := range groups { + if group.ImGroupId == groupId { + inGroup = true + break + } + } + if !inGroup { + return nil + } + // 增加势力上麦经验 + if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { + model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err) + } + // 增加势力上麦时长 + if err := groupPower_m.IncrGroupPowerStarOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { + model.Log.Errorf("IncrGroupPowerOnMicTime fail:%v", err) + } + return nil +} diff --git a/go.mod b/go.mod index c539616..50a47c5 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,13 @@ require ( gorm.io/gorm v1.23.8 ) +require ( + github.com/jinzhu/now v1.1.5 + github.com/jonboulle/clockwork v0.3.0 // indirect + github.com/robfig/cron v1.2.0 + github.com/spf13/cast v1.5.0 +) + require ( github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src v0.0.0-20200910100525-12b7f1b63a6a // indirect github.com/KyleBanks/depth v1.2.1 // indirect @@ -57,7 +64,7 @@ require ( github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/validator/v10 v10.2.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect - github.com/golang/protobuf v1.5.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/hashicorp/consul/api v1.7.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/go-hclog v0.12.0 // indirect @@ -67,10 +74,8 @@ require ( github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/serf v0.9.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/joho/godotenv v1.3.0 // indirect - github.com/jonboulle/clockwork v0.3.0 // indirect github.com/json-iterator/go v1.1.9 // indirect github.com/leodido/go-urn v1.2.0 // indirect github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect @@ -83,8 +88,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect - github.com/robfig/cron v1.2.0 // indirect - github.com/spf13/cast v1.5.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 @@ -92,7 +95,7 @@ require ( golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // 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-20201224043029-2b0845dc783e // 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 diff --git a/go.sum b/go.sum index bc36f40..9ff42a4 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,9 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -75,6 +78,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -91,7 +95,11 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc= github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w= @@ -131,6 +139,7 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -146,8 +155,9 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -160,6 +170,7 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -198,6 +209,8 @@ github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.3 h1:AVF6JDQQens6nMHT9OGERBvK0f8rPrAGILnsKLr6lzM= github.com/hashicorp/serf v0.9.3/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -220,12 +233,14 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= @@ -267,9 +282,20 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -285,6 +311,8 @@ github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5H github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -312,6 +340,7 @@ github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05 github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= github.com/swaggo/swag v1.6.7 h1:e8GC2xDllJZr3omJkm9YfmK0Y56+rMO3cg0JBKNz09s= github.com/swaggo/swag v1.6.7/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc= +github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479 h1:3kwDb6p1J3LxmwnNgSSEheemPffo+vMewoDzKysYdig= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.479/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ims v1.0.479 h1:xDmo1rBmSJ7Hw3iOa6DQ/++z1d7pgsEVKrZno35zR7w= @@ -320,6 +349,7 @@ github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 h1:NavMw9XO2iCLv8hTKaJW2kTaGR github.com/tencentyun/tls-sig-api-v2-golang v1.0.0/go.mod h1:u7WiArmCTXTaQAHJwAOaLgpJ5e2xdY5/cgMEy3ubL60= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= @@ -327,19 +357,24 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -353,7 +388,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -362,8 +399,10 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -371,21 +410,29 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -397,10 +444,14 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18 h1:xFbv3LvlvQAmbNJFCBKRv1Ccvnh9FVsW0FX2kTWWowE= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -427,22 +478,28 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/local.ini b/local.ini index 81bbf6b..d46aed4 100644 --- a/local.ini +++ b/local.ini @@ -59,12 +59,12 @@ TX_OVERSEA_APP_ID=40000066 TX_OVERSEA_KEY=3ab68ea5bddc8774d90b8c764ae71188914bd5fd06f30b28790c51e44ca7885c [EMAS] REGION_ID=cn-hangzhou -ACCESS_KEY_ID=LTAI4FhNPzxdzD4w6bHirL9Z -ACCESS_KEY_SECRET=OQvUJpXDrjGi3g1F2aHiAIFWIvLdbP +ACCESS_KEY_ID=LTAIdQZv5H1kNZp5 +ACCESS_KEY_SECRET=UnwY0ClDkqBMLwPx3OJJiLYyk9xYLO ANDROID_APP_KEY=30250713 ANDROID_APP_SECRET=cae7b9a9d3e54577d2c3b60bf6d23047 -IOS_APP_KEY=30240346 -IOS_APP_SECRET=57f33ab9ca6a957a8c659f2b0b6d1205 +IOS_APP_KEY=30790728 +IOS_APP_SECRET=4fd69ca084c67d4b5a8d15452f0af26a APNS=DEV [AGORA] APP_ID=fc3e087f701b4f788099e1924c3cc7b0 diff --git a/myerr/bizerr/bizCode.go b/myerr/bizerr/bizCode.go index 48eade3..73eceab 100644 --- a/myerr/bizerr/bizCode.go +++ b/myerr/bizerr/bizCode.go @@ -71,12 +71,26 @@ var ( GroupNoPowerToSvip6 = myerr.NewBusinessCode(14026, "Cannot use this permission for SVIP6", myerr.BusinessData{}) // 踢出,无法对SVIP6使用此权限 // 家族 - GroupPowerHasJoinOther = myerr.NewBusinessCode(15001, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了其它国家势力 - GroupPowerHasJoinMy = myerr.NewBusinessCode(15002, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了该国家势力 - GroupPowerOwnerLeave = myerr.NewBusinessCode(15003, "power owner cannot exit", myerr.BusinessData{}) // 势力主不能退出 - GroupPowerNotExist = myerr.NewBusinessCode(15004, "国家势力不存在", myerr.BusinessData{}) // 国家势力不存在 - GroupPowerNoOwner = myerr.NewBusinessCode(15005, "power owner not exits or unique", myerr.BusinessData{}) // 国家势力主不存在或不唯一 - GroupPowerStayTooShort = myerr.NewBusinessCode(15006, "You joined this power not more than 10 days ago", myerr.BusinessData{}) // 加入国家势力不超过10天 + GroupPowerHasJoinOther = myerr.NewBusinessCode(15001, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了其它国家势力 + GroupPowerHasJoinMy = myerr.NewBusinessCode(15002, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了该国家势力 + GroupPowerOwnerLeave = myerr.NewBusinessCode(15003, "power owner cannot exit", myerr.BusinessData{}) // 势力主不能退出 + GroupPowerNotExist = myerr.NewBusinessCode(15004, "国家势力不存在", myerr.BusinessData{}) // 国家势力不存在 + GroupPowerNoOwner = myerr.NewBusinessCode(15005, "power owner not exits or unique", myerr.BusinessData{}) // 国家势力主不存在或不唯一 + GroupPowerStayTooShort = myerr.NewBusinessCode(15006, "You joined this power not more than 10 days ago", myerr.BusinessData{}) // 加入国家势力不超过10天 + GroupPowerDealerNotMember = myerr.NewBusinessCode(15007, "Not family member", myerr.BusinessData{}) // 代理转账失败-非家族成员 + GroupPowerDealerCanNotSole = myerr.NewBusinessCode(15008, "This user already has a family agent and cannot sell diamonds", myerr.BusinessData{}) // 代理转账失败-此用户已有家族代理,不能出售钻石 + GroupPowerDealerCanNotBuy = myerr.NewBusinessCode(15009, "Buy diamonds from your family agent", myerr.BusinessData{}) // 请向本家族代理购买钻石 + GroupPowerDealerNeedJoin = myerr.NewBusinessCode(15010, "Please join the agent's family to purchase", myerr.BusinessData{}) // 请加入代理的家族后进行购买 + GroupPowerHaveNoJoin = myerr.NewBusinessCode(15011, "You have no joined power", myerr.BusinessData{}) // 还未加入国家势力 + GroupPowerHaveNoPower = myerr.NewBusinessCode(15012, "You have no power", myerr.BusinessData{}) // 没有权限 + GroupPowerHaveNoApply = myerr.NewBusinessCode(15013, "User have no apply", myerr.BusinessData{}) // 没有找到申请 + GroupPowerHaveAlreadyApply = myerr.NewBusinessCode(15014, "Already applied", myerr.BusinessData{}) // 已经申请过 + GroupPowerHaveAlreadyChange = myerr.NewBusinessCode(15015, "Already changed", myerr.BusinessData{}) // 已经改变了 + GroupPowerHaveChangeInfo = myerr.NewBusinessCode(15016, "Setting failed", myerr.BusinessData{}) // 修改失败 + GroupPowerHaveTooLong = myerr.NewBusinessCode(15017, "too long", myerr.BusinessData{}) // 长度太长 + GroupPowerCannotRepeated = myerr.NewBusinessCode(15018, "Cannot be repeated", myerr.BusinessData{}) // 不能重复 + GroupPowerCannotQuit = myerr.NewBusinessCode(15019, "Cannot quit", myerr.BusinessData{}) // 不能退出 + GroupPowerUserHaveNoJoin = myerr.NewBusinessCode(15020, "User have no joined power", myerr.BusinessData{}) // 还未加入国家势力 TaskHasAward = myerr.NewBusinessCode(19001, "task has award", myerr.BusinessData{}) diff --git a/mysql/3.5.0.sql b/mysql/3.5.0.sql new file mode 100644 index 0000000..e2d5040 --- /dev/null +++ b/mysql/3.5.0.sql @@ -0,0 +1,45 @@ +ALTER TABLE hilo.group_power ADD nameplate varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' NOT NULL COMMENT '家族铭牌'; +ALTER TABLE hilo.group_power ADD declaration varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' NOT NULL COMMENT '家族宣言'; +ALTER TABLE hilo.group_power ADD icon varchar(200) DEFAULT '' NOT NULL COMMENT '家族头像'; +update hilo.group_power set nameplate = id; +CREATE UNIQUE INDEX nameplate_IDX USING BTREE ON hilo.group_power (nameplate); + +CREATE TABLE `group_power_invite_join` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_id` bigint unsigned NOT NULL COMMENT '被邀请者id', + `group_power_id` bigint unsigned NOT NULL, + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `invite_user_id` bigint unsigned NOT NULL COMMENT '邀请者id', + `is_accept` tinyint NOT NULL DEFAULT '0' COMMENT '是否已经接受邀请', + PRIMARY KEY (`id`), + UNIQUE KEY `user_group` (`user_id`,`group_power_id`), + KEY `group_power_id` (`group_power_id`), + KEY `invite_user_id` (`invite_user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邀请加入家族'; + +CREATE TABLE `group_power_apply_join` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_id` bigint unsigned NOT NULL COMMENT '申请者id', + `group_power_id` bigint unsigned NOT NULL, + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `is_accept` tinyint NOT NULL DEFAULT '0' COMMENT '是否已经接受', + `mgr_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '审核的管理员id', + PRIMARY KEY (`id`), + KEY `group_power_id` (`group_power_id`), + KEY `user_id` (`user_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='申请加入家族'; + +CREATE TABLE `group_power_quit_log` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_id` bigint unsigned NOT NULL COMMENT '用户id', + `mgr_id` bigint unsigned NOT NULL COMMENT '操作人id', + `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `group_power_id` bigint unsigned NOT NULL, + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`) USING BTREE, + KEY `created_time` (`created_time`) USING BTREE, + KEY `mgr_id` (`mgr_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/route/charge_r/charge.go b/route/charge_r/charge.go new file mode 100644 index 0000000..7007aac --- /dev/null +++ b/route/charge_r/charge.go @@ -0,0 +1,41 @@ +package charge_r + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "github.com/gin-gonic/gin" + "hilo-group/domain/cache/user_c" + "hilo-group/domain/service/diamond_s" + "hilo-group/req" + "hilo-group/resp" +) + +// @Tags 充值 +// @Summary 是否可以分享充值链接 +// @Param externalId query string true "分享对象的external id" +// @Success 200 +// @Router /v1/charge/share [get] +func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + + userId, lang, err := req.GetUserIdLang(c, myContext) + if err != nil { + return myContext, err + } + + extId := c.Query("externalId") + model := domain.CreateModelContext(myContext) + toUser, err := user_c.GetUserByExternalId(model, extId) + if err != nil { + return myContext, err + } + + // 家族限制检查 + if err = diamond_s.NewDiamondService(myContext).CheckDealerTransferFamilyLimit(userId, toUser.ID, lang); err != nil { + myContext.Log.Errorf("CanShareChargeLink err:%v", err) + return myContext, err + } + + resp.ResponseOk(c, nil) + return myContext, nil +} diff --git a/route/group_power_r/group_power.go b/route/group_power_r/group_power.go index f3e1cc4..c5d8e03 100644 --- a/route/group_power_r/group_power.go +++ b/route/group_power_r/group_power.go @@ -13,11 +13,13 @@ import ( "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/msg_e" "hilo-group/_const/redis_key" + "hilo-group/common" "hilo-group/cv/group_cv" "hilo-group/cv/group_power_cv" "hilo-group/cv/medal_cv" "hilo-group/cv/user_cv" "hilo-group/domain/cache/res_c" + "hilo-group/domain/cache/user_c" "hilo-group/domain/model/game_m" "hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/group_m" @@ -375,7 +377,7 @@ func GetGroupPowerGroups(c *gin.Context) (*mycontext.MyContext, error) { groupIds = append(groupIds, i.ImGroupId) owners = append(owners, i.Owner) } - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return myContext, err } @@ -487,9 +489,16 @@ func GetGroupPowerGroups(c *gin.Context) (*mycontext.MyContext, error) { MicNumType: int(i.MicNumType), GroupMedals: medals, }, - HasOnMic: len(roomMicUserMap[i.ImGroupId]) > 0, - GroupPowerId: powerIds[i.Owner], - GroupPowerName: powerNames[i.Owner], + HasOnMic: len(roomMicUserMap[i.ImGroupId]) > 0, + GroupPowerId: powerIds[i.Owner], + GroupPowerName: powerNames[i.Owner], + GroupPowerNameplate: powerNameplates[i.Owner], + GroupPower: group_cv.GroupPower{ + Id: powerIds[i.Owner], + Name: powerNames[i.Owner], + Nameplate: powerNameplates[i.Owner], + Grade: powerGrades[i.Owner], + }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i.ImGroupId]), @@ -692,3 +701,738 @@ func GroupPowerBillboardOwnerWeek(c *gin.Context) (*mycontext.MyContext, error) resp.ResponseOk(c, results) return myContext, nil } + +// @Tags 家族 +// @Summary 家族信息 +// @Param id query int true "家族id" +// @Success 200 {object} group_power_cv.GroupPowerInfo +// @Router /v1/groupPower/info [get] +func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + myUserId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + familyId, err := strconv.ParseUint(c.Query("id"), 10, 64) + if err != nil { + return myContext, err + } + model := domain.CreateModelContext(myContext) + gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: familyId}} + gpInfo, err := gp.Get(model) + if err != nil { + return myContext, myerr.WrapErr(err) + } + gpU := &groupPower_m.GroupPowerUser{GroupPowerId: gpInfo.ID} + members, total, _, _, err := gpU.GetBy(model, 5, 0) + if err != nil { + return myContext, myerr.WrapErr(err) + } + uids := make([]uint64, 0, len(members)) + for _, v := range members { + uids = append(uids, v.UserId) + } + //查找用户信息 + //uids = common.UniqueSliceUInt64(uids) + userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true) + if err != nil { + return myContext, err + } + resMembers := make([]*group_power_cv.GroupPowerUser, 0, len(members)) + for _, v := range members { + resMembers = append(resMembers, &group_power_cv.GroupPowerUser{User: userMap[v.UserId], Role: v.Role}) + } + groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID}) + info := &group_power_cv.GroupPower{ + Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon, + Grade: gpInfo.Grade, Exp: gpInfo.Exp, NextExp: gpInfo.NextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal, + MemberNum: mysql.Num(total), MemberMax: mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[gp.ID].Grade][0].Num), + } + if info.Icon != "" { + info.Icon = common.MakeFullUrl(info.Icon) + } + if info.Nameplate == "" { + groupInfo, err := group_m.GetGroupInfoByOwner(model, myUserId) + if err != nil { + return myContext, err + } + if groupInfo != nil { + info.Nameplate = groupInfo.Name + } + } + // 我在该家族中的角色 + myPU := groupPower_m.GroupPowerUser{UserId: myUserId} + myGroupPUser, err := myPU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + if myGroupPUser != nil && myGroupPUser.GroupPowerId == info.Id { + info.Role = int(myGroupPUser.Role) + } else { + // 是否申请了加入 + apply, err := groupPower_m.GetGroupPowerApplyJoin(model, myUserId, info.Id, -1) + if err != nil { + return myContext, err + } + if apply != nil && apply.IsAccept == 0 { + info.IsApply = true + } + } + // 补上家族之星三个榜一 + stars, err := groupPower_m.GetGroupPowerMonthStartTop1(model, gp.ID) + if err != nil { + return myContext, myerr.WrapErr(err) + } + var cvStar []*group_power_cv.GroupPowerStar + if len(stars) > 0 { + var userIds []uint64 + for _, star := range stars { + userIds = append(userIds, star.UserId) + } + userM, err := user_cv.GetUserTinyMap(userIds) + if err != nil { + return myContext, err + } + for _, star := range stars { + cvStar = append(cvStar, &group_power_cv.GroupPowerStar{ + User: userM[star.UserId], + RankingType: groupPower_e.GroupPowerRankType(star.Type), + }) + } + } + res := group_power_cv.GroupPowerInfo{Info: info, Members: resMembers, Stars: cvStar} + + resp.ResponseOk(c, res) + return myContext, nil +} + +// @Tags 家族 +// @Summary 获取某个家族房间列表 +// @Param id query int true "家族id" +// @Param pageSize query int true "分页大小 默认:10" default(10) +// @Param pageIndex query int true "分页开始索引,偏移量" default(1) +// @Success 200 {object} []group_cv.PopularGroupInfo +// @Router /v1/groupPower/rooms [get] +func GroupPowerRooms(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + familyId, err := strconv.ParseUint(c.Query("id"), 10, 64) + if err != nil { + return myContext, err + } + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil { + return myContext, err + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil { + return myContext, err + } + if pageIndex == 1 { + pageIndex = 0 + } + model := domain.CreateModelContext(myContext) + rooms, nextPageIndex, hasNextPage, err := group_m.GetFamilyRooms(model, familyId, pageSize, pageIndex) + if err != nil { + return myContext, err + } + resRooms, err := group_cv.BuildPopularGroupInfo(model, userId, rooms) + if err != nil { + return myContext, err + } + + resp.ResponsePageBaseOk(c, resRooms, nextPageIndex, hasNextPage) + return myContext, nil +} + +// @Tags 家族 +// @Summary 获取家族成员列表 +// @Param userCode query string false "用户extId,搜索时输入" +// @Param id query int true "家族id" +// @Param pageSize query int true "分页大小 默认:10" default(10) +// @Param pageIndex query int true "分页开始索引,偏移量" default(1) +// @Success 200 {object} []group_power_cv.FamilyMemberDetail +// @Router /v1/groupPower/members [get] +func GroupPowerMembers(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + familyId, err := strconv.ParseUint(c.Query("id"), 10, 64) + if err != nil { + return myContext, err + } + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil { + return myContext, err + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil { + return myContext, err + } + if pageIndex == 1 { + pageIndex = 0 + } + model := domain.CreateModelContext(myContext) + userCode := c.Query("userCode") + + gpU := &groupPower_m.GroupPowerUser{GroupPowerId: familyId} + if userCode != "" { + u, err := user_m.GetUserByCode(model, userCode) + if err != nil || u == nil || u.ID <= 0 { + resp.ResponsePageBaseOk(c, nil, 0, false) + return myContext, nil + } + if u != nil && u.ID > 0 { + gpU.UserId = u.ID + } + } + + members, _, nextPageIndex, hasNextPage, err := gpU.GetBy(model, pageSize, pageIndex) + if err != nil { + return myContext, err + } + + userIds := make([]uint64, 0) + for _, v := range members { + userIds = append(userIds, v.UserId) + } + + result := make([]group_power_cv.FamilyMemberDetail, 0) + if len(userIds) > 0 { + users, err := user_cv.BatchGetUserExtend(model, userIds, userId) + if err != nil { + return myContext, err + } + + for _, v := range members { + result = append(result, group_power_cv.FamilyMemberDetail{ + User: users[v.UserId], + Role: v.Role, + }) + } + } + + resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage) + return myContext, nil +} + +// @Tags 家族 +// @Summary 申请加入家族 +// @Param id formData int true "家族id" +// @Success 200 +// @Router /v1/groupPower/apply [post] +func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + familyId, err := strconv.ParseUint(c.PostForm("id"), 10, 64) + if err != nil { + return myContext, myerr.WrapErr(err) + } + model := domain.CreateModelContext(myContext) + + // 判断家族是否存在 + gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: familyId}} + gpInfo, err := gp.Get(model) + if err != nil { + return myContext, err + } + if gpInfo == nil || gpInfo.ID <= 0 { + return myContext, bizerr.GroupPowerNotExist + } + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + uList, err := gpU.Get(model.Db) + if err != nil { + return myContext, err + } + if len(uList) > 0 { + return myContext, bizerr.GroupPowerHasJoinOther + } + + // 插入申请表 + err = groupPower_m.InsertGroupPowerApplyJoin(model, userId, gpInfo.ID) + if err != nil { + return myContext, err + } + + resp.ResponseOk(c, nil) + return myContext, nil +} + +// @Tags 家族 +// @Summary 审核加入家族申请 +// @Param userExtId formData string true "用户extId" +// @Param type formData int true "1.通过,2.不通过" +// @Success 200 +// @Router /v1/groupPower/apply/pass [post] +func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + optType, err := strconv.Atoi(c.PostForm("type")) + if err != nil { + return myContext, bizerr.InvalidParameter + } + if optType < 1 || optType > 2 { + return myContext, bizerr.InvalidParameter + } + userExtId := c.PostForm("userExtId") + if userExtId == "" { + return myContext, bizerr.InvalidParameter + } + model := domain.CreateModelContext(myContext) + optUser, err := user_c.GetUserByExternalId(model, userExtId) + if err != nil { + return myContext, err + } + + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil || myGroupPUser.ID == 0 { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 查找申请记录 + apply, err := groupPower_m.GetGroupPowerApplyJoin(model, optUser.ID, myGroupPUser.GroupPowerId, 0) + if err != nil { + return myContext, err + } + if apply == nil { + return myContext, bizerr.GroupPowerHaveNoApply + } + + if optType == 2 { // 拒绝 + // 更改申请表状态 + err = groupPower_m.OptGroupPowerApplyJoinById(model, apply.Id, userId, optType) + if err != nil { + return myContext, err + } + resp.ResponseOk(c, nil) + return myContext, nil + } + + err = model.Transaction(func(model *domain.Model) error { + txModel := domain.CreateModel(model.CtxAndDb) + // 插入家族成员表 + gpU := groupPower_m.GroupPowerUser{GroupPowerId: apply.GroupPowerId, UserId: apply.UserId, Role: groupPower_e.GroupPowerUserRoleUser} + err := gpU.Create(txModel.Db) + if err != nil { + txModel.Log.Errorf("GroupPowerApplyPass err:%v, info:%v", err, gpU) + return err + } + // 更改申请表状态 + err = groupPower_m.OptGroupPowerApplyJoinById(model, apply.Id, userId, optType) + if err != nil { + return err + } + return nil + }) + if err != nil { + return myContext, err + } + + resp.ResponseOk(c, nil) + return myContext, nil +} + +// @Tags 家族 +// @Summary 申请加入列表 +// @Param pageSize query int true "分页大小 默认:10" default(10) +// @Param pageIndex query int true "分页开始索引,偏移量" default(1) +// @Success 200 {object} []group_power_cv.FamilyApplyList +// @Router /v1/groupPower/apply/list [get] +func GroupPowerApplyList(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil { + return myContext, err + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil { + return myContext, err + } + model := domain.CreateModelContext(myContext) + + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil || myGroupPUser.ID == 0 { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 申请列表 + rows, nextPageIndex, hasNextPage, err := groupPower_m.OptGroupPowerApplyList(model, myGroupPUser.GroupPowerId, pageSize, pageIndex) + if err != nil { + return myContext, err + } + + uids := make([]uint64, 0, len(rows)) + for _, v := range rows { + uids = append(uids, v.UserId, v.MgrId) + } + //查找用户信息 + uids = common.UniqueSliceUInt64(uids) + userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true) + + result := make([]*group_power_cv.FamilyApplyList, 0, len(rows)) + for _, v := range rows { + info := &group_power_cv.FamilyApplyList{User: userMap[v.UserId], Time: v.CreatedTime.UnixMilli(), Status: v.IsAccept} + if v.MgrId > 0 { + info.MgrName = userMap[v.MgrId].Nick + } + result = append(result, info) + } + + resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage) + return myContext, nil +} + +// @Tags 家族 +// @Summary 退出/踢出家族 +// @Param type formData int true "1.自己退出,2.踢人" +// @Param userExtId formData string false "用户extId" +// @Success 200 +// @Router /v1/groupPower/quit [post] +func GroupPowerQuit(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + quitType, err := strconv.Atoi(c.PostForm("type")) + if err != nil { + return myContext, myerr.WrapErr(err) + } + if quitType < 1 || quitType > 2 { + return myContext, bizerr.InvalidParameter + } + model := domain.CreateModelContext(myContext) + + if quitType == 1 { // 主动退出 + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + groupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + if groupPUser == nil { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if groupPUser.Role == groupPower_e.GroupPowerUserRoleMgr { + return myContext, bizerr.GroupPowerCannotQuit + } + // 退出家族、log + err = model.Transaction(func(model *domain.Model) error { + return groupPower_m.QuitFamily(model, userId, userId, groupPUser.GroupPowerId) + }) + if err != nil { + return myContext, err + } + + resp.ResponseOk(c, nil) + return myContext, nil + } + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 被踢人信息 + userExtId := c.PostForm("userExtId") + if userExtId == "" { + return myContext, bizerr.InvalidParameter + } + u, err := user_c.GetUserByExternalId(model, userExtId) + if err != nil { + return myContext, err + } + // 被踢者 + gpUKick := groupPower_m.GroupPowerUser{UserId: userId} + kickGroupPUser, err := gpUKick.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + if kickGroupPUser == nil { + return myContext, bizerr.GroupPowerHaveNoJoin + } + // 退出家族、log + err = model.Transaction(func(model *domain.Model) error { + return groupPower_m.QuitFamily(model, u.ID, userId, kickGroupPUser.GroupPowerId) + }) + if err != nil { + return myContext, err + } + + resp.ResponseOk(c, nil) + return myContext, nil +} + +// @Tags 家族 +// @Summary 家族退出列表 +// @Param pageSize query int true "分页大小 默认:10" default(10) +// @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1) +// @Success 200 {object} []group_power_cv.FamilyQuitList +// @Router /v1/groupPower/quit/list [get] +func GroupPowerQuitList(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + pageSize, err := strconv.Atoi(c.Query("pageSize")) + if err != nil { + return myContext, err + } + pageIndex, err := strconv.Atoi(c.Query("pageIndex")) + if err != nil { + return myContext, err + } + model := domain.CreateModelContext(myContext) + + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil || myGroupPUser.ID == 0 { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 列表 + rows, nextPageIndex, hasNextPage, err := groupPower_m.GroupPowerQuitList(model, myGroupPUser.GroupPowerId, pageSize, pageIndex) + if err != nil { + return myContext, err + } + + uids := make([]uint64, 0, len(rows)) + for _, v := range rows { + uids = append(uids, v.UserId, v.MgrId) + } + //查找用户信息 + uids = common.UniqueSliceUInt64(uids) + userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true) + + result := make([]*group_power_cv.FamilyQuitList, 0, len(rows)) + for _, v := range rows { + item := &group_power_cv.FamilyQuitList{User: userMap[v.UserId], Time: v.CreatedTime.UnixMilli()} + if v.UserId == v.MgrId { + item.QuitType = 1 // 主动退出 + } else { + item.QuitType = 2 // 被踢出 + item.MgrName = userMap[v.MgrId].Nick + } + result = append(result, item) + } + + resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage) + return myContext, nil +} + +// @Tags 家族 +// @Summary 设置/取消管理员 +// @Param userExtId formData string false "用户extId" +// @Param type formData int true "1.设置为管理员,2.取消管理员" +// @Success 200 +// @Router /v1/groupPower/admin [post] +func GroupPowerSetAdmin(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + optType, err := strconv.Atoi(c.PostForm("type")) + if err != nil { + return myContext, bizerr.InvalidParameter + } + if optType < 1 || optType > 2 { + return myContext, bizerr.InvalidParameter + } + userExtId := c.PostForm("userExtId") + if userExtId == "" { + return myContext, bizerr.InvalidParameter + } + model := domain.CreateModelContext(myContext) + optUser, err := user_c.GetUserByExternalId(model, userExtId) + if err != nil { + return myContext, err + } + + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role != groupPower_e.GroupPowerUserRoleMgr { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 被操作者是否加入了家族 + gpOptUser := groupPower_m.GroupPowerUser{UserId: optUser.ID} + optGroupPUser, err := gpOptUser.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + if optGroupPUser == nil { + return myContext, bizerr.GroupPowerUserHaveNoJoin + } + // 目标身份 + var targetRole groupPower_e.GroupPowerUserRole + if optType == 1 { + targetRole = groupPower_e.GroupPowerUserRoleAdmin + } else { + targetRole = groupPower_e.GroupPowerUserRoleUser + } + // 和原来的身份是否一致 + if optGroupPUser.Role == targetRole { + return myContext, bizerr.GroupPowerHaveAlreadyChange + } + // 变更 + err = groupPower_m.UpdateFamilyAdmin(model, userId, optGroupPUser.GroupPowerId, targetRole) + if optGroupPUser == nil { + return myContext, myerr.WrapErr(err) + } + + resp.ResponseOk(c, nil) + return myContext, nil +} + +// @Tags 家族 +// @Summary 设置家族信息 +// @Param id formData int true "家族id" +// @Param icon formData string false "家族图片" +// @Param name formData string false "家族名称" +// @Param nameplate formData string false "家族铭牌" +// @Param declaration formData string false "家族宣言" +// @Success 200 group_power_cv.GroupPower +// @Router /v1/groupPower/info/set [post] +func GroupPowerSetInfo(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + type param struct { + Id uint64 `form:"id"` + Name string `form:"name"` + Nameplate string `form:"nameplate"` // 铭牌 + Declaration string `form:"declaration"` // 宣言 + Icon string `form:"icon"` // 头像 + } + var para param + if err := c.ShouldBind(¶); err != nil { + return myContext, err + } + if para.Id <= 0 { + return myContext, bizerr.InvalidParameter + } + model := domain.CreateModelContext(myContext) + + // 判断是否加入了家族 + gpU := groupPower_m.GroupPowerUser{UserId: userId} + myGroupPUser, err := gpU.GetGroupPowerUser(model) + if err != nil { + return myContext, err + } + // 操作者是否加入了家族,是否有操作权限 + if myGroupPUser == nil { + return myContext, bizerr.GroupPowerHaveNoJoin + } + if myGroupPUser.Role != groupPower_e.GroupPowerUserRoleMgr { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 检查铭牌是否能够修改 + if para.Nameplate != "" { + // 等级检查 + gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: myGroupPUser.GroupPowerId}} + groupPInfo, err := gp.Get(model) + if err != nil { + return myContext, err + } + if groupPInfo.Grade < 1 { + return myContext, bizerr.GroupPowerHaveNoPower + } + // 检查铭牌长度和唯一性 + if len(para.Nameplate) > 10 { + return myContext, bizerr.GroupPowerHaveTooLong + } + if groupPower_m.IsExistsNameplate(model, para.Nameplate) { + return myContext, bizerr.GroupPowerCannotRepeated + } + } + + // 修改家族信息 + err = groupPower_m.UpdateFamily(model, para.Id, para.Name, para.Nameplate, para.Declaration, para.Icon) + if err != nil { + return myContext, myerr.WrapErr(err) + } + // 返回家族信息 + gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: para.Id}} + gpInfo, err := gp.Get(model) + if err != nil { + return myContext, myerr.WrapErr(err) + } + gpMember := &groupPower_m.GroupPowerUser{GroupPowerId: gpInfo.ID} + _, total, _, _, err := gpMember.GetBy(model, 5, 0) + if err != nil { + return myContext, myerr.WrapErr(err) + } + groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID}) + info := &group_power_cv.GroupPower{ + Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon, + Grade: gpInfo.Grade, Exp: gpInfo.Exp, NextExp: gpInfo.NextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal, + MemberNum: mysql.Num(total), MemberMax: mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[gp.ID].Grade][0].Num), + } + if info.Icon != "" { + info.Icon = common.MakeFullUrl(info.Icon) + } + // 我在该家族中的角色 + if myGroupPUser != nil && myGroupPUser.GroupPowerId == info.Id { + info.Role = int(myGroupPUser.Role) + } + + resp.ResponseOk(c, info) + return myContext, nil +} diff --git a/route/group_power_r/group_rank.go b/route/group_power_r/group_rank.go new file mode 100644 index 0000000..04d97e6 --- /dev/null +++ b/route/group_power_r/group_rank.go @@ -0,0 +1,232 @@ +package group_power_r + +import ( + "git.hilo.cn/hilo-common/domain" + "git.hilo.cn/hilo-common/mycontext" + "git.hilo.cn/hilo-common/resource/mysql" + "git.hilo.cn/hilo-common/utils" + "github.com/gin-gonic/gin" + "github.com/jinzhu/now" + "hilo-group/_const/enum/groupPower_e" + "hilo-group/cv/group_power_cv" + "hilo-group/cv/user_cv" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/user_m" + "hilo-group/myerr/bizerr" + "hilo-group/req" + "hilo-group/resp" + "strconv" + "time" +) + +// @Tags 国家势力 +// @Summary 家族榜单 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param period path string true "榜单周期 day:日 week:周 month:月" +// @Success 200 {object} group_power_cv.CvGroupPowerRank +// @Router /v1/groupPower/rank/{period} [get] +func GroupPowerRank(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + period := c.Param("period") + if period != "day" && period != "week" && period != "month" { + return myContext, bizerr.InvalidParameter + } + var beginDate, endDate string + switch period { + case "day": + beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02") + case "week": + beginDate, endDate = utils.GetMonday(time.Now()).Format("2006-01-02"), utils.GetMonday(time.Now()).AddDate(0, 0, 6).Format("2006-01-02") + case "month": + beginDate, endDate = now.BeginningOfMonth().Format("2006-01-02"), now.EndOfMonth().Format("2006-01-02") + } + var model = domain.CreateModelContext(myContext) + rank, err := groupPower_m.GetGroupPowerExpRank(model, beginDate, endDate, 30) + if err != nil { + return myContext, err + } + var ids []mysql.ID + for _, g := range rank { + ids = append(ids, g.GroupPowerId) + } + response := group_power_cv.CvGroupPowerRank{} + myGroupPower, err := groupPower_m.GetGroupPowerUserOrNil(model, userId) + if err != nil { + return myContext, err + } + if myGroupPower != nil { + ids = append(ids, myGroupPower.GroupPowerId) + } + grades, err := groupPower_m.MGetGroupPowerGrade(model, ids) + if err != nil { + return myContext, err + } + groupPowers, err := groupPower_m.MGetGroupPowerInfoMap(model, ids) + if err != nil { + return myContext, err + } + for _, v := range rank { + if myGroupPower != nil && v.GroupPowerId == myGroupPower.GroupPowerId && myGroupPower.Role == groupPower_e.GroupPowerUserRoleMgr { + response.MyGroupPower = &group_power_cv.CvGroupPowerRankData{ + CvGroupPowerBase: group_power_cv.CvGroupPowerBase{ + Id: myGroupPower.GroupPowerId, + Icon: groupPowers[myGroupPower.GroupPowerId].Icon, + Name: groupPowers[myGroupPower.GroupPowerId].Name, + Nameplate: groupPowers[myGroupPower.GroupPowerId].Nameplate, + }, + CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{ + Grade: grades[myGroupPower.GroupPowerId].Grade, + Exp: v.Exp, + }, + Rank: v.Rank, + } + } + response.Items = append(response.Items, group_power_cv.CvGroupPowerRankData{ + CvGroupPowerBase: group_power_cv.CvGroupPowerBase{ + Id: v.GroupPowerId, + Icon: groupPowers[v.GroupPowerId].Icon, + Name: groupPowers[v.GroupPowerId].Name, + Nameplate: groupPowers[v.GroupPowerId].Nameplate, + }, + CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{ + Grade: grades[v.GroupPowerId].Grade, + Exp: v.Exp, + }, + Rank: v.Rank, + }) + } + if response.MyGroupPower != nil && response.MyGroupPower.Rank == 0 { + response.MyGroupPower.Rank = 31 // 客户端统一显示30+ + } + resp.ResponseOk(c, response) + return myContext, nil +} + +type GroupPowerStarReq struct { + GroupPowerId mysql.ID `form:"groupPowerId" binding:"required"` + Type groupPower_e.GroupPowerStarType `form:"type" binding:"required"` + PageSize int `form:"pageSize"` + PageIndex int `form:"pageIndex"` +} + +// @Tags 国家势力 +// @Summary 家族之星 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId query int true "家族id" +// @Param type query integer true "类型 1:送礼 2:活跃 3:收礼物" +// @Param pageSize query int false "分页大小 默认:30" default(30) +// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1) +// @Success 200 {object} []group_power_cv.CvGroupPowerStarData +// @Router /v1/groupPower/star [get] +func GroupPowerStar(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + param := new(GroupPowerStarReq) + if err := c.ShouldBindQuery(param); err != nil { + return myContext, err + } + if param.PageIndex <= 0 { + param.PageIndex = 1 + } + if param.PageSize <= 0 { + param.PageSize = 30 + } + var model = domain.CreateModelContext(myContext) + offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize + rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, param.GroupPowerId, param.Type, offset, limit) + if err != nil { + return myContext, err + } + var response []group_power_cv.CvGroupPowerStarData + var userIds []mysql.ID + for _, row := range rank { + userIds = append(userIds, row.UserId) + } + users, err := user_m.GetUserMapByIds(model, userIds) + for _, row := range rank { + user := users[row.UserId] + response = append(response, group_power_cv.CvGroupPowerStarData{ + User: user_cv.CvUserTiny{ + Id: user.ID, + ExternalId: user.ExternalId, + Code: user.Code, + Nick: user.Nick, + Avatar: user.Avatar, + }, + Score: row.Score, + }) + } + resp.ResponsePageBaseOk(c, response, 0, false) + return myContext, nil +} + +// @Tags 国家势力 +// @Summary 家族等级页 +// @Param token header string true "token" +// @Param nonce header string true "随机数字" +// @Param groupPowerId query int true "家族id" +// @Success 200 {object} group_power_cv.CvGroupPowerGradeDetail +// @Router /v1/h5/groupPower/grade/detail [get] +func GroupPowerGradeDetail(c *gin.Context) (*mycontext.MyContext, error) { + myContext := mycontext.CreateMyContext(c.Keys) + userId, err := req.GetUserId(c) + if err != nil { + return myContext, err + } + groupPowerId, err := strconv.ParseUint(c.Query("groupPowerId"), 10, 16) + if err != nil || groupPowerId <= 0 { + return myContext, bizerr.InvalidParameter + } + var model = domain.CreateModelContext(myContext) + groupPowerInfo, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId}) + if err != nil { + return myContext, err + } + gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId}) + if err != nil { + return myContext, err + } + groupPower, ok := groupPowerInfo[groupPowerId] + if !ok { + return myContext, bizerr.GroupNotFound + } + grade := gradeM[groupPowerId] + nextExp := mysql.Num(0) + if grade.Grade != groupPower_e.GroupPowerGradeMax { + nextExp = groupPower_e.GroupPowerGradeExp[grade.Grade+1] + } + expireAt := "" + if grade.ExpireAt.After(time.Now()) { + expireAt = grade.ExpireAt.Format("2006-01-02") + } + isMember := false + if exits, _, err := groupPower_m.CheckGroupPowerUser(model, userId); err != nil { + return myContext, err + } else if exits { + isMember = true + } + response := group_power_cv.CvGroupPowerGradeDetail{ + GroupPowerBase: group_power_cv.CvGroupPowerBase{ + Id: groupPower.ID, + Icon: groupPower.Icon, + Name: groupPower.Name, + Nameplate: groupPower.Nameplate, + }, + GroupPowerGrade: group_power_cv.CvGroupPowerGrade{ + Grade: grade.Grade, + Exp: grade.Exp, + NextExp: nextExp, + ExpireAt: expireAt, + }, + ResGradeList: group_power_cv.CvResGradeList, + PrivilegeList: group_power_cv.GroupPowerGradePrivilegeNum[grade.Grade], + IsMember: isMember, + } + resp.ResponseOk(c, response) + return myContext, nil +} diff --git a/route/group_power_r/inner.go b/route/group_power_r/inner.go new file mode 100644 index 0000000..11989a1 --- /dev/null +++ b/route/group_power_r/inner.go @@ -0,0 +1,93 @@ +package group_power_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-group/_const/enum/groupPower_e" + "hilo-group/_const/enum/msg_e" + "hilo-group/cv/group_power_cv" + "hilo-group/domain/model/groupPower_m" + "hilo-group/domain/model/msg_m" + "hilo-group/domain/model/user_m" + "hilo-group/resp" +) + +type MGetGroupPowerReq struct { + Ids []mysql.ID `form:"ids" binding:"required"` +} + +// @Tags 国家势力-内部 +// @Summary 批量获取国家势力信息 +// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3" +// @Success 200 {object} map[mysql.ID]group_power_cv.CvGroupPowerInfo +// @Router /inner/groupPower/infos [get] +func MGetGroupPowers(c *gin.Context) (*mycontext.MyContext, error) { + myCtx := mycontext.CreateMyContext(c.Keys) + var model = domain.CreateModelContext(myCtx) + var req MGetGroupPowerReq + if err := c.ShouldBindQuery(&req); err != nil { + return myCtx, err + } + groupPowers, err := groupPower_m.MGetGroupPowerInfoMap(model, req.Ids) + if err != nil { + return myCtx, err + } + groupPowerUsers, err := groupPower_m.MGetGroupPowerUsers(model, req.Ids) + if err != nil { + return myCtx, err + } + groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(model, req.Ids) + if err != nil { + return myCtx, err + } + response := make(map[mysql.ID]group_power_cv.CvGroupPowerInfo) + for groupPowerId, info := range groupPowers { + // 成员上限 + var memberMax mysql.Num + grade := groupPowerGrade[groupPowerId].Grade + if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax { + memberMax = mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[groupPowerId].Grade][0].Num) + } + memberNum := mysql.Num(len(groupPowerUsers[groupPowerId])) + if memberNum > memberMax { + memberMax = memberNum + } + response[groupPowerId] = group_power_cv.CvGroupPowerInfo{ + CvGroupPowerBase: group_power_cv.CvGroupPowerBase{ + Id: groupPowerId, + Icon: info.Icon, + Name: info.Name, + Nameplate: info.Nameplate, + }, + CvGroupPowerMember: group_power_cv.CvGroupPowerMember{ + MemberNum: memberNum, + MemberMax: memberMax, + }, + CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{ + Grade: grade, + Exp: groupPowerGrade[groupPowerId].Exp, + }, + } + } + resp.ResponseOk(c, response) + return myCtx, nil +} + +func Test(c *gin.Context) (*mycontext.MyContext, error) { + var model = domain.CreateModelNil() + if err := msg_m.NewUserRecord(model, 4522, msg_e.GroupPowerUserJoin, "frozen", 4522, "", "", "", "", "").Persistent(); err != nil { + return nil, err + } + mgrUser, _ := user_m.GetUser(model, 4522) + err := msg_m.SendEmasMsgAssistant(model, mgrUser.ExternalId, mgrUser.DeviceType) + if err != nil { + return nil, err + } + //err := emas.SendIosMsgAll("全部消息测试") + //if err != nil { + // return nil, err + //} + return nil, nil +} diff --git a/route/group_r/group_info.go b/route/group_r/group_info.go index 51f14bb..160ed4d 100644 --- a/route/group_r/group_info.go +++ b/route/group_r/group_info.go @@ -133,7 +133,7 @@ func GetTheirGroups(c *gin.Context) (*mycontext.MyContext, error) { } model.Log.Info("GetTheirGroups: theirRoles - ", theirRoles) - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return myContext, err } @@ -273,8 +273,15 @@ func GetTheirGroups(c *gin.Context) (*mycontext.MyContext, error) { GroupMedals: medals, }, //HasOnMic: onMicScore[i.GroupId] != 0, - GroupPowerId: powerIds[gi.Owner], - GroupPowerName: powerNames[gi.Owner], + GroupPowerId: powerIds[gi.Owner], + GroupPowerName: powerNames[gi.Owner], + GroupPowerNameplate: powerNameplates[gi.Owner], + GroupPower: group_cv.GroupPower{ + Id: powerIds[gi.Owner], + Name: powerNames[gi.Owner], + Nameplate: powerNameplates[gi.Owner], + Grade: powerGrades[gi.Owner], + }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i.GroupId]), @@ -362,7 +369,7 @@ func PluginReady(c *gin.Context) (*mycontext.MyContext, error) { // @Param token header string true "token" // @Param nonce header string true "随机数字" // @Param groupId path string true "群ID" -// @Success 200 {object} cv.RoomInfo +// @Success 200 {object} group_cv.RoomInfo // @Router /v1/imGroup/roomInfo/{groupId} [get] func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) @@ -1195,7 +1202,7 @@ func GroupMedalAll(c *gin.Context) (*mycontext.MyContext, error) { // @Param token header string true "token" // @Param nonce header string true "随机数字" // @Param groupId query string false "群ID" -// @Success 200 {object} cv.RoomMedalInfo +// @Success 200 {object} group_cv.RoomMedalInfo // @Router /v1/imGroup/medal/room [get] func GetRoomMedal(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) diff --git a/route/group_r/group_list.go b/route/group_r/group_list.go index d6a8928..5a31d97 100644 --- a/route/group_r/group_list.go +++ b/route/group_r/group_list.go @@ -246,7 +246,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { groupIds = append(groupIds, i.ImGroupId) owners = append(owners, i.Owner) } - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return myContext, err } @@ -338,9 +338,16 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { MicNumType: int(i.MicNumType), GroupMedals: medals, }, - HasOnMic: true, - GroupPowerId: powerIds[i.Owner], - GroupPowerName: powerNames[i.Owner], + HasOnMic: true, + GroupPowerId: powerIds[i.Owner], + GroupPowerName: powerNames[i.Owner], + GroupPowerNameplate: powerNameplates[i.Owner], + GroupPower: group_cv.GroupPower{ + Id: powerIds[i.Owner], + Name: powerNames[i.Owner], + Nameplate: powerNameplates[i.Owner], + Grade: powerGrades[i.Owner], + }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[i.ImGroupId]), @@ -468,7 +475,7 @@ func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) { for _, group := range groupInfos { owners = append(owners, group.Owner) } - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return myContext, err } @@ -555,9 +562,16 @@ func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) { MicNumType: int(group.MicNumType), GroupMedals: medals, }, - HasOnMic: true, - GroupPowerId: powerIds[group.Owner], - GroupPowerName: powerNames[group.Owner], + HasOnMic: true, + GroupPowerId: powerIds[group.Owner], + GroupPowerName: powerNames[group.Owner], + GroupPowerNameplate: powerNameplates[group.Owner], + GroupPower: group_cv.GroupPower{ + Id: powerIds[group.Owner], + Name: powerNames[group.Owner], + Nameplate: powerNameplates[group.Owner], + Grade: powerGrades[group.Owner], + }, }, MicUsers: micUsers, RoomUserCount: uint(roomCount[group.ImGroupId]), @@ -1150,7 +1164,7 @@ func buildRoleMembers(model *domain.Model, groupId string, userId uint64) ([]gro // @Param countryShortName query string true "国家缩写" // @Param pageSize query int true "分页大小 默认:10" default(10) // @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1) -// @Success 200 {object} cv.PopularGroupInfo +// @Success 200 {object} group_cv.PopularGroupInfo // @Router /v1/imGroup/country [get] func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) @@ -1289,7 +1303,7 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) { groupIds = append(groupIds, i.ImGroupId) owners = append(owners, i.Owner) } - powerIds, powerNames, err := group_power_cv.BatchGetGroupPower(model.Db, owners) + powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners) if err != nil { return myContext, err } @@ -1369,9 +1383,16 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) { MicNumType: int(i.MicNumType), GroupMedals: medals, }, - HasOnMic: micGroupNum[i.ImGroupId] > 0, - GroupPowerId: powerIds[i.Owner], - GroupPowerName: powerNames[i.Owner], + HasOnMic: micGroupNum[i.ImGroupId] > 0, + GroupPowerId: powerIds[i.Owner], + GroupPowerName: powerNames[i.Owner], + GroupPowerNameplate: powerNameplates[i.Owner], + GroupPower: group_cv.GroupPower{ + Id: powerIds[i.Owner], + Name: powerNames[i.Owner], + Nameplate: powerNameplates[i.Owner], + Grade: powerGrades[i.Owner], + }, }, MicUsers: []user_cv.CvUserTiny{}, RoomUserCount: uint(roomCount[i.ImGroupId]), @@ -1436,7 +1457,7 @@ func getCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, // @Param signature header string true "sha1加密结果" // @Param deviceType header string true "系统类型 ios android" // @Param deviceVersion header string true "系统版本" -// @Success 200 {object} cv.CvCountry +// @Success 200 {object} group_cv.CvCountry // @Router /v1/imGroup/country/prior [get] func GroupountryPrior(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) diff --git a/route/group_r/group_mic.go b/route/group_r/group_mic.go index 1a6cfa8..0d8d6bf 100644 --- a/route/group_r/group_mic.go +++ b/route/group_r/group_mic.go @@ -921,7 +921,7 @@ func GroupMicMute(c *gin.Context) (*mycontext.MyContext, error) { // @Param nonce header string true "随机数字" // @Param groupId formData string true "群ID" // @Param content formData string true "内容" -// @Success 200 {object} cv.CvDiamond +// @Success 200 {object} diamond_cv.CvDiamond // @Router /v1/imGroup/mic/mass [post] func GroupMicMass(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) @@ -960,7 +960,7 @@ func GroupMicMass(c *gin.Context) (*mycontext.MyContext, error) { // @Param nonce header string true "随机数字" // @Param groupId formData string true "群ID" // @Param content formData string true "内容" -// @Success 200 {object} cv.CvDiamond +// @Success 200 {object} diamond_cv.CvDiamond // @Router /v1/imGroup/mgr/mass [post] func GroupMgrMass(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) diff --git a/route/group_r/group_support.go b/route/group_r/group_support.go index 57c20c9..7164f5f 100644 --- a/route/group_r/group_support.go +++ b/route/group_r/group_support.go @@ -67,7 +67,7 @@ func GetSupportPage(c *gin.Context) (*mycontext.MyContext, error) { // @Param token header string true "token" // @Param nonce header string true "随机数字" // @Param groupId query string false "群ID" -// @Success 200 {object} cv.SupportPageDetail +// @Success 200 {object} group_cv.SupportPageDetail // @Router /v1/imGroup/support/detail [get] func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) @@ -256,7 +256,7 @@ func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) { // @Param nonce header string true "随机数字" // @Param groupId path string true "群ID" // @Param supporters formData string false "群支持者的externalId,用逗号分隔" -// @Success 200 {object} cv.AwardResult +// @Success 200 {object} group_cv.AwardResult // @Router /v1/imGroup/support/award/{groupId} [post] func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) diff --git a/route/mic_r/inner.go b/route/mic_r/inner.go new file mode 100644 index 0000000..d212ae9 --- /dev/null +++ b/route/mic_r/inner.go @@ -0,0 +1,37 @@ +package mic_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-group/domain/model/mic_m" + "hilo-group/resp" +) + +type MGetUserOnMicSecondsReq struct { + Day string `form:"day" binding:"required"` + Ids []mysql.ID `form:"ids" binding:"required"` +} + +// @Tags 麦位-内部 +// @Summary 批量获取用户天上麦时长 +// @Param day query string true "天 格式2006-001-02" +// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3" +// @Success 200 {object} map[uint64]uint32 +// @Router /inner/mic/onMicSeconds [get] +func MGetUserOnMicSeconds(c *gin.Context) (*mycontext.MyContext, error) { + myCtx := mycontext.CreateMyContext(c.Keys) + var model = domain.CreateModelContext(myCtx) + var req MGetUserOnMicSecondsReq + if err := c.ShouldBindQuery(&req); err != nil { + return myCtx, err + } + onMic, err := mic_m.MGetUserOnMicSeconds(model, req.Day, req.Ids) + if err != nil { + return myCtx, err + } + response := onMic + resp.ResponseOk(c, response) + return myCtx, nil +} diff --git a/route/router.go b/route/router.go index ab74633..b143095 100644 --- a/route/router.go +++ b/route/router.go @@ -9,8 +9,10 @@ import ( "hilo-group/_const/enum/mgr_e" _ "hilo-group/docs" "hilo-group/domain/model/mgr_m" + "hilo-group/route/charge_r" "hilo-group/route/group_power_r" "hilo-group/route/group_r" + "hilo-group/route/mic_r" ) func InitRouter() *gin.Engine { @@ -125,7 +127,40 @@ func InitRouter() *gin.Engine { groupPower.GET("/team", wrapper(group_power_r.GroupPowerTeam)) groupPower.GET("/billboard/week", wrapper(group_power_r.GroupPowerBillboardWeek)) groupPower.GET("/billboard/owner/week", wrapper(group_power_r.GroupPowerBillboardOwnerWeek)) + groupPower.GET("/info", wrapper(group_power_r.GroupPowerInfo)) + groupPower.GET("/rooms", wrapper(group_power_r.GroupPowerRooms)) + groupPower.GET("/members", wrapper(group_power_r.GroupPowerMembers)) + groupPower.POST("/apply", wrapper(group_power_r.GroupPowerApplyJoin)) + groupPower.POST("/apply/pass", wrapper(group_power_r.GroupPowerApplyPass)) + groupPower.GET("/apply/list", wrapper(group_power_r.GroupPowerApplyList)) + groupPower.POST("/quit", wrapper(group_power_r.GroupPowerQuit)) + groupPower.GET("/quit/list", wrapper(group_power_r.GroupPowerQuitList)) + groupPower.POST("/admin", wrapper(group_power_r.GroupPowerSetAdmin)) + groupPower.GET("/rank/:period", wrapper(group_power_r.GroupPowerRank)) + groupPower.GET("/star", wrapper(group_power_r.GroupPowerStar)) + groupPower.POST("/info/set", wrapper(group_power_r.GroupPowerSetInfo)) } + h5GroupPower := v1.Group("/h5/groupPower") + { + h5GroupPower.GET("/grade/detail", wrapper(group_power_r.GroupPowerGradeDetail)) + } + + charge := v1.Group("/charge") + { + charge.GET("/share", wrapper(charge_r.CanShareChargeLink)) + } + + // 内部接口 + inner := r.Group("/inner") + innerGroupPower := inner.Group("/groupPower") + { + innerGroupPower.GET("/infos", wrapper(group_power_r.MGetGroupPowers)) + } + innerMic := inner.Group("/mic") + { + innerMic.GET("/onMicSeconds", wrapper(mic_r.MGetUserOnMicSeconds)) + } + r.GET("/test", wrapper(group_power_r.Test)) return r } diff --git a/test/.env b/test/.env new file mode 100644 index 0000000..aaa4b80 --- /dev/null +++ b/test/.env @@ -0,0 +1 @@ +MODE=local diff --git a/test/group_power_test.go b/test/group_power_test.go new file mode 100644 index 0000000..3a56844 --- /dev/null +++ b/test/group_power_test.go @@ -0,0 +1,12 @@ +package test + +import ( + "git.hilo.cn/hilo-common/domain" + "hilo-group/domain/model/groupPower_m" + "testing" +) + +func TestGetAllGroupPowerOwner(t *testing.T) { + owners, err := groupPower_m.GetAllGroupPowerOwners(domain.CreateModelNil()) + println(owners, err) +} diff --git a/test/local.ini b/test/local.ini new file mode 100644 index 0000000..81bbf6b --- /dev/null +++ b/test/local.ini @@ -0,0 +1,171 @@ +[DATABASE] +MYSQL_HOST=47.244.34.27:3306 +MYSQL_USERNAME=root +MYSQL_PASSWORD=yX0jPAhO0I4s2zlA +MYSQL_DB=hilo +[DATABASECODE] +MYSQL_HOST=47.244.34.27:3306 +MYSQL_USERNAME=root +MYSQL_PASSWORD=yX0jPAhO0I4s2zlA +MYSQL_DB=hilo_code +[REDIS] +REDIS_HOST=47.244.34.27:6379 +REDIS_PASSWORD=8QZ9JD1zLvPR3yHf +[JWT] +SECRET=hilo1632 +ISSUER_API=hiloApi +ISSUER_Mgr=hiloMgr +EXPIRE=240h +[GAMEJWT] +SECRET=hilo1632 +ISSUER_CLIENT=hiloClient +ISSUER_SERVER=hiloServer +EXPIRE=240h +[APP] +MASTER=false +BIZ_SECRET=biz +WEB_SECRET=webHilo1258 +OPERATION_SECRET=operation1258236 +SUPERUSER=2701,2831 +OFFICIAL_STAFF=2701,2831 +OFFICIAL_GROUP=@TGS#3NC2ATRHS,@TGS#33W3KNLHK +MINIMAL_VERSION_ANDROID=212 +MINIMAL_VERSION_IOS=100 +MODERATE=AWS +[OSS] +OSS_ACCESS_KEY_ID=LTAIxdazV2pCuV3T +OSS_ACCESS_KEY_SECRET=zuAnreAXQ6vlAKnvvmolFLfb1N5w5S +OSS_ROLE_ARN=acs:ram::1509841556585969:role/aliyunosstokengeneratorrole +OSS_END_POINT=http://oss-accelerate.aliyuncs.com +OSS_BUCKET=starvoice +OSS_CDN=https://oss.chathot.me/ +OSS_EXPIRED_TIME=3600 +OSS_STS_POINT=me-east-1 +OSS_STS=sts-faceline-demo +OSS_STS_AES=484194d4d0f968a7 +[AWS] +AWS_BUCKET=starchat +AWS_CDN=https://image.whoisamy.shop/ +AWS_DIR=hilo/ +CONFIDENCE=80 +[RONGYUN] +RONG_CLOUD_APP_KEY=pvxdm17jpe9tr +RONG_CLOUD_APP_SECRET=rI4giiKWaBS4 +RONG_CLOUD_URL=https://api-sg01.ronghub.com +[TENCENTYUN] +TENCENTYUN_APP_ID=1400548270 +TENCENTYUN_KEY=321bd60f73096b059c7350f1cd97d51028850b34fa58c5c0d26bb4a19e783de8 +TX_OVERSEA_APP_ID=40000066 +TX_OVERSEA_KEY=3ab68ea5bddc8774d90b8c764ae71188914bd5fd06f30b28790c51e44ca7885c +[EMAS] +REGION_ID=cn-hangzhou +ACCESS_KEY_ID=LTAI4FhNPzxdzD4w6bHirL9Z +ACCESS_KEY_SECRET=OQvUJpXDrjGi3g1F2aHiAIFWIvLdbP +ANDROID_APP_KEY=30250713 +ANDROID_APP_SECRET=cae7b9a9d3e54577d2c3b60bf6d23047 +IOS_APP_KEY=30240346 +IOS_APP_SECRET=57f33ab9ca6a957a8c659f2b0b6d1205 +APNS=DEV +[AGORA] +APP_ID=fc3e087f701b4f788099e1924c3cc7b0 +APP_CERTIFICATE=ff29c100a613433db82324e8411eabc8 +CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a +CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce +CALLBACK_SECRET=n_ZizS_N8 +[CHECKOUT] +AUTHORIZATION=sk_test_9b5e771c-5a3f-4a8d-a4da-31b19bd43d83 +URL=https://api.sandbox.checkout.com/hosted-payments +H5=http://test.chathot.me/action/hiloHtml/22_05_30_recharge/topup.html +HILO_SECRET_KEY=sk_test_dfbaa3b6-135d-4376-9996-2089b7d8a086 +[MATCH] +MATCH_FREE_TIME=60 +MATCH_FREE_TIME_VIP=300 +MATCH_ADD_TIME_FREE=90 +MATCH_AGORA_TIME=30 +MATCH_CYCLE=8 +MATCH_USER_EXPIRES=480 +MATCH_SUCCESS_WAIT_DURATION=10 +MATCH_SUCCESS_SINGLE_WAIT_TIME_IN_SEC=12 +MATCH_SUCCESS_DUAL_WAIT_TIME_IN_SEC=15 +[ONLINE] +ONLINE_CYCLE=600 +ONLINE_USER_EXPIRES=259200 +[VIDEO] +VIDEO_DAILY_FREE_NUM=20 +VIDEO_FREE_TIME=60 +VIDEO_FREE_TIME_VIP=300 +VIDEO_ADD_TIME_FREE=60 +VIDEO_AGORA_TIME=30 +VIDEO_MINUTE_NORMAL=1000 +VIDEO_MINUTE_UNION=2000 +[SESSION] +SESSION_DAILY_FREE_NUM=50 +[BEAN] +DIAMOND_BEAN_RATE=90 +[H5] +USER_LEVEL=http://test.chathot.me/action/activityhtml/hiloUserLevel/index.html +GROUP_SUPPORT=http://test.chathot.me/action/activityhtml/21_12_06/page.html +LUCKY_WHEEL=https://h5.whoisamy.shop/action/activityhtml/21_12_30/page.html +NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html +[GROUPIM] +MSG_SORT_EXPIRE=43200 +MSG_SORT_SNAP=300 +[GRADE] +CHARM_SPEED_VIP=15 +ACTITY_SPEED_VIP=15 +WEALTH_SPEED_VIP=15 +[LIKE] +I_LIKE_NUM=30 +I_LIKE_NUM_VIP=100 +I_LIKE_NUM_NOBLE=1000 +[APPLEPAY] +PASSWORD=38702750a05c4cb09c9d6ca646835634 +[REGISTER] +IMEI_TOTAL=3 +IMEI_OAUTH=2 +ACCOUNT_IP=100 +ACCOUNT_IP_DURATION=21600 +[BANNER] +GIFT_BANNER_LEVEL1=100 +GIFT_BANNER_LEVEL2=2000 +GIFT_BANNER_LEVEL3=5000 +[DIAMOND] +DAILY_LOGIN_IMEI_LIMIT=200 +DAILY_LOGIN_IP_LIMIT=5 +PRIVATE_GIFT_RETURN=1440 +NEW_USER_INVITE_AWARD=5000 +[LUCKY_WHEEL] +MINIMAL_PARTICIPANT=2 +WAIT_TIMELONG=10 +WINNER_DIAMOND_BANNER=100 +[GROUP_CUSTOM_THEME] +PIC_LIMIT=5 +DAY=10 +[GIFT] +WALL_DIAMOND=10 +[DAILY] +LOGIN_COMMON=5 +LOGIN_VIP=300 +[DAILY] +LOGIN_COMMON=5 +LOGIN_VIP=300 +[FRUIT_TYCOON] +POOL_RATIO=20 +WATERMELON_RATIO=70 +[ACTIVITY] +COUNTRY_STAR_POOL_RATIO=20 +COUNTRY_STAR_ORDINARY_RATIO=20 +[PAYER_MAX] +URL=https://pay-gate-uat.payermax.com/aggregate-pay-gate/api/gateway +KEY=d50d149a883b8bb6 +MERCHANT_ID=SP11018326 +BIZ_TYPE=CUSTOMIZE +VERSION=2.3 +FRONT_CALLBACK_URL=https://www.hiloconn.com +SHOW_RESULT=1 +EXPIRE_TIME=1800 +LANGUAGE=en +[SUD] +API_LIST=https://sim-asc.sudden.ltd +[URL] +BIZ_HTTP=https://test.apiv1.faceline.live \ No newline at end of file -- 2.22.0