extended receive endpoint + AUTO_RECEIVE_SCHEDULE functionality

* added timeout, ignore_attachments and ignore_stories query parameter
  to receive endpoint.

* added AUTO_RECEIVE_SCHEDULE_RECEIVE_TIMEOUT,
  AUTO_RECEIVE_SCHEDULE_IGNORE_ATTACHMENTS and
  AUTO_RECEIVE_SCHEDULE_IGNORE_STORIES environment variables to the
  AUTO_RECEIVE_SCHEDULE functionality.

see #365
This commit is contained in:
Bernhard B
2023-05-14 21:21:38 +02:00
parent 99da94d048
commit 0dd742cb23
6 changed files with 233 additions and 68 deletions

View File

@@ -454,6 +454,13 @@ func wsPing(ws *websocket.Conn, stop chan struct{}) {
} }
} }
func StringToBool(input string) bool {
if input == "true" {
return true
}
return false
}
// @Summary Receive Signal Messages. // @Summary Receive Signal Messages.
// @Tags Messages // @Tags Messages
// @Description Receives Signal Messages from the Signal Network. If you are running the docker container in normal/native mode, this is a GET endpoint. In json-rpc mode this is a websocket endpoint. // @Description Receives Signal Messages from the Signal Network. If you are running the docker container in normal/native mode, this is a GET endpoint. In json-rpc mode this is a websocket endpoint.
@@ -463,6 +470,8 @@ func wsPing(ws *websocket.Conn, stop chan struct{}) {
// @Failure 400 {object} Error // @Failure 400 {object} Error
// @Param number path string true "Registered Phone Number" // @Param number path string true "Registered Phone Number"
// @Param timeout query string false "Receive timeout in seconds (default: 1)" // @Param timeout query string false "Receive timeout in seconds (default: 1)"
// @Param ignore_attachments query string false "Specify whether the attachments of the received message should be ignored" (default: false)"
// @Param ignore_stories query string false "Specify whether stories should be ignored when receiving messages" (default: false)"
// @Router /v1/receive/{number} [get] // @Router /v1/receive/{number} [get]
func (a *Api) Receive(c *gin.Context) { func (a *Api) Receive(c *gin.Context) {
number := c.Param("number") number := c.Param("number")
@@ -486,7 +495,19 @@ func (a *Api) Receive(c *gin.Context) {
return return
} }
jsonStr, err := a.signalClient.Receive(number, timeoutInt) ignoreAttachments := c.DefaultQuery("ignore_attachments", "false")
if ignoreAttachments != "true" && ignoreAttachments != "false" {
c.JSON(400, Error {Msg: "Couldn't process request - ignore_attachments parameter needs to be either 'true' or 'false'"})
return
}
ignoreStories := c.DefaultQuery("ignore_stories", "false")
if ignoreStories != "true" && ignoreStories != "false" {
c.JSON(400, Error {Msg: "Couldn't process request - ignore_stories parameter needs to be either 'true' or 'false'"})
return
}
jsonStr, err := a.signalClient.Receive(number, timeoutInt, StringToBool(ignoreAttachments), StringToBool(ignoreStories))
if err != nil { if err != nil {
c.JSON(400, Error{Msg: err.Error()}) c.JSON(400, Error{Msg: err.Error()})
return return

View File

@@ -595,12 +595,20 @@ func (s *SignalClient) SendV2(number string, message string, recps []string, bas
return &timestamps, nil return &timestamps, nil
} }
func (s *SignalClient) Receive(number string, timeout int64) (string, error) { func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments bool, ignoreStories bool) (string, error) {
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
return "", errors.New("Not implemented") return "", errors.New("Not implemented")
} else { } else {
command := []string{"--config", s.signalCliConfig, "--output", "json", "-a", number, "receive", "-t", strconv.FormatInt(timeout, 10)} command := []string{"--config", s.signalCliConfig, "--output", "json", "-a", number, "receive", "-t", strconv.FormatInt(timeout, 10)}
if ignoreAttachments {
command = append(command, "--ignore-attachments")
}
if ignoreStories {
command = append(command, "--ignore-stories")
}
out, err := s.cliClient.Execute(true, command, "") out, err := s.cliClient.Execute(true, command, "")
if err != nil { if err != nil {
return "", err return "", err

View File

@@ -241,9 +241,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"200": { "200": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -283,9 +281,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -327,9 +323,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -371,9 +365,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1156,6 +1148,18 @@ var doc = `{
"description": "Receive timeout in seconds (default: 1)", "description": "Receive timeout in seconds (default: 1)",
"name": "timeout", "name": "timeout",
"in": "query" "in": "query"
},
{
"type": "string",
"description": "Specify whether the attachments of the received message should be ignored",
"name": "ignore_attachments",
"in": "query"
},
{
"type": "string",
"description": "Specify whether stories should be ignored when receiving messages",
"name": "ignore_stories",
"in": "query"
} }
], ],
"responses": { "responses": {
@@ -1208,9 +1212,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"201": { "201": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1482,9 +1484,7 @@ var doc = `{
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1732,17 +1732,41 @@ var doc = `{
"data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e" "data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e"
] ]
}, },
"mentions": {
"type": "array",
"items": {
"$ref": "#/definitions/client.MessageMention"
}
},
"message": { "message": {
"type": "string" "type": "string"
}, },
"number": { "number": {
"type": "string" "type": "string"
}, },
"quote_author": {
"type": "string"
},
"quote_mentions": {
"type": "array",
"items": {
"$ref": "#/definitions/client.MessageMention"
}
},
"quote_message": {
"type": "string"
},
"quote_timestamp": {
"type": "integer"
},
"recipients": { "recipients": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
},
"sticker": {
"type": "string"
} }
} }
}, },
@@ -1834,6 +1858,15 @@ var doc = `{
"build": { "build": {
"type": "integer" "type": "integer"
}, },
"capabilities": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"mode": { "mode": {
"type": "string" "type": "string"
}, },
@@ -1911,6 +1944,20 @@ var doc = `{
"type": "string" "type": "string"
} }
} }
},
"client.MessageMention": {
"type": "object",
"properties": {
"author": {
"type": "string"
},
"length": {
"type": "integer"
},
"start": {
"type": "integer"
}
}
} }
}, },
"tags": [ "tags": [

View File

@@ -225,9 +225,7 @@
} }
], ],
"responses": { "responses": {
"200": { "200": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -267,9 +265,7 @@
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -311,9 +307,7 @@
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -355,9 +349,7 @@
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1140,6 +1132,18 @@
"description": "Receive timeout in seconds (default: 1)", "description": "Receive timeout in seconds (default: 1)",
"name": "timeout", "name": "timeout",
"in": "query" "in": "query"
},
{
"type": "string",
"description": "Specify whether the attachments of the received message should be ignored",
"name": "ignore_attachments",
"in": "query"
},
{
"type": "string",
"description": "Specify whether stories should be ignored when receiving messages",
"name": "ignore_stories",
"in": "query"
} }
], ],
"responses": { "responses": {
@@ -1192,9 +1196,7 @@
} }
], ],
"responses": { "responses": {
"201": { "201": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1466,9 +1468,7 @@
} }
], ],
"responses": { "responses": {
"204": { "204": {},
"description": ""
},
"400": { "400": {
"description": "Bad Request", "description": "Bad Request",
"schema": { "schema": {
@@ -1716,17 +1716,41 @@
"data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e" "data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e"
] ]
}, },
"mentions": {
"type": "array",
"items": {
"$ref": "#/definitions/client.MessageMention"
}
},
"message": { "message": {
"type": "string" "type": "string"
}, },
"number": { "number": {
"type": "string" "type": "string"
}, },
"quote_author": {
"type": "string"
},
"quote_mentions": {
"type": "array",
"items": {
"$ref": "#/definitions/client.MessageMention"
}
},
"quote_message": {
"type": "string"
},
"quote_timestamp": {
"type": "integer"
},
"recipients": { "recipients": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
},
"sticker": {
"type": "string"
} }
} }
}, },
@@ -1818,6 +1842,15 @@
"build": { "build": {
"type": "integer" "type": "integer"
}, },
"capabilities": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"mode": { "mode": {
"type": "string" "type": "string"
}, },
@@ -1895,6 +1928,20 @@
"type": "string" "type": "string"
} }
} }
},
"client.MessageMention": {
"type": "object",
"properties": {
"author": {
"type": "string"
},
"length": {
"type": "integer"
},
"start": {
"type": "integer"
}
}
} }
}, },
"tags": [ "tags": [

View File

@@ -106,9 +106,7 @@ definitions:
api.SendMessageV1: api.SendMessageV1:
properties: properties:
base64_attachment: base64_attachment:
example: '''<BASE64 ENCODED DATA>'' OR ''data:<MIME-TYPE>;base64,<BASE64 ENCODED example: '''<BASE64 ENCODED DATA>'' OR ''data:<MIME-TYPE>;base64,<BASE64 ENCODED DATA>'' OR ''data:<MIME-TYPE>;filename=<FILENAME>;base64,<BASE64 ENCODED DATA>'''
DATA>'' OR ''data:<MIME-TYPE>;filename=<FILENAME>;base64,<BASE64 ENCODED
DATA>'''
type: string type: string
is_group: is_group:
type: boolean type: boolean
@@ -131,14 +129,30 @@ definitions:
items: items:
type: string type: string
type: array type: array
mentions:
items:
$ref: '#/definitions/client.MessageMention'
type: array
message: message:
type: string type: string
number: number:
type: string type: string
quote_author:
type: string
quote_mentions:
items:
$ref: '#/definitions/client.MessageMention'
type: array
quote_message:
type: string
quote_timestamp:
type: integer
recipients: recipients:
items: items:
type: string type: string
type: array type: array
sticker:
type: string
type: object type: object
api.TrustIdentityRequest: api.TrustIdentityRequest:
properties: properties:
@@ -197,6 +211,12 @@ definitions:
properties: properties:
build: build:
type: integer type: integer
capabilities:
additionalProperties:
items:
type: string
type: array
type: object
mode: mode:
type: string type: string
version: version:
@@ -248,6 +268,15 @@ definitions:
status: status:
type: string type: string
type: object type: object
client.MessageMention:
properties:
author:
type: string
length:
type: integer
start:
type: integer
type: object
info: info:
contact: {} contact: {}
description: This is the Signal Cli REST API documentation. description: This is the Signal Cli REST API documentation.
@@ -396,8 +425,7 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"200": "200": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:
@@ -424,8 +452,7 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"204": "204": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:
@@ -453,22 +480,19 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"204": "204": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:
$ref: '#/definitions/api.Error' $ref: '#/definitions/api.Error'
summary: Updates the info associated to a number on the contact list. If the summary: Updates the info associated to a number on the contact list. If the contact doesnt exist yet, it will be added.
contact doesnt exist yet, it will be added.
tags: tags:
- Contacts - Contacts
/v1/devices/{number}: /v1/devices/{number}:
post: post:
consumes: consumes:
- application/json - application/json
description: Links another device to this device. Only works, if this is the description: Links another device to this device. Only works, if this is the master device.
master device.
parameters: parameters:
- description: Registered Phone Number - description: Registered Phone Number
in: path in: path
@@ -484,8 +508,7 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"204": "204": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:
@@ -857,8 +880,7 @@ paths:
- Identities - Identities
/v1/identities/{number}/trust/{numberToTrust}: /v1/identities/{number}/trust/{numberToTrust}:
put: put:
description: Trust an identity. When 'trust_all_known_keys' is set to' true', description: Trust an identity. When 'trust_all_known_keys' is set to' true', all known keys of this user are trusted. **This is only recommended for testing.**
all known keys of this user are trusted. **This is only recommended for testing.**
parameters: parameters:
- description: Input Data - description: Input Data
in: body in: body
@@ -993,9 +1015,7 @@ paths:
get: get:
consumes: consumes:
- application/json - application/json
description: Receives Signal Messages from the Signal Network. If you are running description: Receives Signal Messages from the Signal Network. If you are running the docker container in normal/native mode, this is a GET endpoint. In json-rpc mode this is a websocket endpoint.
the docker container in normal/native mode, this is a GET endpoint. In json-rpc
mode this is a websocket endpoint.
parameters: parameters:
- description: Registered Phone Number - description: Registered Phone Number
in: path in: path
@@ -1006,6 +1026,14 @@ paths:
in: query in: query
name: timeout name: timeout
type: string type: string
- description: Specify whether the attachments of the received message should be ignored
in: query
name: ignore_attachments
type: string
- description: Specify whether stories should be ignored when receiving messages
in: query
name: ignore_stories
type: string
produces: produces:
- application/json - application/json
responses: responses:
@@ -1041,8 +1069,7 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"201": "201": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:
@@ -1089,8 +1116,7 @@ paths:
get: get:
consumes: consumes:
- application/json - application/json
description: Check if one or more phone numbers are registered with the Signal description: Check if one or more phone numbers are registered with the Signal Service.
Service.
parameters: parameters:
- collectionFormat: multi - collectionFormat: multi
description: Numbers to check description: Numbers to check
@@ -1208,9 +1234,7 @@ paths:
post: post:
consumes: consumes:
- application/json - application/json
description: Disables push support for this device. **WARNING:** If *delete_account* description: Disables push support for this device. **WARNING:** If *delete_account* is set to *true*, the account will be deleted from the Signal Server. This cannot be undone without loss.
is set to *true*, the account will be deleted from the Signal Server. This
cannot be undone without loss.
parameters: parameters:
- description: Registered Phone Number - description: Registered Phone Number
in: path in: path
@@ -1225,8 +1249,7 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"204": "204": {}
description: ""
"400": "400":
description: Bad Request description: Bad Request
schema: schema:

View File

@@ -280,14 +280,33 @@ func main() {
log.Fatal("AUTO_RECEIVE_SCHEDULE: Couldn't parse accounts.json: ", err.Error()) log.Fatal("AUTO_RECEIVE_SCHEDULE: Couldn't parse accounts.json: ", err.Error())
} }
autoReceiveScheduleReceiveTimeout := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_RECEIVE_TIMEOUT", "10")
autoReceiveScheduleIgnoreAttachments := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_ATTACHMENTS", "false")
autoReceiveScheduleIgnoreStories := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_STORIES", "false")
c := cron.New() c := cron.New()
c.Schedule(schedule, cron.FuncJob(func() { c.Schedule(schedule, cron.FuncJob(func() {
for _, account := range signalCliAccountConfigs.Accounts { for _, account := range signalCliAccountConfigs.Accounts {
client := &http.Client{}
log.Debug("AUTO_RECEIVE_SCHEDULE: Calling receive for number ", account.Number) log.Debug("AUTO_RECEIVE_SCHEDULE: Calling receive for number ", account.Number)
resp, err := http.Get("http://127.0.0.1:" + port + "/v1/receive/" + account.Number) req, err := http.NewRequest("GET", "http://127.0.0.1:" + port + "/v1/receive/" + account.Number, nil)
if err != nil { if err != nil {
log.Error("AUTO_RECEIVE_SCHEDULE: Couldn't call receive for number ", account.Number, ": ", err.Error()) log.Error("AUTO_RECEIVE_SCHEDULE: Couldn't call receive for number ", account.Number, ": ", err.Error())
} }
q := req.URL.Query()
q.Add("timeout", autoReceiveScheduleReceiveTimeout)
q.Add("ignore_attachments", autoReceiveScheduleIgnoreAttachments)
q.Add("ignore_stories", autoReceiveScheduleIgnoreStories)
req.URL.RawQuery = q.Encode()
resp, err := client.Do(req)
if err != nil {
log.Error("AUTO_RECEIVE_SCHEDULE: Couldn't call receive for number ", account.Number, ": ", err.Error())
}
if resp.StatusCode != 200 { if resp.StatusCode != 200 {
jsonResp, err := ioutil.ReadAll(resp.Body) jsonResp, err := ioutil.ReadAll(resp.Body)
resp.Body.Close() resp.Body.Close()