diff --git a/Dockerfile b/Dockerfile index d72f9b4..96fe257 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -ARG SIGNAL_CLI_VERSION=0.12.0 +ARG SIGNAL_CLI_VERSION=0.12.1 ARG LIBSIGNAL_CLIENT_VERSION=0.30.0 -ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.12.0-1 +ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.12.1-1 ARG SWAG_VERSION=1.6.7 ARG GRAALVM_JAVA_VERSION=17 diff --git a/README.md b/README.md index 8ae4c9b..1d04a03 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ This launches a instance of the REST service accessible under http://localhost:9 > :warning: This setting is only needed in normal/native mode! -[signal-cli](https://github.com/AsamK/signal-cli), which this REST API wrapper is based on, recommends to call `receive` on a regular basis. So, if you are not already calling the `receive` endpoint regularily, it is recommended to set the `AUTO_RECEIVE_SCHEDULE` parameter in the docker-compose.yml file. The `AUTO_RECEIVE_SCHEDULE` accepts cron schedule expressions and automatically calls the `receive` endpoint at the given time. e.g: `0 22 * * *` calls `receive` daily at 10pm. If you are not familiar with cron schedule expressions, you can use this [website](https://crontab.guru). +[signal-cli](https://github.com/AsamK/signal-cli), which this REST API wrapper is based on, recommends to call `receive` on a regular basis. So, if you are not already calling the `receive` endpoint regularly, it is recommended to set the `AUTO_RECEIVE_SCHEDULE` parameter in the docker-compose.yml file. The `AUTO_RECEIVE_SCHEDULE` accepts cron schedule expressions and automatically calls the `receive` endpoint at the given time. e.g: `0 22 * * *` calls `receive` daily at 10pm. If you are not familiar with cron schedule expressions, you can use this [website](https://crontab.guru). **WARNING** Calling `receive` will fetch all the messages for the registered Signal number from the Signal Server! So, if you are using the REST API for receiving messages, it's _not_ a good idea to use the `AUTO_RECEIVE_SCHEDULE` parameter, as you might lose some messages that way. @@ -127,6 +127,8 @@ There are a bunch of environmental variables that can be set inside the docker c * `SWAGGER_IP`: The IP that's used in the Swagger UI for the interactive examples. Defaults to the container ip. +* `PORT`: Defaults to port `8080` unless this env var is set to tell it otherwise. + ## Clients & Libraries | Name | Client | Library | Language | Maintainer | diff --git a/src/api/api.go b/src/api/api.go index 44d5813..f105f4c 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -473,6 +473,7 @@ func StringToBool(input string) bool { // @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)" +// @Param max_messages query string false "Specify the maximum number of messages to receive (default: unlimited)". Not available in json-rpc mode. // @Router /v1/receive/{number} [get] func (a *Api) Receive(c *gin.Context) { number := c.Param("number") @@ -496,19 +497,26 @@ func (a *Api) Receive(c *gin.Context) { return } + maxMessages := c.DefaultQuery("max_messages", "0") + maxMessagesInt, err := strconv.ParseInt(maxMessages, 10, 32) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - max_messages needs to be numeric!"}) + return + } + 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'"}) + 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'"}) + 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)) + jsonStr, err := a.signalClient.Receive(number, timeoutInt, StringToBool(ignoreAttachments), StringToBool(ignoreStories), maxMessagesInt) if err != nil { c.JSON(400, Error{Msg: err.Error()}) return diff --git a/src/client/cli.go b/src/client/cli.go index 991963f..2aeb19f 100644 --- a/src/client/cli.go +++ b/src/client/cli.go @@ -83,10 +83,9 @@ func (s *CliClient) Execute(wait bool, args []string, stdin string) (string, err cmd.Stdin = strings.NewReader(stdin) } if wait { - var errBuffer bytes.Buffer - var outBuffer bytes.Buffer - cmd.Stderr = &errBuffer - cmd.Stdout = &outBuffer + var combinedOutput bytes.Buffer + cmd.Stdout = &combinedOutput + cmd.Stderr = &combinedOutput err := cmd.Start() if err != nil { @@ -106,11 +105,11 @@ func (s *CliClient) Execute(wait bool, args []string, stdin string) (string, err return "", errors.New("process killed as timeout reached") case err := <-done: if err != nil { - return "", errors.New(errBuffer.String()) + return "", errors.New(combinedOutput.String()) } } - return outBuffer.String(), nil + return combinedOutput.String(), nil } else { stdout, err := cmd.StdoutPipe() if err != nil { diff --git a/src/client/client.go b/src/client/client.go index cb9b57c..beb5e6d 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -474,12 +474,12 @@ func (s *SignalClient) send(number string, message string, func (s *SignalClient) About() About { about := About{ - SupportedApiVersions: []string{"v1", "v2"}, - BuildNr: 2, - Mode: getSignalCliModeString(s.signalCliMode), - Version: utils.GetEnv("BUILD_VERSION", "unset"), - Capabilities: map[string][]string{"v2/send": []string{"quotes", "mentions"}}, - } + SupportedApiVersions: []string{"v1", "v2"}, + BuildNr: 2, + Mode: getSignalCliModeString(s.signalCliMode), + Version: utils.GetEnv("BUILD_VERSION", "unset"), + Capabilities: map[string][]string{"v2/send": []string{"quotes", "mentions"}}, + } return about } @@ -610,7 +610,7 @@ func (s *SignalClient) SendV2(number string, message string, recps []string, bas return ×tamps, nil } -func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments bool, ignoreStories bool) (string, error) { +func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments bool, ignoreStories bool, maxMessages int64) (string, error) { if s.signalCliMode == JsonRpc { return "", errors.New("Not implemented") } else { @@ -624,6 +624,11 @@ func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments b command = append(command, "--ignore-stories") } + if maxMessages > 0 { + command = append(command, "--max-messages") + command = append(command, strconv.FormatInt(maxMessages, 10)) + } + out, err := s.cliClient.Execute(true, command, "") if err != nil { return "", err