diff --git a/src/api/api.go b/src/api/api.go index e7ef1eee..4204a8ce 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -9,8 +9,8 @@ import ( "github.com/gabriel-vasile/mimetype" "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" "github.com/gorilla/websocket" + log "github.com/sirupsen/logrus" "github.com/bbernhard/signal-cli-rest-api/client" utils "github.com/bbernhard/signal-cli-rest-api/utils" @@ -29,23 +29,23 @@ const ( type GroupPermissions struct { AddMembers string `json:"add_members" enums:"only-admins,every-member"` - EditGroup string `json:"edit_group" enums:"only-admins,every-member"` + EditGroup string `json:"edit_group" enums:"only-admins,every-member"` } type CreateGroupRequest struct { - Name string `json:"name"` - Members []string `json:"members"` - Description string `json:"description"` - Permissions GroupPermissions `json:"permissions"` - GroupLinkState string `json:"group_link" enums:"disabled,enabled,enabled-with-approval"` + Name string `json:"name"` + Members []string `json:"members"` + Description string `json:"description"` + Permissions GroupPermissions `json:"permissions"` + GroupLinkState string `json:"group_link" enums:"disabled,enabled,enabled-with-approval"` } type LoggingConfiguration struct { - Level string `json:"Level"` + Level string `json:"Level"` } type Configuration struct { - Logging LoggingConfiguration `json:"logging"` + Logging LoggingConfiguration `json:"logging"` } type RegisterNumberRequest struct { @@ -76,7 +76,11 @@ type Error struct { Msg string `json:"error"` } - +type UpdateContactRequest struct { + Name string `json:"name"` + ExpirationTime int `json:"expiration_time"` + Recipient string `json:"recipient"` +} type CreateGroupResponse struct { Id string `json:"id"` @@ -102,12 +106,12 @@ var connectionUpgrader = websocket.Upgrader{ } type Api struct { - signalClient *client.SignalClient + signalClient *client.SignalClient } func NewApi(signalClient *client.SignalClient) *Api { return &Api{ - signalClient: signalClient, + signalClient: signalClient, } } @@ -279,7 +283,6 @@ func (a *Api) SendV2(c *gin.Context) { c.JSON(201, SendMessageResponse{Timestamp: strconv.FormatInt((*timestamps)[0].Timestamp, 10)}) } - func (a *Api) handleSignalReceive(ws *websocket.Conn, number string) { for { data, err := a.signalClient.Receive(number, 0) @@ -400,7 +403,7 @@ func (a *Api) CreateGroup(c *gin.Context) { } if req.GroupLinkState != "" && !utils.StringInSlice(req.GroupLinkState, []string{"enabled", "enabled-with-approval", "disabled"}) { - c.JSON(400, Error{Msg: "Invalid group link provided - only 'enabled', 'enabled-with-approval' and 'disabled' allowed!" }) + c.JSON(400, Error{Msg: "Invalid group link provided - only 'enabled', 'enabled-with-approval' and 'disabled' allowed!"}) return } @@ -465,6 +468,52 @@ func (a *Api) GetGroup(c *gin.Context) { } } +// @Summary Update contact. +// @Tags Contact +// @Description Update message expiration time for a user. +// @Accept json +// @Produce json +// @Success 201 {string} string "OK" +// @Failure 400 {object} Error +// @Param data body UpdateContactRequest true "Input Data" +// @Router /v1/contact/{number} [post] +func (a *Api) Contact(c *gin.Context) { + var req UpdateContactRequest + number := c.Param("number") + err := c.BindJSON(&req) + if err != nil { + c.JSON(400, gin.H{"error": "Couldn't process request - invalid request"}) + log.Error(err.Error()) + return + } + + if len(number) == 0 { + c.JSON(400, gin.H{"error": "Couldn't process request - please provide the recipients number"}) + return + } + + if len(req.Name) == 0 { + c.JSON(400, gin.H{"error": "Couldn't process request - please provide the recipients name"}) + return + } + + if len(req.Recipient) == 0 { + c.JSON(400, gin.H{"error": "Couldn't process request - please provide the recipients number"}) + return + } + + if !(req.ExpirationTime >= 0) { + c.JSON(400, gin.H{"error": "Couldn't process request - please provide an expiry time in seconds"}) + return + } + + err = a.signalClient.UpdateContact(number, req.Recipient, req.Name, req.ExpirationTime) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } +} + // @Summary Delete a Signal Group. // @Tags Groups // @Description Delete the specified Signal Group. @@ -553,18 +602,18 @@ func (a *Api) RemoveAttachment(c *gin.Context) { err := a.signalClient.RemoveAttachment(attachment) if err != nil { switch err.(type) { - case *client.InvalidNameError: - c.JSON(400, Error{Msg: err.Error()}) - return - case *client.NotFoundError: - c.JSON(404, Error{Msg: err.Error()}) - return - case *client.InternalError: - c.JSON(500, Error{Msg: err.Error()}) - return - default: - c.JSON(500, Error{Msg: err.Error()}) - return + case *client.InvalidNameError: + c.JSON(400, Error{Msg: err.Error()}) + return + case *client.NotFoundError: + c.JSON(404, Error{Msg: err.Error()}) + return + case *client.InternalError: + c.JSON(500, Error{Msg: err.Error()}) + return + default: + c.JSON(500, Error{Msg: err.Error()}) + return } } @@ -585,18 +634,18 @@ func (a *Api) ServeAttachment(c *gin.Context) { attachmentBytes, err := a.signalClient.GetAttachment(attachment) if err != nil { switch err.(type) { - case *client.InvalidNameError: - c.JSON(400, Error{Msg: err.Error()}) - return - case *client.NotFoundError: - c.JSON(404, Error{Msg: err.Error()}) - return - case *client.InternalError: - c.JSON(500, Error{Msg: err.Error()}) - return - default: - c.JSON(500, Error{Msg: err.Error()}) - return + case *client.InvalidNameError: + c.JSON(400, Error{Msg: err.Error()}) + return + case *client.NotFoundError: + c.JSON(404, Error{Msg: err.Error()}) + return + case *client.InternalError: + c.JSON(500, Error{Msg: err.Error()}) + return + default: + c.JSON(500, Error{Msg: err.Error()}) + return } } diff --git a/src/client/client.go b/src/client/client.go index 720a7880..28208fd3 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "fmt" "io/ioutil" "os" "os/exec" @@ -14,9 +15,10 @@ import ( "strings" "time" - "github.com/cyphar/filepath-securejoin" + securejoin "github.com/cyphar/filepath-securejoin" "github.com/gabriel-vasile/mimetype" "github.com/h2non/filetype" + //"github.com/sourcegraph/jsonrpc2"//"net/rpc/jsonrpc" log "github.com/sirupsen/logrus" @@ -470,6 +472,7 @@ func (s *SignalClient) RegisterNumber(number string, useVoice bool, captcha stri if s.signalCliMode == JsonRpc { return errors.New(endpointNotSupportedInJsonRpcMode) } + command := []string{"--config", s.signalCliConfig, "-u", number, "register"} if useVoice { @@ -613,8 +616,8 @@ func (s *SignalClient) CreateGroup(number string, name string, members []string, } type Response struct { - GroupId string `json:"groupId"` - Timestamp int64 `json:"timestamp"` + GroupId string `json:"groupId"` + Timestamp int64 `json:"timestamp"` } var resp Response json.Unmarshal([]byte(rawData), &resp) @@ -729,6 +732,11 @@ func (s *SignalClient) DeleteGroup(number string, groupId string) error { return err } +func (s *SignalClient) UpdateContact(number string, recipient string, name string, expiration_time int) error { + _, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "updateContact", recipient, "-n", name, "-e", fmt.Sprintf("%v", expiration_time)}, "", s.signalCliMode) + return err +} + func (s *SignalClient) GetQrCodeLink(deviceName string) ([]byte, error) { if s.signalCliMode == JsonRpc { return []byte{}, errors.New(endpointNotSupportedInJsonRpcMode) diff --git a/src/docs/docs.go b/src/docs/docs.go index 4279001f..5352d946 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -1064,6 +1064,20 @@ var doc = `{ } } }, + "api.UpdateContactRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "expiration_time": { + "type": "integer" + } + } + }, "api.TrustIdentityRequest": { "type": "object", "properties": { diff --git a/src/docs/swagger.json b/src/docs/swagger.json index b7fcad00..07d8377a 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -902,6 +902,53 @@ } } }, + "/v1/contact/{number}": { + "post": { + "description": "Update Contact", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Update Contact" + ], + "summary": "Update contact expiration", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "description": "Input Data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.UpdateContactRequest" + } + } + ], + "responses": { + "201": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "definitions": { "api.Configuration": { "type": "object", diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 139e792c..bb96bb89 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -96,6 +96,17 @@ definitions: type: string type: array type: object + api.UpdateContactRequest: + properties: + number: + type: string + name: + type: string + expiration_time: + type: intteger + recipient: + type: string + type: object api.TrustIdentityRequest: properties: verified_safety_number: diff --git a/src/go.sum b/src/go.sum index 236835ed..1a7388d1 100644 --- a/src/go.sum +++ b/src/go.sum @@ -77,6 +77,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/src/main.go b/src/main.go index 3c1480c7..cbb5e077 100644 --- a/src/main.go +++ b/src/main.go @@ -114,7 +114,6 @@ func main() { } } - jsonRpc2ClientConfigPathPath := *signalCliConfig + "/jsonrpc2.yml" signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir, signalCliMode, jsonRpc2ClientConfigPathPath) err = signalClient.Init() @@ -190,6 +189,10 @@ func main() { identities.GET(":number", api.ListIdentities) identities.PUT(":number/trust/:numbertotrust", api.TrustIdentity) } + contacts := v1.Group("/contact") + { + contacts.POST(":number", api.Contact) + } } v2 := router.Group("/v2") @@ -222,7 +225,7 @@ func main() { filename := filepath.Base(path) if strings.HasPrefix(filename, "+") && info.Mode().IsRegular() { log.Debug("AUTO_RECEIVE_SCHEDULE: Calling receive for number ", filename) - resp, err := http.Get("http://127.0.0.1:" + port + "/v1/receive/"+filename) + resp, err := http.Get("http://127.0.0.1:" + port + "/v1/receive/" + filename) if err != nil { log.Error("AUTO_RECEIVE_SCHEDULE: Couldn't call receive for number ", filename, ": ", err.Error()) } @@ -235,7 +238,7 @@ func main() { } type ReceiveResponse struct { - Error string `json:"error"` + Error string `json:"error"` } var receiveResponse ReceiveResponse err = json.Unmarshal(jsonResp, &receiveResponse) @@ -258,8 +261,5 @@ func main() { c.Start() } - router.Run() } - -