Commit 7aca0b0f authored by hujiebin's avatar hujiebin

init

parents
Pipeline #1900 failed with stages
MODE=local
.idea
/protocol/userProxy/
/protocol/userCenter/
/protocol/biz/
proto:
protoc --go_out=./ --go-grpc_out=. ./protocol/*.proto
\ No newline at end of file
This diff is collapsed.
package algo
import (
"context"
"encoding/json"
"github.com/go-redis/redis/v8"
"hilo-algoCenter/common/config"
"hilo-algoCenter/common/mylogrus"
"hilo-algoCenter/common/redisCli"
"strconv"
"strings"
"time"
)
type RecommendUserCache struct {
UserId uint64
Sex uint8
Country string
ExternalId string
}
// MatchCycle 匹配周期
type MatchCycle struct {
cycle string
}
type MatchTradeUnionCache struct {
UserId uint64
Sex uint8
Country string
ExternalId string
}
// MatchUserCache 用户信息
type MatchUserCache struct {
UserId uint64
Sex uint8
Country string
ExternalId string
IsVip bool
}
// MatchRelation 用户关系分数
type MatchRelation struct {
UserId uint64
RelationUserId uint64
Score float64
}
func GetMatchCycle() int64 {
return time.Now().Unix() / int64(config.GetMatchConfig().MATCH_CYCLE)
}
func SetCycle(cycle int64) (bool, error) {
return redisCli.RedisClient.SetNX(context.Background(), GetPrefixMatchCycle(cycle), cycle, time.Hour).Result()
}
// InitMatchCycle 初始化匹配周期
func InitMatchCycle(cycle int64) *MatchCycle {
return &MatchCycle{cycle: strconv.Itoa(int(cycle))}
}
func (matchCycle *MatchCycle) GetCycle() string {
return matchCycle.cycle
}
func (matchCycle *MatchCycle) GetUser(userIds []string) (map[string]MatchUserCache, error) {
key := GetPrefixMatchUser(matchCycle.cycle)
dList, err := redisCli.RedisClient.HMGet(context.Background(), key, userIds...).Result()
if err != nil {
return nil, err
}
userCacheMap := map[string]MatchUserCache{}
for _, v := range dList {
//转换成json
matchUserCache := MatchUserCache{}
if err := json.Unmarshal([]byte(v.(string)), &matchUserCache); err != nil {
mylogrus.MyLog.Errorf("match cache user 转换成结构失败,string:%v, 错误:%v", v.(string), err)
}
userCacheMap[strconv.Itoa(int(matchUserCache.UserId))] = matchUserCache
}
return userCacheMap, nil
}
// GetExcellentData 获取某个周期下,获取所有的质量分数
func (matchCycle *MatchCycle) GetExcellentData() ([]redis.Z, error) {
key := GetPrefixMatchExcellent(matchCycle.cycle)
zList, err := redisCli.RedisClient.ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
return zList, nil
}
// GetPriorityData 获取某个周期下,获取的排序数据
func (matchCycle *MatchCycle) GetPriorityData() ([]redis.Z, error) {
key := GetPrefixMatchPriority(matchCycle.cycle)
zList, err := redisCli.RedisClient.ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
return zList, nil
}
// GetRelationData 获取关系分数
func (matchCycle *MatchCycle) GetRelationData(userId string) ([]MatchRelation, error) {
key := GetPrefixMatchRelation(matchCycle.cycle, userId)
values, err := redisCli.RedisClient.HVals(context.Background(), key).Result()
if err != nil {
return nil, err
}
var matchRelations []MatchRelation
for _, v := range values {
var matchRelation MatchRelation
if err := json.Unmarshal([]byte(v), &matchRelation); err != nil {
mylogrus.MyLog.Errorf("match cache matchRelations 转换成结构失败,string:%v, 错误:%v", v, err)
}
matchRelations = append(matchRelations, matchRelation)
}
return matchRelations, nil
}
//匹配第一帧
const matchCallReady = "match_call_ready_{matchUid}"
func GetPrefixMatchCycle(cycle int64) string {
return strings.Replace(matchCallReady, "{matchUid}", strconv.Itoa(int(cycle)), -1)
}
//推荐用户, 记录起来,用户算法中心获取。
const recommendUser = "recommend_user"
func GetPreRecommendUser() string {
return recommendUser
}
//匹配的工会用户
const matchTradeUnion = "match_trade_union_{version}"
func GetPreMatchTradeUnion(version string) string {
return strings.Replace(matchTradeUnion, "{version}", version, -1)
}
//匹配,用户信息
const matchUserKey = "match_user_{version}"
func GetPrefixMatchUser(version string) string {
return strings.Replace(matchUserKey, "{version}", version, -1)
}
//匹配,质量分数
const matchExcellent = "match_excellent_{version}"
func GetPrefixMatchExcellent(version string) string {
return strings.Replace(matchExcellent, "{version}", version, -1)
}
//匹配,用户优先度排序
const matchPriority = "match_priority_{version}"
func GetPrefixMatchPriority(version string) string {
return strings.Replace(matchPriority, "{version}", version, -1)
}
//匹配,关系分数
const matchRelation = "match_relation_{version}_{userId}"
func GetPrefixMatchRelation(version string, userId string) string {
return strings.Replace(strings.Replace(matchRelation, "{version}", version, -1), "{userId}", userId, -1)
}
//匹配,拉黑名单
const matchBlock = "match_block_{version}"
func GetPrefixMatchBlock(version string) string {
return strings.Replace(matchBlock, "{version}", version, -1)
}
//匹配,条件性别
const matchConditionSex = "match_condition_sex_{version}"
func GetPrefixMatchConditionSex(version string) string {
return strings.Replace(matchConditionSex, "{version}", version, -1)
}
//匹配,条件国家
const matchConditionCountry = "match_condition_country_{version}"
func GetPrefixMatchConditionCountry(version string) string {
return strings.Replace(matchConditionCountry, "{version}", version, -1)
}
// GetRecommendCache 获取推荐人信息
func GetRecommendCache() ([]RecommendUserCache, error) {
//获取推荐人信息缓存
key := GetPreRecommendUser()
strs, err := redisCli.RedisClient.HVals(context.Background(), key).Result()
if err != nil {
return nil, err
}
var recommendUserCaches []RecommendUserCache
for i := 0; i < len(strs); i++ {
var recommendUserCache RecommendUserCache
if err := json.Unmarshal([]byte(strs[i]), &recommendUserCache); err != nil {
mylogrus.MyLog.Errorf("match cache recommendUserCache 转换成结构失败,string:%v, 错误:%v", strs[i], err)
}
recommendUserCaches = append(recommendUserCaches, recommendUserCache)
}
return recommendUserCaches, nil
}
func GetMatchTradeUnionCache(version string) ([]MatchTradeUnionCache, error) {
key := GetPreMatchTradeUnion(version)
strs, err := redisCli.RedisClient.HVals(context.Background(), key).Result()
if err != nil {
return nil, err
}
var matchTradeUnionCaches []MatchTradeUnionCache
for i := 0; i < len(strs); i++ {
var matchTradeUnionCache MatchTradeUnionCache
if err := json.Unmarshal([]byte(strs[i]), &matchTradeUnionCache); err != nil {
mylogrus.MyLog.Errorf("match cache matchTradeUnionCache 转换成结构失败,string:%v, 错误:%v", strs[i], err)
}
matchTradeUnionCaches = append(matchTradeUnionCaches, matchTradeUnionCache)
}
return matchTradeUnionCaches, nil
}
func (matchCycle *MatchCycle) CheckBlock(userId string, otherUserId string) (bool, error) {
key := GetPrefixMatchBlock(matchCycle.cycle)
u, _ := strconv.ParseUint(userId, 10, 64)
o, _ := strconv.ParseUint(otherUserId, 10, 64)
if u > o {
flag, err := redisCli.RedisClient.SIsMember(context.Background(), key, userId+"_"+otherUserId).Result()
if err != nil {
return flag, err
}
return flag, err
} else {
flag, err := redisCli.RedisClient.SIsMember(context.Background(), key, otherUserId+"_"+userId).Result()
if err != nil {
return flag, err
}
return flag, err
}
}
func (matchCycle *MatchCycle) GetConditionSex(userId string) (string, error) {
key := GetPrefixMatchConditionSex(matchCycle.cycle)
str, err := redisCli.RedisClient.HGet(context.Background(), key, userId).Result()
if err != nil {
return "", nil
}
return str, nil
}
func (matchCycle *MatchCycle) GetConditionCountry(userId string) (string, error) {
key := GetPrefixMatchConditionCountry(matchCycle.cycle)
str, err := redisCli.RedisClient.HGet(context.Background(), key, userId).Result()
if err != nil {
return "", nil
}
return str, nil
}
package common
import (
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"time"
)
const (
MsgTypeLogin = 1 + iota
MsgTypeLoginRsp
MsgTypeHeartBeat
MsgTypeHeartBeatRsp
MsgTypeKickUser
MsgTypeBiz = 7
MsgTypeBizRsp
)
const (
MsgTypeMatchSuccess = 100 + iota
MsgTypeMatchConfirm
MsgTypeCallReady
MsgTypeAddTimeGift
MsgTypeAddTimeFree
)
const (
MsgTypeRecallWindow = 109
MsgTypeVideo = 110 // 1v1视频-v1-黄钻
MsgTypeVideoCallReady = 111
MsgTypeLikeEach = 112
MsgTypeLikeMe = 113
MsgTypeDailyInAppDiamond = 114
MsgTypeGlobalGiftBanner = 115 // 礼物横幅
MsgTypeGlobalGiftBannerRsp = 116
MsgTypeLuckyWheel = 117 //已丢弃
MsgTypeLuckyWheelBanner = 118
MsgTypeDiamondChange = 119 // Kludge:事实上是通用的钻石变更通知了
MsgTypeConfigChange = 120 // 配置变更通知
MsgTypeGlobalRocketNotice = 121 // 火箭全局横幅
MsgTypeGroupChatNotice = 122 // 群发消息弹窗
MsgTypeGlobalBroadcast = 123 // 群发消息弹窗
MsgMicTaskFinish = 124 // 麦上任务完成
MsgFruitMachine = 125 // 水果机开奖
MsgTypeNobleChange = 126 // 贵族变更
MsgTypeJoinGroup = 127 // 加入群组成功
MsgTypeVideoTimeMinuteSuccess = 128 // 1对1视频加时成功
MsgTypeVideoTimeMinuteCheck = 129 // 1对1视频加时检查
MsgTypeVideoMiss = 130 // 1对1视频错过
MsgTypeRoomGroupActivity = 131 // 进房,群组活动推送
MsgTypeVideoV2 = 132 // 1v1视频-v2-粉钻
MsgTypeVideoV2TimeMinuteCheck = 133 // 1v1视频-v2-加时检查
MsgTypeVideoV2CallReady = 134 // 1v1视频-v2-callReady
MsgTypeVideoV2TimeMinuteSuccess = 135 // 1v1视频-v2-加时成功
MsgTypeMatchV2Success = 140 // 匹配-v2-成功
MsgTypeMatchV2Confirm = 141 // 匹配-v2-确认
MsgTypeMatchV2CallReady = 142 // 匹配-v2-callReady
MsgTypeMatchV2AddTimeGift = 143 // 匹配-v2-送礼加时长
)
const (
RoomBannerChange = 1 // 房间banner变更
GiftConfigChange = 2 // 礼物配置变更
OpenScreenChange = 3 // 开屏配置变更
MatchConfigChange = 4 // 匹配配置发生了变化
)
func EncodeMessage(msgType uint32, serialNum uint64, userdata []byte) []byte {
msg := make([]byte, 26)
dataLen := len(userdata)
binary.BigEndian.PutUint16(msg, 1)
binary.BigEndian.PutUint32(msg[2:], msgType)
binary.BigEndian.PutUint64(msg[6:], serialNum)
binary.BigEndian.PutUint64(msg[14:], uint64(time.Now().UnixNano()/1000))
binary.BigEndian.PutUint32(msg[22:], uint32(dataLen))
msg = append(msg, userdata...)
checkSum := crc32.ChecksumIEEE(msg)
msg = append(msg, 0, 0, 0, 0)
binary.BigEndian.PutUint32(msg[26+dataLen:], checkSum)
return msg
}
func DecodeMessage(message []byte) (uint32, uint64, uint64, []byte, error) {
length := len(message)
// 保证消息至少有26bytes
if length >= 26 {
//version := binary.BigEndian.Uint16(message[0:2])
msgType := binary.BigEndian.Uint32(message[2:6])
msgId := binary.BigEndian.Uint64(message[6:14])
timeStamp := binary.BigEndian.Uint64(message[14:22])
dataLen := binary.BigEndian.Uint32(message[22:26])
//log.Printf("DecodeMessage version = %d, msgType = %d, msgId = %d, timeStamp = %d, dataLen = %d\n", version, msgType, msgId, timeStamp, dataLen)
// 保证ws消息至少有msgLen长
if uint32(length) >= dataLen+30 {
pbData := message[26 : dataLen+26]
checksum := binary.BigEndian.Uint32(message[dataLen+26 : dataLen+30])
//fmt.Printf("pbData size = %d, checksum = %d\n", len(pbData), checksum)
myCheckSum := crc32.ChecksumIEEE(message[0 : dataLen+26])
if checksum != myCheckSum {
return 0, msgId, timeStamp, nil, errors.New("checksum error")
}
return msgType, msgId, timeStamp, pbData, nil
} else {
fmt.Printf("payload too short length = %d, msgType = %d\n", length, msgType)
return 0, msgId, timeStamp, nil, errors.New("payload too short")
}
} else {
fmt.Printf("message too short for header %d\n ", length)
return 0, 0, 0, nil, errors.New("message too short")
}
}
This diff is collapsed.
package consul
import (
"fmt"
"github.com/hashicorp/consul/api"
"math/rand"
"strconv"
)
func GetAgentInfo(client *api.Client) (string, string) {
info, err := client.Agent().Self()
if err != nil {
fmt.Printf("%v\n", err)
return "", ""
}
if info == nil {
fmt.Println("Fail to get consul info.")
return "", ""
}
ip := ""
inter := info["DebugConfig"]["AdvertiseAddrLAN"]
switch inter.(type) {
case string:
ip = inter.(string)
break
}
nodeName := ""
inter = info["Config"]["NodeName"]
switch inter.(type) {
case string:
nodeName = inter.(string)
break
}
return ip, nodeName
}
func SelectService(cataLog *api.Catalog, serviceName string, nodeName string) (string, error) {
services, _, err := cataLog.Service(serviceName, "", nil)
if err != nil {
return "", err
}
if len(services) == 0 {
fmt.Println("userCenter not found in catalog.")
return "", nil
}
var count int32 = 0
addr := ""
for _, s := range services {
fmt.Printf("service info: %v\n", s)
if s.ServiceWeights.Passing == 1 {
count++
if s.Node == nodeName {
addr = s.ServiceAddress + ":" + strconv.Itoa(s.ServicePort)
break
} else {
if rand.Int31n(count) == 0 {
addr = s.ServiceAddress + ":" + strconv.Itoa(s.ServicePort)
}
}
}
}
return addr, nil
}
func GetServices(cataLog *api.Catalog, serviceName string) ([]string, error) {
addrs := make([]string, 0)
services, _, err := cataLog.Service(serviceName, "", nil)
if err == nil {
for _, s := range services {
fmt.Printf("service info: %s, %s, %s:%d", s.ID, s.Node, s.ServiceAddress, s.ServicePort)
if s.ServiceWeights.Passing == 1 {
addrs = append(addrs, s.ServiceAddress+":"+strconv.Itoa(s.ServicePort))
}
}
}
return addrs, nil
}
package mylogrus
import (
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"hilo-algoCenter/common/config"
"io"
"os"
"path/filepath"
"time"
)
const logDir = "/var/log/hilo/"
var filenamePrefix string
var MyLog = logrus.New()
func Info(v interface{}) {
MyLog.Info("")
}
func init() {
filenamePrefix = logDir + filepath.Base(os.Args[0]) + "."
//if runtime.GOOS == "darwin" { // mac本地调试
// filenamePrefix = "./log/hilo/" + filepath.Base(os.Args[0]) + "."
//}
// stderr日志重定向
MyLog.SetOutput(os.Stdout)
RewriteStderrFile()
if config.AppIsRelease() {
MyLog.SetFormatter(&logrus.JSONFormatter{
DisableHTMLEscape: true,
TimestampFormat: "2006-01-02 15:04:05.000",
})
hook := lfshook.NewHook(lfshook.WriterMap{
logrus.DebugLevel: getLevelWrite(logrus.DebugLevel),
logrus.InfoLevel: getLevelWrite(logrus.InfoLevel),
logrus.WarnLevel: getLevelWrite(logrus.WarnLevel),
logrus.ErrorLevel: getLevelWrite(logrus.ErrorLevel),
logrus.FatalLevel: getLevelWrite(logrus.FatalLevel),
logrus.PanicLevel: getLevelWrite(logrus.PanicLevel),
}, &logrus.JSONFormatter{DisableHTMLEscape: true, TimestampFormat: time.RFC3339Nano})
MyLog.AddHook(hook)
MyLog.SetLevel(logrus.InfoLevel)
MyLog.SetReportCaller(true)
} else {
MyLog.SetFormatter(&logrus.TextFormatter{
ForceQuote: false,
DisableQuote: true,
TimestampFormat: "2006-01-02 15:04:05.000",
FullTimestamp: true,
})
hook := lfshook.NewHook(lfshook.WriterMap{
logrus.DebugLevel: getLevelWrite(logrus.DebugLevel),
logrus.InfoLevel: getLevelWrite(logrus.InfoLevel),
logrus.WarnLevel: getLevelWrite(logrus.WarnLevel),
logrus.ErrorLevel: getLevelWrite(logrus.ErrorLevel),
logrus.FatalLevel: getLevelWrite(logrus.FatalLevel),
logrus.PanicLevel: getLevelWrite(logrus.PanicLevel),
}, &logrus.TextFormatter{ForceQuote: false, DisableQuote: true, TimestampFormat: time.RFC3339Nano})
MyLog.AddHook(hook)
MyLog.SetLevel(logrus.InfoLevel)
MyLog.SetReportCaller(true)
}
}
func GetInfoLog() io.Writer {
return getLevelWrite(logrus.InfoLevel)
}
func getLevelWrite(level logrus.Level) io.Writer {
var name string
switch level {
case logrus.DebugLevel:
name = "debug.log"
case logrus.InfoLevel:
name = "info.log"
case logrus.WarnLevel:
name = "warn.log"
case logrus.ErrorLevel:
name = "error.log"
case logrus.FatalLevel:
name = "fatal.log"
case logrus.PanicLevel:
name = "panic.log"
}
name = filenamePrefix + name
writer, err := rotatelogs.New(
name+".%Y%m%d%H",
rotatelogs.WithLinkName(name), // 生成软链,指向最新日志文件
rotatelogs.WithMaxAge(7*24*time.Hour), // 文件最大保存时间
rotatelogs.WithRotationTime(time.Hour), // 日志切割时间间隔
)
if err != nil {
MyLog.Fatal("Failed to create log file:", err.Error())
}
return writer
}
func GetSqlLog() io.Writer {
//if !config.AppIsRelease() {
// return GetInfoLog()
//}
//name := filenamePrefix + "sql.log"
//file, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
//if err == nil {
// return file
//} else {
// MyLog.Fatal("Failed to create sql log file:", err.Error())
//}
var name string = "sql.log"
name = filenamePrefix + name
writer, err := rotatelogs.New(
name+".%Y%m%d%H",
rotatelogs.WithLinkName(name), // 生成软链,指向最新日志文件
rotatelogs.WithMaxAge(7*24*time.Hour), // 文件最大保存时间
rotatelogs.WithRotationTime(time.Hour), // 日志切割时间间隔
)
if err != nil {
MyLog.Fatal("Failed to create log file:", err.Error())
}
return writer
}
//go:build !windows
// +build !windows
package mylogrus
import (
"fmt"
"os"
"path/filepath"
"runtime"
"syscall"
"time"
)
var stdErrFileHandler *os.File
func RewriteStderrFile() {
filename := logDir + filepath.Base(os.Args[0]) + ".stderr.log"
//if runtime.GOOS == "darwin" { // mac本地调试
// filename = "./log/hilo/" + filepath.Base(os.Args[0]) + ".stderr.log"
//}
if exits, _ := pathExists(filename); exits {
os.Rename(filename, filename+"_"+time.Now().Format("20060102150405"))
}
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Println(err)
return
}
stdErrFileHandler = file //把文件句柄保存到全局变量,避免被GC回收
if err = syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil {
fmt.Println(err)
return
}
// 内存回收前关闭文件描述符
runtime.SetFinalizer(stdErrFileHandler, func(fd *os.File) {
fd.Close()
})
return
}
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
//go:build windows
// +build windows
package mylogrus
import (
"os"
"path/filepath"
"time"
)
func RewriteStderrFile() {
filename := logDir + filepath.Base(os.Args[0]) + ".stderr.log"
if exits, _ := pathExists(filename); exits {
os.Rename(filename, filename+"_"+time.Now().Format("20060102150405"))
}
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
MyLog.Errorf("stderr log in:%v,err:%v", file, err)
}
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
package mysql
import (
"strconv"
)
/**
基于PDM,建立统计的数据domain结构。注意,不要选择0, 因为go的int默认值为0
*/
//主键ID
type ID = uint64
//性别
type Sex = uint8
//加减
type AddReduce = uint8
//拥有
type YesNo = uint8
//短描述
type Str = string
//时间戳
type Time = int64
//状态
type UserYesNo = uint8
//平台
type Platform = uint8
//多枚举类型
type Type = uint8
//数量
type Num = uint32
//时间戳
type Timestamp = uint64
//排序
type Index = uint16
//数量,并且用到-1作为特殊标记位
type NumAll = int
//开启关闭
type OpenClose = uint8
//逻辑删除
type LogicDel = uint8
//设备
type Device = uint8
type PeriodType = uint8
type FinishYesNo = uint8
type PayOrderType = uint8
//性别
const (
MAN Sex = 1
WOMAN Sex = 2
EMPTY Sex = 0
)
//yes no
const (
YES YesNo = 1
NO YesNo = 2
)
const (
OPEN OpenClose = 1
CLOSE OpenClose = 2
)
//加,减
const (
ADD AddReduce = 1
REDUCE AddReduce = 2
NilAddREDUCE AddReduce = 3
)
const (
USER UserYesNo = 1
NOUSER UserYesNo = 2
)
const (
Apple Platform = 1
GOOGLE Platform = 2
EGG_PLANT Platform = 3 // 通过starchat回调的茄子充值 代理充值
Checkout Platform = 4
PayerMax Platform = 5 // 通过hilo发起,starchat回调的PayerMax/茄子充值
Paypal Platform = 6 // paypal
ApplePink Platform = 31 // Apple pay 购买粉钻
GOOGLEPink Platform = 32 // GOOGLE pay 购买粉钻
PayTypeZero PayOrderType = 0 //
PayTypeProxy PayOrderType = 1 // 1.代理给自己充值
PayTypeUserToProxy PayOrderType = 2 // 2.用户给代理充值
CheckoutName = "cheakout支付"
PayerMaxName = "茄子支付"
PayPalName = "PayPal支付"
)
//逻辑删除
const (
EXIST LogicDel = 1
DEL LogicDel = 2
)
const (
DAY PeriodType = 1
Week PeriodType = 2
Month PeriodType = 3
Year PeriodType = 4
)
const (
FinishNo FinishYesNo = 0
FinishYes FinishYesNo = 1
)
const (
DiamondYellow Type = 1
DiamondPink Type = 2
)
func IdToStr(id ID) string {
return strconv.Itoa(int(id))
}
func StrToId(id string) (ID, error) {
var idInt int
var err error
if idInt, err = strconv.Atoi(id); err != nil {
return 0, err
}
return ID(idInt), nil
}
func NumToString(num Num) string {
return strconv.Itoa(int(num))
}
func TypeToString(t Type) string {
return strconv.Itoa(int(t))
}
func StrToType(t string) (Type, error) {
var tInt int
var err error
if tInt, err = strconv.Atoi(t); err != nil {
return 0, err
}
return Type(tInt), nil
}
/*func IdToUint64(id ID) uint64 {
return uint64(id)
}*/
func IdsToUint64(ids []ID) []uint64 {
uints := []uint64{}
for i := 0; i < len(ids); i++ {
uints = append(uints, uint64(ids[i]))
}
return uints
}
package mysql
import "time"
type EntityI interface {
GetID() ID
//用于判断数据是否进行持久化
IsLazyLoad() bool
//默认值为false true:代表要移除数据
CheckDel() bool
//检查是否唯一键冲突,依旧更新
CheckOnDuplicateKeyUPDATE() bool
//检查是否唯一键冲突,则不插入
CheckOnDuplicateKeyIGNORE() bool
//更新乐观锁 默认值为false true:乐观锁更新
CheckUpdateVersion() bool
//更新条件.
CheckUpdateCondition() bool
//获取版本号
GetUpdateVersionBefore() uint
//更新情况
GetUpdateCondition() string
//save 动作排除字段
GetOmit() []string
}
type Entity struct {
ID ID `gorm:"primary_key"`
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
lazyLoad bool `gorm:"-"`
del bool `gorm:"-"`
onDuplicateKeyUPDATE bool `gorm:"-"`
onDuplicateKeyIGNORE bool `gorm:"-"`
updateVersionFlag bool `gorm:"-"`
updateVersionBefore uint `gorm:"-"`
updateCondition string `gorm:"-"`
omit []string `gorm:"-"` //更新排除
updateColumns map[string]interface{} `gorm:"-"` //更新字段
}
func (t *Entity) GetID() ID {
return t.ID
}
func (t *Entity) IsLazyLoad() bool {
return t.lazyLoad
}
func (t *Entity) SetLasyLoad() {
t.lazyLoad = true
}
func (t *Entity) SetDel() {
t.del = true
}
func (t *Entity) CheckDel() bool {
return t.del
}
func (t *Entity) SetOnDuplicateKeyUPDATE() {
t.onDuplicateKeyUPDATE = true
}
func (t *Entity) SetOnDuplicateKeyIGNORE() {
t.onDuplicateKeyIGNORE = true
}
func (t *Entity) CheckOnDuplicateKeyUPDATE() bool {
return t.onDuplicateKeyUPDATE
}
func (t *Entity) CheckOnDuplicateKeyIGNORE() bool {
return t.onDuplicateKeyIGNORE
}
func (t *Entity) SetCheckUpdateVersionBefore(versionBefore uint) {
t.updateVersionBefore = versionBefore
t.updateVersionFlag = true
}
func (t *Entity) SetCheckUpdateCondition(condition string) {
t.updateCondition = condition
}
func (t *Entity) CheckUpdateVersion() bool {
return t.updateVersionFlag
}
func (t *Entity) CheckUpdateCondition() bool {
return t.updateCondition != ""
}
func (t *Entity) GetUpdateCondition() string {
return t.updateCondition
}
func (t *Entity) GetUpdateVersionBefore() uint {
return t.updateVersionBefore
}
func (t *Entity) GetOmit() []string {
return t.omit
}
func (t *Entity) SetOmit(omit []string) {
t.omit = omit
}
func (t *Entity) SetUpdateColumns(updateColumns map[string]interface{}) {
t.updateColumns = updateColumns
}
func (t *Entity) GetUpdateColumns() map[string]interface{} {
return t.updateColumns
}
package mysql
import (
"context"
"fmt"
. "gorm.io/gorm/logger"
"gorm.io/gorm/utils"
"time"
)
func MyNew(writer Writer, config Config) Interface {
var (
infoStr = "%s[info] "
warnStr = "%s[warn] "
errStr = "%s[error] "
traceStr = "%s[%.3fms] [rows:%v] %s"
traceWarnStr = "%s %s[%.3fms] [rows:%v] %s"
traceErrStr = "%s %s[%.3fms] [rows:%v] %s"
)
//if config.Colorful {
// infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset
// warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset
// errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset
// traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
// traceWarnStr = Green + "%s " + Yellow + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
// traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
//}
myTraceStr := " traceId:%v userId:%v"
infoStr += myTraceStr
warnStr += myTraceStr
errStr += myTraceStr
traceStr += myTraceStr
traceWarnStr += myTraceStr
traceErrStr += myTraceStr
return &myLogger{
Writer: writer,
Config: config,
infoStr: infoStr,
warnStr: warnStr,
errStr: errStr,
traceStr: traceStr,
traceWarnStr: traceWarnStr,
traceErrStr: traceErrStr,
}
}
type myLogger struct {
Writer
Config
infoStr, warnStr, errStr string
traceStr, traceErrStr, traceWarnStr string
}
// LogMode log mode
func (l *myLogger) LogMode(level LogLevel) Interface {
newlogger := *l
newlogger.LogLevel = level
return &newlogger
}
// Info print info
func (l myLogger) Info(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= Info {
l.Printf(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
// Warn print warn messages
func (l myLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= Warn {
l.Printf(l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
// Error print error messages
func (l myLogger) Error(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= Error {
l.Printf(l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
}
}
// Trace print sql message
func (l myLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
traceId, userId := ctx.Value("traceId"), ctx.Value("userId")
if l.LogLevel > Silent {
elapsed := time.Since(begin)
switch {
case err != nil && l.LogLevel >= Error:
sql, rows := fc()
if rows == -1 {
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql, traceId, userId)
} else {
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql, traceId, userId)
}
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn:
sql, rows := fc()
slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)
if rows == -1 {
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql, traceId, userId)
} else {
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql, traceId, userId)
}
case l.LogLevel == Info:
sql, rows := fc()
if rows == -1 {
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql, traceId, userId)
} else {
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql, traceId, userId)
}
}
}
}
package mysql
import (
"fmt"
_ "github.com/go-sql-driver/mysql" //加载mysql驱动
_ "github.com/joho/godotenv/autoload"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"hilo-algoCenter/common/config"
"hilo-algoCenter/common/mylogrus"
"log"
"net/url"
"time"
)
var Db *gorm.DB
func init() {
var err error
mysqlConfigData := config.GetConfigMysql()
options := "?charset=utf8mb4&parseTime=True&loc=Local&time_zone=" + url.QueryEscape("'+8:00'")
dsn := "" + mysqlConfigData.MYSQL_USERNAME + ":" + mysqlConfigData.MYSQL_PASSWORD + "@(" + mysqlConfigData.MYSQL_HOST + ")/" + mysqlConfigData.MYSQL_DB + options
sqlLogger := logger.Default.LogMode(logger.Info)
if file := mylogrus.GetSqlLog(); file != nil {
//sqlLogger = logger.New(log.New(file, "\r\n", log.Ldate|log.Lmicroseconds), logger.Config{
sqlLogger = MyNew(log.New(file, "", log.Ldate|log.Lmicroseconds), logger.Config{
SlowThreshold: 200 * time.Millisecond,
LogLevel: logger.Info,
Colorful: false,
})
}
Db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: sqlLogger,
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
})
if err != nil {
log.Fatalf("mysql connect error %v", err)
} else {
log.Println("mysql connect success")
}
if Db.Error != nil {
fmt.Printf("database error %v", Db.Error)
}
if d, err := Db.DB(); err == nil {
d.SetConnMaxLifetime(time.Minute * 30) // 连接可复用的最大时间。
d.SetMaxIdleConns(200) // 空闲连接数
}
//移除entity的tableName
/* gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return strings.Replace(defaultTableName, "_entities", "", 1)
}*/
//Db.Callback().Create().Replace("gorm:update_time_stamp", updateTimeStampForCreateCallback)
//Db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback)
/* Db.SingularTable(true)
Db.DB().SetMaxIdleConns(10)
Db.DB().SetMaxOpenConns(100)
Db.LogMode(true)
Db.SetLogger(log.New(os.Stdout, "\r\n", 0))*/
}
/*func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
if _, ok := scope.Get("gorm:update_column"); !ok {
_ = scope.SetColumn("UpdatedTime", time.Now().Unix())
}
}
func updateTimeStampForCreateCallback(scope *gorm.Scope) {
if !scope.HasError() {
nowTime := time.Now().Unix()
if createTimeField, ok := scope.FieldByName("CreatedTime"); ok {
if createTimeField.IsBlank {
_ = createTimeField.Set(nowTime)
}
}
if modifyTimeField, ok := scope.FieldByName("UpdatedTime"); ok {
if modifyTimeField.IsBlank {
_ = modifyTimeField.Set(nowTime)
}
}
}
}*/
func HasTable(tableName string) bool {
//var num int
//err := Db.Exec("SELECT COUNT(*) num FROM information_schema.TABLES WHERE table_name =%s;", tableName).Pluck("num", &num).Error
//if err != nil {
// mylogrus.MyLog.Errorf("HasTable err: %v, stack: %v", err, string(debug.Stack()))
// return
//}
//if num > 0 {
// has = true
//}
return Db.Migrator().HasTable(tableName)
}
package redisCli
import (
"context"
"github.com/go-redis/redis/v8"
"hilo-algoCenter/common/config"
"hilo-algoCenter/common/mylogrus"
"log"
)
var RedisClient *redis.Client
var RedisClient1 *redis.Client
func init() {
RedisClient = redis.NewClient(&redis.Options{
Addr: config.GetConfigRedis().REDIS_HOST,
Password: config.GetConfigRedis().REDIS_PASSWORD, // no password set
DB: 0, // use default DB
PoolSize: 2000,
MinIdleConns: 200,
})
mylogrus.MyLog.Infoln(config.GetConfigRedis().REDIS_HOST)
mylogrus.MyLog.Infoln(config.GetConfigRedis().REDIS_PASSWORD)
pong, err := RedisClient.Ping(context.Background()).Result()
if err != nil {
mylogrus.MyLog.Warn(err)
mylogrus.MyLog.Fatal("redis db0 connect fail")
} else {
mylogrus.MyLog.Info("redis db0 connection success - ", pong)
}
RedisClient1 = redis.NewClient(&redis.Options{
Addr: config.GetConfigRedis().REDIS_HOST,
Password: config.GetConfigRedis().REDIS_PASSWORD, // no password set
DB: 1, // use default DB
PoolSize: 200,
MinIdleConns: 20,
})
mylogrus.MyLog.Infoln(config.GetConfigRedis().REDIS_HOST)
mylogrus.MyLog.Infoln(config.GetConfigRedis().REDIS_PASSWORD)
pong, err = RedisClient1.Ping(context.Background()).Result()
if err != nil {
mylogrus.MyLog.Warn(err)
mylogrus.MyLog.Fatal("redis db1 connect fail")
} else {
log.Println("redis db1 connection success - " + pong)
}
// log hook
//RedisClient.AddHook(redisHook{})
}
func GetRedis() *redis.Client {
return RedisClient
}
func GetRedis1() *redis.Client {
return RedisClient1
}
package redisCli
import (
"context"
"github.com/go-redis/redis/v8"
"hilo-algoCenter/common/mylogrus"
"time"
)
type redisCost struct{}
var redisCostKey = redisCost{}
type redisHook struct{}
func (redisHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
ctx = context.WithValue(ctx, redisCostKey, time.Now())
return ctx, nil
}
func (redisHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
traceId, userId := ctx.Value("traceId"), ctx.Value("userId")
start := ctx.Value(redisCostKey)
var cost int64
if s, ok := start.(time.Time); ok {
cost = time.Now().Sub(s).Milliseconds()
}
mylogrus.MyLog.Infof("redis cmd: <%s>,err:%v traceId:%v,userId:%v,cost:%v ms", cmd.String(), cmd.Err(), traceId, userId, cost)
return nil
}
func (redisHook) BeforeProcessPipeline(ctx context.Context, cmds []redis.Cmder) (context.Context, error) {
return ctx, nil
}
func (redisHook) AfterProcessPipeline(ctx context.Context, cmds []redis.Cmder) error {
return nil
}
package redisCli
import (
"context"
"hilo-algoCenter/common/mylogrus"
"strconv"
"time"
)
//这个用户避免多个服务器并发问题。
func SetNX(key string, value interface{}, expiration time.Duration, callBack func()) {
flag, err := RedisClient.SetNX(context.Background(), key, value, expiration).Result()
if err != nil {
mylogrus.MyLog.Errorf("key:%v lock start setNx err: %v", key, err)
}
if !flag {
mylogrus.MyLog.Infof("key:%v lock setNx has lock", key)
return
}
mylogrus.MyLog.Infof("key:%v lock setNx begin", key)
callBack()
//执行结束之后,移除key
//RedisClient.Del(context.Background(), key)
mylogrus.MyLog.Infof("key:%v lock setNx end", key)
}
//setNx没有,结束后,没有移除
/*func SetNxNoDel(key string, value interface{}, expiration time.Duration, callBack func()) {
flag, err := RedisClient.SetNX(context.Background(), key, value, expiration).Result()
if err != nil {
mylogrus.MyLog.Errorf("key:%v lock start setNx err: %v", key, err)
}
if !flag {
mylogrus.MyLog.Infof("key:%v lock setNx has lock", key)
return
}
mylogrus.MyLog.Infof("key:%v lock setNx begin", key)
callBack()
mylogrus.MyLog.Infof("key:%v lock setNx end", key)
}*/
func ClearExpired(key string, expireSec int64) error {
return GetRedis().ZRemRangeByScore(context.Background(), key,
"0", strconv.FormatInt(time.Now().Unix()-expireSec, 10)).Err()
}
func Lock(key string, expiration time.Duration) bool {
flag, err := RedisClient.SetNX(context.Background(), key, 1, expiration).Result()
if err != nil {
return false
}
if !flag {
return false
}
return true
}
package cv
import (
"hilo-algoCenter/common/mysql"
"time"
)
// User 用户信息
type User struct {
mysql.Entity
ExternalId mysql.Str
Avatar mysql.Str
DefaultAvatar bool
Nick mysql.Str
Sex mysql.Sex
Birthday mysql.Timestamp
Country mysql.Str
CountryIcon mysql.Str
Language mysql.Str
Description mysql.Str
Code mysql.Str
OriginCode mysql.Str
IsPush mysql.OpenClose
IsShowAge mysql.OpenClose
Status mysql.Type
DeviceType mysql.Str
LogoutTime int64
}
// UserVip 用户Vip
type UserVip struct {
mysql.Entity
UserId mysql.ID
ExpireAt time.Time //结束时间
Type mysql.Type
Platform mysql.Platform
VipSubscribeOrderId mysql.ID //最后的订单ID
}
type CvUserTiny struct {
Id uint64 `json:"id,omitempty"`
ExternalId string `json:"externalId"`
Avatar string `json:"avatar"`
Nick string `json:"nick"`
Sex uint8 `json:"sex"`
Code string `json:"code"`
Country string `json:"country"`
CountryIcon string `json:"countryIcon"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
IsLogout bool `json:"isLogout"` //是否注销 true:已经注销, false:没有注销
//生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示
Birthday *uint64 `json:"birthday"`
}
type CvUserTinyVip struct {
CvUserTiny
//是否VIP用户
IsVip bool `json:"isVip"`
//VIP用户过期时间(只有自己查询自己,才返回)
VipExpireTime *int64 `json:"vipExpireTime"`
}
func GetUserTinyVips(userIds []uint64) ([]CvUserTinyVip, error) {
userTinys, _, err := GetUserTinys(userIds)
if err != nil {
return nil, err
}
vipMap, err := BatchGetVips(userIds)
if err != nil {
return nil, err
}
userTinyVips := make([]CvUserTinyVip, 0, len(userTinys))
for i, r := range userTinys {
vipExpireTime, _ := vipMap[r.Id]
userTinyVips = append(userTinyVips, CvUserTinyVip{
CvUserTiny: userTinys[i],
IsVip: vipExpireTime != nil,
VipExpireTime: vipExpireTime,
})
}
return userTinyVips, nil
}
// GetUserTinys 批量获取用户tiny信息
func GetUserTinys(userIds []mysql.ID) ([]CvUserTiny, []uint64, error) {
if len(userIds) == 0 {
return nil, nil, nil
}
var users []User
if err := mysql.Db.Model(&User{}).Where("id IN ?", userIds).Find(&users).Error; err != nil {
return nil, nil, err
}
userTinys := make([]CvUserTiny, 0, len(users))
for _, r := range users {
userTinys = append(userTinys, GetUserTinyBy(r))
}
return userTinys, userIds, nil
}
func GetUserTinyVipMap(userIds []uint64) (map[uint64]CvUserTinyVip, error) {
userTinyVips, err := GetUserTinyVips(userIds)
if err != nil {
return nil, err
}
userTinyVipMap := map[uint64]CvUserTinyVip{}
for i, r := range userTinyVips {
userTinyVipMap[r.Id] = userTinyVips[i]
}
return userTinyVipMap, nil
}
func GetUserTinyBy(user User) CvUserTiny {
return CvUserTiny{
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 IfLogoutStr(condition bool, trueVal, falseVal string) string {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutNick(condition bool, code string, nick string) string {
if condition {
return "Hilo No." + code
}
return nick
}
func IfLogout(logoutTime int64) bool {
return logoutTime > 0 && time.Now().Unix() > logoutTime
}
func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 {
if *birthday == 0 {
return nil
}
return (*uint64)(birthday)
}
func (u User) IsPrettyCode() bool {
return u.Code != u.OriginCode
}
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error
if err != nil {
return nil, err
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds {
result[i] = nil
}
now := time.Now()
for _, i := range rows {
if i.ExpireAt.After(now) {
ts := i.ExpireAt.Unix()
result[i.UserId] = &ts
}
}
return result, nil
}
package cv
import (
"hilo-algoCenter/common/mysql"
"hilo-algoCenter/protocol/userProxy"
)
type CvUserTinyVipLike struct {
CvUserTinyVip
//是否喜欢别人
IsLike bool `json:"isLike"`
//别人是否喜欢我
IsLikeMe bool `json:"isLikeMe"`
}
func GetUserTinyVipLikes(myUserId uint64, userIds []uint64) ([]CvUserTinyVipLike, error) {
if len(userIds) == 0 {
return []CvUserTinyVipLike{}, nil
}
userTinyVipMap, err := GetUserTinyVipMap(userIds)
if err != nil {
return nil, err
}
iLikeMap, err := CheckILike(myUserId, userIds)
if err != nil {
return nil, err
}
//
likeMeMap, err := CheckLikeMe(myUserId, userIds)
if err != nil {
return nil, err
}
results := make([]CvUserTinyVipLike, 0, len(userIds))
for _, r := range userIds {
results = append(results, CvUserTinyVipLike{
CvUserTinyVip: userTinyVipMap[r],
IsLike: iLikeMap[r],
IsLikeMe: likeMeMap[r],
})
}
return results, nil
}
// GetOtherUserInfo 获取otherUserId的信息
// param myUserId:用来判断喜欢/被喜欢等关系
// param otherUserId:需要获取的用户
func GetOtherUserInfo(myUserId, otherUserId uint64) (*userProxy.User, error) {
otherUser, err := GetUserTinyVipLikes(myUserId, []uint64{otherUserId})
if err != nil {
return nil, err
}
if len(otherUser) <= 0 {
return nil, err
}
otherUserInfo := otherUser[0]
var birthday uint64
if otherUserInfo.Birthday != nil {
birthday = *otherUserInfo.Birthday
}
return &userProxy.User{
Id: otherUserInfo.Id,
ExternalId: otherUserInfo.ExternalId,
Nick: otherUserInfo.Nick,
Avatar: otherUserInfo.Avatar,
Country: otherUserInfo.Country,
CountryIcon: otherUserInfo.CountryIcon,
Birthday: birthday,
IsVip: otherUserInfo.IsVip,
IsLike: otherUserInfo.IsLike,
IsLikeMe: otherUserInfo.IsLikeMe,
}, nil
}
//用户喜欢
type UserLike struct {
mysql.Entity
UserId mysql.ID
LikeUserId mysql.ID
SceneType mysql.Type
}
func CheckILike(myUserId uint64, userIds []uint64) (map[uint64]bool, error) {
var userLikes []UserLike
if err := mysql.Db.Model(&UserLike{}).Where(&UserLike{
UserId: myUserId,
}).Where("like_user_id in (?)", userIds).Find(&userLikes).Error; err != nil {
return nil, err
}
m := map[uint64]struct{}{}
for _, r := range userLikes {
m[r.LikeUserId] = struct{}{}
}
result := make(map[uint64]bool, len(userIds))
for _, r := range userIds {
_, flag := m[r]
result[r] = flag
}
return result, nil
}
func CheckLikeMe(myUserId uint64, userIds []uint64) (map[uint64]bool, error) {
var userLikes []UserLike
if err := mysql.Db.Model(&UserLike{}).Where(&UserLike{
LikeUserId: myUserId,
}).Where("user_id in (?)", userIds).Find(&userLikes).Error; err != nil {
return nil, err
}
m := map[uint64]struct{}{}
for _, r := range userLikes {
m[r.UserId] = struct{}{}
}
result := make(map[uint64]bool, len(userIds))
for _, r := range userIds {
_, flag := m[r]
result[r] = flag
}
return result, nil
}
\ No newline at end of file
[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
[APP]
MASTER=true
BIZ_SECRET=biz
WEB_SECRET=webHilo1258
OPERATION_SECRET=operation1258236
SUPERUSER=2701,2831,4504
OFFICIAL_STAFF=2701,2831,3411,2511
OFFICIAL_GROUP=@TGS#3FDW3MPHZ
MINIMAL_VERSION_ANDROID=22001
MINIMAL_VERSION_IOS=22000
MODERATE=TENCENT
[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=LTAIdQZv5H1kNZp5
ACCESS_KEY_SECRET=UnwY0ClDkqBMLwPx3OJJiLYyk9xYLO
ANDROID_APP_KEY=30250713
ANDROID_APP_SECRET=cae7b9a9d3e54577d2c3b60bf6d23047
IOS_APP_KEY=30790728
IOS_APP_SECRET=4fd69ca084c67d4b5a8d15452f0af26a
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=https://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=60
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=30
VIDEO_MINUTE_UNION=30
[SESSION]
SESSION_DAILY_FREE_NUM=50
GUILD_USER_HELLO_DAY=30
[BEAN]
DIAMOND_BEAN_RATE=90
[GEM]
DIAMOND_GEM_RATE=10
[H5]
USER_LEVEL=http://test.chathot.me/action/hiloHtml/hiloUserLevel/index.html
GROUP_SUPPORT=http://test.chathot.me/action/activityhtml/21_12_06/page.html
LUCKY_WHEEL=https://test.chathot.me/action/activityhtml/21_12_30/page.html
WEEKLY_STAR=http://test.chathot.me/action/hiloHtml/lxt_h5/page.html
WEEKLY_CP=https://test.chathot.me/action/hiloHtml/Valentines_22_1_18/page.html
COUNTRY_STAR=https://test.chathot.me/action/hiloHtml/22_08_18_nation_star/page.html
NOBLE_BUY_IOS=https://test.chathot.me/action/hiloHtml/22_05_26_buy_nobility/page.html
NOBLE_BUY_IOS_AUDIT=https://test.chathot.me/action/hiloHtml/lxt_h5/page.html
GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://test.chathot.me/action/activitiesPage/2022_10_17HiloLiveH5/index.html
GROUP_POWER_GRADE_URL=https://test.chathot.me/action/hiloHtml/2023Activity/2023_3_21FamilyLevel/index.html
GROUP_POWER_ACT_URL=
SHEEP_H5_URL=https://gzds.vip/yangyang?game_id=hilo_sheep
ID_URL=https://h5.whoisamy.shop/action/hiloHtml/new_upgrade/index.html
[GROUPIM]
MSG_SORT_EXPIRE=21600
MSG_SORT_SNAP=300
MSG_PARALLEL_SIZE=10
[GRADE]
CHARM_SPEED_VIP=15
ACTITY_SPEED_VIP=15
WEALTH_SPEED_VIP=15
[LIKE]
I_LIKE_NUM=30
I_LIKE_NUM_VIP=300
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=500
GIFT_BANNER_LEVEL2=2000
GIFT_BANNER_LEVEL3=5000
[DIAMOND]
DAILY_LOGIN_IMEI_LIMIT=2
DAILY_LOGIN_IP_LIMIT=5
PRIVATE_GIFT_RETURN=10
[LUCKY_WHEEL]
MINIMAL_PARTICIPANT=2
WAIT_TIMELONG=10
WINNER_DIAMOND_BANNER=10
[GROUP_CUSTOM_THEME]
PIC_LIMIT=5
DAY=10
[GIFT]
WALL_DIAMOND=10
[DAILY]
LOGIN_COMMON=5
LOGIN_VIP=300
[FRUIT_TYCOON]
POOL_RATIO=80
WATERMELON_RATIO=24
[RISK_CONTROL]
USER_QPS_LIMIT=60
[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
[PAYPAL]
PAYPAL_CLIENT_ID=AQCXHyXFhNLNWoorcj3Du0J4WwBDy25DoQ7SZKNKRe4PNY0BLpeCzV_zm1HKwAvd7reWeOBCte-vMakM
PAYPAL_SECRET_ID=EDBTK99v6wXhGXhDqDTOksK2j8NPAfJKT-wRTqTrNGrUmn8xsjkrVcO_xSvMVR6CB2bN74rGl_AFm098
RETURN_URL=https://test.apiv1.faceline.live/v1/callback/paypal
\ No newline at end of file
module hilo-algoCenter
go 1.17
require (
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.9.0 // indirect
github.com/go-redis/redis/v8 v8.3.3 // indirect
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/golang/protobuf v1.4.3 // 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
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
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.1 // indirect
github.com/joho/godotenv v1.3.0 // indirect
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/sirupsen/logrus v1.7.0 // indirect
go.opentelemetry.io/otel v0.13.0 // indirect
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 // indirect
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
golang.org/x/text v0.3.3 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/ini.v1 v1.63.2 // indirect
gorm.io/driver/mysql v1.0.3 // indirect
gorm.io/gorm v1.20.12 // indirect
)
This diff is collapsed.
[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
[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
[GEM]
DIAMOND_GEM_RATE=10
[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
NOBLE_BUY_IOS_AUDIT=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html
GROUP_POWER_GRADE_URL=https://test.chathot.me/action/hiloHtml/2023Activity/2023_3_21FamilyLevel/index.html
GROUP_POWER_ACT_URL=https://www.baidu.com
SHEEP_H5_URL=https://gzds.vip/yangyang?game_id=hilo_sheep
ID_URL=https://h5.whoisamy.shop/action/hiloHtml/new_upgrade/index.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
\ No newline at end of file
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
consulapi "github.com/hashicorp/consul/api"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/resolver/manual"
"hilo-algoCenter/algo"
"hilo-algoCenter/common/consul"
"hilo-algoCenter/common/mylogrus"
"hilo-algoCenter/protocol/userCenter"
"time"
)
const (
default_redis_address = "47.244.34.27:6379"
default_redis_password = "8QZ9JD1zLvPR3yHf"
redis_section = 0
)
var kacp = keepalive.ClientParameters{
Time: 10 * time.Second, // send pings every 10 seconds if there is no activity
Timeout: time.Second, // wait 1 second for ping ack before considering the connection dead
PermitWithoutStream: true, // send pings even without active streams
}
func main() {
client, err := consulapi.NewClient(consulapi.DefaultConfig()) //非默认情况下需要设置实际的参数
if err != nil {
mylogrus.MyLog.Fatalln(err)
}
if client == nil {
mylogrus.MyLog.Fatalln("Fail to get consul client.")
}
redisAddress := default_redis_address
redisPassword := default_redis_password
kv := client.KV()
if kv != nil {
p, _, err := kv.Get("redis_address", nil)
if err == nil && p != nil {
redisAddress = string(p.Value)
}
p, _, err = kv.Get("redis_password", nil)
if err == nil && p != nil {
redisPassword = string(p.Value)
}
}
rdb := redis.NewClient(&redis.Options{
Addr: redisAddress,
Password: redisPassword,
DB: redis_section,
})
if rdb == nil {
mylogrus.MyLog.Fatalf("failed to connect redis %s\n", redisAddress)
}
result, err := rdb.Ping(context.Background()).Result()
if err != nil {
mylogrus.MyLog.Fatal(err)
} else if result != "PONG" {
mylogrus.MyLog.Fatalf("Invalid ping response %s", result)
}
cataLog := client.Catalog()
if cataLog == nil {
mylogrus.MyLog.Fatalln("No catalog.")
}
addr, err := consul.GetServices(cataLog, "userCenter")
if err != nil {
mylogrus.MyLog.Fatalln(err)
}
if len(addr) == 0 {
mylogrus.MyLog.Fatalln("No userCenter available.")
}
addresses := make([]resolver.Address, len(addr))
for i, s := range addr {
addresses[i].Addr = s
mylogrus.MyLog.Infof("address : %s", s)
}
r := manual.NewBuilderWithScheme("hilo")
r.InitialState(resolver.State{Addresses: addresses})
userCenterAddr := fmt.Sprintf("%s:///usercenter", r.Scheme())
// Set up addresses connection to the userCenter.
conn, err := grpc.Dial(userCenterAddr,
grpc.WithInsecure(),
grpc.WithBlock(),
grpc.WithKeepaliveParams(kacp),
grpc.WithResolvers(r),
grpc.WithDefaultServiceConfig("{ \"loadBalancingPolicy\": \"round_robin\" }"))
if err != nil {
mylogrus.MyLog.Fatalf("did not connect: %v", err)
}
//defer conn.Close()
userClient := userCenter.NewUserClient(conn)
if userClient == nil {
mylogrus.MyLog.Fatalln("userClient null")
}
algo.Start(userClient, rdb)
select {}
}
package protocol
const MatchResultPubSubChannel = "match_result"
type MatchResult struct {
MatchCycle string `json:"matchCycle"`
MatchUniqueId string `json:"matchUniqueId"`
//Total uint32 `json:"total"`
User1Id uint64 `json:"user1Id"`
User2Id uint64 `json:"user2Id"`
//true:正常匹配 false:落单
Status bool `json:"status"`
//1, 是正常结果,2:只有一个用户,发起工会广播
//Type uint32 `json:"type"`
//user1Id的优先度分数
Priority float64
//user2Id的质量分数
Excellen float64
//user1Id同user2Id的关系分数
Relation float64
ExcellentRelation float64
//rpc状态
RpcStatus bool
//rpc错误信息
RPcErr string
}
const MatchCyclePubSubChannel = "match_cycle"
//匹配周期结果
type MatchCycle struct {
//周期
MatchCycle string `json:"matchCycle"`
//参与匹配的人数
JoinNum uint32 `json:"joinNum"`
//匹配成功的人数
SuccessNum uint32 `json:"successNum"`
//匹配失败的人数
FailNum uint32 `json:"failNum"`
//是否发出工会广播 1:广播 2:不广播
TradeUnionBroadcast uint8 `json:"tradeUnionBroadcast"`
}
syntax = "proto3";
package userCenter;
option go_package = "protocol/userCenter";
/* id = 1 */
message RouteMessage {
uint64 uid = 1;
uint32 msgType = 2;
bytes payLoad = 3;
}
/* id = 2 */
message RouteMessageRsp {
uint32 status = 1;
}
/* id = 3 */
message LoginMessage {
string proxyAddr = 1; // userProxy的地址:ip:port
string token = 2;
string clientAddr = 3; // 客户端地址(websocket):ip:port
}
/* id = 4 */
message LoginMessageRsp {
uint32 status = 1;
uint64 uid = 2;
}
/* id = 5 */
message LogoutMessage {
string clientAddr = 1; // 客户端地址(websocket):ip:port
uint64 uid = 2;
}
/* id = 6 */
message LogoutMessageRsp {
uint32 status = 1;
}
/* id = 7 */
message MulticastMessage {
repeated uint64 uids = 1;
uint32 msgType = 2;
bytes payLoad = 3;
}
/* id = 8 */
message MulticastMessageRsp {
repeated uint64 failedUids = 1;
}
/* id = 9 */
message KickMessage {
uint64 uid = 1;
string addr = 2;
}
/* id = 10 */
message KickMessageRsp {
uint32 status = 1;
}
/* id = 11 */
message BroadcastMessage {
uint32 msgType = 2;
bytes payLoad = 3;
}
/* id = 12 */
message BroadcastMessageRsp {
repeated uint64 failedUids = 1;
}
/* id = 13 */
message BizMessage {
uint64 uid = 1;
uint32 msgType = 2;
string payLoad = 3;
}
/* id = 14 */
message BizMessageRsp {
uint32 status = 1;
}
service Router {
rpc route(RouteMessage) returns (RouteMessageRsp) {}
rpc kickUser(KickMessage) returns (KickMessageRsp) {}
}
service User {
rpc login(LoginMessage) returns (LoginMessageRsp) {}
rpc logout(LogoutMessage) returns (LogoutMessageRsp) {}
rpc multicast(MulticastMessage) returns (MulticastMessageRsp) {}
rpc broadcast(BroadcastMessage) returns (BroadcastMessageRsp) {}
rpc transmit(BizMessage) returns (BizMessageRsp) {}
}
\ No newline at end of file
syntax = "proto3";
package userProxy;
option go_package = "protocol/userProxy";
/* user*/
message User {
uint64 id = 1;
string externalId = 2;
string nick = 3;
string avatar = 4;
string country = 5;
string countryIcon = 6;
uint64 birthday = 7;
bool isVip = 8;
bool isLike = 9;
bool isLikeMe = 10;
}
/* Svip*/
message Svip {
uint64 svipLevel = 1;
repeated SvipPrivilege privileges = 2;
}
message SvipPrivilege {
int32 type = 1;
bool canSwitch = 2;
bool userSwitch = 3;
string mysteryCode = 4;
}
/* id = 1 登录*/
message Login {
string token = 1;
}
/* id = 2 登录的回应 */
message LoginRsp {
uint32 status = 1;
}
/* id = 3 客户端心跳 */
message HeartBeat {
string externalUid = 1;
}
/* id = 4 客户端心跳的回应 */
message HeartBeatRsp {
uint32 status = 1;
}
/* id = 7 客户端上行消息 */
message BizRequest {
uint32 type = 1;
string payLoad = 2;
}
/* id = 8 客户端上行消息的应答 */
message BizResponse {
uint32 status = 1;
}
/* id == 100 | 140 匹配结果通知 waitDuration:开始/下一个时间 matchUniqueId:匹配一对的唯一标识码, status:是否是落单 singleWaitTimeInSec:单方等待连接最长时间 dualWaitTimeInSec:双方连接中最长时间*/
message MatchSuccess {
string localUserId = 1;
string remoteUserId = 2;
uint32 waitDuration = 3;
string matchUniqueId = 4;
bool status = 5;
uint32 singleWaitTimeInSec = 6;
uint32 dualWaitTimeInSec = 7;
User remoteUser = 8;
}
/* id == 101 匹配后用户选择结果通知, failType: 只有status=2 才有值,其它为0,failType=1:等待时间到了,拒绝 failType=2:主动拒绝 */
message MatchConfirm {
uint32 status = 1;
string channelId = 2;
string token = 3;
string localUserId = 4;
string remoteUserId = 5;
uint32 remoteAgoraId = 6;
uint32 callDuration = 7;
uint32 localAgoraId = 8;
uint32 diamondBalance = 9;
string matchUniqueId = 10;
uint32 failType = 11;
}
/* id == 102 视频通话准备 */
message CallReady {
uint64 startTimestamp = 1;
uint64 endTimestamp = 2;
uint64 callDuration = 3;
string channelId = 4;
uint64 remainDiamond = 5;
}
/* id == 103 礼物加时 */
message AddTimeGift {
uint32 giftId = 1;
string token = 2;
uint32 duration = 3;
uint64 endTimestamp = 4;
string channelId = 5;
bool isSender = 6;
uint32 giftNum = 7;
string iconUrl = 8;
string svgaUrl = 9;
string senderAvatar = 10;
string receiverAvatar = 11;
}
/* id == 104 免费加时 */
message AddTimeFree {
string token = 1;
uint32 duration = 2;
uint64 endTimestamp = 3;
string channelId = 4;
uint32 senderAgoraId = 5;
}
/* id == 105 退出 */
message ConnectsQuit {
uint64 from_user_id = 1;
}
/* id == 106 连接状态 */
message ConnectStatus {
uint64 from_user_id = 1;
float user_diamonds = 2;
bool diamonds_enough = 3;
}
/* id == 107 ??? */
message ConnectsCall {
uint64 from_user_id = 1;
string rong_room_name = 2;
bool is_join = 3;
}
/* id == 108 */
message ConnectCommon {
string rong_room_name = 1;
uint64 from_user_id = 2;
string extra = 3;
string message = 4;
}
/* id == 109 召回授权弹框 */
message RecallWindow {
}
/* id == 110 | 132 视频发送 status:(1:接收到邀请, 2:接收到对方同意, 3:双方拒绝(还没接通), 4:对方挂断(接通后)diamondBalance 只有status=2,才出现)*/
message Video {
string videoUniqueId = 1;
string channelId = 2;
uint32 localAgoraId = 3;
uint32 remoteAgoraId = 4;
string agoraToken = 5;
string sendUserId = 6;
string receiveUserId = 7;
uint32 status = 8;
uint32 diamondBalance = 9;
User sendUser = 10;
}
/* id == 111 视频通话准备 */
message VideoCallReady {
uint64 startTimestamp = 1;
uint64 endTimestamp = 2;
uint64 callDuration = 3;
string channelId = 4;
uint64 remainDiamond = 5;
}
/* id == 112 互相喜欢 */
message LikeEach {
string remoteUserId = 1;
}
/* id == 113 喜欢我 */
message LikeMe {
string remoteUserId = 1;
string remoteNick = 2;
string channelId = 3;
}
/* id == 114 日常进入app,获取钻石 */
message DailyInAppDiamond {
uint32 diamondNum = 1;
}
/* id == 115 横幅 */
message GlobalGiftBanner {
uint32 bannerLevel = 1;
uint64 giftId = 2;
uint32 giftNum = 3;
string sendUserId = 4;
string receiveUserId = 5;
string groupId = 6;
string sendUserCode = 7;
string sendUserAvatar = 8;
string sendUserNick = 9;
string receiveUserNick = 10;
string giftPicUrl = 11;
Svip svip = 12;
Svip receiveSvip = 13;
}
/* id == 116 横幅的回应,用来测量RTT */
message GlobalGiftBannerRsp {
uint32 bannerLevel = 1;
uint64 giftId = 2;
uint32 giftNum = 3;
string sendUserId = 4;
string receiveUserId = 5;
string groupId = 6;
}
/*id==117 幸运转盘通知,客户端重新拉取查询, type:客户端不用理*/
message LuckyWheel {
string groupId = 1;
uint32 type = 2;
}
/* id == 118 幸运转盘获胜者全服广播 */
message LuckyWheelBanner {
uint32 diamondNum = 1;
string sendUserId = 2;
string groupId = 3;
string nick = 4;
string code = 5;
string avatar = 6;
Svip svip = 7;
}
/* id == 119 幸运转盘钻石变化 */
message LuckyWheelDiamondChange {
string groupId = 1;
}
/* id == 120 服务器配置变更 */
message ConfigChange {
uint32 type = 1;
}
/* id == 121 全局火箭横幅 */
message GlobalRocketNotice {
string groupId = 1;
string period = 2;
uint32 round = 3;
uint32 stage = 4;
string topUserIcon = 5;
string nick = 6;
string code = 7;
string avatar = 8;
Svip svip = 9;
}
/* id == 122 群发功能弹窗 */
message GroupSendNotice {
string senderExtId = 1;
string senderCode = 2;
uint32 senderSex = 3;
string senderAvatar = 4;
string text = 5;
string groupName = 6;
string groupCode = 7;
string groupAvatar = 8;
uint32 userInNum = 9; // 最近进入房间的人数
string groupId = 10;
}
/* id == 123 全球消息 */
message GlobalBroadcast {
string senderExtId = 1;
string senderCode = 2;
uint32 senderSex = 3;
string senderAvatar = 4;
string senderNick = 5;
string msg = 6;
string groupId = 7;
uint32 senderNobleLevel = 8;
}
/* id == 124 全球消息 */
message MicTaskFinish {
string userId = 1;
uint32 diamond = 2;
}
/* id == 125 水果机开奖通知 */
message FruitMachine {
string date = 1;
uint32 round = 2;
}
/* id == 126 贵族变化 */
message NobleChange {
}
/* id == 127 加入群组成功 */
message JoinGroup {
string groupId = 1;
string externalId = 2;
}
/* id == 128 1对1视频1分钟加时成功 */
message VideoTimeMinuteSuccess {
string token = 1;
uint32 duration = 2;
uint64 endTimestamp = 3;
string channelId = 4;
uint32 senderAgoraId = 5;
string videoUniqueId = 6;
bool isSend = 7;
uint32 sendRemainDiamond = 8;
}
/* id == 129 1对1视频1分钟加时询问检查 */
message VideoTimeMinuteCheck {
string videoUniqueId = 1;
uint32 diamond = 2;
string uuid = 3;
}
/* id == 130 1对1视频,错过 */
message VideoMiss {
uint32 totalNum = 1;
}
/* id == 131 进房,群组活动信息 */
message GroupActivity {
string ActivityId = 1;// id
uint64 StartAt = 2; // 开始时间戳,东八区时间戳
uint64 EndAt = 3; // 结束时间戳,东八区时间戳
string Banner = 4; // banner url
int32 AcType = 5; // 类型1.游戏2.比赛3.排队4.诗歌
string Theme = 6; // 活动主题
int32 PersonNum = 7; // 订阅人数
bool IsSubscribe = 8; // 我是否订阅该活动
string GroupId = 9; // 群id
}
/* id == 144 邀请用户成为房间会员 */
message RoomInviteMember {
string group_id = 1;
}
\ No newline at end of file
[DATABASE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo
MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo
[DATABASECODE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo
MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD=
[JWT]
SECRET=hilo1504
ISSUER_API=hiloApi
ISSUER_Mgr=hiloMgr
EXPIRE=720h
[APP]
MASTER=true
BIZ_SECRET=biz
OPERATION_SECRET=operation1258236
WEB_SECRET=webHilo1258
SUPERUSER=28201,23951,133101,41,2020531,955271,1575531
OFFICIAL_STAFF=133101,435731,486461,41
OFFICIAL_GROUP=@TGS#33W3KNLHK,@TGS#3XA5RJ5HH,@TGS#3O6PKBTH6
MINIMAL_VERSION_ANDROID=22600
MINIMAL_VERSION_IOS=22600
ROOM_MODE=AVChatRoom
MODERATE=TENCENT
[OSS]
OSS_ACCESS_KEY_ID=LTAIxdazV2pCuV3T
OSS_ACCESS_KEY_SECRET=zuAnreAXQ6vlAKnvvmolFLfb1N5w5S
OSS_ROLE_ARN=acs:ram::1509841556585969:role/aliyunosstokengeneratorrole
OSS_END_POINT=https://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=uwd1c0sxu5t41
RONG_CLOUD_APP_SECRET=vo9djozyBl9bZ
RONG_CLOUD_URL=https://api-sg01.ronghub.com
[TENCENTYUN]
TENCENTYUN_APP_ID=1400487464
TENCENTYUN_KEY=cb4c1f2e3398a88e0e9468b403f671e60d66a564df86f7db925c6ab4f18b66e5
TX_OVERSEA_APP_ID=40000066
TX_OVERSEA_KEY=3ab68ea5bddc8774d90b8c764ae71188914bd5fd06f30b28790c51e44ca7885c
[EMAS]
REGION_ID=cn-hangzhou
ACCESS_KEY_ID=LTAIdQZv5H1kNZp5
ACCESS_KEY_SECRET=UnwY0ClDkqBMLwPx3OJJiLYyk9xYLO
ANDROID_APP_KEY=30774987
ANDROID_APP_SECRET=297a0f231f1286a2de9aab097cc8ff5c
IOS_APP_KEY=30790728
IOS_APP_SECRET=4fd69ca084c67d4b5a8d15452f0af26a
APNS=PRODUCT
[AGORA]
APP_ID=6291d069123642d9929a49c734c50719
APP_CERTIFICATE=d5de40350aa54e60bcdce90c71e9598a
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
[CHECKOUT]
AUTHORIZATION=sk_fca6e213-b7df-4bd7-99f4-7c0a9f7c778c
URL=https://api.checkout.com/hosted-payments
H5=https://h5.whoisamy.shop/action/hiloHtml/22_05_30_recharge/topup.html
HILO_SECRET_KEY=sk_26806bf4-e6e3-45e2-a093-c72c5b53eaf5
[MATCH]
MATCH_FREE_TIME=60
MATCH_FREE_TIME_VIP=60
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=60
VIDEO_MINUTE_UNION=60
[SESSION]
SESSION_DAILY_FREE_NUM=50
GUILD_USER_HELLO_DAY=30
[BEAN]
DIAMOND_BEAN_RATE=90
[GEM]
DIAMOND_GEM_RATE=10
[H5]
USER_LEVEL=https://h5.whoisamy.shop/action/hiloHtml/hiloUserLevel/index.html
GROUP_SUPPORT=https://h5.whoisamy.shop/action/activityhtml/21_12_06/page.html
LUCKY_WHEEL=https://h5.whoisamy.shop/action/activityhtml/21_12_30/page.html
WEEKLY_STAR=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html
WEEKLY_CP=https://h5.whoisamy.shop/action/hiloHtml/Valentines_22_1_18/page.html
COUNTRY_STAR=https://h5.whoisamy.shop/action/hiloHtml/22_08_18_nation_star/page.html
NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/22_05_26_buy_nobility/page.html
NOBLE_BUY_IOS_AUDIT=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html
GUILD_DATA_URL=https://h5.whoisamy.shop/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://h5.whoisamy.shop/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://h5.whoisamy.shop/action/activitiesPage/2022_10_17HiloLiveH5/index.html
GROUP_POWER_GRADE_URL=https://h5.whoisamy.shop/action/hiloHtml/2023Activity/2023_3_21FamilyLevel/index.html
ID_URL=https://h5.whoisamy.shop/action/hiloHtml/new_upgrade/index.html
GROUP_POWER_ACT_URL=https://h5.whoisamy.shop/action/hiloHtml/2023Activity/2023_4_21FamilyMonth/index.html
SHEEP_H5_URL=https://h5.whoisamy.shop/action/slotRelease/sheep0322v1/index.html?game_id=hilo_sheep
[GROUPIM]
MSG_SORT_EXPIRE=1209600
MSG_SORT_SNAP=300
MSG_PARALLEL_SIZE=10
[GRADE]
CHARM_SPEED_VIP=15
ACTITY_SPEED_VIP=15
WEALTH_SPEED_VIP=15
[LIKE]
I_LIKE_NUM=500
I_LIKE_NUM_VIP=1000
I_LIKE_NUM_NOBLE=5000
[APPLEPAY]
PASSWORD=38702750a05c4cb09c9d6ca646835634
[REGISTER]
IMEI_TOTAL=5
IMEI_OAUTH=2
ACCOUNT_IP=100
ACCOUNT_IP_DURATION=21600
[BANNER]
GIFT_BANNER_LEVEL1=3000
GIFT_BANNER_LEVEL2=5000
GIFT_BANNER_LEVEL3=10000
[DIAMOND]
DAILY_LOGIN_IMEI_LIMIT=5
DAILY_LOGIN_IP_LIMIT=30
PRIVATE_GIFT_RETURN=1440
NEW_USER_INVITE_AWARD=5000
[LUCKY_WHEEL]
MINIMAL_PARTICIPANT=2
WAIT_TIMELONG=10
WINNER_DIAMOND_BANNER=200
[GROUP_CUSTOM_THEME]
PIC_LIMIT=50
DAY=10
[GIFT]
WALL_DIAMOND=2000
[DAILY]
LOGIN_COMMON=10
LOGIN_VIP=1000
[FRUIT_TYCOON]
BIG_WINNER_THRESDHOLD=30000
BIG_WINNER_LOW=10000
BIG_WINNER_HIGH=20000
POOL_RATIO=5
WATERMELON_RATIO=24
[ACTIVITY]
COUNTRY_STAR_POOL_RATIO=20
COUNTRY_STAR_ORDINARY_RATIO=20
[RISK_CONTROL]
USER_QPS_LIMIT=128
USER_URL_QPS_LIMIT=64
[PAYER_MAX]
URL=https://pay-gate.payermax.com/aggregate-pay-gate/api/gateway
KEY=503a970695756efa
MERCHANT_ID=SP11018326
BIZ_TYPE=CUSTOMIZE
VERSION=2.3
FRONT_CALLBACK_URL=https://www.hiloconn.com
SHOW_RESULT=1
EXPIRE_TIME=1800
LANGUAGE=en
[PAYPAL]
PAYPAL_CLIENT_ID=AXn-z2U6D2uKW0eJBoH3Hg0MzH6i8mLackAP9bcub2W_YmfMC-YBuPD3sTQgwJSecmAVtHIS9IsqBiIy
PAYPAL_SECRET_ID=EBNCFnSEwbteb8TDVtCMcOUcQBimG7hABmSe0bgC05HriWmje7cKFV2F4xI9pZnt1hDetKLnYxfmWYSY
RETURN_URL=https://apiv1.faceline.live/v1/callback/paypal
\ No newline at end of file
#!/usr/bin/bash
if [ $# -lt 1 ]
then
echo "Parameters missing."
echo "Usage: $0 <executable name>"
exit
fi
while :
do
$1
printf "$(date) : $1 return $?, wait for 5 seconds to restart\n"
sleep 5
done
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment