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"`
|
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 {
|
type RegisterNumberRequest struct {
|
||||||
UseVoice bool `json:"use_voice"`
|
UseVoice bool `json:"use_voice"`
|
||||||
Captcha string `json:"captcha"`
|
Captcha string `json:"captcha"`
|
||||||
@@ -79,6 +87,10 @@ type UpdateProfileRequest struct {
|
|||||||
Base64Avatar string `json:"base64_avatar"`
|
Base64Avatar string `json:"base64_avatar"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TrustIdentityRequest struct {
|
||||||
|
VerifiedSafetyNumber string `json:"verified_safety_number"`
|
||||||
|
}
|
||||||
|
|
||||||
func convertInternalGroupIdToGroupId(internalId string) string {
|
func convertInternalGroupIdToGroupId(internalId string) string {
|
||||||
return groupPrefix + base64.StdEncoding.EncodeToString([]byte(internalId))
|
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)
|
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) {
|
func getGroups(number string, signalCliConfig string) ([]GroupEntry, error) {
|
||||||
groupEntries := []GroupEntry{}
|
groupEntries := []GroupEntry{}
|
||||||
|
|
||||||
@@ -789,6 +831,11 @@ func (a *Api) ServeAttachment(c *gin.Context) {
|
|||||||
func (a *Api) UpdateProfile(c *gin.Context) {
|
func (a *Api) UpdateProfile(c *gin.Context) {
|
||||||
number := c.Param("number")
|
number := c.Param("number")
|
||||||
|
|
||||||
|
if number == "" {
|
||||||
|
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var req UpdateProfileRequest
|
var req UpdateProfileRequest
|
||||||
err := c.BindJSON(&req)
|
err := c.BindJSON(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -870,3 +917,88 @@ func (a *Api) UpdateProfile(c *gin.Context) {
|
|||||||
func (a *Api) Health(c *gin.Context) {
|
func (a *Api) Health(c *gin.Context) {
|
||||||
c.Status(http.StatusNoContent)
|
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}": {
|
"/v1/profiles/{number}": {
|
||||||
"put": {
|
"put": {
|
||||||
"description": "Set your name and optional an avatar.",
|
"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": {
|
"api.SendMessageV1": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -673,6 +770,14 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api.TrustIdentityRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"verified_safety_number": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"api.UpdateProfileRequest": {
|
"api.UpdateProfileRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -717,6 +822,10 @@ var doc = `{
|
|||||||
{
|
{
|
||||||
"description": "Update Profile.",
|
"description": "Update Profile.",
|
||||||
"name": "Profiles"
|
"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}": {
|
"/v1/profiles/{number}": {
|
||||||
"put": {
|
"put": {
|
||||||
"description": "Set your name and optional an avatar.",
|
"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": {
|
"api.SendMessageV1": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -658,6 +755,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api.TrustIdentityRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"verified_safety_number": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"api.UpdateProfileRequest": {
|
"api.UpdateProfileRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -702,6 +807,10 @@
|
|||||||
{
|
{
|
||||||
"description": "Update Profile.",
|
"description": "Update Profile.",
|
||||||
"name": "Profiles"
|
"name": "Profiles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "List and Trust Identities.",
|
||||||
|
"name": "Identities"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,19 @@ definitions:
|
|||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
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:
|
api.SendMessageV1:
|
||||||
properties:
|
properties:
|
||||||
base64_attachment:
|
base64_attachment:
|
||||||
@@ -66,6 +79,11 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
type: object
|
type: object
|
||||||
|
api.TrustIdentityRequest:
|
||||||
|
properties:
|
||||||
|
verified_safety_number:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
api.UpdateProfileRequest:
|
api.UpdateProfileRequest:
|
||||||
properties:
|
properties:
|
||||||
base64_avatar:
|
base64_avatar:
|
||||||
@@ -257,6 +275,57 @@ paths:
|
|||||||
summary: API Health Check
|
summary: API Health Check
|
||||||
tags:
|
tags:
|
||||||
- General
|
- 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}:
|
/v1/profiles/{number}:
|
||||||
put:
|
put:
|
||||||
description: Set your name and optional an avatar.
|
description: Set your name and optional an avatar.
|
||||||
@@ -459,3 +528,5 @@ tags:
|
|||||||
name: Attachments
|
name: Attachments
|
||||||
- description: Update Profile.
|
- description: Update Profile.
|
||||||
name: Profiles
|
name: Profiles
|
||||||
|
- description: List and Trust Identities.
|
||||||
|
name: Identities
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ import (
|
|||||||
// @tag.name Profiles
|
// @tag.name Profiles
|
||||||
// @tag.description Update Profile.
|
// @tag.description Update Profile.
|
||||||
|
|
||||||
|
// @tag.name Identities
|
||||||
|
// @tag.description List and Trust Identities.
|
||||||
|
|
||||||
// @host 127.0.0.1:8080
|
// @host 127.0.0.1:8080
|
||||||
// @BasePath /
|
// @BasePath /
|
||||||
func main() {
|
func main() {
|
||||||
@@ -106,6 +109,12 @@ func main() {
|
|||||||
{
|
{
|
||||||
profiles.PUT(":number", api.UpdateProfile)
|
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")
|
v2 := router.Group("/v2")
|
||||||
|
|||||||
Reference in New Issue
Block a user