diff --git a/src/api/api.go b/src/api/api.go index 72c8661..4bb63ce 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -1843,6 +1843,35 @@ func (a *Api) AddDevice(c *gin.Context) { c.Status(http.StatusNoContent) } +// @Summary List linked devices. +// @Tags Devices +// @Description List linked devices associated to this device. +// @Accept json +// @Produce json +// @Param number path string true "Registered Phone Number" +// @Success 200 {object} []client.ListDevicesResponse +// @Failure 400 {object} Error +// @Router /v1/devices/{number} [get] +func (a *Api) ListDevices(c *gin.Context) { + number, err := url.PathUnescape(c.Param("number")) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - malformed number"}) + return + } + if number == "" { + c.JSON(400, Error{Msg: "Couldn't process request - number missing"}) + return + } + + devices, err := a.signalClient.ListDevices(number) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + + c.JSON(200, devices) +} + // @Summary Set account specific settings. // @Tags General // @Description Set account specific settings. diff --git a/src/client/client.go b/src/client/client.go index 651911c..2c35e46 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -217,6 +217,12 @@ type ListContactsResponse struct { Nickname Nickname `json:"nickname"` } +type ListDevicesResponse struct { + Name string `json:"name"` + LastSeenTimestamp int64 `json:"last_seen_timestamp"` + CreationTimestamp int64 `json:"creation_timestamp"` +} + func cleanupTmpFiles(paths []string) { for _, path := range paths { os.Remove(path) @@ -2026,6 +2032,51 @@ func (s *SignalClient) AddDevice(number string, uri string) error { return err } +func (s *SignalClient) ListDevices(number string) ([]ListDevicesResponse, error) { + resp := []ListDevicesResponse{} + + type ListDevicesSignalCliResponse struct { + Id int64 `json:"id"` + Name string `json:"name"` + CreatedTimestamp int64 `json:"createdTimestamp"` + LastSeenTimestamp int64 `json:"lastSeenTimestamp"` + } + + var err error + var rawData string + if s.signalCliMode == JsonRpc { + jsonRpc2Client, err := s.getJsonRpc2Client() + if err != nil { + return resp, err + } + rawData, err = jsonRpc2Client.getRaw("listDevices", &number, nil) + } else { + cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "listDevices"} + rawData, err = s.cliClient.Execute(true, cmd, "") + } + + if err != nil { + return resp, err + } + + var signalCliResp []ListDevicesSignalCliResponse + err = json.Unmarshal([]byte(rawData), &signalCliResp) + if err != nil { + return resp, err + } + + for _, entry := range signalCliResp { + deviceEntry := ListDevicesResponse{ + Name: entry.Name, + CreationTimestamp: entry.CreatedTimestamp, + LastSeenTimestamp: entry.LastSeenTimestamp, + } + resp = append(resp, deviceEntry) + } + + return resp, nil +} + func (s *SignalClient) SetTrustMode(number string, trustMode utils.SignalCliTrustMode) error { s.signalCliApiConfig.SetTrustModeForNumber(number, trustMode) return s.signalCliApiConfig.Persist() diff --git a/src/docs/docs.go b/src/docs/docs.go index d8c12ce..c0f5e60 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -666,6 +666,45 @@ const docTemplate = `{ } }, "/v1/devices/{number}": { + "get": { + "description": "List linked devices associated to this device.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Devices" + ], + "summary": "List linked devices.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/client.ListDevicesResponse" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, "post": { "description": "Links another device to this device. Only works, if this is the master device.", "consumes": [ @@ -2722,6 +2761,20 @@ const docTemplate = `{ } } }, + "client.ListDevicesResponse": { + "type": "object", + "properties": { + "creation_timestamp": { + "type": "integer" + }, + "last_seen_timestamp": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "client.ListInstalledStickerPacksResponse": { "type": "object", "properties": { diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 6841a16..d14c41d 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -663,6 +663,45 @@ } }, "/v1/devices/{number}": { + "get": { + "description": "List linked devices associated to this device.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Devices" + ], + "summary": "List linked devices.", + "parameters": [ + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/client.ListDevicesResponse" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, "post": { "description": "Links another device to this device. Only works, if this is the master device.", "consumes": [ @@ -2719,6 +2758,20 @@ } } }, + "client.ListDevicesResponse": { + "type": "object", + "properties": { + "creation_timestamp": { + "type": "integer" + }, + "last_seen_timestamp": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "client.ListInstalledStickerPacksResponse": { "type": "object", "properties": { diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 2d46d3a..87a6135 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -393,6 +393,15 @@ definitions: uuid: type: string type: object + client.ListDevicesResponse: + properties: + creation_timestamp: + type: integer + last_seen_timestamp: + type: integer + name: + type: string + type: object client.ListInstalledStickerPacksResponse: properties: author: @@ -879,6 +888,32 @@ paths: tags: - Contacts /v1/devices/{number}: + get: + consumes: + - application/json + description: List linked devices associated to this device. + parameters: + - description: Registered Phone Number + in: path + name: number + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/client.ListDevicesResponse' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.Error' + summary: List linked devices. + tags: + - Devices post: consumes: - application/json diff --git a/src/main.go b/src/main.go index 70327a2..e1dd09e 100644 --- a/src/main.go +++ b/src/main.go @@ -230,6 +230,7 @@ func main() { devices := v1.Group("devices") { devices.POST(":number", api.AddDevice) + devices.GET(":number", api.ListDevices) } attachments := v1.Group("attachments")