Compare commits

...

12 Commits

Author SHA1 Message Date
Stephan Richter
2d8099e1d8
Merge 7e1b98f0c2163bceaa159d89816b2b6c2d0cb2d1 into d11faf371431acfe5643eeeff02243f4b0ea6b60 2026-03-08 21:54:16 +01:00
Bernhard B
d11faf3714 updated signal-cli-native to v0.14.1+1 2026-03-08 17:43:24 +01:00
Bernhard B
a15e6ef409 updated signal-cli to v0.14.1 2026-03-08 17:03:47 +01:00
Bernhard B.
76511ae14f
Merge pull request #809 from bexelbie/feature/ignore-avatars-stickers
Add --ignore-avatars and --ignore-stickers support
2026-03-07 23:17:23 +01:00
Bernhard B.
fcc62a7fe7
Merge branch 'master' into feature/ignore-avatars-stickers 2026-03-07 23:17:01 +01:00
Bernhard B
05235bd7ae fixed docker-compose.yml
* removed accidental debug commit
2026-03-07 23:01:40 +01:00
Bernhard B
d7ffe54883 removed debug logging 2026-03-07 22:58:57 +01:00
Brian (bex) Exelbierd
2760fe0b70 add --ignore-avatars and --ignore-stickers support
Expose the new signal-cli v0.14.0 --ignore-avatars and --ignore-stickers
flags across all modes:

* JSON-RPC mode: JSON_RPC_IGNORE_AVATARS and JSON_RPC_IGNORE_STICKERS
  environment variables
* Normal/Native mode: ignore_avatars and ignore_stickers query parameters
  on the /v1/receive endpoint
* Auto-receive scheduler: AUTO_RECEIVE_SCHEDULE_IGNORE_AVATARS and
  AUTO_RECEIVE_SCHEDULE_IGNORE_STICKERS environment variables

Follows the existing pattern of --ignore-attachments and --ignore-stories.

Refs #776, #723

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-07 22:52:26 +01:00
Bernhard B
4fb1be6657 removed fifo pathname from json-rpc config
* not needed anymore
2026-03-07 21:17:45 +01:00
Bernhard B
877bc9e845 remove accidental commit 2026-03-07 16:53:27 +01:00
Stephan Richter
7e1b98f0c2 fix: use absolute path for libsignal-client jar copy
The BUILT_LIBSIGNAL_JAR variable captured a relative path that became
invalid after cd /tmp. Switch to capturing just the filename and using
the already-copied absolute path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:17:50 -05:00
Stephan Richter
40dd9a21b2 fix: Signal Desktop v8.0.0 binary ACI compatibility
Signal Desktop v8.0.0 switched from string ACI fields to binary ACI
encoding in protobuf messages. This breaks reactions, mentions, quotes,
and other message features when the library cannot parse the new format.

Two-part fix applied via patch to signal-cli v0.13.24 source build:

1. Bump signal-service-java from unofficial_137 to unofficial_138, which
   adds dual-format ACI parsing (string + binary fallback via
   ServiceId.parseOrNull).

2. Add defensive null guards in MessageEnvelope.java for cases where
   ServiceId resolution still fails (e.g. ACI.UNKNOWN). Preserves
   message content with UNKNOWN_UUID fallback rather than dropping
   entire message components (quotes, reactions, mentions, etc.).

The patch is applied during the x86_64 source build. The source-built
installDist output replaces the release tarball, so both the JVM and
native (GraalVM) paths get the fix.

Non-x86_64 architectures continue using the unpatched release tarball
until signal-cli cuts a new release with unofficial_138.

See: https://github.com/AsamK/signal-cli/pull/1944

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 19:24:30 -05:00
12 changed files with 204 additions and 65 deletions

View File

