diff --git a/Dockerfile b/Dockerfile index fa8a2f2..b05b0c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -118,7 +118,7 @@ COPY src/go.mod /tmp/signal-cli-rest-api-src/ COPY src/go.sum /tmp/signal-cli-rest-api-src/ # build signal-cli-rest-api -RUN cd /tmp/signal-cli-rest-api-src && swag init && go build +RUN cd /tmp/signal-cli-rest-api-src && swag init && go test ./client -v && go build # build supervisorctl_config_creator RUN cd /tmp/signal-cli-rest-api-src/scripts && go build -o jsonrpc2-helper diff --git a/src/api/api.go b/src/api/api.go index a7be4f8..58c3a44 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -69,7 +69,7 @@ type RegisterNumberRequest struct { } type UnregisterNumberRequest struct { - DeleteAccount bool `json:"delete_account" example:"false"` + DeleteAccount bool `json:"delete_account" example:"false"` DeleteLocalData bool `json:"delete_local_data" example:"false"` } @@ -88,7 +88,7 @@ type SendMessageV1 struct { Number string `json:"number"` Recipients []string `json:"recipients"` Message string `json:"message"` - Base64Attachment string `json:"base64_attachment"` + Base64Attachment string `json:"base64_attachment" example:"'' OR 'data:;base64,' OR 'data:;filename=;base64,'"` IsGroup bool `json:"is_group"` } @@ -96,7 +96,7 @@ type SendMessageV2 struct { Number string `json:"number"` Recipients []string `json:"recipients"` Message string `json:"message"` - Base64Attachments []string `json:"base64_attachments"` + Base64Attachments []string `json:"base64_attachments" example:",data:;base64,data:;filename=;base64"` } type TypingIndicatorRequest struct { diff --git a/src/client/attachment.go b/src/client/attachment.go index d33c260..9121d89 100644 --- a/src/client/attachment.go +++ b/src/client/attachment.go @@ -28,7 +28,7 @@ func NewAttachmentEntry(attachmentData string) *AttachmentEntry { func (attachmentEntry *AttachmentEntry) extractMetaData(attachmentData string) { base64FlagIndex := strings.LastIndex(attachmentData, "base64,") - if !strings.Contains(attachmentData, "data:") && base64FlagIndex == -1 { + if !strings.Contains(attachmentData, "data:") || base64FlagIndex == -1 { attachmentEntry.Base64 = attachmentData return } @@ -77,12 +77,15 @@ func (attachmentEntry *AttachmentEntry) isWithMetaData() bool { } func (attachmentEntry *AttachmentEntry) toDataForSignal() string { - result := "" - if !attachmentEntry.isWithMetaData() && len(attachmentEntry.FilePath) > 0 { + if len(attachmentEntry.FilePath) > 0 { return attachmentEntry.FilePath } - result = "data:" + attachmentEntry.MimeInfo + if !attachmentEntry.isWithMetaData() { + return attachmentEntry.Base64 + } + + result := "data:" + attachmentEntry.MimeInfo if len(attachmentEntry.FileName) > 0 { result = result + ";filename=" + attachmentEntry.FileName diff --git a/src/client/attachment_test.go b/src/client/attachment_test.go new file mode 100644 index 0000000..8385dde --- /dev/null +++ b/src/client/attachment_test.go @@ -0,0 +1,72 @@ +package client + +import ( + "strings" + "testing" +) + +func Test_Attachment_ExtractMetadata_ShouldPrepareDataFor_toDataForSignal(t *testing.T) { + testCases := []struct { + nameTest string + inputData string + resultIsWithMetaData bool + base64Expected string + fileNameExpected string + mimeInfoExpected string + toDataForSignal string + }{ + { + "BC base64 - compatibility", "MTIzNDU=", false, "MTIzNDU=", "", "", "MTIzNDU=", + }, + { + "+base64 -data -filename", "base64,MTIzNDU=", false, "base64,MTIzNDU=", "", "", "base64,MTIzNDU=", + }, + { + "+base64 +data -filename", "data:someData;base64,MTIzNDU=", true, "MTIzNDU=", "", "someData", "data:someData;base64,MTIzNDU=", + }, + { + "+base64 -data +filename", "filename=file.name;base64,MTIzNDU=", false, "filename=file.name;base64,MTIzNDU=", "", "", "filename=file.name;base64,MTIzNDU=", + }, + { + "+base64 +data +filename", "data:someData;filename=file.name;base64,MTIzNDU=", true, "MTIzNDU=", "file.name", "someData", "data:someData;filename=file.name;base64,MTIzNDU=", + }, + { + "-base64 -data -filename", "INVALIDMTIzNDU=", false, "INVALIDMTIzNDU=", "", "", "INVALIDMTIzNDU=", + }, + { + "-base64 +data -filename", "data:someData;INVALIDMTIzNDU=", false, "INVALIDMTIzNDU=", "", "", "data:someData;INVALIDMTIzNDU=", + }, + { + "-base64 -data +filename", "filename=file.name;INVALIDMTIzNDU=", false, "filename=file.name;INVALIDMTIzNDU=", "", "", "filename=file.name;INVALIDMTIzNDU=", + }, + { + "-base64 +data +filename", "data:someData;filename=file.name;INVALIDMTIzNDU=", false, "data:someData;filename=file.name;INVALIDMTIzNDU=", "", "", "data:someData;filename=file.name;INVALIDMTIzNDU=", + }, + } + + for _, tt := range testCases { + t.Run(tt.nameTest, func(t *testing.T) { + attachmentEntry := NewAttachmentEntry(tt.inputData) + + if attachmentEntry.isWithMetaData() != tt.resultIsWithMetaData { + t.Errorf("isWithMetaData() got \"%v\", want \"%v\"", attachmentEntry.isWithMetaData(), tt.resultIsWithMetaData) + } + + if strings.Compare(attachmentEntry.Base64, tt.base64Expected) != 0 { + t.Errorf("Base64 got \"%v\", want \"%v\"", attachmentEntry.Base64, tt.base64Expected) + } + + if strings.Compare(attachmentEntry.FileName, tt.fileNameExpected) != 0 { + t.Errorf("FileName got \"%v\", want \"%v\"", attachmentEntry.FileName, tt.fileNameExpected) + } + + if strings.Compare(attachmentEntry.MimeInfo, tt.mimeInfoExpected) != 0 { + t.Errorf("MimeInfo got \"%v\", want \"%v\"", attachmentEntry.MimeInfo, tt.mimeInfoExpected) + } + + if strings.Compare(attachmentEntry.toDataForSignal(), tt.toDataForSignal) != 0 { + t.Errorf("toDataForSignal() got \"%v\", want \"%v\"", attachmentEntry.toDataForSignal(), tt.toDataForSignal) + } + }) + } +} diff --git a/src/client/client.go b/src/client/client.go index 0615df5..449dce5 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -461,7 +461,7 @@ func (s *SignalClient) UnregisterNumber(number string, deleteAccount bool, delet command := []string{"--config", s.signalCliConfig, "-a", number, "deleteLocalAccountData"} _, err2 := s.cliClient.Execute(true, command, "") if (err2 != nil) && (err != nil) { - err = fmt.Errorf("%w (%w)", err, err2) + err = fmt.Errorf("%w (%s)", err, err2.Error()) } else if (err2 != nil) && (err == nil) { err = err2 } diff --git a/src/docs/docs.go b/src/docs/docs.go index 6bb1c69..926e2bb 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -241,7 +241,9 @@ var doc = `{ } ], "responses": { - "200": {}, + "200": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -281,7 +283,9 @@ var doc = `{ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -323,7 +327,9 @@ var doc = `{ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -365,7 +371,9 @@ var doc = `{ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1200,7 +1208,9 @@ var doc = `{ } ], "responses": { - "201": {}, + "201": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1472,7 +1482,9 @@ var doc = `{ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1687,7 +1699,7 @@ var doc = `{ "properties": { "base64_attachment": { "type": "string", - "example": " or 'data:;base64,' or 'data:;filename=;base64,'" + "example": "'\u003cBASE64 ENCODED DATA\u003e' OR 'data:\u003cMIME-TYPE\u003e;base64,\u003cBASE64 ENCODED DATA\u003e' OR 'data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64,\u003cBASE64 ENCODED DATA\u003e'" }, "is_group": { "type": "boolean" @@ -1712,9 +1724,13 @@ var doc = `{ "base64_attachments": { "type": "array", "items": { - "type": "string", - "example": " or 'data:;base64,' or 'data:;filename=;base64,'" - } + "type": "string" + }, + "example": [ + "\u003cBASE64 ENCODED DATA\u003e", + "data:\u003cMIME-TYPE\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e", + "data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e" + ] }, "message": { "type": "string" diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 90ae731..5d59150 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -225,7 +225,9 @@ } ], "responses": { - "200": {}, + "200": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -265,7 +267,9 @@ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -307,7 +311,9 @@ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -349,7 +355,9 @@ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1184,7 +1192,9 @@ } ], "responses": { - "201": {}, + "201": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1456,7 +1466,9 @@ } ], "responses": { - "204": {}, + "204": { + "description": "" + }, "400": { "description": "Bad Request", "schema": { @@ -1671,7 +1683,7 @@ "properties": { "base64_attachment": { "type": "string", - "example": " or 'data:;base64,' or 'data:;filename=;base64,'" + "example": "'\u003cBASE64 ENCODED DATA\u003e' OR 'data:\u003cMIME-TYPE\u003e;base64,\u003cBASE64 ENCODED DATA\u003e' OR 'data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64,\u003cBASE64 ENCODED DATA\u003e'" }, "is_group": { "type": "boolean" @@ -1696,9 +1708,13 @@ "base64_attachments": { "type": "array", "items": { - "type": "string", - "example": " or 'data:;base64,' or 'data:;filename=;base64,'" - } + "type": "string" + }, + "example": [ + "\u003cBASE64 ENCODED DATA\u003e", + "data:\u003cMIME-TYPE\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e", + "data:\u003cMIME-TYPE\u003e;filename=\u003cFILENAME\u003e;base64\u003ccomma\u003e\u003cBASE64 ENCODED DATA\u003e" + ] }, "message": { "type": "string" diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 18efe84..4e710bb 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -106,8 +106,10 @@ definitions: api.SendMessageV1: properties: base64_attachment: + example: ''''' OR ''data:;base64,'' OR ''data:;filename=;base64,''' type: string - example: " or 'data:;base64,' or 'data:;filename=;base64,'" is_group: type: boolean message: @@ -122,9 +124,12 @@ definitions: api.SendMessageV2: properties: base64_attachments: + example: + - + - data:;base64 + - data:;filename=;base64 items: type: string - example: " or 'data:;base64,' or 'data:;filename=;base64,'" type: array message: type: string @@ -391,7 +396,8 @@ paths: produces: - application/json responses: - "200": {} + "200": + description: "" "400": description: Bad Request schema: @@ -418,7 +424,8 @@ paths: produces: - application/json responses: - "204": {} + "204": + description: "" "400": description: Bad Request schema: @@ -446,19 +453,22 @@ paths: produces: - application/json responses: - "204": {} + "204": + description: "" "400": description: Bad Request schema: $ref: '#/definitions/api.Error' - summary: Updates the info associated to a number on the contact list. If the contact doesn’t exist yet, it will be added. + summary: Updates the info associated to a number on the contact list. If the + contact doesn’t exist yet, it will be added. tags: - Contacts /v1/devices/{number}: post: consumes: - application/json - description: Links another device to this device. Only works, if this is the master device. + description: Links another device to this device. Only works, if this is the + master device. parameters: - description: Registered Phone Number in: path @@ -474,7 +484,8 @@ paths: produces: - application/json responses: - "204": {} + "204": + description: "" "400": description: Bad Request schema: @@ -846,7 +857,8 @@ paths: - Identities /v1/identities/{number}/trust/{numberToTrust}: put: - description: Trust an identity. When 'trust_all_known_keys' is set to' true', all known keys of this user are trusted. **This is only recommended for testing.** + description: Trust an identity. When 'trust_all_known_keys' is set to' true', + all known keys of this user are trusted. **This is only recommended for testing.** parameters: - description: Input Data in: body @@ -981,7 +993,9 @@ paths: get: consumes: - application/json - description: Receives Signal Messages from the Signal Network. If you are running the docker container in normal/native mode, this is a GET endpoint. In json-rpc mode this is a websocket endpoint. + description: Receives Signal Messages from the Signal Network. If you are running + the docker container in normal/native mode, this is a GET endpoint. In json-rpc + mode this is a websocket endpoint. parameters: - description: Registered Phone Number in: path @@ -1027,7 +1041,8 @@ paths: produces: - application/json responses: - "201": {} + "201": + description: "" "400": description: Bad Request schema: @@ -1074,7 +1089,8 @@ paths: get: consumes: - application/json - description: Check if one or more phone numbers are registered with the Signal Service. + description: Check if one or more phone numbers are registered with the Signal + Service. parameters: - collectionFormat: multi description: Numbers to check @@ -1192,7 +1208,9 @@ paths: post: consumes: - application/json - description: Disables push support for this device. **WARNING:** If *delete_account* is set to *true*, the account will be deleted from the Signal Server. This cannot be undone without loss. + description: Disables push support for this device. **WARNING:** If *delete_account* + is set to *true*, the account will be deleted from the Signal Server. This + cannot be undone without loss. parameters: - description: Registered Phone Number in: path @@ -1207,7 +1225,8 @@ paths: produces: - application/json responses: - "204": {} + "204": + description: "" "400": description: Bad Request schema: