user.go 9.59 KB
package tim_m

import (
	"context"
	"encoding/json"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mylogrus"
	"git.hilo.cn/hilo-common/resource/redisCli"
	"git.hilo.cn/hilo-common/sdk/tencentyun"
	"hilo-group/_const/enum/msg_e"
	"hilo-group/_const/enum/online_e"
	"hilo-group/_const/enum/tim_e"
	"hilo-group/_const/redis_key"
	"hilo-group/domain/model/groupPower_m"
	"hilo-group/domain/model/res_m"
	"hilo-group/domain/model/user_m"
	"runtime/debug"
	"strconv"
	"time"
)

func FlushGrades(userExtId string, wealthGrade uint32, charmGrade uint32) error {
	level := (charmGrade & 0x000000FF << 8) | wealthGrade&0x000000FF

	return tencentyun.SetUserLevel(userExtId, level)
}

func SyncWealthGrade(userExtId string, wealthGrade uint32) error {
	level, err := tencentyun.GetUserLevel(userExtId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Infof("SyncWealthGrade, user %s, level before = %x, wealthGrade = %d", userExtId, level, wealthGrade)

	level = level&0xFFFFFF00 | wealthGrade&0x000000FF

	return tencentyun.SetUserLevel(userExtId, level)
}

func SyncCharmGrade(userExtId string, charmGrade uint32) error {
	level, err := tencentyun.GetUserLevel(userExtId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Infof("SyncCharmGrade, user %s, level before = %x, charmGrade = %d", userExtId, level, charmGrade)

	level = level&0xFFFF00FF | (charmGrade & 0x000000FF << 8)

	return tencentyun.SetUserLevel(userExtId, level)
}

type TimHiloInfo struct {
	IsVip      bool     `json:"isVip"`
	IsPretty   bool     `json:"isPretty"`
	Medals     []uint32 `json:"medals"`
	PowerName  string   `json:"powerName"` // 用户加入的国家势力的绑定群组的名称
	NobleLevel uint16   `json:"nobleLevel"`
}

func GetHiloInfo(extId string) (string, error) {
	result, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return "", err
	}
	return result, nil
}

func ResetHiloInfo(extId string) error {
	info := TimHiloInfo{}
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}
	return tencentyun.SetUserHiloInfo(extId, string(buf))
}

func SyncIsVip(model *domain.Model, userId uint64, externalId string) error {
	//detail, err := cv.GetUserVip(model, userId)
	//if err != nil {
	//	return err
	//}

	isVip, _, err := user_m.IsVip(userId)
	if err != nil {
		return err
	}
	//isVip := false
	//if detail != nil {
	//	isVip = true
	//}
	if err = SaveIsVip(externalId, isVip); err != nil {
		model.Log.Info("Sync TIM hilo info failed: ", err)
	}
	return nil
}

func SaveIsVip(extId string, isVip bool) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.IsVip = isVip
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}
	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func SyncIsPretty(extId string, isPretty bool) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.IsPretty = isPretty
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}
	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func SyncMedals(model *domain.Model, userId uint64, externalId string) error {
	// 同步勋章
	medals, err := user_m.GetUserMedalMerge(model.Log, model.Db, userId)
	if err != nil {
		return nil
	}

	if err = SaveMedals(externalId, medals); err != nil {
		mylogrus.MyLog.Info("Sync TIM hilo info failed: ", err)
	}
	return nil
}

// fixme:同步贵族信息,购买、续费贵族时需要
func SyncNobleLevel(extId string, nobleLevel uint16) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.NobleLevel = nobleLevel
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}
	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func SaveMedals(extId string, medals []uint32) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.Medals = medals
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}

	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

// fixme: 以下时机要同步:用户加入/退出势力;势力被取消;势力改绑定群组;群组改名称,欢迎补充
func SyncPowerName(model *domain.Model, userId uint64, externalId string) error {
	_, powerName, err := groupPower_m.GetUserGroupPower(model, userId)
	if err != nil {
		return err
	}

	if err = SavePowerName(externalId, powerName); err != nil {
		mylogrus.MyLog.Info("Sync TIM hilo info failed: ", err)
	}
	return nil
}

