SendEvent implements: /rooms/{roomID}/send/{eventType} /rooms/{roomID}/send/{eventType}/{txnID} /rooms/{roomID}/state/{eventType}/{stateKey}
( req *http.Request, device *userapi.Device, roomID, eventType string, txnID, stateKey *string, cfg *config.ClientAPI, rsAPI api.ClientRoomserverAPI, txnCache *transactions.Cache, )
| 70 | // /rooms/{roomID}/send/{eventType}/{txnID} |
| 71 | // /rooms/{roomID}/state/{eventType}/{stateKey} |
| 72 | func SendEvent( |
| 73 | req *http.Request, |
| 74 | device *userapi.Device, |
| 75 | roomID, eventType string, txnID, stateKey *string, |
| 76 | cfg *config.ClientAPI, |
| 77 | rsAPI api.ClientRoomserverAPI, |
| 78 | txnCache *transactions.Cache, |
| 79 | ) util.JSONResponse { |
| 80 | |
| 81 | if os.Getenv("CHAT_SERVER_MODE") == "chain" { |
| 82 | localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID) |
| 83 | if err != nil { |
| 84 | return util.JSONResponse{ |
| 85 | Code: http.StatusBadRequest, |
| 86 | JSON: jsonerror.Unknown(err.Error()), |
| 87 | } |
| 88 | } |
| 89 | mortgaged := new_feature.CheckMortgage(localpart) |
| 90 | if !mortgaged { |
| 91 | return util.JSONResponse{ |
| 92 | Code: http.StatusPaymentRequired, |
| 93 | JSON: jsonerror.NotMortgaged("not mortgaged"), |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID} |
| 99 | verRes := api.QueryRoomVersionForRoomResponse{} |
| 100 | if err := rsAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil { |
| 101 | return util.JSONResponse{ |
| 102 | Code: http.StatusBadRequest, |
| 103 | JSON: jsonerror.UnsupportedRoomVersion(err.Error()), |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | if txnID != nil { |
| 108 | // Try to fetch response from transactionsCache |
| 109 | if res, ok := txnCache.FetchTransaction(device.AccessToken, *txnID); ok { |
| 110 | return *res |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | // create a mutex for the specific user in the specific room |
| 115 | // this avoids a situation where events that are received in quick succession are sent to the roomserver in a jumbled order |
| 116 | userID := device.UserID |
| 117 | mutex, _ := userRoomSendMutexes.LoadOrStore(roomID+userID, &sync.Mutex{}) |
| 118 | mutex.(*sync.Mutex).Lock() |
| 119 | defer mutex.(*sync.Mutex).Unlock() |
| 120 | |
| 121 | var r map[string]interface{} // must be a JSON object |
| 122 | resErr := httputil.UnmarshalJSONRequest(req, &r) |
| 123 | if resErr != nil { |
| 124 | return *resErr |
| 125 | } |
| 126 | |
| 127 | if stateKey != nil { |
| 128 | // If the existing/new state content are equal, return the existing event_id, making the request idempotent. |
| 129 | if resp := stateEqual(req.Context(), rsAPI, eventType, *stateKey, roomID, r); resp != nil { |
no test coverage detected