From 12ddd2cbfb45a0142cfbf792b29cee4f3d27b4ab Mon Sep 17 00:00:00 2001 From: mountain Date: Wed, 2 Aug 2023 00:55:36 +0900 Subject: [PATCH] =?UTF-8?q?=EC=AB=93=EC=95=84=EB=82=B4=EA=B8=B0=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20/=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=20=EC=B1=84=EB=84=90=20expire=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/group_party.go | 108 ++++++++++++++++++++++++++++++++++---------- core/tavern.go | 10 +--- 2 files changed, 86 insertions(+), 32 deletions(-) diff --git a/core/group_party.go b/core/group_party.go index e088081..0508753 100644 --- a/core/group_party.go +++ b/core/group_party.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "reflect" + "strings" "time" "github.com/go-redis/redis/v8" @@ -38,6 +39,16 @@ func makeTid(gid groupID, in accountID) string { return out.Hex() } +func midFromTid(gid groupID, in string) accountID { + h, _ := primitive.ObjectIDFromHex(in) + + var out accountID + for i := range h { + out[12-i-1] = gid[i] ^ h[12-i-1] + } + return out +} + type Invitation struct { GroupID groupID `json:"_gid"` TicketID string `json:"_tid"` @@ -181,15 +192,33 @@ func (gd *groupDoc) addMember(mid accountID, doc bson.M) (bson.M, error) { if err := gd.rh.JSONMDel(gd.strid(), []string{prefix + "._invite", prefix + "._invite_exp"}); err != nil { return nil, err } + gd.rh.Persist(gd.rh.Context(), gd.strid()).Result() return gd.loadMemberFull(tid) } -func (gd *groupDoc) removeMember(mid accountID) error { - _, err := gd.rh.JSONDel(gd.strid(), "$._members."+gd.tid(mid)) +func (gd *groupDoc) removeMemberByTid(tid string) error { + _, err := gd.rh.JSONDel(gd.strid(), "$._members."+tid) + if err != nil { + return err + } + + counts, err := gd.rh.JSONObjLen(gd.strid(), "$._members") + if err != nil { + return err + } + + if len(counts) > 0 && counts[0] == 0 { + _, err = gd.rh.Del(gd.rh.Context(), gd.strid()).Result() + } + return err } +func (gd *groupDoc) removeMember(mid accountID) error { + return gd.removeMemberByTid(gd.tid(mid)) +} + func (gd *groupDoc) getMembers() (map[string]any, error) { res, err := gd.rh.JSONGet(gd.strid(), "$._members") if err != nil { @@ -220,10 +249,10 @@ type partyConfig struct { type groupParty struct { partyConfig - sendUpstreamMessage func(*wshandler.UpstreamMessage) - enterRoom func(groupID, accountID) - leaveRoom func(groupID, accountID) - rh *gocommon.RedisonHandler + sendUpstreamMessage func(*wshandler.UpstreamMessage) + enterRoom func(groupID, accountID) + leaveRoom func(groupID, accountID) + rh *gocommon.RedisonHandler } func (gp *groupParty) Initialize(sub *subTavern, cfg configDocument) error { @@ -439,8 +468,7 @@ func (gp *groupParty) AcceptPartyInvitation(w http.ResponseWriter, r *http.Reque w.WriteHeader(http.StatusInternalServerError) return } - - cnt, err := gp.rh.Del(context.Background(), mid.Hex()).Result() + cnt, err := gp.rh.Del(context.Background(), "inv."+mid.Hex()).Result() if err != nil { logger.Error("AcceptPartyInvitation failed. gp.rh.Del returns err :", err) w.WriteHeader(http.StatusInternalServerError) @@ -487,7 +515,7 @@ func (gp *groupParty) DenyPartyInvitation(w http.ResponseWriter, r *http.Request gid, _ := gocommon.ReadObjectIDFormValue(r.Form, "gid") mid, _ := gocommon.ReadObjectIDFormValue(r.Form, "mid") - gp.rh.Del(context.Background(), mid.Hex()).Result() + gp.rh.Del(context.Background(), "inv."+mid.Hex()).Result() gd := groupDoc{ id: gid, rh: gp.rh, @@ -529,23 +557,58 @@ func (gp *groupParty) LeaveParty(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) return } - + tid, tidok := gocommon.ReadStringFormValue(r.Form, "tid") gd := groupDoc{ id: gid, rh: gp.rh, } - if err := gd.removeMember(mid); err != nil { + + var err error + if tidok { + if tid != gd.tid(mid) { + // mid가 incharge여야 한다. 그래야 tid를 쫓아낼 수 있음 + incharge, err := gp.rh.JSONGet(gd.strid(), "$._incharge") + if err != nil { + logger.Println("LeaveParty failed. gp.rh.JSONGet returns err :", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + if !strings.Contains(incharge.(string), gd.tid(mid)) { + // incharge가 아니네? + logger.Println("LeaveParty failed. mid is not incharge") + w.WriteHeader(http.StatusBadRequest) + return + } + mid = midFromTid(gd.id, tid) + } + + err = gd.removeMemberByTid(tid) + } else { + err = gd.removeMember(mid) + } + + if err != nil { logger.Println("LeaveParty failed. gd.removeMember returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } - // 나한테는 빈 GroupDocFull을 보낸다. 그러면 지워짐 + // mid한테는 빈 GroupDocFull을 보낸다. 그러면 지워짐 gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ Target: "@" + mid.Hex(), Body: bson.M{"gid": gid}, Tag: []string{"GroupDocFull", gid.Hex()}, }) + + // gid에는 제거 메시지 보냄 + gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ + Target: "#" + gd.strid(), + Body: bson.M{ + tid: bson.M{}, + }, + Tag: []string{"MemberDocFull"}, + }) + gp.leaveRoom(gid, mid) } @@ -722,18 +785,15 @@ func (gp *groupParty) memberDisconnected(room string, mid primitive.ObjectID) { rh: gp.rh, } - tid := gd.tid(mid) - deleted, _ := gp.rh.JSONDel(room, "$._members."+tid) - if deleted > 0 { - // 퇴장을 알림 - gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ - Target: "#" + room, - Body: bson.M{ - tid: bson.M{}, - }, - Tag: []string{"MemberDocFull"}, - }) - } + gd.removeMember(mid) + // 퇴장을 알림 + gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ + Target: "#" + room, + Body: bson.M{ + gd.tid(mid): bson.M{}, + }, + Tag: []string{"MemberDocFull"}, + }) } func (gp *groupParty) ClientMessageReceived(sender *wshandler.Sender, mt wshandler.WebSocketMessageType, message any) { diff --git a/core/tavern.go b/core/tavern.go index 1f4ae3a..52eb588 100644 --- a/core/tavern.go +++ b/core/tavern.go @@ -240,17 +240,11 @@ func (sub *subTavern) OnClientMessageReceived(sender *wshandler.Sender, messageT } func (sub *subTavern) OnRoomCreated(region, name string) { - _, err := sub.redisClient.Persist(context.Background(), name).Result() - if err != nil { - logger.Println("OnRoomCreate Persist failed :", err) - } + } func (sub *subTavern) OnRoomDestroyed(region, name string) { - _, err := sub.redisClient.Expire(context.Background(), name, 3600*time.Second).Result() - if err != nil { - logger.Println("OnRoomDestroyed Expire failed :", err) - } + } func (sub *subTavern) api(w http.ResponseWriter, r *http.Request) {