현 상태를 친구에게 공개
This commit is contained in:
107
core/friend.go
107
core/friend.go
@ -21,7 +21,6 @@ import (
|
||||
|
||||
const (
|
||||
monitoring_center_count = 100
|
||||
state_online = "online"
|
||||
state_offline = "offline"
|
||||
)
|
||||
|
||||
@ -42,7 +41,7 @@ type registerListener struct {
|
||||
|
||||
type monitoringCenter struct {
|
||||
regChan chan registerListener
|
||||
publishState func(string, string, string)
|
||||
publishState func(primitive.ObjectID, string)
|
||||
}
|
||||
|
||||
type friends struct {
|
||||
@ -60,9 +59,8 @@ type listener struct {
|
||||
|
||||
type listenerMap struct {
|
||||
listeners map[primitive.ObjectID]*listener
|
||||
connected bool
|
||||
online []byte
|
||||
offline []byte
|
||||
lastState []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -82,28 +80,17 @@ func combineObjectID(l primitive.ObjectID, r primitive.ObjectID) (out primitive.
|
||||
return
|
||||
}
|
||||
|
||||
func makeSrcMap(src string, connected bool) *listenerMap {
|
||||
online, _ := json.Marshal(wshandler.DownstreamMessage{
|
||||
Body: bson.M{
|
||||
"from": src,
|
||||
"state": state_online,
|
||||
},
|
||||
Tag: friend_state_tag,
|
||||
})
|
||||
|
||||
func makeSrcMap(src string, state []byte) *listenerMap {
|
||||
offline, _ := json.Marshal(wshandler.DownstreamMessage{
|
||||
Body: bson.M{
|
||||
"from": src,
|
||||
"state": state_offline,
|
||||
},
|
||||
Tag: friend_state_tag,
|
||||
Alias: src,
|
||||
Body: bson.M{},
|
||||
Tag: friend_state_tag,
|
||||
})
|
||||
|
||||
return &listenerMap{
|
||||
listeners: make(map[primitive.ObjectID]*listener),
|
||||
connected: connected,
|
||||
online: online,
|
||||
offline: offline,
|
||||
lastState: state,
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,8 +107,12 @@ func makeFriends(ctx context.Context, so *Social, conns *connections) (*friends,
|
||||
regChan := make(chan registerListener)
|
||||
moncen = append(moncen, monitoringCenter{
|
||||
regChan: regChan,
|
||||
publishState: func(src, alias, state string) {
|
||||
so.redison.Publish(ctx, subChannel, src+alias+":"+state).Result()
|
||||
publishState: func(accid primitive.ObjectID, state string) {
|
||||
if len(state) == 0 {
|
||||
so.redison.Publish(ctx, subChannel, accid.Hex()).Result()
|
||||
} else {
|
||||
so.redison.Publish(ctx, subChannel, accid.Hex()+state).Result()
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@ -132,9 +123,9 @@ func makeFriends(ctx context.Context, so *Social, conns *connections) (*friends,
|
||||
select {
|
||||
case reg := <-regChan:
|
||||
// 내가 관심있는 애들 등록
|
||||
srcmap, online := listeners[reg.src]
|
||||
if !online {
|
||||
srcmap = makeSrcMap(reg.alias, false)
|
||||
srcmap, exists := listeners[reg.src]
|
||||
if !exists {
|
||||
srcmap = makeSrcMap(reg.alias, nil)
|
||||
listeners[reg.src] = srcmap
|
||||
}
|
||||
|
||||
@ -142,51 +133,54 @@ func makeFriends(ctx context.Context, so *Social, conns *connections) (*friends,
|
||||
// 등록 해제. 모니터링 종료
|
||||
// listener목록에서 나(reg.l.me)를 제거
|
||||
delete(srcmap.listeners, reg.l.me)
|
||||
online = false
|
||||
exists = false
|
||||
logger.Println("regChan unregistered :", reg.src.Hex(), reg.l.me.Hex())
|
||||
} else if oldl, ok := srcmap.listeners[reg.l.me]; ok {
|
||||
// 내가 이미 리스너로 등록되어 있다.
|
||||
// 상대방이 나를 차단했을 경우에는 기존 리스너가 nil임
|
||||
online = oldl != nil
|
||||
logger.Println("regChan registered :", reg.src.Hex(), reg.l.me.Hex(), "old", online)
|
||||
exists = oldl != nil
|
||||
} else {
|
||||
logger.Println("regChan registered :", reg.src.Hex(), reg.l.me.Hex())
|
||||
srcmap.listeners[reg.l.me] = reg.l
|
||||
}
|
||||
|
||||
if online && srcmap != nil {
|
||||
logger.Println("regChan send online :", reg.l.me.Hex(), string(srcmap.online))
|
||||
reg.l.c.WriteMessage(websocket.TextMessage, srcmap.online)
|
||||
if exists && srcmap != nil && len(srcmap.lastState) > 0 {
|
||||
reg.l.c.WriteMessage(websocket.TextMessage, srcmap.lastState)
|
||||
}
|
||||
|
||||
if len(srcmap.listeners) == 0 && !srcmap.connected {
|
||||
if len(srcmap.listeners) == 0 && len(srcmap.lastState) == 0 {
|
||||
delete(listeners, reg.src)
|
||||
}
|
||||
|
||||
case msg := <-pubsub.Channel():
|
||||
target, _ := primitive.ObjectIDFromHex(msg.Payload[:24])
|
||||
aliasstate := strings.SplitN(msg.Payload[24:], ":", 2)
|
||||
var sent []byte
|
||||
state := msg.Payload[24:]
|
||||
if srcmap, ok := listeners[target]; ok {
|
||||
if aliasstate[1] == state_online {
|
||||
sent = srcmap.online
|
||||
srcmap.connected = true
|
||||
} else if aliasstate[1] == state_offline {
|
||||
sent = srcmap.offline
|
||||
srcmap.connected = false
|
||||
if srcmap == nil {
|
||||
delete(listeners, target)
|
||||
break
|
||||
}
|
||||
|
||||
if len(state) == 0 {
|
||||
// 접속 종료
|
||||
srcmap.lastState = nil
|
||||
if len(srcmap.listeners) == 0 {
|
||||
delete(listeners, target)
|
||||
}
|
||||
}
|
||||
|
||||
if len(sent) > 0 {
|
||||
for _, l := range srcmap.listeners {
|
||||
logger.Println("state fire :", l.me, string(sent))
|
||||
l.c.WriteMessage(websocket.TextMessage, sent)
|
||||
l.c.WriteMessage(websocket.TextMessage, srcmap.offline)
|
||||
}
|
||||
} else {
|
||||
srcmap.lastState = []byte(state)
|
||||
for _, l := range srcmap.listeners {
|
||||
l.c.WriteMessage(websocket.TextMessage, srcmap.lastState)
|
||||
}
|
||||
}
|
||||
} else if aliasstate[1] == state_online {
|
||||
listeners[target] = makeSrcMap(aliasstate[0], true)
|
||||
} else if len(state) > 0 {
|
||||
var dnstream wshandler.DownstreamMessage
|
||||
if err := json.Unmarshal([]byte(state), &dnstream); err == nil {
|
||||
listeners[target] = makeSrcMap(dnstream.Alias, []byte(state))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,16 +196,10 @@ func makeFriends(ctx context.Context, so *Social, conns *connections) (*friends,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fs *friends) ClientConnected(conn *websocket.Conn, callby *wshandler.Sender) {
|
||||
// 내 로그인 상태를 알림
|
||||
meidx := callby.Accid[11] % monitoring_center_count
|
||||
fs.moncen[meidx].publishState(callby.Accid.Hex(), callby.Alias, state_online)
|
||||
}
|
||||
|
||||
func (fs *friends) ClientDisconnected(conn *websocket.Conn, callby *wshandler.Sender) {
|
||||
// 로그 오프 상태를 알림
|
||||
meidx := callby.Accid[11] % monitoring_center_count
|
||||
fs.moncen[meidx].publishState(callby.Accid.Hex(), callby.Alias, state_offline)
|
||||
fs.moncen[meidx].publishState(callby.Accid, "")
|
||||
|
||||
fs.stopMonitoringFriends(callby.Accid)
|
||||
}
|
||||
@ -252,6 +240,17 @@ func (fs *friends) addFriend(f *friendDoc) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *friends) BroadcastMyState(ctx wshandler.ApiCallContext) {
|
||||
stateobj := ctx.Arguments[0].(string)
|
||||
meidx := ctx.CallBy.Accid[11] % monitoring_center_count
|
||||
bt, _ := json.Marshal(wshandler.DownstreamMessage{
|
||||
Alias: ctx.CallBy.Alias,
|
||||
Body: "${state}",
|
||||
Tag: friend_state_tag,
|
||||
})
|
||||
fs.moncen[meidx].publishState(ctx.CallBy.Accid, strings.Replace(string(bt), `"${state}"`, stateobj, 1))
|
||||
}
|
||||
|
||||
func (fs *friends) DeleteFriend(ctx wshandler.ApiCallContext) {
|
||||
fid, _ := primitive.ObjectIDFromHex(ctx.Arguments[0].(string))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user