mirror of
https://github.com/aljazceru/signal-cli-rest-api.git
synced 2025-12-20 08:04:28 +01:00
132
src/api/api.go
132
src/api/api.go
@@ -37,6 +37,14 @@ type GroupEntry struct {
|
||||
Blocked bool `json:"blocked"`
|
||||
}
|
||||
|
||||
type IdentityEntry struct {
|
||||
Number string `json:"number"`
|
||||
Status string `json:"status"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Added string `json:"added"`
|
||||
SafetyNumber string `json:"safety_number"`
|
||||
}
|
||||
|
||||
type RegisterNumberRequest struct {
|
||||
UseVoice bool `json:"use_voice"`
|
||||
Captcha string `json:"captcha"`
|
||||
@@ -79,6 +87,10 @@ type UpdateProfileRequest struct {
|
||||
Base64Avatar string `json:"base64_avatar"`
|
||||
}
|
||||
|
||||
type TrustIdentityRequest struct {
|
||||
VerifiedSafetyNumber string `json:"verified_safety_number"`
|
||||
}
|
||||
|
||||
func convertInternalGroupIdToGroupId(internalId string) string {
|
||||
return groupPrefix + base64.StdEncoding.EncodeToString([]byte(internalId))
|
||||
}
|
||||
@@ -192,6 +204,36 @@ func send(c *gin.Context, attachmentTmpDir string, signalCliConfig string, numbe
|
||||
c.JSON(201, nil)
|
||||
}
|
||||
|
||||
func parseWhitespaceDelimitedKeyValueStringList(in string, keys []string) []map[string]string {
|
||||
l := []map[string]string{}
|
||||
lines := strings.Split(in, "\n")
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
m := make(map[string]string)
|
||||
|
||||
temp := line
|
||||
for i, key := range keys {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
idx := strings.Index(temp, " " + key + ": ")
|
||||
pair := temp[:idx]
|
||||
value := strings.TrimPrefix(pair, key + ": ")
|
||||
temp = strings.TrimLeft(temp[idx:], " "+key+": ")
|
||||
|
||||
m[keys[i-1]] = value
|
||||
}
|
||||
m[keys[len(keys)-1]] = temp
|
||||
|
||||
l = append(l, m)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func getGroups(number string, signalCliConfig string) ([]GroupEntry, error) {
|
||||
groupEntries := []GroupEntry{}
|
||||
|
||||
@@ -789,6 +831,11 @@ func (a *Api) ServeAttachment(c *gin.Context) {
|
||||
func (a *Api) UpdateProfile(c *gin.Context) {
|
||||
number := c.Param("number")
|
||||
|
||||
if number == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateProfileRequest
|
||||
err := c.BindJSON(&req)
|
||||
if err != nil {
|
||||
@@ -870,3 +917,88 @@ func (a *Api) UpdateProfile(c *gin.Context) {
|
||||
func (a *Api) Health(c *gin.Context) {
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary List Identities
|
||||
// @Tags Identities
|
||||
// @Description List all identities for the given number.
|
||||
// @Produce json
|
||||
// @Success 200 {object} []IdentityEntry
|
||||
// @Param number path string true "Registered Phone Number"
|
||||
// @Router /v1/identities/{number} [get]
|
||||
func (a *Api) ListIdentities(c *gin.Context) {
|
||||
number := c.Param("number")
|
||||
|
||||
if number == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
|
||||
return
|
||||
}
|
||||
|
||||
out, err := runSignalCli(true, []string{"--config", a.signalCliConfig, "-u", number, "listIdentities"}, "")
|
||||
if err != nil {
|
||||
c.JSON(500, Error{Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
identityEntries := []IdentityEntry{}
|
||||
keyValuePairs := parseWhitespaceDelimitedKeyValueStringList(out, []string{"NumberAndTrustStatus", "Added", "Fingerprint", "Safety Number"})
|
||||
for _, keyValuePair := range keyValuePairs {
|
||||
numberAndTrustStatus := keyValuePair["NumberAndTrustStatus"]
|
||||
numberAndTrustStatusSplitted := strings.Split(numberAndTrustStatus, ":")
|
||||
|
||||
|
||||
identityEntry := IdentityEntry{Number: strings.Trim(numberAndTrustStatusSplitted[0], " "),
|
||||
Status: strings.Trim(numberAndTrustStatusSplitted[1], " "),
|
||||
Added: keyValuePair["Added"],
|
||||
Fingerprint: strings.Trim(keyValuePair["Fingerprint"], " "),
|
||||
SafetyNumber: strings.Trim(keyValuePair["Safety Number"], " "),
|
||||
}
|
||||
identityEntries = append(identityEntries, identityEntry)
|
||||
}
|
||||
|
||||
c.JSON(200, identityEntries)
|
||||
}
|
||||
|
||||
// @Summary Trust Identity
|
||||
// @Tags Identities
|
||||
// @Description Trust an identity.
|
||||
// @Produce json
|
||||
// @Success 204 {string} OK
|
||||
// @Param data body TrustIdentityRequest true "Input Data"
|
||||
// @Param number path string true "Registered Phone Number"
|
||||
// @Param numberToTrust path string true "Number To Trust"
|
||||
// @Router /v1/identities/{number}/{numberToTrust} [put]
|
||||
func (a *Api) TrustIdentity(c *gin.Context) {
|
||||
number := c.Param("number")
|
||||
|
||||
if number == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
|
||||
return
|
||||
}
|
||||
|
||||
numberToTrust := c.Param("numbertotrust")
|
||||
if numberToTrust == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - number to trust missing"})
|
||||
return
|
||||
}
|
||||
|
||||
var req TrustIdentityRequest
|
||||
err := c.BindJSON(&req)
|
||||
if err != nil {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - invalid request"})
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.VerifiedSafetyNumber == "" {
|
||||
c.JSON(400, Error{Msg: "Couldn't process request - verified safety number missing"})
|
||||
return
|
||||
}
|
||||
|
||||
cmd := []string{"--config", a.signalCliConfig, "-u", number, "trust", numberToTrust, "--verified-safety-number", req.VerifiedSafetyNumber}
|
||||
_, err = runSignalCli(true, cmd, "")
|
||||
if err != nil {
|
||||
c.JSON(400, Error{Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
109
src/docs/docs.go
109
src/docs/docs.go
@@ -284,6 +284,83 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/identities/{number}": {
|
||||
"get": {
|
||||
"description": "List all identities for the given number.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Identities"
|
||||
],
|
||||
"summary": "List Identities",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/api.IdentityEntry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/identities/{number}/{numberToTrust}": {
|
||||
"put": {
|
||||
"description": "Trust an identity.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Identities"
|
||||
],
|
||||
"summary": "Trust Identity",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Input Data",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/api.TrustIdentityRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Number To Trust",
|
||||
"name": "numberToTrust",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/profiles/{number}": {
|
||||
"put": {
|
||||
"description": "Set your name and optional an avatar.",
|
||||
@@ -627,6 +704,26 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.IdentityEntry": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"added": {
|
||||
"type": "string"
|
||||
},
|
||||
"fingerprint": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "string"
|
||||
},
|
||||
"safety_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.SendMessageV1": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -673,6 +770,14 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TrustIdentityRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"verified_safety_number": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.UpdateProfileRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -717,6 +822,10 @@ var doc = `{
|
||||
{
|
||||
"description": "Update Profile.",
|
||||
"name": "Profiles"
|
||||
},
|
||||
{
|
||||
"description": "List and Trust Identities.",
|
||||
"name": "Identities"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
@@ -269,6 +269,83 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/identities/{number}": {
|
||||
"get": {
|
||||
"description": "List all identities for the given number.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Identities"
|
||||
],
|
||||
"summary": "List Identities",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/api.IdentityEntry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/identities/{number}/{numberToTrust}": {
|
||||
"put": {
|
||||
"description": "Trust an identity.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Identities"
|
||||
],
|
||||
"summary": "Trust Identity",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Input Data",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/api.TrustIdentityRequest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Registered Phone Number",
|
||||
"name": "number",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Number To Trust",
|
||||
"name": "numberToTrust",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/profiles/{number}": {
|
||||
"put": {
|
||||
"description": "Set your name and optional an avatar.",
|
||||
@@ -612,6 +689,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.IdentityEntry": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"added": {
|
||||
"type": "string"
|
||||
},
|
||||
"fingerprint": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "string"
|
||||
},
|
||||
"safety_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.SendMessageV1": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -658,6 +755,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.TrustIdentityRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"verified_safety_number": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api.UpdateProfileRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -702,6 +807,10 @@
|
||||
{
|
||||
"description": "Update Profile.",
|
||||
"name": "Profiles"
|
||||
},
|
||||
{
|
||||
"description": "List and Trust Identities.",
|
||||
"name": "Identities"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -36,6 +36,19 @@ definitions:
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
api.IdentityEntry:
|
||||
properties:
|
||||
added:
|
||||
type: string
|
||||
fingerprint:
|
||||
type: string
|
||||
number:
|
||||
type: string
|
||||
safety_number:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
api.SendMessageV1:
|
||||
properties:
|
||||
base64_attachment:
|
||||
@@ -66,6 +79,11 @@ definitions:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
api.TrustIdentityRequest:
|
||||
properties:
|
||||
verified_safety_number:
|
||||
type: string
|
||||
type: object
|
||||
api.UpdateProfileRequest:
|
||||
properties:
|
||||
base64_avatar:
|
||||
@@ -257,6 +275,57 @@ paths:
|
||||
summary: API Health Check
|
||||
tags:
|
||||
- General
|
||||
/v1/identities/{number}:
|
||||
get:
|
||||
description: List all identities for the given number.
|
||||
parameters:
|
||||
- description: Registered Phone Number
|
||||
in: path
|
||||
name: number
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/api.IdentityEntry'
|
||||
type: array
|
||||
summary: List Identities
|
||||
tags:
|
||||
- Identities
|
||||
/v1/identities/{number}/{numberToTrust}:
|
||||
put:
|
||||
description: Trust an identity.
|
||||
parameters:
|
||||
- description: Input Data
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/api.TrustIdentityRequest'
|
||||
- description: Registered Phone Number
|
||||
in: path
|
||||
name: number
|
||||
required: true
|
||||
type: string
|
||||
- description: Number To Trust
|
||||
in: path
|
||||
name: numberToTrust
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
schema:
|
||||
type: string
|
||||
summary: Trust Identity
|
||||
tags:
|
||||
- Identities
|
||||
/v1/profiles/{number}:
|
||||
put:
|
||||
description: Set your name and optional an avatar.
|
||||
@@ -459,3 +528,5 @@ tags:
|
||||
name: Attachments
|
||||
- description: Update Profile.
|
||||
name: Profiles
|
||||
- description: List and Trust Identities.
|
||||
name: Identities
|
||||
|
||||
@@ -37,6 +37,9 @@ import (
|
||||
// @tag.name Profiles
|
||||
// @tag.description Update Profile.
|
||||
|
||||
// @tag.name Identities
|
||||
// @tag.description List and Trust Identities.
|
||||
|
||||
// @host 127.0.0.1:8080
|
||||
// @BasePath /
|
||||
func main() {
|
||||
@@ -106,6 +109,12 @@ func main() {
|
||||
{
|
||||
profiles.PUT(":number", api.UpdateProfile)
|
||||
}
|
||||
|
||||
identities := v1.Group("identities")
|
||||
{
|
||||
identities.GET(":number", api.ListIdentities)
|
||||
identities.PUT(":number/trust/:numbertotrust", api.TrustIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
v2 := router.Group("/v2")
|
||||
|
||||
Reference in New Issue
Block a user