func SavePowerName(extId string, powerName string) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.PowerName = powerName
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}

	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func SaveNobleLevel(extId string, nobleLevel uint16) error {
	value, err := tencentyun.GetUserHiloInfo(extId)
	if err != nil {
		return err
	}
	mylogrus.MyLog.Info("TIM hilo info: ", value)

	info := TimHiloInfo{}
	if len(value) > 0 {
		if err = json.Unmarshal([]byte(value), &info); err != nil {
			return err
		}
	}

	info.NobleLevel = nobleLevel
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}

	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, groupPowerName string, nobleLevel uint16) error {
	info := TimHiloInfo{IsVip: isVip, IsPretty: isPrettyCode, Medals: medals, PowerName: groupPowerName, NobleLevel: nobleLevel}
	buf, err := json.Marshal(info)
	if err != nil {
		return err
	}

	if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
		return err
	}
	return nil
}

func SendGroupInvitationShare(model *domain.Model, fromAccount string, toAccounts []string, txGroupId, faceUrl string, lang string) error {
	type TIMInviteEnterRoomMessage struct {
		Identifier   string `json:"identifier"`
		GroupFaceUrl string `json:"groupFaceUrl"`
		GroupId      string `json:"groupId"`
	}
	msg := TIMInviteEnterRoomMessage{
		Identifier:   "TIMGroupInviteMessage",
		GroupFaceUrl: faceUrl,
		GroupId:      txGroupId,
	}
	buf, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	msgBody := string(buf)

	/*	mt := res_m.ResMultiText{MsgId: common.MSG_ID_GROUP_INVITE, Language: lang}
		if err = mt.Get(model.Db); err != nil {
			return err
		}*/
	mt, err := res_m.GetResMultiTextBy(model.Db, msg_e.MSG_ID_GROUP_INVITE, lang)
	if err != nil {
		return err
	}

	return tencentyun.BatchSendCustomMsg(model, tim_e.SYNC_TO_SENDER, fromAccount, toAccounts, msgBody, mt.Content)
}

func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, error) {
	left := make([]string, 0)
	result := make(map[string]uint, 0)

	r, err := getOnlineStatus(extIds)
	if err != nil {
		model.Log.Warnf("getOnlineStatus redis failed")
		left = extIds
	} else {
		model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)

		if len(r) >= len(extIds) {
			for i, e := range extIds {
				if r[i] == nil {
					left = append(left, e)
				} else {
					switch r[i].(type) {
					case string:
						s, err := strconv.Atoi(r[i].(string))
						if err == nil {
							result[e] = uint(s)
						} else {
							left = append(left, e)
						}
					default:
						model.Log.Infof("getOnlineStatus return unknown type %v for %s", r[i], e)
						left = append(left, e)
					}
				}
			}
		} else {
			left = extIds
		}
	}
	model.Log.Debug("getOnlineStatus cache: ", result)

	if len(left) > 0 {
		for _, i := range left {
			result[i] = online_e.IM_STATUS_OFF_LINE
		}

		// 异步去取TIM取数据及更新。查不到的就当离线!
		go func(userIds []string) {
			defer func() {
				if r := recover(); r != nil {
					mylogrus.MyLog.Errorf("SetOnlineStatus SYSTEM ACTION PANIC: %v, stack: %v", r, string(debug.Stack()))
				}
			}()

			st, err := tencentyun.BatchQueryState(model, userIds)
			if err != nil {
				return
			}
			mylogrus.MyLog.Info("getOnlineStatus db: ", st)
			for k, v := range st {
				if err := setOnlineStatus(k, v, time.Hour*12); err != nil {
					model.Log.Warn("SetOnlineStatus failed for ", k)
				} else {
					model.Log.Infof("SetOnlineStatus done %s - %d", k, v)
				}
			}
		}(left)
	}
	return result, nil
}

func getOnlineStatus(extIds []string) ([]interface{}, error) {
	keys := make([]string, 0)
	for _, e := range extIds {
		keys = append(keys, redis_key.GetOnLineStatusKey(e))
	}
	return redisCli.RedisClient.MGet(context.Background(), keys...).Result()
}

func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
	key := redis_key.GetOnLineStatusKey(extId)
	return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err()
}