쫓아내기 버그 수정 / 채팅 채널 expire되는 문제 수정

This commit is contained in:
2023-08-02 00:55:36 +09:00
parent 2b0e60a06a
commit 12ddd2cbfb
2 changed files with 86 additions and 32 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"reflect" "reflect"
"strings"
"time" "time"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
@ -38,6 +39,16 @@ func makeTid(gid groupID, in accountID) string {
return out.Hex() 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 { type Invitation struct {
GroupID groupID `json:"_gid"` GroupID groupID `json:"_gid"`
TicketID string `json:"_tid"` 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 { if err := gd.rh.JSONMDel(gd.strid(), []string{prefix + "._invite", prefix + "._invite_exp"}); err != nil {
return nil, err return nil, err
} }
gd.rh.Persist(gd.rh.Context(), gd.strid()).Result()
return gd.loadMemberFull(tid) return gd.loadMemberFull(tid)
} }
func (gd *groupDoc) removeMember(mid accountID) error { func (gd *groupDoc) removeMemberByTid(tid string) error {
_, err := gd.rh.JSONDel(gd.strid(), "$._members."+gd.tid(mid)) _, err := gd.rh.JSONDel(gd.strid(), "$._members."+tid)
if err != nil {
return err 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) { func (gd *groupDoc) getMembers() (map[string]any, error) {
res, err := gd.rh.JSONGet(gd.strid(), "$._members") res, err := gd.rh.JSONGet(gd.strid(), "$._members")
if err != nil { if err != nil {
@ -439,8 +468,7 @@ func (gp *groupParty) AcceptPartyInvitation(w http.ResponseWriter, r *http.Reque
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
cnt, err := gp.rh.Del(context.Background(), "inv."+mid.Hex()).Result()
cnt, err := gp.rh.Del(context.Background(), mid.Hex()).Result()
if err != nil { if err != nil {
logger.Error("AcceptPartyInvitation failed. gp.rh.Del returns err :", err) logger.Error("AcceptPartyInvitation failed. gp.rh.Del returns err :", err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
@ -487,7 +515,7 @@ func (gp *groupParty) DenyPartyInvitation(w http.ResponseWriter, r *http.Request
gid, _ := gocommon.ReadObjectIDFormValue(r.Form, "gid") gid, _ := gocommon.ReadObjectIDFormValue(r.Form, "gid")
mid, _ := gocommon.ReadObjectIDFormValue(r.Form, "mid") 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{ gd := groupDoc{
id: gid, id: gid,
rh: gp.rh, rh: gp.rh,
@ -529,23 +557,58 @@ func (gp *groupParty) LeaveParty(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return
} }
tid, tidok := gocommon.ReadStringFormValue(r.Form, "tid")
gd := groupDoc{ gd := groupDoc{
id: gid, id: gid,
rh: gp.rh, 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) logger.Println("LeaveParty failed. gd.removeMember returns err :", err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
// 한테는 빈 GroupDocFull을 보낸다. 그러면 지워짐 // mid한테는 빈 GroupDocFull을 보낸다. 그러면 지워짐
gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ gp.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "@" + mid.Hex(), Target: "@" + mid.Hex(),
Body: bson.M{"gid": gid}, Body: bson.M{"gid": gid},
Tag: []string{"GroupDocFull", gid.Hex()}, 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) gp.leaveRoom(gid, mid)
} }
@ -722,19 +785,16 @@ func (gp *groupParty) memberDisconnected(room string, mid primitive.ObjectID) {
rh: gp.rh, rh: gp.rh,
} }
tid := gd.tid(mid) gd.removeMember(mid)
deleted, _ := gp.rh.JSONDel(room, "$._members."+tid)
if deleted > 0 {
// 퇴장을 알림 // 퇴장을 알림
gp.sendUpstreamMessage(&wshandler.UpstreamMessage{ gp.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "#" + room, Target: "#" + room,
Body: bson.M{ Body: bson.M{
tid: bson.M{}, gd.tid(mid): bson.M{},
}, },
Tag: []string{"MemberDocFull"}, Tag: []string{"MemberDocFull"},
}) })
} }
}
func (gp *groupParty) ClientMessageReceived(sender *wshandler.Sender, mt wshandler.WebSocketMessageType, message any) { func (gp *groupParty) ClientMessageReceived(sender *wshandler.Sender, mt wshandler.WebSocketMessageType, message any) {
if mt == wshandler.Disconnected { if mt == wshandler.Disconnected {

View File

@ -240,17 +240,11 @@ func (sub *subTavern) OnClientMessageReceived(sender *wshandler.Sender, messageT
} }
func (sub *subTavern) OnRoomCreated(region, name string) { 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) { 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) { func (sub *subTavern) api(w http.ResponseWriter, r *http.Request) {