@ -1,6 +1,6 @@
ARG SIGNAL_CLI_VERSION=0.14.0 ARG SIGNAL_CLI_VERSION=0.14.1
ARG LIBSIGNAL_CLIENT_VERSION=0.87.4 ARG LIBSIGNAL_CLIENT_VERSION=0.87.4
ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.14.0+morph027+5 ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.14.1+morph027+1
ARG SWAG_VERSION=1.16.4 ARG SWAG_VERSION=1.16.4
ARG GRAALVM_VERSION=25.0.2 ARG GRAALVM_VERSION=25.0.2
@ -18,6 +18,7 @@ ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION
COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries
COPY ext/libraries/libsignal-client/signal-cli-native.patch /tmp/signal-cli-native.patch COPY ext/libraries/libsignal-client/signal-cli-native.patch /tmp/signal-cli-native.patch
COPY ext/patches/fix-binary-aci.patch /tmp/fix-binary-aci.patch
# use architecture specific libsignal_jni.so # use architecture specific libsignal_jni.so
RUN arch="$(uname -m)"; \ RUN arch="$(uname -m)"; \
@ -74,6 +75,7 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \
&& git clone https://github.com/AsamK/signal-cli.git signal-cli-${SIGNAL_CLI_VERSION}-source \ && git clone https://github.com/AsamK/signal-cli.git signal-cli-${SIGNAL_CLI_VERSION}-source \
&& cd signal-cli-${SIGNAL_CLI_VERSION}-source \ && cd signal-cli-${SIGNAL_CLI_VERSION}-source \
&& git checkout -q v${SIGNAL_CLI_VERSION} \ && git checkout -q v${SIGNAL_CLI_VERSION} \
&& git apply /tmp/fix-binary-aci.patch \
&& cd /tmp && mkdir -p /tmp/graalvm && tar xf gvm.tar.gz -C /tmp/graalvm --strip-components=1 \ && cd /tmp && mkdir -p /tmp/graalvm && tar xf gvm.tar.gz -C /tmp/graalvm --strip-components=1 \
&& export GRAALVM_HOME=/tmp/graalvm \ && export GRAALVM_HOME=/tmp/graalvm \
&& export PATH=/tmp/graalvm/bin:$PATH \ && export PATH=/tmp/graalvm/bin:$PATH \
@ -81,10 +83,14 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \
&& sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \ && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \
&& ./gradlew build \ && ./gradlew build \
&& ./gradlew installDist \ && ./gradlew installDist \
&& ls build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found. Maybe the version needs to be bumped in the signal-cli-rest-api Dockerfile?\n\n" && echo "Available version: \n" && ls build/install/signal-cli/lib/libsignal-client-* && echo "\n\n" && exit 1) \ && BUILT_LIBSIGNAL_JAR_NAME=$(ls build/install/signal-cli/lib/ | grep 'libsignal-client-.*\.jar' | head -1) \
&& echo "Built libsignal-client jar: ${BUILT_LIBSIGNAL_JAR_NAME}" \
&& rm -rf /tmp/signal-cli-${SIGNAL_CLI_VERSION} \
&& cp -a build/install/signal-cli /tmp/signal-cli-${SIGNAL_CLI_VERSION} \
&& cd /tmp \ && cd /tmp \
&& cp signal-cli-${SIGNAL_CLI_VERSION}-source/build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal-client.jar \ && cp /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} libsignal-client.jar \
&& zip -qu libsignal-client.jar libsignal_jni.so \ && zip -qu libsignal-client.jar libsignal_jni.so \
&& cp libsignal-client.jar /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} \
&& cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \ && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \
&& git apply /tmp/signal-cli-native.patch \ && git apply /tmp/signal-cli-native.patch \
&& ./gradlew -q nativeCompile; \ && ./gradlew -q nativeCompile; \
@ -112,20 +118,27 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \
echo "Unknown architecture"; \ echo "Unknown architecture"; \
fi; fi;
# replace libsignal-client # Post-processing: inject native libsignal_jni.so and apply BaseConfig workaround.
# On x86_64 the source build (above) already produced a patched installDist with
# the native lib injected, so we only need to package it. On other architectures
# the release tarball is still unpatched — apply the BaseConfig sed workaround and
# inject the native lib there.
RUN ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found. Maybe the version needs to be bumped in the signal-cli-rest-api Dockerfile?\n\n" && echo "Available version: \n" && ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-* && echo "\n\n" && exit 1) RUN if [ "$(uname -m)" != "x86_64" ]; then \
ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar \
# workaround until upstream is fixed || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found.\n\n" \
RUN cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib \ && ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-* && exit 1) \
&& unzip signal-cli-${SIGNAL_CLI_VERSION}.jar \ && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib \
&& sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' org/asamk/signal/BaseConfig.class \ && unzip signal-cli-${SIGNAL_CLI_VERSION}.jar \
&& zip -r signal-cli-${SIGNAL_CLI_VERSION}.jar org/ META-INF/ \ && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' org/asamk/signal/BaseConfig.class \
&& rm -rf META-INF \ && zip -r signal-cli-${SIGNAL_CLI_VERSION}.jar org/ META-INF/ \
&& rm -rf org && rm -rf META-INF \
&& rm -rf org \
&& cd /tmp/ \
&& zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so; \
fi
RUN cd /tmp/ \ RUN cd /tmp/ \
&& zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so \
&& zip -qr signal-cli-${SIGNAL_CLI_VERSION}.zip signal-cli-${SIGNAL_CLI_VERSION}/* \ && zip -qr signal-cli-${SIGNAL_CLI_VERSION}.zip signal-cli-${SIGNAL_CLI_VERSION}/* \
&& unzip -q /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip -d /opt \ && unzip -q /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip -d /opt \
&& rm -f /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip && rm -f /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip
@ -210,8 +223,6 @@ ENV SIGNAL_CLI_UID=1000
ENV SIGNAL_CLI_GID=1000 ENV SIGNAL_CLI_GID=1000
ENV SIGNAL_CLI_CHOWN_ON_STARTUP=true ENV SIGNAL_CLI_CHOWN_ON_STARTUP=true
RUN chown -R 1000:1000 /var/log/
ENTRYPOINT ["/entrypoint.sh"] ENTRYPOINT ["/entrypoint.sh"]
HEALTHCHECK --interval=20s --timeout=10s --retries=3 \ HEALTHCHECK --interval=20s --timeout=10s --retries=3 \

View File

@ -156,4 +156,6 @@ There are a bunch of environmental variables that can be set inside the docker c
* `JSON_RPC_IGNORE_ATTACHMENTS`: When set to `true`, attachments are not automatically downloaded in json-rpc mode (default: `false`) * `JSON_RPC_IGNORE_ATTACHMENTS`: When set to `true`, attachments are not automatically downloaded in json-rpc mode (default: `false`)
* `JSON_RPC_IGNORE_STORIES`: When set to `true`, stories are not automatically downloaded in json-rpc mode (default: `false`) * `JSON_RPC_IGNORE_STORIES`: When set to `true`, stories are not automatically downloaded in json-rpc mode (default: `false`)
* `JSON_RPC_IGNORE_AVATARS`: When set to `true`, avatars are not automatically downloaded in json-rpc mode (default: `false`)
* `JSON_RPC_IGNORE_STICKERS`: When set to `true`, sticker packs are not automatically downloaded in json-rpc mode (default: `false`)
* `JSON_RPC_TRUST_NEW_IDENTITIES`: Choose how to trust new identities in json-rpc mode. Supported values: `on-first-use`, `always`, `never`. (default: `on-first-use`) * `JSON_RPC_TRUST_NEW_IDENTITIES`: Choose how to trust new identities in json-rpc mode. Supported values: `on-first-use`, `always`, `never`. (default: `on-first-use`)

View File

@ -1,22 +1,11 @@
services: services:
signal-cli-rest-api: signal-cli-rest-api:
#image: bbernhard/signal-cli-rest-api:latest-dev image: bbernhard/signal-cli-rest-api:latest
build: "."
environment: environment:
- MODE=normal #supported modes: json-rpc, json-rpc-native, native, normal - MODE=normal #supported modes: json-rpc, native, normal
- ENABLE_PLUGINS=true
- DEFAULT_SIGNAL_TEXT_MODE=styled
- SWAGGER_IP=127.0.0.1
- PODMAN_USERNS=keep-id
#- JSON_RPC_IGNORE_ATTACHMENTS=true
#- JSON_RPC_IGNORE_STORIES=true
#- RECEIVE_WEBHOOK_URL=http://127.0.0.1:8089/webhook
#- JSON_RPC_TRUST_NEW_IDENTITIES=always
#- RECEIVE_WEBHOOK_URL=http://127.0.0.1:8080/v1/plugins/abc
#- AUTO_RECEIVE_SCHEDULE=0 22 * * * #enable this parameter on demand (see description below) #- AUTO_RECEIVE_SCHEDULE=0 22 * * * #enable this parameter on demand (see description below)
#network_mode: host
ports: ports:
- "8080:8080" #map docker port 8080 to host port 8080. - "8080:8080" #map docker port 8080 to host port 8080.
volumes: volumes:
- "./signal-cli-config:/home/.local/share/signal-cli" #map "signal-cli-config" folder on host system into docker container. the folder contains the password and cryptographic keys when a new number is registered - "./signal-cli-config:/home/.local/share/signal-cli" #map "signal-cli-config" folder on host system into docker container. the folder contains the password and cryptographic keys when a new number is registered
- "./plugins:/plugins"

View File

@ -0,0 +1,89 @@
Fix Signal Desktop v8.0.0 binary ACI encoding compatibility.
Signal Desktop v8.0.0 switched from string ACI fields to binary ACI encoding
in protobuf messages. This causes null ServiceId values when the library
cannot parse the new format, breaking reactions, mentions, quotes, and other
message features.
Two-part fix:
1. Bump signal-service-java from unofficial_137 to unofficial_138 which adds
dual-format ACI parsing (string + binary fallback).
2. Add defensive null guards in MessageEnvelope.java for cases where ServiceId
resolution still fails (e.g. ACI.UNKNOWN), preserving message content with
UNKNOWN_UUID fallback rather than dropping entire message components.
See: https://github.com/AsamK/signal-cli/pull/1944
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 9b1bd5f4..0000001 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -11,7 +11,7 @@ slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" }
logback = "ch.qos.logback:logback-classic:1.5.25"
-signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_137"
+signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_138"
sqlite = "org.xerial:sqlite-jdbc:3.51.1.0"
hikari = "com.zaxxer:HikariCP:7.0.2"
junit-jupiter-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java
index 37946057..57a5a0f4 100644
--- a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java
+++ b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java
@@ -132,6 +132,7 @@ public record MessageEnvelope(
return new Data(dataMessage.getTimestamp(),
dataMessage.getGroupContext().map(GroupContext::from),
dataMessage.getStoryContext()
+ .filter(s -> s.getAuthorServiceId() != null)
.map((SignalServiceDataMessage.StoryContext storyContext) -> StoryContext.from(storyContext,
recipientResolver,
addressResolver)),
@@ -143,9 +144,10 @@ public record MessageEnvelope(
dataMessage.isEndSession(),
dataMessage.isProfileKeyUpdate(),
dataMessage.getProfileKey().isPresent(),
- dataMessage.getReaction().map(r -> Reaction.from(r, recipientResolver, addressResolver)),
+ dataMessage.getReaction()
+ .filter(r -> r.getTargetAuthor() != null)
+ .map(r -> Reaction.from(r, recipientResolver, addressResolver)),
dataMessage.getQuote()
- .filter(q -> q.getAuthor() != null && q.getAuthor().isValid())
.map(q -> Quote.from(q, recipientResolver, addressResolver, fileProvider)),
dataMessage.getPayment().map(p -> p.getPaymentNotification().isPresent() ? Payment.from(p) : null),
dataMessage.getAttachments()
@@ -159,10 +161,15 @@ public record MessageEnvelope(
.toList())
.orElse(List.of()),
dataMessage.getPollCreate().map(PollCreate::from),
- dataMessage.getPollVote().map(p -> PollVote.from(p, recipientResolver, addressResolver)),
+ dataMessage.getPollVote()
+ .filter(p -> p.getTargetAuthor() != null)
+ .map(p -> PollVote.from(p, recipientResolver, addressResolver)),
dataMessage.getPollTerminate().map(PollTerminate::from),
dataMessage.getMentions()
- .map(a -> a.stream().map(m -> Mention.from(m, recipientResolver, addressResolver)).toList())
+ .map(a -> a.stream()
+ .filter(m -> m.getServiceId() != null)
+ .map(m -> Mention.from(m, recipientResolver, addressResolver))
+ .toList())
.orElse(List.of()),
dataMessage.getPreviews()
.map(a -> a.stream().map(preview -> Preview.from(preview, fileProvider)).toList())
@@ -241,10 +248,13 @@ public record MessageEnvelope(
RecipientAddressResolver addressResolver,
final AttachmentFileProvider fileProvider
) {
+ final var author = quote.getAuthor() != null && quote.getAuthor().isValid()
+ ? addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor()))
+ .toApiRecipientAddress()
+ : new RecipientAddress(RecipientAddress.UNKNOWN_UUID);
return new Quote(quote.getId(),
- addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor()))
- .toApiRecipientAddress(),
- Optional.of(quote.getText()),
+ author,
+ Optional.ofNullable(quote.getText()),
quote.getMentions() == null
? List.of()
: quote.getMentions()

View File

@ -670,6 +670,8 @@ func StringToBool(input string) bool {
// @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_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 ignore_stories query string false "Specify whether stories should be ignored when receiving messages" (default: false)"
// @Param ignore_avatars query string false "Specify whether avatar downloads should be ignored when receiving messages" (default: false)"
// @Param ignore_stickers query string false "Specify whether sticker pack downloads 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. // @Param max_messages query string false "Specify the maximum number of messages to receive (default: unlimited)". Not available in json-rpc mode.
// @Param send_read_receipts query string false "Specify whether read receipts should be sent when receiving messages" (default: false)" // @Param send_read_receipts query string false "Specify whether read receipts should be sent when receiving messages" (default: false)"
// @Router /v1/receive/{number} [get] // @Router /v1/receive/{number} [get]
@ -718,13 +720,25 @@ func (a *Api) Receive(c *gin.Context) {
return return
} }
ignoreAvatars := c.DefaultQuery("ignore_avatars", "false")
if ignoreAvatars != "true" && ignoreAvatars != "false" {
c.JSON(400, Error{Msg: "Couldn't process request - ignore_avatars parameter needs to be either 'true' or 'false'"})
return
}
ignoreStickers := c.DefaultQuery("ignore_stickers", "false")
if ignoreStickers != "true" && ignoreStickers != "false" {
c.JSON(400, Error{Msg: "Couldn't process request - ignore_stickers parameter needs to be either 'true' or 'false'"})
return
}
sendReadReceipts := c.DefaultQuery("send_read_receipts", "false") sendReadReceipts := c.DefaultQuery("send_read_receipts", "false")
if sendReadReceipts != "true" && sendReadReceipts != "false" { if sendReadReceipts != "true" && sendReadReceipts != "false" {
c.JSON(400, Error{Msg: "Couldn't process request - send_read_receipts parameter needs to be either 'true' or 'false'"}) c.JSON(400, Error{Msg: "Couldn't process request - send_read_receipts parameter needs to be either 'true' or 'false'"})
return return
} }
jsonStr, err := a.signalClient.Receive(number, timeoutInt, StringToBool(ignoreAttachments), StringToBool(ignoreStories), maxMessagesInt, StringToBool(sendReadReceipts)) jsonStr, err := a.signalClient.Receive(number, timeoutInt, StringToBool(ignoreAttachments), StringToBool(ignoreStories), StringToBool(ignoreAvatars), StringToBool(ignoreStickers), maxMessagesInt, StringToBool(sendReadReceipts))
if err != nil { if err != nil {
c.JSON(400, Error{Msg: err.Error()}) c.JSON(400, Error{Msg: err.Error()})
return return
@ -843,7 +857,6 @@ func (a *Api) AddMembersToGroup(c *gin.Context) {
err = a.signalClient.AddMembersToGroup(number, groupId, req.Members) err = a.signalClient.AddMembersToGroup(number, groupId, req.Members)
if err != nil { if err != nil {
log.Info("ERR NOT NULL")
switch err.(type) { switch err.(type) {
case *client.NotFoundError: case *client.NotFoundError:
c.JSON(404, Error{Msg: err.Error()}) c.JSON(404, Error{Msg: err.Error()})

View File

@ -993,7 +993,7 @@ 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, ignoreAttachments bool, ignoreStories bool, maxMessages int64, sendReadReceipts bool) (string, error) { func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments bool, ignoreStories bool, ignoreAvatars bool, ignoreStickers bool, maxMessages int64, sendReadReceipts bool) (string, error) {
if s.signalCliMode == JsonRpc { if s.signalCliMode == JsonRpc {
return "", errors.New("Not implemented") return "", errors.New("Not implemented")
} else { } else {
@ -1007,6 +1007,14 @@ func (s *SignalClient) Receive(number string, timeout int64, ignoreAttachments b
command = append(command, "--ignore-stories") command = append(command, "--ignore-stories")
} }
if ignoreAvatars {
command = append(command, "--ignore-avatars")
}
if ignoreStickers {
command = append(command, "--ignore-stickers")
}
if maxMessages > 0 { if maxMessages > 0 {
command = append(command, "--max-messages") command = append(command, "--max-messages")
command = append(command, strconv.FormatInt(maxMessages, 10)) command = append(command, strconv.FormatInt(maxMessages, 10))

View File

@ -2043,6 +2043,18 @@ const docTemplate = `{
"name": "ignore_stories", "name": "ignore_stories",
"in": "query" "in": "query"
}, },
{
"type": "string",
"description": "Specify whether avatar downloads should be ignored when receiving messages",
"name": "ignore_avatars",
"in": "query"
},
{
"type": "string",
"description": "Specify whether sticker pack downloads should be ignored when receiving messages",
"name": "ignore_stickers",
"in": "query"
},
{ {
"type": "string", "type": "string",
"description": "Specify the maximum number of messages to receive (default: unlimited)", "description": "Specify the maximum number of messages to receive (default: unlimited)",

View File

@ -2040,6 +2040,18 @@
"name": "ignore_stories", "name": "ignore_stories",
"in": "query" "in": "query"
}, },
{
"type": "string",
"description": "Specify whether avatar downloads should be ignored when receiving messages",
"name": "ignore_avatars",
"in": "query"
},
{
"type": "string",
"description": "Specify whether sticker pack downloads should be ignored when receiving messages",
"name": "ignore_stickers",
"in": "query"
},
{ {
"type": "string", "type": "string",
"description": "Specify the maximum number of messages to receive (default: unlimited)", "description": "Specify the maximum number of messages to receive (default: unlimited)",

View File

@ -1916,6 +1916,16 @@ paths:
in: query in: query
name: ignore_stories name: ignore_stories
type: string type: string
- description: Specify whether avatar downloads should be ignored when receiving
messages
in: query
name: ignore_avatars
type: string
- description: Specify whether sticker pack downloads should be ignored when
receiving messages
in: query
name: ignore_stickers
type: string
- description: 'Specify the maximum number of messages to receive (default: - description: 'Specify the maximum number of messages to receive (default:
unlimited)' unlimited)'
in: query in: query

View File

@ -395,6 +395,8 @@ func main() {
autoReceiveScheduleReceiveTimeout := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_RECEIVE_TIMEOUT", "10") autoReceiveScheduleReceiveTimeout := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_RECEIVE_TIMEOUT", "10")
autoReceiveScheduleIgnoreAttachments := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_ATTACHMENTS", "false") autoReceiveScheduleIgnoreAttachments := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_ATTACHMENTS", "false")
autoReceiveScheduleIgnoreStories := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_STORIES", "false") autoReceiveScheduleIgnoreStories := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_STORIES", "false")
autoReceiveScheduleIgnoreAvatars := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_AVATARS", "false")
autoReceiveScheduleIgnoreStickers := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_IGNORE_STICKERS", "false")
autoReceiveScheduleSendReadReceipts := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_SEND_READ_RECEIPTS", "false") autoReceiveScheduleSendReadReceipts := utils.GetEnv("AUTO_RECEIVE_SCHEDULE_SEND_READ_RECEIPTS", "false")
c := cron.New() c := cron.New()
@ -424,6 +426,8 @@ func main() {
q.Add("timeout", autoReceiveScheduleReceiveTimeout) q.Add("timeout", autoReceiveScheduleReceiveTimeout)
q.Add("ignore_attachments", autoReceiveScheduleIgnoreAttachments) q.Add("ignore_attachments", autoReceiveScheduleIgnoreAttachments)
q.Add("ignore_stories", autoReceiveScheduleIgnoreStories) q.Add("ignore_stories", autoReceiveScheduleIgnoreStories)
q.Add("ignore_avatars", autoReceiveScheduleIgnoreAvatars)
q.Add("ignore_stickers", autoReceiveScheduleIgnoreStickers)
q.Add("send_read_receipts", autoReceiveScheduleSendReadReceipts) q.Add("send_read_receipts", autoReceiveScheduleSendReadReceipts)
req.URL.RawQuery = q.Encode() req.URL.RawQuery = q.Encode()

View File

@ -3,7 +3,6 @@ package main
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"os/exec" "os/exec"
"strings" "strings"
@ -14,7 +13,7 @@ import (
const supervisorctlConfigTemplate = ` const supervisorctlConfigTemplate = `
[program:%s] [program:%s]
process_name=%s process_name=%s
command=signal-cli --output=json --config %s%s daemon %s%s --tcp 127.0.0.1:%d command=signal-cli --output=json --config %s%s daemon %s%s%s%s --tcp 127.0.0.1:%d
autostart=true autostart=true
autorestart=true autorestart=true
startretries=10 startretries=10
@ -41,23 +40,8 @@ func main() {
jsonRpc2ClientConfig := utils.NewJsonRpc2ClientConfig() jsonRpc2ClientConfig := utils.NewJsonRpc2ClientConfig()
var tcpPort int64 = 6001 var tcpPort int64 = 6001
fifoPathname := "/tmp/sigsocket1"
jsonRpc2ClientConfig.AddEntry(utils.MULTI_ACCOUNT_NUMBER, utils.JsonRpc2ClientConfigEntry{TcpPort: tcpPort, FifoPathname: fifoPathname}) jsonRpc2ClientConfig.AddEntry(utils.MULTI_ACCOUNT_NUMBER, utils.JsonRpc2ClientConfigEntry{TcpPort: tcpPort})
os.Remove(fifoPathname) //remove any existing named pipe
_, err := exec.Command("mkfifo", fifoPathname).Output()
if err != nil {
log.Fatal("Couldn't create fifo with name ", fifoPathname, ": ", err.Error())
}
uid := utils.GetEnv("SIGNAL_CLI_UID", "1000")
gid := utils.GetEnv("SIGNAL_CLI_GID", "1000")
_, err = exec.Command("chown", uid+":"+gid, fifoPathname).Output()
if err != nil {
log.Fatal("Couldn't change permissions of fifo with name ", fifoPathname, ": ", err.Error())
}
signalCliIgnoreAttachments := "" signalCliIgnoreAttachments := ""
ignoreAttachments := utils.GetEnv("JSON_RPC_IGNORE_ATTACHMENTS", "") ignoreAttachments := utils.GetEnv("JSON_RPC_IGNORE_ATTACHMENTS", "")
@ -71,9 +55,21 @@ func main() {
signalCliIgnoreStories = " --ignore-stories" signalCliIgnoreStories = " --ignore-stories"
} }
signalCliIgnoreAvatars := ""
ignoreAvatars := utils.GetEnv("JSON_RPC_IGNORE_AVATARS", "")
if ignoreAvatars == "true" {
signalCliIgnoreAvatars = " --ignore-avatars"
}
signalCliIgnoreStickers := ""
ignoreStickers := utils.GetEnv("JSON_RPC_IGNORE_STICKERS", "")
if ignoreStickers == "true" {
signalCliIgnoreStickers = " --ignore-stickers"
}
supervisorctlProgramName := "signal-cli-json-rpc-1" supervisorctlProgramName := "signal-cli-json-rpc-1"
supervisorctlLogFolder := "/var/log/" + supervisorctlProgramName supervisorctlLogFolder := "/var/log/" + supervisorctlProgramName
_, err = exec.Command("mkdir", "-p", supervisorctlLogFolder).Output() _, err := exec.Command("mkdir", "-p", supervisorctlLogFolder).Output()
if err != nil { if err != nil {
log.Fatal("Couldn't create log folder ", supervisorctlLogFolder, ": ", err.Error()) log.Fatal("Couldn't create log folder ", supervisorctlLogFolder, ": ", err.Error())
} }
@ -96,7 +92,8 @@ func main() {
supervisorctlConfigFilename := "/etc/supervisor/conf.d/" + "signal-cli-json-rpc-1.conf" supervisorctlConfigFilename := "/etc/supervisor/conf.d/" + "signal-cli-json-rpc-1.conf"
supervisorctlConfig := fmt.Sprintf(supervisorctlConfigTemplate, supervisorctlProgramName, supervisorctlProgramName, supervisorctlConfig := fmt.Sprintf(supervisorctlConfigTemplate, supervisorctlProgramName, supervisorctlProgramName,
signalCliConfigDir, trustNewIdentities, signalCliIgnoreAttachments, signalCliIgnoreStories, tcpPort, signalCliConfigDir, trustNewIdentities, signalCliIgnoreAttachments, signalCliIgnoreStories,
signalCliIgnoreAvatars, signalCliIgnoreStickers, tcpPort,
supervisorctlProgramName, supervisorctlProgramName) supervisorctlProgramName, supervisorctlProgramName)
err = ioutil.WriteFile(supervisorctlConfigFilename, []byte(supervisorctlConfig), 0644) err = ioutil.WriteFile(supervisorctlConfigFilename, []byte(supervisorctlConfig), 0644)

View File

@ -2,15 +2,15 @@ package utils
import ( import (
"errors" "errors"
"gopkg.in/yaml.v2"
"io/ioutil" "io/ioutil"
"gopkg.in/yaml.v2"
) )
const MULTI_ACCOUNT_NUMBER string = "<multi-account>" const MULTI_ACCOUNT_NUMBER string = "<multi-account>"
type JsonRpc2ClientConfigEntry struct { type JsonRpc2ClientConfigEntry struct {
TcpPort int64 `yaml:"tcp_port"` TcpPort int64 `yaml:"tcp_port"`
FifoPathname string `yaml:"fifo_pathname"`
} }
type JsonRpc2ClientConfigEntries struct { type JsonRpc2ClientConfigEntries struct {
@ -47,14 +47,6 @@ func (c *JsonRpc2ClientConfig) GetTcpPortForNumber(number string) (int64, error)
return 0, errors.New("Number " + number + " not found in local map") return 0, errors.New("Number " + number + " not found in local map")
} }
func (c *JsonRpc2ClientConfig) GetFifoPathnameForNumber(number string) (string, error) {
if val, ok := c.config.Entries[number]; ok {
return val.FifoPathname, nil
}
return "", errors.New("Number " + number + " not found in local map")
}
func (c *JsonRpc2ClientConfig) GetTcpPortsForNumbers() map[string]int64 { func (c *JsonRpc2ClientConfig) GetTcpPortsForNumbers() map[string]int64 {
mapping := make(map[string]int64) mapping := make(map[string]int64)
for number, val := range c.config.Entries { for number, val := range c.config.Entries {