diff --git a/Dockerfile b/Dockerfile index 78a8020..6e724f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -ARG SIGNAL_CLI_VERSION=0.14.1 -ARG LIBSIGNAL_CLIENT_VERSION=0.87.4 -ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.14.1+morph027+2 +ARG SIGNAL_CLI_VERSION=0.14.2 +ARG LIBSIGNAL_CLIENT_VERSION=0.90.0 +ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.14.2+morph027+2 ARG SWAG_VERSION=1.16.4 ARG GRAALVM_VERSION=25.0.2 @@ -144,7 +144,7 @@ COPY src/plugin_loader.go /tmp/signal-cli-rest-api-src/ # build signal-cli-rest-api RUN ls -la /tmp/signal-cli-rest-api-src -RUN cd /tmp/signal-cli-rest-api-src && ${GOPATH}/bin/swag init +RUN cd /tmp/signal-cli-rest-api-src && ${GOPATH}/bin/swag init --requiredByDefault RUN cd /tmp/signal-cli-rest-api-src && go build -o signal-cli-rest-api main.go RUN cd /tmp/signal-cli-rest-api-src && go test ./client -v && go test ./utils -v diff --git a/README.md b/README.md index 6b7d940..316bb21 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ The Swagger API documentation can be found [here](https://bbernhard.github.io/si | [signalbot](https://pypi.org/project/signalbot/) | Library | Python | Framework to build Signal bots | [@signalbot-org](https://github.com/orgs/signalbot-org/people) | | [signal-cli-to-file](https://github.com/jneidel/signal-cli-to-file) | Script | JavaScript | Save incoming signal messages as files | [@jneidel](https://github.com/jneidel) | | [signal-rest-ts](https://www.npmjs.com/package/signal-rest-ts) | Library | TypeScript | TypeScript module to build Signal bots | [@pseudogeneric](https://github.com/pseudogeneric) | -| [secured-signal-api](https://github.com/codeshelldev/secured-signal-api) | Proxy | Go | Secure Docker Proxy with many QoL Features | [@codeshelldev](https://github.com/codeshelldev) | +| [secured-signal-api](https://github.com/codeshelldev/secured-signal-api) | API Gateway | Go | Secure Docker API Gateway with many QoL Features | [@codeshelldev](https://github.com/codeshelldev) | In case you need more functionality, please **file a ticket** or **create a PR**. diff --git a/ext/libraries/libsignal-client/Cross.toml b/ext/libraries/libsignal-client/Cross.toml new file mode 100644 index 0000000..87468f8 --- /dev/null +++ b/ext/libraries/libsignal-client/Cross.toml @@ -0,0 +1,13 @@ +[target.aarch64-unknown-linux-gnu] +pre-build = [ + "apt update && apt install -y unzip", + "curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v25.9/protoc-25.9-linux-x86_64.zip && unzip protoc-25.9-linux-x86_64.zip -d /usr/", + "chmod 755 /usr/bin/protoc" +] + +[target.armv7-unknown-linux-gnueabihf] +pre-build = [ + "apt update && apt install -y unzip", + "curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v25.9/protoc-25.9-linux-x86_64.zip && unzip protoc-25.9-linux-x86_64.zip -d /usr/", + "chmod 755 /usr/bin/protoc" +] diff --git a/ext/libraries/libsignal-client/README.md b/ext/libraries/libsignal-client/README.md index 1a67ece..504b255 100644 --- a/ext/libraries/libsignal-client/README.md +++ b/ext/libraries/libsignal-client/README.md @@ -4,7 +4,8 @@ * download new release from `https://github.com/signalapp/libsignal-client/releases` * unzip + change into directory -* cd into `java` directory +* run `rm -rf target` to remove any build artifacts from previous builds +* copy `Cross.toml` to downloaded libsignal-client folder * run `cross build --target x86_64-unknown-linux-gnu --release -p libsignal-jni` run `cross build --target armv7-unknown-linux-gnueabihf --release -p libsignal-jni` diff --git a/ext/libraries/libsignal-client/signal-cli-native.patch b/ext/libraries/libsignal-client/signal-cli-native.patch index 31d3326..523471f 100644 --- a/ext/libraries/libsignal-client/signal-cli-native.patch +++ b/ext/libraries/libsignal-client/signal-cli-native.patch @@ -1,22 +1,23 @@ diff --git a/build.gradle.kts b/build.gradle.kts -index d8e36ea4..dba4dae3 100644 +index 5d127e4c..7ca155f9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -91,6 +91,7 @@ dependencies { implementation(libs.logback) implementation(libs.zxing) implementation(project(":libsignal-cli")) -+ implementation(files("/tmp/libsignal-client.jar")) - } ++ implementation(files("/tmp/libsignal-client.jar")) - configurations { -@@ -99,6 +100,9 @@ configurations { + testImplementation(libs.junit.jupiter) + testImplementation(platform(libs.junit.jupiter.bom)) +@@ -107,6 +108,10 @@ configurations { } } +configurations.all { + exclude(group = "org.signal", module = "libsignal-client") +} ++ tasks.withType().configureEach { isPreserveFileTimestamps = false diff --git a/ext/libraries/libsignal-client/v0.90.0/arm64/libsignal_jni.so b/ext/libraries/libsignal-client/v0.90.0/arm64/libsignal_jni.so new file mode 100644 index 0000000..a774d71 Binary files /dev/null and b/ext/libraries/libsignal-client/v0.90.0/arm64/libsignal_jni.so differ diff --git a/ext/libraries/libsignal-client/v0.90.0/armv7/libsignal_jni.so b/ext/libraries/libsignal-client/v0.90.0/armv7/libsignal_jni.so new file mode 100644 index 0000000..5632444 Binary files /dev/null and b/ext/libraries/libsignal-client/v0.90.0/armv7/libsignal_jni.so differ diff --git a/ext/libraries/libsignal-client/v0.90.0/x86-64/libsignal_jni.so b/ext/libraries/libsignal-client/v0.90.0/x86-64/libsignal_jni.so new file mode 100644 index 0000000..ca15e3e Binary files /dev/null and b/ext/libraries/libsignal-client/v0.90.0/x86-64/libsignal_jni.so differ diff --git a/src/api/api.go b/src/api/api.go index d12efdd..a3db628 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -34,26 +34,37 @@ const ( type UpdateContactRequest struct { Recipient string `json:"recipient"` - Name *string `json:"name"` - ExpirationInSeconds *int `json:"expiration_in_seconds"` + Name *string `json:"name,omitempty"` + ExpirationInSeconds *int `json:"expiration_in_seconds,omitempty"` } type CreateGroupRequest struct { - Name string `json:"name"` - Members []string `json:"members"` - Description string `json:"description"` - Permissions ds.GroupPermissions `json:"permissions"` - GroupLinkState string `json:"group_link" enums:"disabled,enabled,enabled-with-approval"` - ExpirationTime *int `json:"expiration_time"` + Name string `json:"name,omitempty"` + Members []string `json:"members,omitempty"` + Description string `json:"description,omitempty"` + Permissions ds.GroupPermissions `json:"permissions,omitempty"` + GroupLinkState string `json:"group_link,omitempty" enums:"disabled,enabled,enabled-with-approval"` + ExpirationTime *int `json:"expiration_time,omitempty"` } type UpdateGroupRequest struct { - Base64Avatar *string `json:"base64_avatar"` - Description *string `json:"description"` - Name *string `json:"name"` - ExpirationTime *int `json:"expiration_time"` - GroupLinkState *string `json:"group_link" enums:"disabled,enabled,enabled-with-approval"` - Permissions *ds.GroupPermissions `json:"permissions"` + Base64Avatar *string `json:"base64_avatar,omitempty"` + Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + ExpirationTime *int `json:"expiration_time,omitempty"` + GroupLinkState *string `json:"group_link,omitempty" enums:"disabled,enabled,enabled-with-approval"` + Permissions *ds.GroupPermissions `json:"permissions,omitempty"` +} + +type PinMessageInGroupRequest struct { + TargetAuthor string `json:"target_author"` + Timestamp int64 `json:"timestamp"` + Duration *int `json:"duration,omitempty"` +} + +type UnpinMessageInGroupRequest struct { + TargetAuthor string `json:"target_author"` + Timestamp int64 `json:"timestamp"` } type ChangeGroupMembersRequest struct { @@ -73,26 +84,33 @@ type Configuration struct { } type RegisterNumberRequest struct { - UseVoice bool `json:"use_voice"` - Captcha string `json:"captcha"` + UseVoice bool `json:"use_voice,omitempty"` + Captcha string `json:"captcha,omitempty"` } type UnregisterNumberRequest struct { - DeleteAccount bool `json:"delete_account" example:"false"` - DeleteLocalData bool `json:"delete_local_data" example:"false"` + DeleteAccount bool `json:"delete_account,omitempty" example:"false"` + DeleteLocalData bool `json:"delete_local_data,omitempty" example:"false"` } type VerifyNumberSettings struct { - Pin string `json:"pin"` + Pin string `json:"pin,omitempty"` } -type Reaction struct { +type SendReactionRequest struct { Recipient string `json:"recipient"` Reaction string `json:"reaction"` TargetAuthor string `json:"target_author"` Timestamp int64 `json:"timestamp"` } +type RemoveReactionRequest struct { + Recipient string `json:"recipient"` + Reaction string `json:"reaction,omitempty"` + TargetAuthor string `json:"target_author"` + Timestamp int64 `json:"timestamp"` +} + type Receipt struct { Recipient string `json:"recipient"` ReceiptType string `json:"receipt_type" enums:"read,viewed"` @@ -103,27 +121,27 @@ type SendMessageV1 struct { Number string `json:"number"` Recipients []string `json:"recipients"` Message string `json:"message"` - Base64Attachment string `json:"base64_attachment" example:"'' OR 'data:;base64,' OR 'data:;filename=;base64,'"` - IsGroup bool `json:"is_group"` + Base64Attachment string `json:"base64_attachment,omitempty" example:"'' OR 'data:;base64,' OR 'data:;filename=;base64,'"` + IsGroup bool `json:"is_group,omitempty"` } type SendMessageV2 struct { Number string `json:"number"` Recipients []string `json:"recipients"` - Recipient string `json:"recipient" swaggerignore:"true"` //some REST API consumers (like the Synology NAS) do not support an array as recipients, so we provide this string parameter here as backup. In order to not confuse anyone, the parameter won't be exposed in the Swagger UI (most users are fine with the recipients parameter). + Recipient string `json:"recipient,omitempty" swaggerignore:"true"` //some REST API consumers (like the Synology NAS) do not support an array as recipients, so we provide this string parameter here as backup. In order to not confuse anyone, the parameter won't be exposed in the Swagger UI (most users are fine with the recipients parameter). Message string `json:"message"` - Base64Attachments []string `json:"base64_attachments" example:",data:;base64,data:;filename=;base64"` - Sticker string `json:"sticker"` - Mentions []ds.MessageMention `json:"mentions"` - QuoteTimestamp *int64 `json:"quote_timestamp"` - QuoteAuthor *string `json:"quote_author"` - QuoteMessage *string `json:"quote_message"` - QuoteMentions []ds.MessageMention `json:"quote_mentions"` - TextMode *string `json:"text_mode" enums:"normal,styled"` - EditTimestamp *int64 `json:"edit_timestamp"` - NotifySelf *bool `json:"notify_self"` - LinkPreview *ds.LinkPreviewType `json:"link_preview"` - ViewOnce *bool `json:"view_once"` + Base64Attachments []string `json:"base64_attachments,omitempty" example:",data:;base64,data:;filename=;base64"` + Sticker string `json:"sticker,omitempty"` + Mentions []ds.MessageMention `json:"mentions,omitempty"` + QuoteTimestamp *int64 `json:"quote_timestamp,omitempty"` + QuoteAuthor *string `json:"quote_author,omitempty"` + QuoteMessage *string `json:"quote_message,omitempty"` + QuoteMentions []ds.MessageMention `json:"quote_mentions,omitempty"` + TextMode *string `json:"text_mode,omitempty" enums:"normal,styled"` + EditTimestamp *int64 `json:"edit_timestamp,omitempty"` + NotifySelf *bool `json:"notify_self,omitempty"` + LinkPreview *ds.LinkPreviewType `json:"link_preview,omitempty"` + ViewOnce *bool `json:"view_once,omitempty"` } type TypingIndicatorRequest struct { @@ -146,13 +164,13 @@ type CreateGroupResponse struct { type UpdateProfileRequest struct { Name string `json:"name"` - Base64Avatar string `json:"base64_avatar"` - About *string `json:"about"` + Base64Avatar string `json:"base64_avatar,omitempty"` + About *string `json:"about,omitempty"` } type TrustIdentityRequest struct { - VerifiedSafetyNumber *string `json:"verified_safety_number"` - TrustAllKnownKeys *bool `json:"trust_all_known_keys" example:"false"` + VerifiedSafetyNumber *string `json:"verified_safety_number,omitempty"` + TrustAllKnownKeys *bool `json:"trust_all_known_keys,omitempty" example:"false"` } type SendMessageResponse struct { @@ -192,8 +210,8 @@ type RateLimitChallengeRequest struct { } type UpdateAccountSettingsRequest struct { - DiscoverableByNumber *bool `json:"discoverable_by_number"` - ShareNumber *bool `json:"share_number"` + DiscoverableByNumber *bool `json:"discoverable_by_number,omitempty"` + ShareNumber *bool `json:"share_number,omitempty"` } type SetUsernameRequest struct { @@ -215,7 +233,7 @@ type RemoteDeleteRequest struct { } type DeleteLocalAccountDataRequest struct { - IgnoreRegistered bool `json:"ignore_registered" example:"false"` + IgnoreRegistered bool `json:"ignore_registered,omitempty" example:"false"` } type DeviceLinkUriResponse struct { @@ -226,7 +244,7 @@ type CreatePollRequest struct { Recipient string `json:"recipient" example:" OR OR "` Question string `json:"question" example:"What's your favourite fruit?"` Answers []string `json:"answers" example:"apple,banana,orange"` - AllowMultipleSelections *bool `json:"allow_multiple_selections" example:"true"` + AllowMultipleSelections *bool `json:"allow_multiple_selections,omitempty" example:"true"` } type CreatePollResponse struct { @@ -855,6 +873,11 @@ func (a *Api) AddMembersToGroup(c *gin.Context) { return } + if len(req.Members) == 0 { + c.JSON(400, Error{Msg: "Couldn't process request - group members missing"}) + return + } + err = a.signalClient.AddMembersToGroup(number, groupId, req.Members) if err != nil { switch err.(type) { @@ -1173,6 +1196,113 @@ func (a *Api) DeleteGroup(c *gin.Context) { } } +// @Summary Pin a message in a Signal Group. +// @Tags Groups +// @Description Pin a message in a Signal Group. +// @Accept json +// @Produce json +// @Success 200 {string} string "OK" +// @Failure 400 {object} Error +// @Param data body PinMessageInGroupRequest true "Pin" +// @Param number path string true "Registered Phone Number" +// @Param groupid path string true "Group Id" +// @Router /v1/groups/{number}/{groupid}/pin-message [post] +func (a *Api) PinMessageInGroup(c *gin.Context) { + base64EncodedGroupId := c.Param("groupid") + number, err := url.PathUnescape(c.Param("number")) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - malformed number"}) + return + } + + if base64EncodedGroupId == "" { + c.JSON(400, Error{Msg: "Please specify a group id"}) + return + } + + groupId, err := client.ConvertGroupIdToInternalGroupId(base64EncodedGroupId) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + + var req PinMessageInGroupRequest + err = c.BindJSON(&req) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) + return + } + + duration := -1 + if req.Duration != nil { + duration = *req.Duration + } + + err = a.signalClient.PinMessageInGroup(number, groupId, req.TargetAuthor, req.Timestamp, duration) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + + c.Status(201) +} + +// @Summary Unpin a message in a Signal Group. +// @Tags Groups +// @Description Unpin a message in a Signal Group. +// @Accept json +// @Produce json +// @Success 200 {string} string "OK" +// @Failure 400 {object} Error +// @Param data body UnpinMessageInGroupRequest true "Unpin" +// @Param number path string true "Registered Phone Number" +// @Param groupid path string true "Group Id" +// @Router /v1/groups/{number}/{groupid}/pin-message [delete] +func (a *Api) UnpinMessageInGroup(c *gin.Context) { + base64EncodedGroupId := c.Param("groupid") + number, err := url.PathUnescape(c.Param("number")) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - malformed number"}) + return + } + + if base64EncodedGroupId == "" { + c.JSON(400, Error{Msg: "Please specify a group id"}) + return + } + + groupId, err := client.ConvertGroupIdToInternalGroupId(base64EncodedGroupId) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + + var req UnpinMessageInGroupRequest + err = c.BindJSON(&req) + if err != nil { + c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) + return + } + + if req.TargetAuthor == "" { + c.JSON(400, Error{Msg: "Couldn't process request - target author missing"}) + return + } + + if req.Timestamp == 0 { + c.JSON(400, Error{Msg: "Couldn't process request - timestamp missing"}) + return + } + + err = a.signalClient.UnpinMessageInGroup(number, groupId, req.TargetAuthor, req.Timestamp) + if err != nil { + c.JSON(400, Error{Msg: err.Error()}) + return + } + + c.Status(201) +} + // @Summary Link device and generate QR code. // @Tags Devices // @Description Link device and generate QR code @@ -1739,11 +1869,11 @@ func (a *Api) UpdateGroup(c *gin.Context) { // @Produce json // @Success 204 {string} OK // @Failure 400 {object} Error -// @Param data body Reaction true "Reaction" +// @Param data body SendReactionRequest true "Reaction" // @Param number path string true "Registered phone number" // @Router /v1/reactions/{number} [post] func (a *Api) SendReaction(c *gin.Context) { - var req Reaction + var req SendReactionRequest err := c.BindJSON(&req) if err != nil { c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) @@ -1792,11 +1922,11 @@ func (a *Api) SendReaction(c *gin.Context) { // @Produce json // @Success 204 {string} OK // @Failure 400 {object} Error -// @Param data body Reaction true "Reaction" +// @Param data body RemoveReactionRequest true "Reaction" // @Param number path string true "Registered phone number" // @Router /v1/reactions/{number} [delete] func (a *Api) RemoveReaction(c *gin.Context) { - var req Reaction + var req RemoveReactionRequest err := c.BindJSON(&req) if err != nil { c.JSON(400, Error{Msg: "Couldn't process request - invalid request"}) @@ -2270,6 +2400,16 @@ func (a *Api) SubmitRateLimitChallenge(c *gin.Context) { return } + if req.ChallengeToken == "" { + c.JSON(400, Error{Msg: "Couldn't process request - challenge token missing"}) + return + } + + if req.Captcha == "" { + c.JSON(400, Error{Msg: "Couldn't process request - captcha missing"}) + return + } + err = a.signalClient.SubmitRateLimitChallenge(number, req.ChallengeToken, req.Captcha) if err != nil { c.JSON(400, Error{Msg: err.Error()}) diff --git a/src/client/client.go b/src/client/client.go index 5bf2fea..55671ee 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -1080,8 +1080,8 @@ func (s *SignalClient) CreateGroup(number string, name string, members []string, var internalGroupId string if s.signalCliMode == JsonRpc { type Request struct { - Name string `json:"name"` - Members []string `json:"members"` + Name string `json:"name,omitempty"` + Members []string `json:"members,omitempty"` Link string `json:"link,omitempty"` Description string `json:"description,omitempty"` EditGroupPermissions string `json:"setPermissionEditDetails,omitempty"` @@ -1135,8 +1135,16 @@ func (s *SignalClient) CreateGroup(number string, name string, members []string, } internalGroupId = resp.GroupId } else { - cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup", "-n", name, "-m"} - cmd = append(cmd, prefixUsernameMembers(members)...) + cmd := []string{"--config", s.signalCliConfig, "-a", number, "updateGroup"} + + if name != "" { + cmd = append(cmd, []string{"--n", name}...) + } + + if len(members) > 0 { + cmd = append(cmd, "-m") + cmd = append(cmd, prefixUsernameMembers(members)...) + } if addMembersPermission != DefaultGroupPermission { cmd = append(cmd, []string{"--set-permission-add-member", addMembersPermission.String()}...) @@ -1319,10 +1327,11 @@ func (s *SignalClient) GetGroupsExpanded(number string) ([]ExpandedGroupEntry, e var signalCliGroupEntries []SignalCliGroupEntry var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return groupEntries, err } @@ -1456,8 +1465,68 @@ func (s *SignalClient) GetGroupExpanded(number string, groupId string) (*Expande return nil, nil } +func (s *SignalClient) PinMessageInGroup(number string, groupId string, targetAuthor string, timestamp int64, duration int) error { + if s.signalCliMode == JsonRpc { + type Request struct { + TargetAuthor string `json:"target-author"` + TargetTimestamp int64 `json:"target-timestamp"` + PinDuration int `json:"pin-duration"` + GroupId string `json:"group-id"` + } + + req := Request{TargetAuthor: targetAuthor, TargetTimestamp: timestamp, PinDuration: duration, GroupId: groupId} + jsonRpc2Client, err := s.getJsonRpc2Client() + if err != nil { + return err + } + _, err = jsonRpc2Client.getRaw("sendPinMessage", &number, req) + if err != nil { + return err + } + } else { + cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "sendPinMessage", "-g", groupId, + "-a", targetAuthor, "-t", strconv.FormatInt(timestamp, 10), "-d", strconv.Itoa(duration)} + + _, err := s.cliClient.Execute(true, cmd, "") + if err != nil { + return err + } + } + return nil +} + +func (s *SignalClient) UnpinMessageInGroup(number string, groupId string, targetAuthor string, timestamp int64) error { + if s.signalCliMode == JsonRpc { + type Request struct { + TargetAuthor string `json:"target-author"` + TargetTimestamp int64 `json:"target-timestamp"` + GroupId string `json:"group-id"` + } + + req := Request{TargetAuthor: targetAuthor, TargetTimestamp: timestamp, GroupId: groupId} + jsonRpc2Client, err := s.getJsonRpc2Client() + if err != nil { + return err + } + _, err = jsonRpc2Client.getRaw("sendUnpinMessage", &number, req) + if err != nil { + return err + } + } else { + cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "sendUnpinMessage", "-g", groupId, + "-a", targetAuthor, "-t", strconv.FormatInt(timestamp, 10)} + + _, err := s.cliClient.Execute(true, cmd, "") + if err != nil { + return err + } + } + return nil +} + func (s *SignalClient) GetAvatar(number string, id string, avatarType AvatarType) ([]byte, error) { var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if avatarType == GroupAvatar { @@ -1484,7 +1553,7 @@ func (s *SignalClient) GetAvatar(number string, id string, avatarType AvatarType request.Profile = id } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return []byte{}, err } @@ -1668,9 +1737,10 @@ func (s *SignalClient) GetAccounts() ([]string, error) { accounts := make([]string, 0) var rawData string var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return accounts, err } @@ -1840,10 +1910,11 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) { var err error + var jsonRpc2Client *JsonRpc2Client var rawData string identityEntries := []IdentityEntry{} if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return nil, err } @@ -1878,6 +1949,7 @@ func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) { func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifiedSafetyNumber *string, trustAllKnownKeys *bool) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { VerifiedSafetyNumber string `json:"verified-safety-number,omitempty"` @@ -1894,7 +1966,7 @@ func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifi request.TrustAllKnownKeys = *trustAllKnownKeys } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -1917,12 +1989,13 @@ func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifi func (s *SignalClient) BlockGroup(number string, groupId string) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { GroupId string `json:"groupId"` } request := Request{GroupId: groupId} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -1935,12 +2008,13 @@ func (s *SignalClient) BlockGroup(number string, groupId string) error { func (s *SignalClient) JoinGroup(number string, groupId string) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { GroupId string `json:"groupId"` } request := Request{GroupId: groupId} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -1953,12 +2027,13 @@ func (s *SignalClient) JoinGroup(number string, groupId string) error { func (s *SignalClient) QuitGroup(number string, groupId string) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { GroupId string `json:"groupId"` } request := Request{GroupId: groupId} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2101,6 +2176,7 @@ func (s *SignalClient) UpdateGroup(number string, groupId string, base64Avatar * func (s *SignalClient) SendReaction(number string, recipient string, emoji string, target_author string, timestamp int64, remove bool) error { // see https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc#sendreaction var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient isGroup := false if strings.HasPrefix(recipient, groupPrefix) { @@ -2135,7 +2211,7 @@ func (s *SignalClient) SendReaction(number string, recipient string, emoji strin if remove { request.Remove = remove } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2164,6 +2240,7 @@ func (s *SignalClient) SendReaction(number string, recipient string, emoji strin func (s *SignalClient) SendReceipt(number string, recipient string, receipt_type string, timestamp int64) error { // see https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc#sendreceipt var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient if s.signalCliMode == JsonRpc { @@ -2177,7 +2254,7 @@ func (s *SignalClient) SendReceipt(number string, recipient string, receipt_type request.ReceiptType = receipt_type request.Timestamp = timestamp - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2200,6 +2277,7 @@ func (s *SignalClient) SendReceipt(number string, recipient string, receipt_type func (s *SignalClient) SendStartTyping(number string, recipient string) error { var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient isGroup := false if strings.HasPrefix(recipient, groupPrefix) { @@ -2222,7 +2300,7 @@ func (s *SignalClient) SendStartTyping(number string, recipient string) error { request.GroupId = recp } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2242,6 +2320,7 @@ func (s *SignalClient) SendStartTyping(number string, recipient string) error { func (s *SignalClient) SendStopTyping(number string, recipient string) error { var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient isGroup := false if strings.HasPrefix(recipient, groupPrefix) { @@ -2265,7 +2344,7 @@ func (s *SignalClient) SendStopTyping(number string, recipient string) error { request.GroupId = recp } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2343,8 +2422,9 @@ func (s *SignalClient) SearchForNumbers(number string, numbers []string) ([]Sear func (s *SignalClient) SendContacts(number string) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2358,6 +2438,7 @@ func (s *SignalClient) SendContacts(number string) error { func (s *SignalClient) UpdateContact(number string, recipient string, name *string, expirationInSeconds *int) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { Recipient string `json:"recipient"` @@ -2371,7 +2452,7 @@ func (s *SignalClient) UpdateContact(number string, recipient string, name *stri if expirationInSeconds != nil { request.Expiration = *expirationInSeconds } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2391,12 +2472,13 @@ func (s *SignalClient) UpdateContact(number string, recipient string, name *stri func (s *SignalClient) AddDevice(number string, uri string) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { Uri string `json:"uri"` } request := Request{Uri: uri} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2419,9 +2501,10 @@ func (s *SignalClient) ListDevices(number string) ([]ListDevicesResponse, error) } var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return resp, err } @@ -2456,12 +2539,13 @@ func (s *SignalClient) ListDevices(number string) ([]ListDevicesResponse, error) func (s *SignalClient) RemoveDevice(number string, deviceId int64) error { var err error + var jsonRpc2Client *JsonRpc2Client if s.signalCliMode == JsonRpc { type Request struct { DeviceId int64 `json:"deviceId"` } request := Request{DeviceId: deviceId} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -2518,13 +2602,14 @@ func (s *SignalClient) SetUsername(number string, username string) (SetUsernameR var resp SetUsernameResponse var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if s.signalCliMode == JsonRpc { type Request struct { Username string `json:"username"` } request := Request{Username: username} - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return resp, err } @@ -2607,9 +2692,10 @@ func (s *SignalClient) ListInstalledStickerPacks(number string) ([]ListInstalled resp := []ListInstalledStickerPacksResponse{} var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if s.signalCliMode == JsonRpc { - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return resp, err } @@ -2690,6 +2776,7 @@ func (s *SignalClient) ListContacts(number string, allRecipients bool, recipient resp := []ListContactsResponse{} var err error + var jsonRpc2Client *JsonRpc2Client var rawData string if s.signalCliMode == JsonRpc { @@ -2705,7 +2792,7 @@ func (s *SignalClient) ListContacts(number string, allRecipients bool, recipient req.Recipient = recipient } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return nil, err } @@ -2812,6 +2899,7 @@ func (s *SignalClient) RemovePin(number string) error { func (s *SignalClient) RemoteDelete(number string, recipient string, timestamp int64) (RemoteDeleteResponse, error) { // see https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc#remotedelete var err error + var jsonRpc2Client *JsonRpc2Client var resp RemoteDeleteResponse var rawData string @@ -2847,7 +2935,7 @@ func (s *SignalClient) RemoteDelete(number string, recipient string, timestamp i } request.Timestamp = timestamp - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return resp, err } @@ -2886,6 +2974,7 @@ func (s *SignalClient) RemoteDelete(number string, recipient string, timestamp i func (s *SignalClient) CreatePoll(number string, recipient string, question string, answers []string, allowMultipleSelections bool) (string, error) { var err error + var jsonRpc2Client *JsonRpc2Client var rawData string type Response struct { @@ -2927,7 +3016,7 @@ func (s *SignalClient) CreatePoll(number string, recipient string, question stri req.Username = recp } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return "", err } @@ -2977,6 +3066,7 @@ func (s *SignalClient) CreatePoll(number string, recipient string, question stri func (s *SignalClient) VoteInPoll(number string, recipient string, pollAuthor string, pollTimestamp int64, selectedAnswers []int32) error { var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient recipientType, err := getRecipientType(recipient) @@ -3020,7 +3110,7 @@ func (s *SignalClient) VoteInPoll(number string, recipient string, pollAuthor st req.Username = recp } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } @@ -3063,6 +3153,7 @@ func (s *SignalClient) VoteInPoll(number string, recipient string, pollAuthor st func (s *SignalClient) ClosePoll(number string, recipient string, pollTimestamp int64) error { var err error + var jsonRpc2Client *JsonRpc2Client recp := recipient recipientType, err := getRecipientType(recipient) @@ -3096,7 +3187,7 @@ func (s *SignalClient) ClosePoll(number string, recipient string, pollTimestamp req.Username = recp } - jsonRpc2Client, err := s.getJsonRpc2Client() + jsonRpc2Client, err = s.getJsonRpc2Client() if err != nil { return err } diff --git a/src/docs/README.md b/src/docs/README.md index 0117eff..9810225 100644 --- a/src/docs/README.md +++ b/src/docs/README.md @@ -1,32 +1,47 @@ -These files are generated from the [swaggo/swag](https://github.com/swaggo/swag) tool. +# Documentation -To regenerate them, run in /src: +These files are generated using the [swaggo/swag](https://github.com/swaggo/swag) tool. -```bash -docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latest init -``` +There are two steps, first generating the docs and then running the web server. -Or, if you have `swag` installed: +## Generating the docs -```bash -swag init -``` +Regenerate the files with your local source code changes. -Then run the app in `/src` +1. Set the current working dir to `src` + ```bash + cd src + ``` +1. Run swag to generate the docs + * Option 1, via docker + ```bash + docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latest init --requiredByDefault + ``` + * Option 2, install swag and run the command line tool + ```bash + swag init --requiredByDefault + ``` -```bash -go run main.go -``` +## Run the web server -Or with docker compose in the root of the repository -```bash -docker compose up -``` +Run the web server to visualize the generated docs. -Then navigate to the following address to view the docs +1. Run the main script + * Option 1, via docker, run the command at the root of the repository + ```bash + docker compose up + ``` + * Option 2, install go and run the command line tool + ```bash + cd src + ``` + ```bash + go run main.go + ``` -http://127.0.0.1:8080/swagger/index.html -On docker you'll get a Network error, replace the IP for the docker internal IP in the error, e.g: +## Navigate to the docs -http://172.18.0.2:8080/swagger/index.html \ No newline at end of file +The docs are served at: http://127.0.0.1:8080/swagger/index.html + +When serving with docker, if you get a Network error, replace the IP for the docker internal IP in the error, e.g: http://172.18.0.2:8080/swagger/index.html \ No newline at end of file diff --git a/src/docs/docs.go b/src/docs/docs.go index e46b0dd..d4e175d 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -1482,6 +1482,112 @@ const docTemplate = `{ } } }, + "/v1/groups/{number}/{groupid}/pin-message": { + "post": { + "description": "Pin a message in a Signal Group.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Groups" + ], + "summary": "Pin a message in a Signal Group.", + "parameters": [ + { + "description": "Pin", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PinMessageInGroupRequest" + } + }, + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Group Id", + "name": "groupid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, + "delete": { + "description": "Unpin a message in a Signal Group.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Groups" + ], + "summary": "Unpin a message in a Signal Group.", + "parameters": [ + { + "description": "Unpin", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.UnpinMessageInGroupRequest" + } + }, + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Group Id", + "name": "groupid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/v1/groups/{number}/{groupid}/quit": { "post": { "description": "Quit the specified Signal Group.", @@ -1897,7 +2003,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api.Reaction" + "$ref": "#/definitions/api.SendReactionRequest" } }, { @@ -1942,7 +2048,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api.Reaction" + "$ref": "#/definitions/api.RemoveReactionRequest" } }, { @@ -2600,6 +2706,9 @@ const docTemplate = `{ "definitions": { "api.AddDeviceRequest": { "type": "object", + "required": [ + "uri" + ], "properties": { "uri": { "type": "string" @@ -2608,6 +2717,10 @@ const docTemplate = `{ }, "api.AddStickerPackRequest": { "type": "object", + "required": [ + "pack_id", + "pack_key" + ], "properties": { "pack_id": { "type": "string", @@ -2621,6 +2734,9 @@ const docTemplate = `{ }, "api.ChangeGroupAdminsRequest": { "type": "object", + "required": [ + "admins" + ], "properties": { "admins": { "type": "array", @@ -2632,6 +2748,9 @@ const docTemplate = `{ }, "api.ChangeGroupMembersRequest": { "type": "object", + "required": [ + "members" + ], "properties": { "members": { "type": "array", @@ -2643,6 +2762,10 @@ const docTemplate = `{ }, "api.ClosePollRequest": { "type": "object", + "required": [ + "poll_timestamp", + "recipient" + ], "properties": { "poll_timestamp": { "type": "string", @@ -2656,6 +2779,9 @@ const docTemplate = `{ }, "api.Configuration": { "type": "object", + "required": [ + "logging" + ], "properties": { "logging": { "$ref": "#/definitions/api.LoggingConfiguration" @@ -2695,6 +2821,9 @@ const docTemplate = `{ }, "api.CreateGroupResponse": { "type": "object", + "required": [ + "id" + ], "properties": { "id": { "type": "string" @@ -2703,6 +2832,11 @@ const docTemplate = `{ }, "api.CreatePollRequest": { "type": "object", + "required": [ + "answers", + "question", + "recipient" + ], "properties": { "allow_multiple_selections": { "type": "boolean", @@ -2731,6 +2865,9 @@ const docTemplate = `{ }, "api.CreatePollResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string", @@ -2749,6 +2886,9 @@ const docTemplate = `{ }, "api.DeviceLinkUriResponse": { "type": "object", + "required": [ + "device_link_uri" + ], "properties": { "device_link_uri": { "type": "string" @@ -2757,6 +2897,9 @@ const docTemplate = `{ }, "api.Error": { "type": "object", + "required": [ + "error" + ], "properties": { "error": { "type": "string" @@ -2765,14 +2908,39 @@ const docTemplate = `{ }, "api.LoggingConfiguration": { "type": "object", + "required": [ + "Level" + ], "properties": { "Level": { "type": "string" } } }, + "api.PinMessageInGroupRequest": { + "type": "object", + "required": [ + "target_author", + "timestamp" + ], + "properties": { + "duration": { + "type": "integer" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.RateLimitChallengeRequest": { "type": "object", + "required": [ + "captcha", + "challenge_token" + ], "properties": { "captcha": { "type": "string", @@ -2784,25 +2952,13 @@ const docTemplate = `{ } } }, - "api.Reaction": { - "type": "object", - "properties": { - "reaction": { - "type": "string" - }, - "recipient": { - "type": "string" - }, - "target_author": { - "type": "string" - }, - "timestamp": { - "type": "integer" - } - } - }, "api.Receipt": { "type": "object", + "required": [ + "receipt_type", + "recipient", + "timestamp" + ], "properties": { "receipt_type": { "type": "string", @@ -2832,6 +2988,10 @@ const docTemplate = `{ }, "api.RemoteDeleteRequest": { "type": "object", + "required": [ + "recipient", + "timestamp" + ], "properties": { "recipient": { "type": "string" @@ -2843,14 +3003,43 @@ const docTemplate = `{ }, "api.RemoteDeleteResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string" } } }, + "api.RemoveReactionRequest": { + "type": "object", + "required": [ + "recipient", + "target_author", + "timestamp" + ], + "properties": { + "reaction": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.SearchResponse": { "type": "object", + "required": [ + "number", + "registered" + ], "properties": { "number": { "type": "string" @@ -2862,6 +3051,10 @@ const docTemplate = `{ }, "api.SendMessageError": { "type": "object", + "required": [ + "account", + "error" + ], "properties": { "account": { "type": "string" @@ -2879,6 +3072,9 @@ const docTemplate = `{ }, "api.SendMessageResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string" @@ -2887,6 +3083,11 @@ const docTemplate = `{ }, "api.SendMessageV1": { "type": "object", + "required": [ + "message", + "number", + "recipients" + ], "properties": { "base64_attachment": { "type": "string", @@ -2911,6 +3112,11 @@ const docTemplate = `{ }, "api.SendMessageV2": { "type": "object", + "required": [ + "message", + "number", + "recipients" + ], "properties": { "base64_attachments": { "type": "array", @@ -2980,8 +3186,34 @@ const docTemplate = `{ } } }, + "api.SendReactionRequest": { + "type": "object", + "required": [ + "reaction", + "recipient", + "target_author", + "timestamp" + ], + "properties": { + "reaction": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.SetPinRequest": { "type": "object", + "required": [ + "pin" + ], "properties": { "pin": { "type": "string" @@ -2990,6 +3222,9 @@ const docTemplate = `{ }, "api.SetUsernameRequest": { "type": "object", + "required": [ + "username" + ], "properties": { "username": { "type": "string", @@ -3011,6 +3246,9 @@ const docTemplate = `{ }, "api.TrustModeRequest": { "type": "object", + "required": [ + "trust_mode" + ], "properties": { "trust_mode": { "type": "string" @@ -3019,6 +3257,9 @@ const docTemplate = `{ }, "api.TrustModeResponse": { "type": "object", + "required": [ + "trust_mode" + ], "properties": { "trust_mode": { "type": "string" @@ -3027,12 +3268,30 @@ const docTemplate = `{ }, "api.TypingIndicatorRequest": { "type": "object", + "required": [ + "recipient" + ], "properties": { "recipient": { "type": "string" } } }, + "api.UnpinMessageInGroupRequest": { + "type": "object", + "required": [ + "target_author", + "timestamp" + ], + "properties": { + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.UnregisterNumberRequest": { "type": "object", "properties": { @@ -3059,6 +3318,9 @@ const docTemplate = `{ }, "api.UpdateContactRequest": { "type": "object", + "required": [ + "recipient" + ], "properties": { "expiration_in_seconds": { "type": "integer" @@ -3101,6 +3363,9 @@ const docTemplate = `{ }, "api.UpdateProfileRequest": { "type": "object", + "required": [ + "name" + ], "properties": { "about": { "type": "string" @@ -3123,6 +3388,12 @@ const docTemplate = `{ }, "api.VoteRequest": { "type": "object", + "required": [ + "poll_author", + "poll_timestamp", + "recipient", + "selected_answers" + ], "properties": { "poll_author": { "type": "string", @@ -3149,6 +3420,13 @@ const docTemplate = `{ }, "client.About": { "type": "object", + "required": [ + "build", + "capabilities", + "mode", + "version", + "versions" + ], "properties": { "build": { "type": "integer" @@ -3178,6 +3456,13 @@ const docTemplate = `{ }, "client.ContactProfile": { "type": "object", + "required": [ + "about", + "given_name", + "has_avatar", + "last_updated_timestamp", + "lastname" + ], "properties": { "about": { "type": "string" @@ -3198,6 +3483,19 @@ const docTemplate = `{ }, "client.GroupEntry": { "type": "object", + "required": [ + "admins", + "blocked", + "description", + "id", + "internal_id", + "invite_link", + "members", + "name", + "pending_invites", + "pending_requests", + "permissions" + ], "properties": { "admins": { "type": "array", @@ -3248,6 +3546,14 @@ const docTemplate = `{ }, "client.IdentityEntry": { "type": "object", + "required": [ + "added", + "fingerprint", + "number", + "safety_number", + "status", + "uuid" + ], "properties": { "added": { "type": "string" @@ -3271,6 +3577,20 @@ const docTemplate = `{ }, "client.ListContactsResponse": { "type": "object", + "required": [ + "blocked", + "color", + "given_name", + "message_expiration", + "name", + "nickname", + "note", + "number", + "profile", + "profile_name", + "username", + "uuid" + ], "properties": { "blocked": { "type": "boolean" @@ -3312,6 +3632,12 @@ const docTemplate = `{ }, "client.ListDevicesResponse": { "type": "object", + "required": [ + "creation_timestamp", + "id", + "last_seen_timestamp", + "name" + ], "properties": { "creation_timestamp": { "type": "integer" @@ -3329,6 +3655,13 @@ const docTemplate = `{ }, "client.ListInstalledStickerPacksResponse": { "type": "object", + "required": [ + "author", + "installed", + "pack_id", + "title", + "url" + ], "properties": { "author": { "type": "string" @@ -3349,6 +3682,11 @@ const docTemplate = `{ }, "client.Nickname": { "type": "object", + "required": [ + "family_name", + "given_name", + "name" + ], "properties": { "family_name": { "type": "string" @@ -3363,6 +3701,10 @@ const docTemplate = `{ }, "client.SetUsernameResponse": { "type": "object", + "required": [ + "username", + "username_link" + ], "properties": { "username": { "type": "string" @@ -3374,6 +3716,11 @@ const docTemplate = `{ }, "data.GroupPermissions": { "type": "object", + "required": [ + "add_members", + "edit_group", + "send_messages" + ], "properties": { "add_members": { "type": "string", @@ -3400,6 +3747,12 @@ const docTemplate = `{ }, "data.LinkPreviewType": { "type": "object", + "required": [ + "base64_thumbnail", + "description", + "title", + "url" + ], "properties": { "base64_thumbnail": { "type": "string" @@ -3417,6 +3770,11 @@ const docTemplate = `{ }, "data.MessageMention": { "type": "object", + "required": [ + "author", + "length", + "start" + ], "properties": { "author": { "type": "string" diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 8ab740d..e8fbd6f 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -1479,6 +1479,112 @@ } } }, + "/v1/groups/{number}/{groupid}/pin-message": { + "post": { + "description": "Pin a message in a Signal Group.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Groups" + ], + "summary": "Pin a message in a Signal Group.", + "parameters": [ + { + "description": "Pin", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.PinMessageInGroupRequest" + } + }, + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Group Id", + "name": "groupid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + }, + "delete": { + "description": "Unpin a message in a Signal Group.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Groups" + ], + "summary": "Unpin a message in a Signal Group.", + "parameters": [ + { + "description": "Unpin", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.UnpinMessageInGroupRequest" + } + }, + { + "type": "string", + "description": "Registered Phone Number", + "name": "number", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Group Id", + "name": "groupid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/v1/groups/{number}/{groupid}/quit": { "post": { "description": "Quit the specified Signal Group.", @@ -1894,7 +2000,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api.Reaction" + "$ref": "#/definitions/api.SendReactionRequest" } }, { @@ -1939,7 +2045,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api.Reaction" + "$ref": "#/definitions/api.RemoveReactionRequest" } }, { @@ -2597,6 +2703,9 @@ "definitions": { "api.AddDeviceRequest": { "type": "object", + "required": [ + "uri" + ], "properties": { "uri": { "type": "string" @@ -2605,6 +2714,10 @@ }, "api.AddStickerPackRequest": { "type": "object", + "required": [ + "pack_id", + "pack_key" + ], "properties": { "pack_id": { "type": "string", @@ -2618,6 +2731,9 @@ }, "api.ChangeGroupAdminsRequest": { "type": "object", + "required": [ + "admins" + ], "properties": { "admins": { "type": "array", @@ -2629,6 +2745,9 @@ }, "api.ChangeGroupMembersRequest": { "type": "object", + "required": [ + "members" + ], "properties": { "members": { "type": "array", @@ -2640,6 +2759,10 @@ }, "api.ClosePollRequest": { "type": "object", + "required": [ + "poll_timestamp", + "recipient" + ], "properties": { "poll_timestamp": { "type": "string", @@ -2653,6 +2776,9 @@ }, "api.Configuration": { "type": "object", + "required": [ + "logging" + ], "properties": { "logging": { "$ref": "#/definitions/api.LoggingConfiguration" @@ -2692,6 +2818,9 @@ }, "api.CreateGroupResponse": { "type": "object", + "required": [ + "id" + ], "properties": { "id": { "type": "string" @@ -2700,6 +2829,11 @@ }, "api.CreatePollRequest": { "type": "object", + "required": [ + "answers", + "question", + "recipient" + ], "properties": { "allow_multiple_selections": { "type": "boolean", @@ -2728,6 +2862,9 @@ }, "api.CreatePollResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string", @@ -2746,6 +2883,9 @@ }, "api.DeviceLinkUriResponse": { "type": "object", + "required": [ + "device_link_uri" + ], "properties": { "device_link_uri": { "type": "string" @@ -2754,6 +2894,9 @@ }, "api.Error": { "type": "object", + "required": [ + "error" + ], "properties": { "error": { "type": "string" @@ -2762,14 +2905,39 @@ }, "api.LoggingConfiguration": { "type": "object", + "required": [ + "Level" + ], "properties": { "Level": { "type": "string" } } }, + "api.PinMessageInGroupRequest": { + "type": "object", + "required": [ + "target_author", + "timestamp" + ], + "properties": { + "duration": { + "type": "integer" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.RateLimitChallengeRequest": { "type": "object", + "required": [ + "captcha", + "challenge_token" + ], "properties": { "captcha": { "type": "string", @@ -2781,25 +2949,13 @@ } } }, - "api.Reaction": { - "type": "object", - "properties": { - "reaction": { - "type": "string" - }, - "recipient": { - "type": "string" - }, - "target_author": { - "type": "string" - }, - "timestamp": { - "type": "integer" - } - } - }, "api.Receipt": { "type": "object", + "required": [ + "receipt_type", + "recipient", + "timestamp" + ], "properties": { "receipt_type": { "type": "string", @@ -2829,6 +2985,10 @@ }, "api.RemoteDeleteRequest": { "type": "object", + "required": [ + "recipient", + "timestamp" + ], "properties": { "recipient": { "type": "string" @@ -2840,14 +3000,43 @@ }, "api.RemoteDeleteResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string" } } }, + "api.RemoveReactionRequest": { + "type": "object", + "required": [ + "recipient", + "target_author", + "timestamp" + ], + "properties": { + "reaction": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.SearchResponse": { "type": "object", + "required": [ + "number", + "registered" + ], "properties": { "number": { "type": "string" @@ -2859,6 +3048,10 @@ }, "api.SendMessageError": { "type": "object", + "required": [ + "account", + "error" + ], "properties": { "account": { "type": "string" @@ -2876,6 +3069,9 @@ }, "api.SendMessageResponse": { "type": "object", + "required": [ + "timestamp" + ], "properties": { "timestamp": { "type": "string" @@ -2884,6 +3080,11 @@ }, "api.SendMessageV1": { "type": "object", + "required": [ + "message", + "number", + "recipients" + ], "properties": { "base64_attachment": { "type": "string", @@ -2908,6 +3109,11 @@ }, "api.SendMessageV2": { "type": "object", + "required": [ + "message", + "number", + "recipients" + ], "properties": { "base64_attachments": { "type": "array", @@ -2977,8 +3183,34 @@ } } }, + "api.SendReactionRequest": { + "type": "object", + "required": [ + "reaction", + "recipient", + "target_author", + "timestamp" + ], + "properties": { + "reaction": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.SetPinRequest": { "type": "object", + "required": [ + "pin" + ], "properties": { "pin": { "type": "string" @@ -2987,6 +3219,9 @@ }, "api.SetUsernameRequest": { "type": "object", + "required": [ + "username" + ], "properties": { "username": { "type": "string", @@ -3008,6 +3243,9 @@ }, "api.TrustModeRequest": { "type": "object", + "required": [ + "trust_mode" + ], "properties": { "trust_mode": { "type": "string" @@ -3016,6 +3254,9 @@ }, "api.TrustModeResponse": { "type": "object", + "required": [ + "trust_mode" + ], "properties": { "trust_mode": { "type": "string" @@ -3024,12 +3265,30 @@ }, "api.TypingIndicatorRequest": { "type": "object", + "required": [ + "recipient" + ], "properties": { "recipient": { "type": "string" } } }, + "api.UnpinMessageInGroupRequest": { + "type": "object", + "required": [ + "target_author", + "timestamp" + ], + "properties": { + "target_author": { + "type": "string" + }, + "timestamp": { + "type": "integer" + } + } + }, "api.UnregisterNumberRequest": { "type": "object", "properties": { @@ -3056,6 +3315,9 @@ }, "api.UpdateContactRequest": { "type": "object", + "required": [ + "recipient" + ], "properties": { "expiration_in_seconds": { "type": "integer" @@ -3098,6 +3360,9 @@ }, "api.UpdateProfileRequest": { "type": "object", + "required": [ + "name" + ], "properties": { "about": { "type": "string" @@ -3120,6 +3385,12 @@ }, "api.VoteRequest": { "type": "object", + "required": [ + "poll_author", + "poll_timestamp", + "recipient", + "selected_answers" + ], "properties": { "poll_author": { "type": "string", @@ -3146,6 +3417,13 @@ }, "client.About": { "type": "object", + "required": [ + "build", + "capabilities", + "mode", + "version", + "versions" + ], "properties": { "build": { "type": "integer" @@ -3175,6 +3453,13 @@ }, "client.ContactProfile": { "type": "object", + "required": [ + "about", + "given_name", + "has_avatar", + "last_updated_timestamp", + "lastname" + ], "properties": { "about": { "type": "string" @@ -3195,6 +3480,19 @@ }, "client.GroupEntry": { "type": "object", + "required": [ + "admins", + "blocked", + "description", + "id", + "internal_id", + "invite_link", + "members", + "name", + "pending_invites", + "pending_requests", + "permissions" + ], "properties": { "admins": { "type": "array", @@ -3245,6 +3543,14 @@ }, "client.IdentityEntry": { "type": "object", + "required": [ + "added", + "fingerprint", + "number", + "safety_number", + "status", + "uuid" + ], "properties": { "added": { "type": "string" @@ -3268,6 +3574,20 @@ }, "client.ListContactsResponse": { "type": "object", + "required": [ + "blocked", + "color", + "given_name", + "message_expiration", + "name", + "nickname", + "note", + "number", + "profile", + "profile_name", + "username", + "uuid" + ], "properties": { "blocked": { "type": "boolean" @@ -3309,6 +3629,12 @@ }, "client.ListDevicesResponse": { "type": "object", + "required": [ + "creation_timestamp", + "id", + "last_seen_timestamp", + "name" + ], "properties": { "creation_timestamp": { "type": "integer" @@ -3326,6 +3652,13 @@ }, "client.ListInstalledStickerPacksResponse": { "type": "object", + "required": [ + "author", + "installed", + "pack_id", + "title", + "url" + ], "properties": { "author": { "type": "string" @@ -3346,6 +3679,11 @@ }, "client.Nickname": { "type": "object", + "required": [ + "family_name", + "given_name", + "name" + ], "properties": { "family_name": { "type": "string" @@ -3360,6 +3698,10 @@ }, "client.SetUsernameResponse": { "type": "object", + "required": [ + "username", + "username_link" + ], "properties": { "username": { "type": "string" @@ -3371,6 +3713,11 @@ }, "data.GroupPermissions": { "type": "object", + "required": [ + "add_members", + "edit_group", + "send_messages" + ], "properties": { "add_members": { "type": "string", @@ -3397,6 +3744,12 @@ }, "data.LinkPreviewType": { "type": "object", + "required": [ + "base64_thumbnail", + "description", + "title", + "url" + ], "properties": { "base64_thumbnail": { "type": "string" @@ -3414,6 +3767,11 @@ }, "data.MessageMention": { "type": "object", + "required": [ + "author", + "length", + "start" + ], "properties": { "author": { "type": "string" diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index b189493..0d10fc6 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -4,6 +4,8 @@ definitions: properties: uri: type: string + required: + - uri type: object api.AddStickerPackRequest: properties: @@ -13,6 +15,9 @@ definitions: pack_key: example: 19546e18eba0ff69dea78eb591465289d39e16f35e58389ae779d4f9455aff3a type: string + required: + - pack_id + - pack_key type: object api.ChangeGroupAdminsRequest: properties: @@ -20,6 +25,8 @@ definitions: items: type: string type: array + required: + - admins type: object api.ChangeGroupMembersRequest: properties: @@ -27,6 +34,8 @@ definitions: items: type: string type: array + required: + - members type: object api.ClosePollRequest: properties: @@ -36,11 +45,16 @@ definitions: recipient: example: OR OR type: string + required: + - poll_timestamp + - recipient type: object api.Configuration: properties: logging: $ref: '#/definitions/api.LoggingConfiguration' + required: + - logging type: object api.CreateGroupRequest: properties: @@ -67,6 +81,8 @@ definitions: properties: id: type: string + required: + - id type: object api.CreatePollRequest: properties: @@ -87,12 +103,18 @@ definitions: recipient: example: OR OR type: string + required: + - answers + - question + - recipient type: object api.CreatePollResponse: properties: timestamp: example: "1769271479" type: string + required: + - timestamp type: object api.DeleteLocalAccountDataRequest: properties: @@ -104,16 +126,34 @@ definitions: properties: device_link_uri: type: string + required: + - device_link_uri type: object api.Error: properties: error: type: string + required: + - error type: object api.LoggingConfiguration: properties: Level: type: string + required: + - Level + type: object + api.PinMessageInGroupRequest: + properties: + duration: + type: integer + target_author: + type: string + timestamp: + type: integer + required: + - target_author + - timestamp type: object api.RateLimitChallengeRequest: properties: @@ -123,17 +163,9 @@ definitions: challenge_token: example: type: string - type: object - api.Reaction: - properties: - reaction: - type: string - recipient: - type: string - target_author: - type: string - timestamp: - type: integer + required: + - captcha + - challenge_token type: object api.Receipt: properties: @@ -146,6 +178,10 @@ definitions: type: string timestamp: type: integer + required: + - receipt_type + - recipient + - timestamp type: object api.RegisterNumberRequest: properties: @@ -160,11 +196,31 @@ definitions: type: string timestamp: type: integer + required: + - recipient + - timestamp type: object api.RemoteDeleteResponse: properties: timestamp: type: string + required: + - timestamp + type: object + api.RemoveReactionRequest: + properties: + reaction: + type: string + recipient: + type: string + target_author: + type: string + timestamp: + type: integer + required: + - recipient + - target_author + - timestamp type: object api.SearchResponse: properties: @@ -172,6 +228,9 @@ definitions: type: string registered: type: boolean + required: + - number + - registered type: object api.SendMessageError: properties: @@ -183,11 +242,16 @@ definitions: type: array error: type: string + required: + - account + - error type: object api.SendMessageResponse: properties: timestamp: type: string + required: + - timestamp type: object api.SendMessageV1: properties: @@ -206,6 +270,10 @@ definitions: items: type: string type: array + required: + - message + - number + - recipients type: object api.SendMessageV2: properties: @@ -254,17 +322,41 @@ definitions: type: string view_once: type: boolean + required: + - message + - number + - recipients + type: object + api.SendReactionRequest: + properties: + reaction: + type: string + recipient: + type: string + target_author: + type: string + timestamp: + type: integer + required: + - reaction + - recipient + - target_author + - timestamp type: object api.SetPinRequest: properties: pin: type: string + required: + - pin type: object api.SetUsernameRequest: properties: username: example: test type: string + required: + - username type: object api.TrustIdentityRequest: properties: @@ -278,16 +370,32 @@ definitions: properties: trust_mode: type: string + required: + - trust_mode type: object api.TrustModeResponse: properties: trust_mode: type: string + required: + - trust_mode type: object api.TypingIndicatorRequest: properties: recipient: type: string + required: + - recipient + type: object + api.UnpinMessageInGroupRequest: + properties: + target_author: + type: string + timestamp: + type: integer + required: + - target_author + - timestamp type: object api.UnregisterNumberRequest: properties: @@ -313,6 +421,8 @@ definitions: type: string recipient: type: string + required: + - recipient type: object api.UpdateGroupRequest: properties: @@ -341,6 +451,8 @@ definitions: type: string name: type: string + required: + - name type: object api.VerifyNumberSettings: properties: @@ -364,6 +476,11 @@ definitions: items: type: integer type: array + required: + - poll_author + - poll_timestamp + - recipient + - selected_answers type: object client.About: properties: @@ -383,6 +500,12 @@ definitions: items: type: string type: array + required: + - build + - capabilities + - mode + - version + - versions type: object client.ContactProfile: properties: @@ -396,6 +519,12 @@ definitions: type: integer lastname: type: string + required: + - about + - given_name + - has_avatar + - last_updated_timestamp + - lastname type: object client.GroupEntry: properties: @@ -429,6 +558,18 @@ definitions: type: array permissions: $ref: '#/definitions/data.GroupPermissions' + required: + - admins + - blocked + - description + - id + - internal_id + - invite_link + - members + - name + - pending_invites + - pending_requests + - permissions type: object client.IdentityEntry: properties: @@ -444,6 +585,13 @@ definitions: type: string uuid: type: string + required: + - added + - fingerprint + - number + - safety_number + - status + - uuid type: object client.ListContactsResponse: properties: @@ -471,6 +619,19 @@ definitions: type: string uuid: type: string + required: + - blocked + - color + - given_name + - message_expiration + - name + - nickname + - note + - number + - profile + - profile_name + - username + - uuid type: object client.ListDevicesResponse: properties: @@ -482,6 +643,11 @@ definitions: type: integer name: type: string + required: + - creation_timestamp + - id + - last_seen_timestamp + - name type: object client.ListInstalledStickerPacksResponse: properties: @@ -495,6 +661,12 @@ definitions: type: string url: type: string + required: + - author + - installed + - pack_id + - title + - url type: object client.Nickname: properties: @@ -504,6 +676,10 @@ definitions: type: string name: type: string + required: + - family_name + - given_name + - name type: object client.SetUsernameResponse: properties: @@ -511,6 +687,9 @@ definitions: type: string username_link: type: string + required: + - username + - username_link type: object data.GroupPermissions: properties: @@ -529,6 +708,10 @@ definitions: - only-admins - every-member type: string + required: + - add_members + - edit_group + - send_messages type: object data.LinkPreviewType: properties: @@ -540,6 +723,11 @@ definitions: type: string url: type: string + required: + - base64_thumbnail + - description + - title + - url type: object data.MessageMention: properties: @@ -549,6 +737,10 @@ definitions: type: integer start: type: integer + required: + - author + - length + - start type: object host: localhost:8080 info: @@ -1543,6 +1735,77 @@ paths: summary: Add one or more members to an existing Signal Group. tags: - Groups + /v1/groups/{number}/{groupid}/pin-message: + delete: + consumes: + - application/json + description: Unpin a message in a Signal Group. + parameters: + - description: Unpin + in: body + name: data + required: true + schema: + $ref: '#/definitions/api.UnpinMessageInGroupRequest' + - description: Registered Phone Number + in: path + name: number + required: true + type: string + - description: Group Id + in: path + name: groupid + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.Error' + summary: Unpin a message in a Signal Group. + tags: + - Groups + post: + consumes: + - application/json + description: Pin a message in a Signal Group. + parameters: + - description: Pin + in: body + name: data + required: true + schema: + $ref: '#/definitions/api.PinMessageInGroupRequest' + - description: Registered Phone Number + in: path + name: number + required: true + type: string + - description: Group Id + in: path + name: groupid + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.Error' + summary: Pin a message in a Signal Group. + tags: + - Groups /v1/groups/{number}/{groupid}/quit: post: consumes: @@ -1817,7 +2080,7 @@ paths: name: data required: true schema: - $ref: '#/definitions/api.Reaction' + $ref: '#/definitions/api.RemoveReactionRequest' - description: Registered phone number in: path name: number @@ -1847,7 +2110,7 @@ paths: name: data required: true schema: - $ref: '#/definitions/api.Reaction' + $ref: '#/definitions/api.SendReactionRequest' - description: Registered phone number in: path name: number diff --git a/src/main.go b/src/main.go index b71ab2d..2450496 100644 --- a/src/main.go +++ b/src/main.go @@ -84,6 +84,7 @@ func main() { } else { docs.SwaggerInfo.Schemes = []string{"https", "http"} } + docs.SwaggerInfo.Version = utils.GetEnv("BUILD_VERSION", "1.0") router := gin.New() router.Use(gin.LoggerWithConfig(gin.LoggerConfig{ @@ -163,7 +164,7 @@ func main() { jsonRpc2ClientConfigPathPath := *signalCliConfig + "/jsonrpc2.yml" signalCliApiConfigPath := *signalCliConfig + "/api-config.yml" signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir, signalCliMode, jsonRpc2ClientConfigPathPath, signalCliApiConfigPath, webhookUrl) - err = signalClient.Init(15) + err = signalClient.Init(60) if err != nil { log.Fatal("Couldn't init Signal Client: ", err.Error()) } @@ -225,6 +226,8 @@ func main() { groups.DELETE(":number/:groupid/members", api.RemoveMembersFromGroup) groups.POST(":number/:groupid/admins", api.AddAdminsToGroup) groups.DELETE(":number/:groupid/admins", api.RemoveAdminsFromGroup) + groups.POST(":number/:groupid/pin-message", api.PinMessageInGroup) + groups.DELETE(":number/:groupid/pin-message", api.UnpinMessageInGroup) } link := v1.Group("qrcodelink") diff --git a/src/scripts/jsonrpc2-helper.go b/src/scripts/jsonrpc2-helper.go index ee4a433..9773a9b 100644 --- a/src/scripts/jsonrpc2-helper.go +++ b/src/scripts/jsonrpc2-helper.go @@ -31,6 +31,8 @@ func main() { signalMode := utils.GetEnv("MODE", "json-rpc") if signalMode == "json-rpc-native" { signalCliBinary = "signal-cli-native" + } else if signalMode != "json-rpc" { + log.Fatal("The mode needs to be either 'json-rpc' or 'json-rpc-native'") } trustNewIdentitiesEnv := utils.GetEnv("JSON_RPC_TRUST_NEW_IDENTITIES", "")