1068 lines
30 KiB
Go
1068 lines
30 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
|
|
common "repositories.action2quare.com/ayo/gocommon"
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
|
"repositories.action2quare.com/ayo/gocommon/wshandler"
|
|
|
|
"github.com/go-redis/redis/v8"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
func splitDocument(doc bson.M) bson.M {
|
|
setdoc := bson.M{}
|
|
unsetdoc := bson.M{}
|
|
findoc := bson.M{}
|
|
|
|
for k, v := range doc {
|
|
if k == "$set" {
|
|
setdoc = v.(bson.M)
|
|
} else if k == "$unset" {
|
|
unsetdoc = v.(bson.M)
|
|
}
|
|
}
|
|
|
|
for k, v := range doc {
|
|
if v == nil {
|
|
unsetdoc[k] = 1
|
|
} else if k[0] != '$' {
|
|
setdoc[k] = v
|
|
}
|
|
}
|
|
|
|
if len(setdoc) > 0 {
|
|
findoc["$set"] = setdoc
|
|
}
|
|
if len(unsetdoc) > 0 {
|
|
findoc["$unset"] = unsetdoc
|
|
}
|
|
|
|
return findoc
|
|
}
|
|
|
|
// CreateGroup : 그룹 생성
|
|
// - 그룹 : 멤버와 권한을 관리할 수 있다. 그룹 타입에 따라 디비에 저장되거나 메모리에만 존재한다.
|
|
// - 생성 요청이 오면 파티를 만든다. 파티을 만들 수 있는지 여부는 서비스에서 결정할 것이고, 이 요청을 호출했다는 것은 서비스가 결정한 그룹 생성 조건을 다 통과했다는 의미이다.
|
|
// - parameter :
|
|
// - type : 그룹 종류. 그룹 종류에 따라 인덱스와 쿼리 가능 field가 다르다.
|
|
func (sub *subTavern) CreateGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
grouptype := sub.groups[typename]
|
|
if grouptype == nil {
|
|
logger.Println("CreateGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
doc := bson.M{}
|
|
if err := readBsonDoc(r.Body, &doc); err != nil {
|
|
logger.Error("CreateGroup failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
inserted, err := grouptype.Create(r.Form, doc)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Write(inserted[:])
|
|
}
|
|
|
|
// JoinGroup : 그룹에 참가
|
|
// - type : 그룹 타입
|
|
// - 그룹 타입에 맞는 키(주로 _id)
|
|
// - member_id : 참가 멤버의 아이디
|
|
// - body : 멤버의 속성 bson document
|
|
func (sub *subTavern) JoinGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("JoinGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
doc := bson.M{}
|
|
if err := readBsonDoc(r.Body, &doc); err != nil {
|
|
logger.Error("JoinGroup failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("JoinGroup failed. gid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
midobj, midok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tidobj, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !midok && !tidok {
|
|
// 둘다 없네?
|
|
logger.Println("JoinGroup failed. tid or mid should be exist")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var err error
|
|
if candidate, ok := common.ReadBoolFormValue(r.Form, "candidate"); ok && candidate {
|
|
err = group.Candidate(gidobj, midobj, doc)
|
|
} else {
|
|
tidobj, err = group.Join(gidobj, midobj, tidobj, doc)
|
|
}
|
|
|
|
if err == nil {
|
|
json.NewEncoder(w).Encode(map[string]string{
|
|
"gid": gidobj.Hex(),
|
|
"tid": tidobj.Hex(),
|
|
})
|
|
} else if err == errGroupNotExist {
|
|
w.Write([]byte("{}"))
|
|
} else if err != nil {
|
|
logger.Error("JoinGroup failed :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) EnterCandidateChannel(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
if _, ok := sub.groups[typename]; !ok {
|
|
logger.Println("EnterCandidateChannel failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("EnterCandidateChannel failed. mid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("EnterCandidateChannel failed. gid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// candidate channel은 big endian 최상위 비트가 1
|
|
gidobj[0] |= 0x80
|
|
|
|
if conn := sub.wsh.Conn(sub.region, midobj); conn != nil {
|
|
richConnOuter{wsh: sub.wsh, rc: conn}.JoinTag(sub.region, gidobj, midobj, typename)
|
|
} else {
|
|
sub.wshRpc.caller.One(midobj).JoinTag(sub.region, gidobj, midobj, typename)
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) LeaveCandidateChannel(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
if _, ok := sub.groups[typename]; !ok {
|
|
logger.Println("EnterCandidateChannel failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("EnterCandidateChannel failed. mid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("EnterCandidateChannel failed. gid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// candidate channel은 big endian 최상위 비트가 1
|
|
gidobj[0] |= 0x80
|
|
|
|
if conn := sub.wsh.Conn(sub.region, midobj); conn != nil {
|
|
richConnOuter{wsh: sub.wsh, rc: conn}.LeaveTag(sub.region, gidobj, midobj, typename)
|
|
} else {
|
|
sub.wshRpc.caller.One(midobj).LeaveTag(sub.region, gidobj, midobj, typename)
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) EnterGroupChannel(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("EnterGroupChannel failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("EnterGroupChannel failed. mid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("EnterGroupChannel failed. gid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
tid := group.FindTicketID(gidobj, midobj)
|
|
if tid.IsZero() {
|
|
logger.Println("EnterGroupChannel failed. tid is zero")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if conn := sub.wsh.Conn(sub.region, midobj); conn != nil {
|
|
richConnOuter{wsh: sub.wsh, rc: conn}.JoinTag(sub.region, gidobj, tid, typename)
|
|
} else {
|
|
sub.wshRpc.caller.One(midobj).JoinTag(sub.region, gidobj, tid, typename)
|
|
}
|
|
writeBsonDoc(w, primitive.M{"_id": tid})
|
|
}
|
|
|
|
func (sub *subTavern) SetStateInGroup(w http.ResponseWriter, r *http.Request) {
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("SetStateInGroup failed. tag is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("SetStateInGroup failed. mid form value is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
state, ok := common.ReadStringFormValue(r.Form, "state")
|
|
if !ok {
|
|
logger.Println("SetStateInGroup failed. state is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
typename, ok := common.ReadStringFormValue(r.Form, "type")
|
|
if !ok {
|
|
logger.Println("SetStateInGroup failed. type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
var doc bson.M
|
|
if err := readBsonDoc(r.Body, &doc); err != nil {
|
|
logger.Error("SetStateInGroup failed. readBsonDoc err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
tid := doc["_id"].(primitive.ObjectID)
|
|
if conn := sub.wsh.Conn(sub.region, mid); conn != nil {
|
|
richConnOuter{wsh: sub.wsh, rc: conn}.SetStateInTag(sub.region, gid, tid, state, typename)
|
|
} else {
|
|
sub.wshRpc.caller.One(mid).SetStateInTag(sub.region, gid, tid, state, typename)
|
|
}
|
|
}
|
|
|
|
// Invite : 초대
|
|
// - type : 초대 타입 (required)
|
|
// - from : 초대하는 자 (required)
|
|
// - to : 초대받는 자 (required)
|
|
// - timeout : 초대 유지시간(optional. 없으면 config 기본 값)
|
|
// - (body) : 검색시 노출되는 document
|
|
func (sub *subTavern) Invite(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("Invite failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("Invite failed. gid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("Invite failed. mid is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var reqdoc struct {
|
|
Inviter bson.M `bson:"inviter"`
|
|
Invitee bson.M `bson:"invitee"`
|
|
}
|
|
if err := readBsonDoc(r.Body, &reqdoc); err != nil {
|
|
logger.Error("Invite failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
result, err := group.Invite(gid, mid, reqdoc.Inviter, reqdoc.Invitee)
|
|
if err != nil {
|
|
logger.Error("Invite failed. group.Invite returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(result))
|
|
}
|
|
|
|
func (sub *subTavern) UpdateGroupMember(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("UpdateGroupMember failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("UpdateGroupMember failed. gid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, midok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tidobj, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !midok && !tidok {
|
|
// 둘다 없네?
|
|
logger.Println("JoinGroup failed. tid or mid should be exist")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var err error
|
|
delete, _ := common.ReadBoolFormValue(r.Form, "delete")
|
|
if delete {
|
|
err = group.UpdateGroupMember(gidobj, midobj, tidobj, nil)
|
|
} else {
|
|
var doc bson.M
|
|
if err := readBsonDoc(r.Body, &doc); err != nil {
|
|
logger.Error("UpdateGroupMember failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
err = group.UpdateGroupMember(gidobj, midobj, tidobj, doc)
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Println("UpdateGroupMember failed. Update returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) CancelInvitation(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("CancelInvitation failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
tid, ok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !ok {
|
|
logger.Println("CancelInvitation failed. form value 'tid' is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("CancelInvitation failed. form value 'gid' is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.CancelInvitation(gid, tid); err != nil {
|
|
logger.Println("CancelInvitation failed. group.CancelInvitation returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) AcceptInvitation(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("CancelInvitation failed. group type is missing :", r)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, _ := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
mid, _ := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tid, ok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !ok {
|
|
logger.Println("CancelInvitation failed. form value 'tid' is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var member bson.M
|
|
if err := readBsonDoc(r.Body, &member); err != nil {
|
|
logger.Error("AcceptInvitation failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
gidbytes, err := group.AcceptInvitation(gid, mid, tid, member)
|
|
if err != nil {
|
|
logger.Error("AcceptInvitation failed. group.AcceptInvitation returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(gidbytes.Hex()))
|
|
}
|
|
|
|
func (sub *subTavern) DenyInvitation(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("DenyInvitation failed. group type is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, _ := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
mid, _ := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tid, ok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !ok {
|
|
logger.Println("DenyInvitation failed. tid is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
err := group.DenyInvitation(gid, mid, tid)
|
|
if err != nil {
|
|
logger.Error("DenyInvitation failed. group.DenyInvitation returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) QueryInvitations(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("QueryInvitations failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("QueryInvitations failed. mid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var after primitive.Timestamp
|
|
if v, ok := common.ReadStringFormValue(r.Form, "after"); ok && v != "0.0" {
|
|
after = common.DotStringToTimestamp(v)
|
|
}
|
|
|
|
result, err := group.QueryInvitations(mid, after)
|
|
|
|
if err != nil {
|
|
logger.Println("QueryInvitations failed. group.QueryInvitations returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err := writeBsonArr(w, result); err != nil {
|
|
logger.Println("QueryInvitations failed. Encode returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) TurnGroupOnline(w http.ResponseWriter, r *http.Request) {
|
|
// group을 online 상태로 만든다.
|
|
// 요청을 보내는 클라이언트의 conn이 끊이면 online에서 제거한다.
|
|
// online인 group을 가지고 뭘 할지는 게임이 알아서...
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("TurnGroupOnline failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "_id")
|
|
if !ok {
|
|
logger.Println("TurnGroupOnline failed. group id '_id' form value is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("TurnGroupOnline failed. mid form value is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var filter bson.M
|
|
if err := readBsonDoc(r.Body, &filter); err != nil {
|
|
logger.Error("TurnGroupOnline failed. readBsonDoc return err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
exist, err := group.Exist(gid, filter)
|
|
if err != nil {
|
|
logger.Error("TurnGroupOnline failed. FindOne return err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if !exist {
|
|
logger.Println("TurnGroupOnline failed. filter not match", filter)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
score, ok := common.ReadFloatFormValue(r.Form, "score")
|
|
if !ok {
|
|
score = 100
|
|
}
|
|
|
|
if conn := sub.wsh.Conn(sub.region, mid); conn != nil {
|
|
err = richConnOuter{wsh: sub.wsh, rc: conn}.TurnGroupOnline(onlineGroupQueryKey(typename), gid, score)
|
|
} else {
|
|
err = sub.wshRpc.caller.One(mid).TurnGroupOnline(onlineGroupQueryKey(typename), gid, score)
|
|
}
|
|
if err != nil {
|
|
logger.Error("TurnGroupOnline failed. TurnGroupOnline err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) TurnGroupOffline(w http.ResponseWriter, r *http.Request) {
|
|
// group을 offline 상태로 만든다.
|
|
// 요청을 보내는 클라이언트의 conn이 끊이면 online에서 제거한다.
|
|
// online인 group을 가지고 뭘 할지는 게임이 알아서...
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("TurnGroupOffline failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "_id")
|
|
if !ok {
|
|
logger.Println("TurnGroupOffline failed. group id '_id' form value is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("TurnGroupOffline failed. mid form value is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// onlinename := onlineGroupQueryKey(typename)
|
|
// if onClose := conn.UnregistOnCloseFunc(onlinename); onClose != nil {
|
|
// onClose()
|
|
// } else {
|
|
// gid, ok := common.ReadStringFormValue(form, "_id")
|
|
// if ok {
|
|
// sub.redisSync.ZRem(context.Background(), onlinename, gid)
|
|
// }
|
|
// }
|
|
|
|
var err error
|
|
if conn := sub.wsh.Conn(sub.region, mid); conn != nil {
|
|
err = richConnOuter{wsh: sub.wsh, rc: conn}.TurnGroupOffline(onlineGroupQueryKey(typename), gid)
|
|
} else {
|
|
err = sub.wshRpc.caller.One(mid).TurnGroupOffline(onlineGroupQueryKey(typename), gid)
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Error("TurnGroupOffline failed. TurnGroupOnline err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) QueryOnlineGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("QueryOnlineGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var cmd *redis.StringSliceCmd
|
|
scoreStart, _ := common.ReadStringFormValue(r.Form, "score_start")
|
|
scoreStop, _ := common.ReadStringFormValue(r.Form, "score_stop")
|
|
|
|
if len(scoreStart) > 0 || len(scoreStop) > 0 {
|
|
if len(scoreStart) == 0 {
|
|
scoreStart = "-inf"
|
|
}
|
|
if len(scoreStop) == 0 {
|
|
scoreStop = "+inf"
|
|
}
|
|
cmd = sub.wsh.RedisSync.ZRangeArgs(context.Background(), redis.ZRangeArgs{
|
|
Key: onlineGroupQueryKey(typename),
|
|
ByScore: true,
|
|
Start: scoreStart,
|
|
Stop: scoreStop,
|
|
Rev: true,
|
|
Count: 1,
|
|
})
|
|
} else {
|
|
// 아무거나
|
|
cmd = sub.wsh.RedisSync.ZRandMember(context.Background(), onlineGroupQueryKey(typename), 1, false)
|
|
}
|
|
|
|
result, err := cmd.Result()
|
|
if err != nil {
|
|
logger.Error("QueryOnlineGroup failed. redid.ZRandMember returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writeBsonDoc(w, bson.M{"r": result})
|
|
}
|
|
|
|
func (sub *subTavern) SearchGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("SearchGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
projection, _ := common.ReadStringFormValue(r.Form, "projection")
|
|
|
|
var filter bson.M
|
|
if err := readBsonDoc(r.Body, &filter); err != nil {
|
|
logger.Error("SearchGroup failed. readBsonDoc returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
result, err := group.FindAll(filter, projection, primitive.Timestamp{})
|
|
if err != nil {
|
|
logger.Error("SearchGroup failed. FindAll err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
if err := writeBsonArr(w, result); err != nil {
|
|
logger.Error("json marshal failed :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) QueryOnlineState(w http.ResponseWriter, r *http.Request) {
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("IsOnline failed. mid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
state, err := sub.wsh.GetState(mid)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Write([]byte(state))
|
|
}
|
|
|
|
func (sub *subTavern) IsOnline(w http.ResponseWriter, r *http.Request) {
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("IsOnline failed. mid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
ok, err := sub.wsh.IsOnline(mid)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
w.Write([]byte("true"))
|
|
} else {
|
|
w.Write([]byte("false"))
|
|
}
|
|
}
|
|
|
|
// QueryGroup : 그룹조회
|
|
// - type : 그룹 타입
|
|
// - 그룹 타입에 맞는 키(주로 _id)
|
|
// - projection : select할 필드. ,로 구분
|
|
func (sub *subTavern) QueryGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("QueryGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "_id")
|
|
if !ok {
|
|
logger.Println("QueryGroup failed. _id is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
projection, _ := common.ReadStringFormValue(r.Form, "projection")
|
|
|
|
after, _ := common.ReadStringFormValue(r.Form, "after")
|
|
if after != "0.0" {
|
|
projection += ",+luts"
|
|
}
|
|
|
|
result, err := group.FindOne(gid, projection)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if result == nil {
|
|
return
|
|
}
|
|
if len(after) > 0 {
|
|
if luts, ok := result["luts"].(primitive.Timestamp); ok {
|
|
afterts := common.DotStringToTimestamp(after)
|
|
if primitive.CompareTimestamp(luts, afterts) < 0 {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := writeBsonDoc(w, result); err != nil {
|
|
logger.Error("json marshal failed :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
// QueryGroupMembers : 그룹내 멤버 조회
|
|
// - type : 그룹 타입
|
|
// - 그룹 타입에 맞는 키(주로 _id)
|
|
// - projection : select할 필드. ,로 구분
|
|
func (sub *subTavern) QueryGroupMembers(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("QueryGroupMembers failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("QueryGroupMembers failed. _id is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, _ := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
var after primitive.Timestamp
|
|
if ts, ok := common.ReadStringFormValue(r.Form, "after"); ok && ts != "0.0" {
|
|
after = common.DotStringToTimestamp(ts)
|
|
}
|
|
projection, _ := common.ReadStringFormValue(r.Form, "projection")
|
|
|
|
result, err := group.QueryMembers(gidobj, midobj, projection, after)
|
|
if err != nil {
|
|
logger.Error("QueryGroupMembers failed. FindAll err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
if err := writeBsonDoc(w, result); err != nil {
|
|
logger.Error("QueryGroupMembers failed. writeBsonArr err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) QueryGroupMember(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("QueryGroupMember failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("QueryGroupMember failed. gid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
mid, midok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tid, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !midok && !tidok {
|
|
// 둘 중 하나는 있어야지
|
|
logger.Println("QueryGroupMember failed. tid and mid are both missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
projection, _ := common.ReadStringFormValue(r.Form, "projection")
|
|
result, err := group.QueryMember(gid, mid, tid, projection)
|
|
if err != nil {
|
|
logger.Println("QueryGroupMember failed. group.QueryMember returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
if err := writeBsonDoc(w, result); err != nil {
|
|
logger.Error("QueryGroupMember failed. writeBsonDoc err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
// LeaveGroup : 그룹에서 나감 or 내보냄
|
|
// - type : 그룹 타입
|
|
// - 그룹 타입에 맞는 키(주로 _id)
|
|
// - member_id : 나갈 멤버의 아이디
|
|
func (sub *subTavern) LeaveGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("LeaveGroup failed. group type is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("LeaveGroup failed. gid is missing :", r.Form)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
mid, midok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
tid, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
|
|
if !midok && !tidok {
|
|
// 둘 중 하나는 있어야지
|
|
logger.Println("LeaveGroup failed. tid and mid are both missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.Leave(gid, mid, tid); err != nil {
|
|
// 둘 중 하나는 있어야지
|
|
logger.Println("LeaveGroup failed. group.Leave returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) UpdateMemberDocument(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("DismissGroup failed. type is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("UpdateMemberDocument failed. member_id is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("UpdateMemberDocument failed. _id is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var updatedoc bson.M
|
|
if err := readBsonDoc(r.Body, &updatedoc); err != nil {
|
|
logger.Error("UpdateMemberDocument failed. body decoding error :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.UpdateMemberDocument(gidobj, midobj, updatedoc); err != nil {
|
|
logger.Println("UpdateMemberDocument failed :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) DismissGroup(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("DismissGroup failed. type is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("DismissGroup failed. gid is missing :")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.Dismiss(gid); err != nil {
|
|
logger.Error("DismissGroup failed. group.Dismiss returns err :", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) UpdateGroupDocument(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("UpdateGroupDocument failed. type is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("UpdateGroupDocument failed. gid is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
logger.Error("UpdateGroupDocument failed. readBsonDoc err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.UpdateGroupDocument(gid, body); err != nil {
|
|
logger.Error("UpdateGroupDocument failed. group.UpdateGroupDocument returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) DropPausedMember(w http.ResponseWriter, r *http.Request) {
|
|
typename, _ := common.ReadStringFormValue(r.Form, "type")
|
|
group := sub.groups[typename]
|
|
if group == nil {
|
|
logger.Println("DropDeadMember failed. type is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
|
|
if !ok {
|
|
logger.Println("DropDeadMember failed. gid is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
|
|
if !ok {
|
|
logger.Println("DropDeadMember failed. mid is missing")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := group.DropPausedMember(gid, mid); err != nil {
|
|
logger.Error("DropDeadMember failed. group.DropDeadMember returns err :", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (sub *subTavern) deliveryMessageHandler(deliveryChan <-chan wshandler.DeliveryMessage) {
|
|
defer func() {
|
|
r := recover()
|
|
if r != nil {
|
|
logger.Error(r)
|
|
}
|
|
}()
|
|
|
|
redisSync := sub.wsh.RedisSync
|
|
for msg := range deliveryChan {
|
|
mid := msg.Alias
|
|
if msg.Body != nil {
|
|
buffer := msg.Body
|
|
|
|
var channame string
|
|
for i, ch := range buffer {
|
|
if ch == 0 {
|
|
channame = string(buffer[:i])
|
|
buffer = buffer[i+1:]
|
|
break
|
|
}
|
|
}
|
|
|
|
if len(channame) == 0 {
|
|
continue
|
|
}
|
|
|
|
buffer = append(mid[:], buffer...)
|
|
_, err := redisSync.Publish(context.Background(), channame, buffer).Result()
|
|
if err != nil {
|
|
logger.Error(err)
|
|
}
|
|
}
|
|
|
|
if len(msg.Command) > 0 {
|
|
switch msg.Command {
|
|
case "pause":
|
|
gidtype := msg.Conn.GetTag("gid")
|
|
if len(gidtype) > 0 {
|
|
tokens := strings.SplitN(gidtype, "@", 2)
|
|
gidobj, _ := primitive.ObjectIDFromHex(tokens[0])
|
|
gtype := tokens[1]
|
|
group := sub.groups[gtype]
|
|
if group != nil {
|
|
group.PauseMember(gidobj, msg.Alias, msg.Conn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
logger.Println("delivery chan fin")
|
|
}
|