diff --git a/src/api/api.go b/src/api/api.go index e7ef1ee..6819b3c 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -72,6 +72,10 @@ type SendMessageV2 struct { Base64Attachments []string `json:"base64_attachments"` } +type TypingIndicatorRequest struct { + Recipient string `json:"recipient"` +} + type Error struct { Msg string `json:"error"` } @@ -885,3 +889,69 @@ func (a *Api) QuitGroup(c *gin.Context) { } c.Status(http.StatusNoContent) } + +// @Summary Show Typing Indicator. +// @Tags Messages +// @Description Show Typing Indicator. +// @Accept json +// @Produce json +// @Success 201 {string} OK +// @Failure 400 {object} Error +// @Param number path string true "Registered Phone Number" +// @Param data body TypingIndicatorRequest true "Type" +// @Router /v1/typing-indicator/{number} [put] +func (a *Api) SendStartTyping(c *gin.Context) { + var req TypingIndicatorRequest + err := c.BindJSON(&req) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) + log.Error(err.Error()) + return + } + + number := c.Param("number") + if number == "" { + c.JSON(400, Error{Msg: "Couldn't process request - number missing"}) + return + } + + err = a.signalClient.SendStartTyping(number, req.Recipient) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + c.Status(http.StatusNoContent) +} + +// @Summary Hide Typing Indicator. +// @Tags Messages +// @Description Hide Typing Indicator. +// @Accept json +// @Produce json +// @Success 201 {string} OK +// @Failure 400 {object} Error +// @Param number path string true "Registered Phone Number" +// @Param data body TypingIndicatorRequest true "Type" +// @Router /v1/typing-indicator/{number} [delete] +func (a *Api) SendStopTyping(c *gin.Context) { + var req TypingIndicatorRequest + err := c.BindJSON(&req) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) + log.Error(err.Error()) + return + } + + number := c.Param("number") + if number == "" { + c.JSON(400, Error{Msg: "Couldn't process request - number missing"}) + return + } + + err = a.signalClient.SendStopTyping(number, req.Recipient) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + c.Status(http.StatusNoContent) +} diff --git a/src/client/client.go b/src/client/client.go index 720a788..b3d16e1 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -994,3 +994,88 @@ func (s *SignalClient) QuitGroup(number string, groupId string) error { } return err } + +func (s *SignalClient) SendStartTyping(number string, recipient string) error { + var err error + recp := recipient + isGroup := false + if strings.HasPrefix(recipient, groupPrefix) { + isGroup = true + recp, err = ConvertGroupIdToInternalGroupId(recipient) + if err != nil { + return errors.New("Invalid group id") + } + } + + if s.signalCliMode == JsonRpc { + type Request struct { + Recipient string `json:"recipient,omitempty"` + GroupId string `json:"group-id,omitempty"` + } + request := Request{} + if !isGroup { + request.Recipient = recp + } else { + request.GroupId = recp + } + + jsonRpc2Client, err := s.getJsonRpc2Client(number) + if err != nil { + return err + } + _, err = jsonRpc2Client.getRaw("sendTyping", request) + } else { + cmd := []string{"--config", s.signalCliConfig, "-u", number, "sendTyping"} + if !isGroup { + cmd = append(cmd, recp) + } else { + cmd = append(cmd, []string{"-g", recp}...) + } + _, err = runSignalCli(true, cmd, "", s.signalCliMode) + } + + return err +} + +func (s *SignalClient) SendStopTyping(number string, recipient string) error { + var err error + recp := recipient + isGroup := false + if strings.HasPrefix(recipient, groupPrefix) { + isGroup = true + recp, err = ConvertGroupIdToInternalGroupId(recipient) + if err != nil { + return errors.New("Invalid group id") + } + } + + if s.signalCliMode == JsonRpc { + type Request struct { + Recipient string `json:"recipient,omitempty"` + GroupId string `json:"group-id,omitempty"` + Stop bool `json:"stop"` + } + request := Request{Stop: true} + if !isGroup { + request.Recipient = recp + } else { + request.GroupId = recp + } + + jsonRpc2Client, err := s.getJsonRpc2Client(number) + if err != nil { + return err + } + _, err = jsonRpc2Client.getRaw("sendTyping", request) + } else { + cmd := []string{"--config", s.signalCliConfig, "-u", number, "sendTyping", "--stop"} + if !isGroup { + cmd = append(cmd, recp) + } else { + cmd = append(cmd, []string{"-g", recp}...) + } + _, err = runSignalCli(true, cmd, "", s.signalCliMode) + } + + return err +} diff --git a/src/docs/docs.go b/src/docs/docs.go index 4279001..0ae64c5 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -876,6 +876,98 @@ var doc = `{ } } }, + "/v1/typing-indicator/{number}": { + "put": { + "description": "Show Typing Indicator.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Messages" + ], + "summary": "Show Typing Indicator.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "description": "Type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.TypingIndicatorRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, + "delete": { + "description": "Hide Typing Indicator.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Messages" + ], + "summary": "Hide Typing Indicator.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "description": "Type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.TypingIndicatorRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/v2/send": { "post": { "description": "Send a signal message", @@ -1072,6 +1164,14 @@ var doc = `{ } } }, + "api.TypingIndicatorRequest": { + "type": "object", + "properties": { + "recipient": { + "type": "string" + } + } + }, "api.UpdateProfileRequest": { "type": "object", "properties": { @@ -1097,6 +1197,9 @@ var doc = `{ "build": { "type": "integer" }, + "mode": { + "type": "string" + }, "versions": { "type": "array", "items": { diff --git a/src/docs/swagger.json b/src/docs/swagger.json index b7fcad0..4d58533 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -861,6 +861,98 @@ } } }, + "/v1/typing-indicator/{number}": { + "put": { + "description": "Show Typing Indicator.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Messages" + ], + "summary": "Show Typing Indicator.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "description": "Type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.TypingIndicatorRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, + "delete": { + "description": "Hide Typing Indicator.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Messages" + ], + "summary": "Hide Typing Indicator.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "description": "Type", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.TypingIndicatorRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/v2/send": { "post": { "description": "Send a signal message", @@ -1057,6 +1149,14 @@ } } }, + "api.TypingIndicatorRequest": { + "type": "object", + "properties": { + "recipient": { + "type": "string" + } + } + }, "api.UpdateProfileRequest": { "type": "object", "properties": { @@ -1082,6 +1182,9 @@ "build": { "type": "integer" }, + "mode": { + "type": "string" + }, "versions": { "type": "array", "items": { diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 139e792..9b7aee6 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -101,6 +101,11 @@ definitions: verified_safety_number: type: string type: object + api.TypingIndicatorRequest: + properties: + recipient: + type: string + type: object api.UpdateProfileRequest: properties: base64_avatar: @@ -117,6 +122,8 @@ definitions: properties: build: type: integer + mode: + type: string versions: items: type: string @@ -731,6 +738,67 @@ paths: summary: Send a signal message. tags: - Messages + /v1/typing-indicator/{number}: + delete: + consumes: + - application/json + description: Hide Typing Indicator. + parameters: + - description: Registered Phone Number + in: path + name: number + required: true + type: string + - description: Type + in: body + name: data + required: true + schema: + $ref: '#/definitions/api.TypingIndicatorRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.Error' + summary: Hide Typing Indicator. + tags: + - Messages + put: + consumes: + - application/json + description: Show Typing Indicator. + parameters: + - description: Registered Phone Number + in: path + name: number + required: true + type: string + - description: Type + in: body + name: data + required: true + schema: + $ref: '#/definitions/api.TypingIndicatorRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.Error' + summary: Show Typing Indicator. + tags: + - Messages /v2/send: post: consumes: diff --git a/src/main.go b/src/main.go index 3c1480c..c6ae4b8 100644 --- a/src/main.go +++ b/src/main.go @@ -190,6 +190,12 @@ func main() { identities.GET(":number", api.ListIdentities) identities.PUT(":number/trust/:numbertotrust", api.TrustIdentity) } + + typingIndicator := v1.Group("typing-indicator") + { + typingIndicator.PUT(":number", api.SendStartTyping) + typingIndicator.DELETE(":number", api.SendStopTyping) + } } v2 := router.Group("/v2")