mirror of
https://github.com/bbernhard/signal-cli-rest-api.git
synced 2026-01-26 19:03:33 +00:00
added two new endpoints
* added endpoint to list a contact * added endpoint to get a contact's avatar
This commit is contained in:
parent
3a2b77b31f
commit
08cd2bd12c
@ -1014,7 +1014,7 @@ func (a *Api) GetGroupAvatar(c *gin.Context) {
|
||||
}
|
||||
groupId := c.Param("groupid")
|
||||
|
||||
groupAvatar, err := a.signalClient.GetGroupAvatar(number, groupId)
|
||||
groupAvatar, err := a.signalClient.GetAvatar(number, groupId, client.GroupAvatar)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case *client.NotFoundError:
|
||||
@ -2311,6 +2311,81 @@ func (a *Api) ListContacts(c *gin.Context) {
|
||||
c.JSON(200, contacts)
|
||||
}
|
||||
|
||||
// @Summary List Contact
|
||||
// @Tags Contacts
|
||||
// @Description List a specific contact.
|
||||
// @Produce json
|
||||
// @Success 200 {object} client.ListContactsResponse
|
||||
// @Param number path string true "Registered Phone Number"
|
||||
// @Router /v1/contacts/{number}/{uuid} [get]
|
||||
func (a *Api) ListContact(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
|
||||
}
|
||||
|
||||
uuid := c.Param("uuid")
|
||||
if uuid == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - uuid missing"})
|
||||
return
|
||||
}
|
||||
|
||||
contact, err := a.signalClient.ListContact(number, uuid)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case *client.NotFoundError:
|
||||
c.JSON(404, Error{Msg: err.Error()})
|
||||
return
|
||||
default:
|
||||
c.JSON(400, Error{Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(200, contact)
|
||||
}
|
||||
|
||||
// @Summary Returns the avatar of a contact
|
||||
// @Tags Contacts
|
||||
// @Description Returns the avatar of a contact.
|
||||
// @Produce json
|
||||
// @Success 200 {string} string "Image"
|
||||
// @Param number path string true "Registered Phone Number"
|
||||
// @Router /v1/contacts/{number}/{uuid}/avatar [get]
|
||||
func (a *Api) GetProfileAvatar(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
|
||||
}
|
||||
|
||||
uuid := c.Param("uuid")
|
||||
if uuid == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - uuid missing"})
|
||||
return
|
||||
}
|
||||
|
||||
avatar, err := a.signalClient.GetAvatar(number, uuid, client.ProfileAvatar)
|
||||
if err != nil {
|
||||
c.JSON(400, Error{Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
mimeType := mimetype.Detect(avatar)
|
||||
c.Data(200, mimeType.String(), avatar)
|
||||
}
|
||||
|
||||
// @Summary Set Pin
|
||||
// @Tags Accounts
|
||||
// @Description Sets a new Signal Pin
|
||||
|
||||
@ -29,6 +29,14 @@ const signalCliV2GroupError = "Cannot create a V2 group as self does not have a
|
||||
|
||||
const endpointNotSupportedInJsonRpcMode = "This endpoint is not supported in JSON-RPC mode."
|
||||
|
||||
type AvatarType int
|
||||
|
||||
const (
|
||||
GroupAvatar AvatarType = iota + 1
|
||||
ContactAvatar
|
||||
ProfileAvatar
|
||||
)
|
||||
|
||||
type GroupPermission int
|
||||
|
||||
const (
|
||||
@ -1323,21 +1331,33 @@ func (s *SignalClient) GetGroup(number string, groupId string) (*GroupEntry, err
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *SignalClient) GetGroupAvatar(number string, groupId string) ([]byte, error) {
|
||||
func (s *SignalClient) GetAvatar(number string, id string, avatarType AvatarType) ([]byte, error) {
|
||||
var err error
|
||||
var rawData string
|
||||
|
||||
internalGroupId, err := ConvertGroupIdToInternalGroupId(groupId)
|
||||
if err != nil {
|
||||
return []byte{}, errors.New("Invalid group id")
|
||||
if avatarType == GroupAvatar {
|
||||
id, err = ConvertGroupIdToInternalGroupId(id)
|
||||
if err != nil {
|
||||
return []byte{}, errors.New("Invalid group id")
|
||||
}
|
||||
}
|
||||
|
||||
if s.signalCliMode == JsonRpc {
|
||||
type Request struct {
|
||||
GroupId string `json:"groupId"`
|
||||
GroupId string `json:"groupId,omitempty"`
|
||||
Contact string `json:"contact,omitempty"`
|
||||
Profile string `json:"profile,omitempty"`
|
||||
}
|
||||
|
||||
request := Request{GroupId: internalGroupId}
|
||||
var request Request
|
||||
|
||||
if avatarType == GroupAvatar {
|
||||
request.GroupId = id
|
||||
} else if avatarType == ContactAvatar {
|
||||
request.Contact = id
|
||||
} else if avatarType == ProfileAvatar {
|
||||
request.Profile = id
|
||||
}
|
||||
|
||||
jsonRpc2Client, err := s.getJsonRpc2Client()
|
||||
if err != nil {
|
||||
@ -1351,8 +1371,21 @@ func (s *SignalClient) GetGroupAvatar(number string, groupId string) ([]byte, er
|
||||
return []byte{}, err
|
||||
}
|
||||
} else {
|
||||
rawData, err = s.cliClient.Execute(true, []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "getAvatar", "-g", internalGroupId}, "")
|
||||
cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "getAvatar"}
|
||||
|
||||
if avatarType == GroupAvatar {
|
||||
cmd = append(cmd, []string{"-g", id}...)
|
||||
} else if avatarType == ContactAvatar {
|
||||
cmd = append(cmd, []string{"--contact", id}...)
|
||||
} else if avatarType == ProfileAvatar {
|
||||
cmd = append(cmd, []string{"--profile", id}...)
|
||||
}
|
||||
|
||||
rawData, err = s.cliClient.Execute(true, cmd, "")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Could not find avatar") {
|
||||
return []byte{}, &NotFoundError{Description: "No avatar found."}
|
||||
}
|
||||
return []byte{}, err
|
||||
}
|
||||
}
|
||||
@ -2528,6 +2561,21 @@ func (s *SignalClient) ListContacts(number string) ([]ListContactsResponse, erro
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *SignalClient) ListContact(number string, uuid string) (ListContactsResponse, error) {
|
||||
contacts, err := s.ListContacts(number)
|
||||
if err != nil {
|
||||
return ListContactsResponse{}, err
|
||||
}
|
||||
|
||||
for _, contact := range contacts {
|
||||
if contact.Uuid == uuid {
|
||||
return contact, nil
|
||||
}
|
||||
}
|
||||
|
||||
return ListContactsResponse{}, &NotFoundError{Description: "No contact with that id (" + uuid + ") found"}
|
||||
}
|
||||
|
||||
func (s *SignalClient) SetPin(number string, registrationLockPin string) error {
|
||||
if s.signalCliMode == JsonRpc {
|
||||
type Request struct {
|
||||
@ -2544,11 +2592,10 @@ func (s *SignalClient) SetPin(number string, registrationLockPin string) error {
|
||||
}
|
||||
} else {
|
||||
cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "setPin", registrationLockPin}
|
||||
rawData, err := s.cliClient.Execute(true, cmd, "")
|
||||
_, err := s.cliClient.Execute(true, cmd, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info(string(rawData))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -665,6 +665,64 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/contacts/{number}/{uuid}": {
|
||||
"get": {
|
||||
"description": "List a specific contact.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Contacts"
|
||||
],
|
||||
"summary": "List Contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/client.ListContactsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/contacts/{number}/{uuid}/avatar": {
|
||||
"get": {
|
||||
"description": "Returns the avatar of a contact.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Contacts"
|
||||
],
|
||||
"summary": "Returns the avatar of a contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Image",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/devices/{number}": {
|
||||
"get": {
|
||||
"description": "List linked devices associated to this device.",
|
||||
|
||||
@ -662,6 +662,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/contacts/{number}/{uuid}": {
|
||||
"get": {
|
||||
"description": "List a specific contact.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Contacts"
|
||||
],
|
||||
"summary": "List Contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/client.ListContactsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/contacts/{number}/{uuid}/avatar": {
|
||||
"get": {
|
||||
"description": "Returns the avatar of a contact.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Contacts"
|
||||
],
|
||||
"summary": "Returns the avatar of a contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Image",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/devices/{number}": {
|
||||
"get": {
|
||||
"description": "List linked devices associated to this device.",
|
||||
|
||||
@ -903,6 +903,44 @@ paths:
|
||||
contact doesn’t exist yet, it will be added.
|
||||
tags:
|
||||
- Contacts
|
||||
/v1/contacts/{number}/{uuid}:
|
||||
get:
|
||||
description: List a specific contact.
|
||||
parameters:
|
||||
- description: Registered Phone Number
|
||||
in: path
|
||||
name: number
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/client.ListContactsResponse'
|
||||
summary: List Contact
|
||||
tags:
|
||||
- Contacts
|
||||
/v1/contacts/{number}/{uuid}/avatar:
|
||||
get:
|
||||
description: Returns the avatar of a contact.
|
||||
parameters:
|
||||
- description: Registered Phone Number
|
||||
in: path
|
||||
name: number
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Image
|
||||
schema:
|
||||
type: string
|
||||
summary: Returns the avatar of a contact
|
||||
tags:
|
||||
- Contacts
|
||||
/v1/contacts/{number}/sync:
|
||||
post:
|
||||
consumes:
|
||||
|
||||
14
src/main.go
14
src/main.go
@ -3,6 +3,12 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"plugin"
|
||||
"strconv"
|
||||
|
||||
"github.com/bbernhard/signal-cli-rest-api/api"
|
||||
"github.com/bbernhard/signal-cli-rest-api/client"
|
||||
docs "github.com/bbernhard/signal-cli-rest-api/docs"
|
||||
@ -12,11 +18,6 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"plugin"
|
||||
)
|
||||
|
||||
// @title Signal Cli REST API
|
||||
@ -69,7 +70,6 @@ func main() {
|
||||
avatarTmpDir := flag.String("avatar-tmp-dir", "/tmp/", "Avatar tmp directory")
|
||||
flag.Parse()
|
||||
|
||||
|
||||
logLevel := utils.GetEnv("LOG_LEVEL", "")
|
||||
if logLevel != "" {
|
||||
err := utils.SetLogLevel(logLevel)
|
||||
@ -305,6 +305,8 @@ func main() {
|
||||
{
|
||||
contacts.GET(":number", api.ListContacts)
|
||||
contacts.PUT(":number", api.UpdateContact)
|
||||
contacts.GET(":number/:uuid", api.ListContact)
|
||||
contacts.GET(":number/:uuid/avatar", api.GetProfileAvatar)
|
||||
contacts.POST(":number/sync", api.SendContacts)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user