2023-10-06 11:13:03 +09:00
|
|
|
package core
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
|
|
"github.com/go-redis/redis/v8"
|
|
|
|
|
"repositories.action2quare.com/ayo/gocommon"
|
|
|
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
|
|
|
|
"repositories.action2quare.com/ayo/gocommon/wshandler"
|
|
|
|
|
|
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type instantDoc struct {
|
|
|
|
|
Members map[string]any `json:"_members"`
|
|
|
|
|
Count int64 `json:"_count"`
|
|
|
|
|
Body primitive.M `json:"_body"`
|
|
|
|
|
Gid primitive.ObjectID `json:"_gid"`
|
|
|
|
|
|
|
|
|
|
rh *gocommon.RedisonHandler
|
|
|
|
|
idstr string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gd *instantDoc) loadMemberFull(tid string) (bson.M, error) {
|
|
|
|
|
full, err := gd.rh.JSONGet(gd.strid(), "$._members."+tid)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bt := []byte(full.(string))
|
|
|
|
|
bt = bt[1 : len(bt)-1]
|
|
|
|
|
|
|
|
|
|
var doc bson.M
|
|
|
|
|
if err = json.Unmarshal(bt, &doc); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return doc, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gd *instantDoc) loadFull() (doc bson.M) {
|
|
|
|
|
// 새 멤버에 그룹 전체를 알림
|
|
|
|
|
full, err := gd.rh.JSONGet(gd.strid(), "$")
|
|
|
|
|
if err == nil {
|
|
|
|
|
bt := []byte(full.(string))
|
|
|
|
|
bt = bt[1 : len(bt)-1]
|
|
|
|
|
err = json.Unmarshal(bt, &doc)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("loadFull err :", err)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logger.Println("loadFull err :", err)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gd *instantDoc) strid() string {
|
|
|
|
|
if len(gd.idstr) == 0 {
|
|
|
|
|
gd.idstr = gd.Gid.Hex()
|
|
|
|
|
}
|
|
|
|
|
return gd.idstr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gd *instantDoc) tid(in accountID) string {
|
|
|
|
|
return makeTid(gd.Gid, in)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gd *instantDoc) mid(tid string) accountID {
|
|
|
|
|
tidobj, _ := primitive.ObjectIDFromHex(tid)
|
|
|
|
|
var out primitive.ObjectID
|
|
|
|
|
for i := range tidobj {
|
|
|
|
|
out[12-i-1] = gd.Gid[i] ^ tidobj[12-i-1]
|
|
|
|
|
}
|
|
|
|
|
return out
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gd *instantDoc) addMember(mid accountID, character any) (bson.M, error) {
|
2023-10-06 11:13:03 +09:00
|
|
|
tid := gd.tid(mid)
|
|
|
|
|
if _, err := gd.rh.JSONSet(gd.strid(), "$._members."+tid, character); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
counts, err := gd.rh.JSONNumIncrBy(gd.strid(), "$._count", 1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gd.Count = counts[0]
|
|
|
|
|
|
|
|
|
|
return gd.loadMemberFull(tid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var errGroupAlreadyDestroyed = errors.New("instant group is already destroyed")
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gd *instantDoc) removeMember(mid accountID) error {
|
2023-10-06 11:13:03 +09:00
|
|
|
counts, _ := gd.rh.JSONNumIncrBy(gd.strid(), "$._count", -1)
|
|
|
|
|
if len(counts) == 0 {
|
|
|
|
|
// 이미 지워진 인스턴트그룹
|
|
|
|
|
return errGroupAlreadyDestroyed
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if _, err := gd.rh.JSONDel(gd.strid(), "$._members."+gd.tid(mid)); err != nil {
|
2023-10-06 11:13:03 +09:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gd.Count = counts[0]
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gd *instantDoc) getMembers() (map[primitive.ObjectID]any, error) {
|
2023-10-06 11:13:03 +09:00
|
|
|
res, err := gd.rh.JSONGet(gd.strid(), "$._members")
|
2023-11-15 10:37:32 +09:00
|
|
|
if err == redis.Nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2023-10-06 11:13:03 +09:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var temp []map[string]any
|
|
|
|
|
err = json.Unmarshal([]byte(res.(string)), &temp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
out := make(map[primitive.ObjectID]any)
|
2023-10-06 11:13:03 +09:00
|
|
|
for k, v := range temp[0] {
|
2023-10-09 17:59:15 +09:00
|
|
|
out[gd.mid(k)] = v
|
2023-10-06 11:13:03 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return out, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type groupInstant struct {
|
|
|
|
|
sendUpstreamMessage func(*wshandler.UpstreamMessage)
|
|
|
|
|
enterRoom func(groupID, accountID)
|
|
|
|
|
leaveRoom func(groupID, accountID)
|
|
|
|
|
rh *gocommon.RedisonHandler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) Initialize(tv *Tavern) error {
|
|
|
|
|
gi.rh = tv.redison
|
|
|
|
|
gi.sendUpstreamMessage = func(msg *wshandler.UpstreamMessage) {
|
|
|
|
|
tv.wsh.SendUpstreamMessage(msg)
|
|
|
|
|
}
|
|
|
|
|
gi.enterRoom = func(gid groupID, accid accountID) {
|
|
|
|
|
tv.wsh.EnterRoom(gid.Hex(), accid)
|
|
|
|
|
}
|
|
|
|
|
gi.leaveRoom = func(gid groupID, accid accountID) {
|
|
|
|
|
tv.wsh.LeaveRoom(gid.Hex(), accid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) RegisterApiFunctions() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gi *groupInstant) join(gd *instantDoc, mid primitive.ObjectID, character any) error {
|
|
|
|
|
// 내 정보 업데이트할 때에도 사용됨
|
|
|
|
|
memdoc, err := gd.addMember(mid, character)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2023-10-10 20:32:22 +09:00
|
|
|
delete(memdoc, "_id")
|
2023-10-09 17:59:15 +09:00
|
|
|
|
|
|
|
|
// 기존 유저에게 새 유저 알림
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: "#" + gd.strid(),
|
|
|
|
|
Body: map[string]any{
|
|
|
|
|
gd.tid(mid): memdoc,
|
|
|
|
|
},
|
|
|
|
|
Tag: []string{"MemberDocFull"},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
gi.rh.JSONSet(mid.Hex(), "$.instant", bson.M{"id": gd.strid()})
|
|
|
|
|
|
2023-10-10 20:32:22 +09:00
|
|
|
full := gd.loadFull()
|
|
|
|
|
if f, ok := full["_members"]; ok {
|
|
|
|
|
members := f.(map[string]any)
|
|
|
|
|
for _, char := range members {
|
|
|
|
|
delete(char.(map[string]any), "_id")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
// 최초 입장이라면 새 멤버에 그룹 전체를 알림
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: mid.Hex(),
|
2023-10-10 20:32:22 +09:00
|
|
|
Body: full,
|
2023-10-09 17:59:15 +09:00
|
|
|
Tag: []string{"GroupDocFull"},
|
|
|
|
|
})
|
|
|
|
|
gi.enterRoom(gd.Gid, mid)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 22:27:33 +09:00
|
|
|
func (gi *groupInstant) UpdateInstantDocument(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var data struct {
|
|
|
|
|
Gid primitive.ObjectID
|
|
|
|
|
Doc primitive.M
|
|
|
|
|
Result string
|
|
|
|
|
}
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&data); err != nil {
|
|
|
|
|
logger.Println("UpdateInstantDocument failed. Decode returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gd := partyDoc{
|
|
|
|
|
id: data.Gid,
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
}
|
|
|
|
|
if err := gi.rh.JSONMSetRel(gd.strid(), "$.", data.Doc); err != nil {
|
|
|
|
|
logger.Println("UpdateInstantDocument failed. JSONMSetRel returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 업데이트 알림
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: "#" + gd.strid(),
|
|
|
|
|
Body: data.Doc,
|
|
|
|
|
Tag: []string{"GroupDocFragment"},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if data.Result == "after" {
|
2023-10-10 20:32:22 +09:00
|
|
|
fulldoc := gd.loadFull()
|
|
|
|
|
if fulldoc != nil {
|
|
|
|
|
tids := fulldoc["_members"].(map[string]any)
|
|
|
|
|
mids := make(map[string]any)
|
|
|
|
|
for k, v := range tids {
|
|
|
|
|
mid := midFromTid(data.Gid, k)
|
|
|
|
|
mids[mid.Hex()] = v
|
|
|
|
|
}
|
|
|
|
|
fulldoc["_members"] = mids
|
2023-10-09 22:27:33 +09:00
|
|
|
}
|
2023-10-10 20:32:22 +09:00
|
|
|
gocommon.MakeEncoder(w, r).Encode(fulldoc)
|
2023-10-09 22:27:33 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-06 11:13:03 +09:00
|
|
|
func (gi *groupInstant) Join(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var data struct {
|
|
|
|
|
Gid primitive.ObjectID
|
|
|
|
|
Mid primitive.ObjectID
|
|
|
|
|
Character primitive.M
|
|
|
|
|
}
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&data); err != nil {
|
|
|
|
|
logger.Println("JoinParty failed. DecodeGob returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if data.Gid.IsZero() || data.Mid.IsZero() {
|
2023-11-15 10:37:32 +09:00
|
|
|
logger.Println("groupInstant.Join failed. gid or mid is zero")
|
2023-10-06 11:13:03 +09:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
gd, err := gi.find(data.Gid)
|
|
|
|
|
if err != nil || gd == nil {
|
2023-11-15 10:37:32 +09:00
|
|
|
logger.Println("groupInstant.Join failed. gi find return err :", err)
|
2023-10-06 11:13:03 +09:00
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if err := gi.join(gd, data.Mid, data.Character); err != nil {
|
2023-11-15 10:37:32 +09:00
|
|
|
logger.Println("groupInstant.Join failed :", err)
|
2023-10-06 11:13:03 +09:00
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2023-10-09 17:59:15 +09:00
|
|
|
} else {
|
|
|
|
|
gocommon.MakeEncoder(w, r).Encode(gd.Count)
|
2023-10-06 11:13:03 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) Create(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var data struct {
|
|
|
|
|
Mid primitive.ObjectID
|
|
|
|
|
Body primitive.M
|
|
|
|
|
Character primitive.M
|
|
|
|
|
}
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&data); err != nil {
|
|
|
|
|
logger.Println("CreateParty failed. Decode returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gd, err := gi.createInstantGroup(data.Mid, data.Character, data.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("groupInstant.Create failed. gp.createInstantGroup() return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 내가 wshandler room에 입장
|
|
|
|
|
gi.enterRoom(gd.Gid, data.Mid)
|
|
|
|
|
gi.rh.JSONSet(data.Mid.Hex(), "$.instant", bson.M{"id": gd.strid()})
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: data.Mid.Hex(),
|
|
|
|
|
Body: gd,
|
|
|
|
|
Tag: []string{"GroupDocFull"},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
gocommon.MakeEncoder(w, r).Encode(gd.Gid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) Delete(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var gid primitive.ObjectID
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&gid); err != nil {
|
|
|
|
|
logger.Println("CreateParty failed. Decode returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gi *groupInstant) leave(gd *instantDoc, mid primitive.ObjectID) error {
|
|
|
|
|
if err := gd.removeMember(mid); err != nil {
|
|
|
|
|
if err == errGroupAlreadyDestroyed {
|
|
|
|
|
// 정상
|
|
|
|
|
gd.Count = 0
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gi.rh.JSONDel(mid.Hex(), "$.instant.id")
|
|
|
|
|
|
|
|
|
|
// gid에는 제거 메시지 보냄
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: "#" + gd.strid(),
|
|
|
|
|
Body: bson.M{
|
|
|
|
|
gd.tid(mid): bson.M{},
|
|
|
|
|
},
|
|
|
|
|
Tag: []string{"MemberDocFull"},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
gi.leaveRoom(gd.Gid, mid)
|
|
|
|
|
|
|
|
|
|
if gd.Count == 0 {
|
|
|
|
|
gd.rh.Del(gd.rh.Context(), gd.strid()).Result()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-06 11:13:03 +09:00
|
|
|
func (gi *groupInstant) Leave(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var data struct {
|
|
|
|
|
Gid primitive.ObjectID
|
|
|
|
|
Mid primitive.ObjectID
|
|
|
|
|
}
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&data); err != nil {
|
|
|
|
|
logger.Println("RemoveFromParty failed. Decode returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
gd := instantDoc{
|
|
|
|
|
Gid: data.Gid,
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if err := gi.leave(&gd, data.Mid); err != nil {
|
2023-10-06 11:13:03 +09:00
|
|
|
logger.Println("groupInstant.Leave failed. gd.removeMember returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
gocommon.MakeEncoder(w, r).Encode(gd.Count)
|
|
|
|
|
}
|
2023-10-06 11:13:03 +09:00
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
func (gi *groupInstant) Merge(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var data struct {
|
|
|
|
|
From primitive.ObjectID
|
|
|
|
|
Into primitive.ObjectID
|
|
|
|
|
Max int64
|
|
|
|
|
}
|
|
|
|
|
if err := gocommon.MakeDecoder(r).Decode(&data); err != nil {
|
|
|
|
|
logger.Println("RemoveFromParty failed. Decode returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// From에 있는 mid를 Into로 옮김
|
|
|
|
|
gdinto, err := gi.find(data.Into)
|
2023-11-15 10:37:32 +09:00
|
|
|
if err != nil {
|
2023-10-09 17:59:15 +09:00
|
|
|
logger.Println("groupInstant.Merge failed. gd.getMembers returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-10-06 11:13:03 +09:00
|
|
|
|
2023-11-15 10:37:32 +09:00
|
|
|
if gdinto == nil {
|
|
|
|
|
// 이미 나갔다. 머지 중단
|
|
|
|
|
gocommon.MakeEncoder(w, r).Encode(struct {
|
|
|
|
|
From int64
|
|
|
|
|
Into int64
|
|
|
|
|
}{From: -1, Into: 0}) // -1: 알수 없음, 0: 비었음
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
gdfrom := instantDoc{
|
|
|
|
|
Gid: data.From,
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
}
|
|
|
|
|
fromMembers, err := gdfrom.getMembers()
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("groupInstant.Merge failed. gd.getMembers returns err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-10-06 11:13:03 +09:00
|
|
|
|
2023-11-15 10:37:32 +09:00
|
|
|
if len(fromMembers) == 0 {
|
|
|
|
|
// gdfrom이 비었다. 머지 중단
|
|
|
|
|
gocommon.MakeEncoder(w, r).Encode(struct {
|
|
|
|
|
From int64
|
|
|
|
|
Into int64
|
|
|
|
|
}{From: 0, Into: -1})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
var movedmids []primitive.ObjectID
|
|
|
|
|
for mid, doc := range fromMembers {
|
|
|
|
|
gi.join(gdinto, mid, doc)
|
|
|
|
|
gi.leaveRoom(gdfrom.Gid, mid)
|
|
|
|
|
movedmids = append(movedmids, mid)
|
2023-10-06 11:13:03 +09:00
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if gdinto.Count == data.Max {
|
|
|
|
|
break
|
|
|
|
|
}
|
2023-10-06 11:13:03 +09:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 17:59:15 +09:00
|
|
|
if len(movedmids) == int(gdfrom.Count) {
|
|
|
|
|
gi.rh.JSONDel(gdfrom.strid(), "$")
|
|
|
|
|
} else {
|
|
|
|
|
for _, mid := range movedmids {
|
|
|
|
|
gdfrom.removeMember(mid)
|
|
|
|
|
|
|
|
|
|
// gid에는 제거 메시지 보냄
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: "#" + gdfrom.strid(),
|
|
|
|
|
Body: bson.M{
|
|
|
|
|
gdfrom.tid(mid): bson.M{},
|
|
|
|
|
},
|
|
|
|
|
Tag: []string{"MemberDocFull"},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gocommon.MakeEncoder(w, r).Encode(struct {
|
|
|
|
|
From int64
|
|
|
|
|
Into int64
|
|
|
|
|
}{From: gdfrom.Count, Into: gdinto.Count})
|
2023-10-06 11:13:03 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) createInstantGroup(firstAcc primitive.ObjectID, firstChar primitive.M, instDoc primitive.M) (*instantDoc, error) {
|
|
|
|
|
newid := primitive.NewObjectID()
|
|
|
|
|
tid := makeTid(newid, firstAcc)
|
|
|
|
|
|
|
|
|
|
gd := &instantDoc{
|
|
|
|
|
Members: map[string]any{
|
|
|
|
|
tid: firstChar,
|
|
|
|
|
},
|
|
|
|
|
Body: instDoc,
|
|
|
|
|
Count: 1,
|
|
|
|
|
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
Gid: newid,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := gi.rh.JSONSet(gd.strid(), "$", gd, gocommon.RedisonSetOptionNX)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return gd, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (gi *groupInstant) find(id groupID) (*instantDoc, error) {
|
|
|
|
|
if id.IsZero() {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := gi.rh.JSONObjLen(id.Hex(), "$")
|
|
|
|
|
if err == redis.Nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &instantDoc{
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
Gid: id,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-10 16:41:18 +09:00
|
|
|
func (gi *groupInstant) ClientDisconnected(msg string, callby *wshandler.Sender) {
|
2023-10-06 11:13:03 +09:00
|
|
|
gids, _ := gi.rh.JSONGetString(callby.Accid.Hex(), "$.instant.id")
|
|
|
|
|
|
|
|
|
|
if len(gids) > 0 && len(gids[0]) > 0 {
|
|
|
|
|
gidstr := gids[0]
|
|
|
|
|
gid, _ := primitive.ObjectIDFromHex(gidstr)
|
|
|
|
|
|
|
|
|
|
gd := instantDoc{
|
|
|
|
|
Gid: gid,
|
|
|
|
|
rh: gi.rh,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gi.rh.JSONDel(callby.Accid.Hex(), "$.instant.id")
|
|
|
|
|
|
|
|
|
|
if err := gd.removeMember(callby.Accid); err != nil {
|
|
|
|
|
if err == errGroupAlreadyDestroyed {
|
|
|
|
|
// 정상
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Println("ClientDisconnected failed. gd.removeMember returns err :", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gid에는 제거 메시지 보냄
|
|
|
|
|
gi.sendUpstreamMessage(&wshandler.UpstreamMessage{
|
|
|
|
|
Target: "#" + gd.strid(),
|
|
|
|
|
Body: bson.M{
|
|
|
|
|
gd.tid(callby.Accid): bson.M{},
|
|
|
|
|
},
|
|
|
|
|
Tag: []string{"MemberDocFull"},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
gi.leaveRoom(gd.Gid, callby.Accid)
|
|
|
|
|
|
|
|
|
|
if gd.Count == 0 {
|
|
|
|
|
gd.rh.Del(gd.rh.Context(), gd.strid()).Result()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|