| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- package chat
- import (
- "bet24.com/log"
- "bet24.com/redis"
- user "bet24.com/servers/micros/userservices/proto"
- "encoding/json"
- "fmt"
- "sort"
- "strconv"
- "strings"
- "time"
- )
- func SplitToString(a []int, sep string) string {
- if len(a) == 0 {
- return ""
- }
- b := make([]string, len(a))
- for i, v := range a {
- b[i] = strconv.Itoa(v)
- }
- return strings.Join(b, sep)
- }
- func getChannelKey(userIds []int) string {
- sort.Slice(userIds, func(i, j int) bool {
- return userIds[i] < userIds[j]
- })
- return SplitToString(userIds, "+")
- }
- const CHAT_TIME_OUT = 1800
- const MAX_ARCHIVE_MESSAGE = 20
- const MAX_ARCHIVE_TIME = 432000 // 5天
- const MAX_MESSAGE_LEN = 256
- const ONE_DAY = 86400
- type ChannelUser struct {
- UserId int
- NickName string
- FaceId int
- FaceUrl string
- ReadIndex int // 实际读到哪条了
- getIndex int // 取内容标签,用户退出重进后,需要拉所有记录
- ClearIndex int
- Decorations []user.UserDecoration
- Vip int
- VipPoint int
- VipExpire int
- }
- type chatMsg struct {
- Sender int
- Message string
- SendTime string
- Index int
- MsgType int
- }
- type channel struct {
- //userIds []int // 参与的用户
- Key string
- Users []*ChannelUser
- MessageList []chatMsg
- lastAck time.Time
- ChatIndex int
- }
- func newChannel(users []*ChannelUser) *channel {
- c := new(channel)
- c.Users = users
- if len(c.Users) >= 2 {
- var userIds []int
- for _, v := range users {
- userIds = append(userIds, v.UserId)
- }
- c.Key = getChannelKey(userIds)
- c.restore()
- for _, v := range users {
- c.updateUser(v)
- }
- }
- c.touch()
- return c
- }
- func createChannelByKey(key string) *channel {
- c := new(channel)
- c.Key = key
- if !c.restore() {
- return nil
- }
- return c
- }
- func (c *channel) isUserExist(userId int) bool {
- for _, v := range c.Users {
- if v.UserId == userId {
- return true
- }
- }
- return false
- }
- func (c *channel) isIdle() bool {
- return int(time.Now().Sub(c.lastAck).Seconds()) >= CHAT_TIME_OUT
- }
- func (c *channel) addUser(userId int, nickName string, faceId int, faceUrl string) {
- if c.isUserExist(userId) {
- log.Release("channel.addUser userId[%d] exist", userId)
- return
- }
- channelUser := &ChannelUser{
- UserId: userId,
- NickName: nickName,
- FaceId: faceId,
- FaceUrl: faceUrl,
- }
- usr := user.GetUserInfo(userId)
- if usr != nil {
- channelUser.Vip = usr.Vip
- channelUser.VipPoint = usr.VipPoint
- channelUser.VipExpire = usr.VipExpire
- channelUser.Decorations = usr.Decorations
- }
- c.Users = append(c.Users, channelUser)
- if len(c.Users) >= 2 {
- var userIds []int
- for _, v := range c.Users {
- userIds = append(userIds, v.UserId)
- }
- c.Key = getChannelKey(userIds)
- c.restore()
- }
- c.touch()
- }
- func (c *channel) updateUser(userInfo *ChannelUser) {
- if userInfo.NickName == "" {
- return
- }
- for _, v := range c.Users {
- if v.UserId == userInfo.UserId {
- v.NickName = userInfo.NickName
- v.FaceId = userInfo.FaceId
- v.FaceUrl = userInfo.FaceUrl
- }
- }
- }
- func (c *channel) touch() {
- c.lastAck = time.Now()
- }
- func (c *channel) addChat(userId int, message string, msgType int) {
- if !c.isUserExist(userId) {
- log.Release("channel.addChat userId %d not exist", userId)
- return
- }
- if len(message) > MAX_MESSAGE_LEN && msgType == 0 {
- message = message[:MAX_MESSAGE_LEN]
- }
- c.MessageList = append(c.MessageList, chatMsg{
- Sender: userId,
- Message: message,
- SendTime: time.Now().Format("2006-01-02 15:04:05"),
- Index: c.ChatIndex,
- MsgType: msgType,
- })
- c.ChatIndex++
- c.touch()
- }
- func (c *channel) getClearReadIndex(clearIndex, readIndex int) int {
- if clearIndex == 0 {
- return readIndex
- }
- ret := len(c.MessageList)
- for i := 0; i < len(c.MessageList); i++ {
- if c.MessageList[i].Index >= clearIndex {
- ret = i
- break
- }
- }
- if ret > readIndex {
- return ret
- }
- return readIndex
- }
- func (c *channel) getChatByUser(userId int) string {
- // 获取用户当前读取
- var ch channel
- ch.Key = c.Key
- readIndex := 0
- needUserInfo := false
- for _, v := range c.Users {
- if v.UserId == userId {
- readIndex = v.getIndex
- needUserInfo = readIndex == 0
- // 判断一下是否Clear
- readIndex = c.getClearReadIndex(v.ClearIndex, readIndex)
- v.ReadIndex = len(c.MessageList)
- v.getIndex = v.ReadIndex
- }
- }
- // 是否需要玩家信息?
- if needUserInfo {
- for _, v := range c.Users {
- if v.UserId == userId {
- continue
- }
- ch.Users = append(ch.Users, v)
- }
- }
- if readIndex > len(c.MessageList) {
- readIndex = len(c.MessageList)
- }
- ch.MessageList = c.MessageList[readIndex:]
- d, _ := json.Marshal(ch)
- return string(d)
- }
- func (c *channel) dump() {
- log.Release("channel.dump[%s] ChatIndex[%d] ----------", c.Key, c.ChatIndex)
- defer log.Release("channel.dump end ++++++++++++++++")
- log.Release(" userlist")
- for _, v := range c.Users {
- log.Release(" [%d]%s ReadIndex[%d] ClearIndex[%d]Vip[%d]", v.UserId, v.NickName, v.ReadIndex, v.ClearIndex, v.Vip)
- }
- log.Release(" chatlist")
- for _, v := range c.MessageList {
- log.Release(" [%d][%d]%s", v.Index, v.Sender, v.Message)
- }
- }
- func (c *channel) isInvolved(userId int) bool {
- for _, v := range c.Users {
- if v.UserId == userId {
- return true
- }
- }
- return false
- }
- func (c *channel) release() {
- count := len(c.MessageList) - MAX_ARCHIVE_MESSAGE
- if count > 0 {
- c.MessageList = c.MessageList[count:]
- for _, v := range c.Users {
- v.ReadIndex -= count
- if v.ReadIndex < 0 {
- v.ReadIndex = 0
- }
- //v.getIndex = v.ReadIndex
- }
- }
- c.archive()
- }
- func (c *channel) getRedisKey() string {
- return fmt.Sprintf("channel:%s", c.Key)
- }
- func (c *channel) archive() {
- d, _ := json.Marshal(c)
- redis.String_SetEx(c.getRedisKey(), string(d), MAX_ARCHIVE_TIME)
- }
- func (c *channel) removeFromRedis() {
- redis.Key_Del(c.getRedisKey())
- }
- func (c *channel) restore() bool {
- data, ok := redis.String_Get(c.getRedisKey())
- if !ok || data == "" {
- return false
- }
- json.Unmarshal([]byte(data), &c)
- for _, v := range c.Users {
- usr := user.GetUserInfo(v.UserId)
- if usr != nil {
- v.Vip = usr.Vip
- v.VipPoint = usr.VipPoint
- v.VipExpire = usr.VipExpire
- v.Decorations = usr.Decorations
- }
- v.ReadIndex = 0
- v.getIndex = 0
- }
- c.touch()
- return true
- }
- func (c *channel) onUserExit(userId int) {
- for _, v := range c.Users {
- if v.UserId == userId {
- v.getIndex = 0
- return
- }
- }
- log.Release("channel.onUserExit user[%d] not involve", userId)
- }
- func (c *channel) getNewChatCount(userId int) int {
- ret := 0
- for _, v := range c.Users {
- if v.UserId == userId {
- v.ReadIndex = c.getClearReadIndex(v.ClearIndex, v.ReadIndex)
- ret = len(c.MessageList) - v.ReadIndex
- }
- }
- if ret < 0 {
- ret = 0
- }
- return ret
- }
- func (c *channel) getLatestMessage() string {
- if len(c.MessageList) == 0 {
- return ""
- }
- return c.MessageList[len(c.MessageList)-1].Message
- }
- func (c *channel) getLatestTime() string {
- if len(c.MessageList) == 0 {
- return ""
- }
- return c.MessageList[len(c.MessageList)-1].SendTime
- }
- func (c *channel) getLatestMessageType() int {
- if len(c.MessageList) == 0 {
- return 0
- }
- return c.MessageList[len(c.MessageList)-1].MsgType
- }
- func (c *channel) getInfo() string {
- var ch channel
- ch.Key = c.Key
- for _, v := range c.Users {
- ch.Users = append(ch.Users, v)
- }
- d, _ := json.Marshal(ch)
- return string(d)
- }
- func (c *channel) userClear(userId int) {
- log.Debug("channel.userClear %d", userId)
- for _, v := range c.Users {
- if v.UserId == userId {
- v.ClearIndex = c.ChatIndex
- return
- }
- }
- }
|