From 3b791f813ed1fd6ffc14f1fe6215f1ee28da80c7 Mon Sep 17 00:00:00 2001 From: benkuly <12199167+benkuly@users.noreply.github.com> Date: Wed, 9 Dec 2020 09:37:25 +0100 Subject: [PATCH] fixed small bug, which caused an database referential integrity constraint violation reformatted code --- README.md | 49 ++- build.gradle.kts | 28 +- buildSrc/src/main/kotlin/Versions.kt | 3 +- examples/android/synapse/homeserver.yaml | 4 +- examples/gammu/synapse/homeserver.yaml | 4 +- .../matrix/bridge/sms/SmsBridgeProperties.kt | 74 ++-- .../SmsMatrixAppserviceRoomService.kt | 24 +- .../SmsMatrixAppserviceUserService.kt | 6 +- .../SmsMatrixMembershipChangeService.kt | 24 +- .../bridge/sms/handler/MessageToBotHandler.kt | 58 +-- .../bridge/sms/handler/MessageToSmsHandler.kt | 102 ++--- .../bridge/sms/handler/ReceiveSmsService.kt | 55 ++- .../bridge/sms/handler/SmsAbortCommand.kt | 4 +- .../sms/handler/SmsAbortCommandHandler.kt | 8 +- .../bridge/sms/handler/SmsBotConsole.kt | 2 +- .../bridge/sms/handler/SmsInviteCommand.kt | 4 +- .../sms/handler/SmsInviteCommandHandler.kt | 23 +- .../bridge/sms/handler/SmsMessageHandler.kt | 34 +- .../bridge/sms/handler/SmsSendCommand.kt | 44 +-- .../sms/handler/SmsSendCommandHandler.kt | 226 +++++------ .../bridge/sms/mapping/MatrixSmsMapping.kt | 16 +- .../sms/mapping/MatrixSmsMappingRepository.kt | 4 +- .../sms/mapping/MatrixSmsMappingService.kt | 12 +- .../bridge/sms/message/MatrixMessage.kt | 32 +- .../sms/message/MatrixMessageReceiver.kt | 20 +- .../sms/message/MatrixMessageService.kt | 62 +-- .../bridge/sms/message/MessageQueueHandler.kt | 3 +- .../bridge/sms/provider/PhoneNumberService.kt | 14 +- .../provider/android/AndroidInSmsMessage.kt | 12 +- .../android/AndroidInSmsMessagesResponse.kt | 8 +- .../provider/android/AndroidOutSmsMessage.kt | 20 +- .../android/AndroidOutSmsMessageRequest.kt | 8 +- .../provider/android/AndroidSmsProcessed.kt | 16 +- .../provider/android/AndroidSmsProvider.kt | 76 ++-- .../AndroidSmsProviderConfiguration.kt | 82 ++-- .../android/AndroidSmsProviderLauncher.kt | 16 +- .../android/AndroidSmsProviderProperties.kt | 16 +- .../sms/provider/gammu/GammuSmsProvider.kt | 114 +++--- .../gammu/GammuSmsProviderProperties.kt | 6 +- .../SmsMatrixAppserviceRoomServiceTest.kt | 10 +- .../SmsMatrixMembershipChangeServiceTest.kt | 22 +- .../sms/handler/MessageToBotHandlerTest.kt | 56 +-- .../sms/handler/MessageToSmsHandlerTest.kt | 58 +-- .../sms/handler/ReceiveSmsServiceTest.kt | 64 +-- .../bridge/sms/handler/SmsAbortCommandTest.kt | 2 +- .../sms/handler/SmsMessageHandlerTest.kt | 16 +- .../sms/handler/SmsSendCommandHandlerTest.kt | 366 +++++++++--------- .../bridge/sms/handler/SmsSendCommandTest.kt | 92 ++--- .../mapping/MatrixSmsMappingRepositoryTest.kt | 14 +- .../mapping/MatrixSmsMappingServiceTest.kt | 20 +- .../message/MatrixMessageRepositoryTest.kt | 4 +- .../sms/message/MatrixMessageServiceTest.kt | 115 +++--- .../android/AndroidSmsProviderLauncherTest.kt | 10 +- .../android/AndroidSmsProviderTest.kt | 246 ++++++------ 54 files changed, 1236 insertions(+), 1172 deletions(-) diff --git a/README.md b/README.md index 9af8dd2..6ba457e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ ![Docker Image CI](https://github.com/benkuly/matrix-sms-bridge/workflows/Docker%20Image%20CI/badge.svg) + # matrix-sms-bridge -This is a matrix bridge, which allows you to bridge matrix rooms to SMS with one telephone number only. It is build on top of [matrix-spring-boot-sdk](https://github.com/benkuly/matrix-spring-boot-sdk) and written in kotlin. +This is a matrix bridge, which allows you to bridge matrix rooms to SMS with one telephone number only. It is build on +top of [matrix-spring-boot-sdk](https://github.com/benkuly/matrix-spring-boot-sdk) and written in kotlin. You need help? Ask your questions in [#matrix-sms-bridge:imbitbu.de](https://matrix.to/#/#matrix-sms-bridge:imbitbu.de) Features: + * use with one outgoing telephone number only * send SMS * receive SMS @@ -20,29 +23,46 @@ Features: * modem (with [Gammu](https://github.com/gammu/gammu)) -> not actively maintained anymore ## User Guide + ### Automated room creation -Create a room with you and `@smsBot:yourHomeServer.org` only. Now you can write `sms send --help` which gives you a help, how to use this command. -Example: `sms send -t 01749292923 "Hello World"` creates a new room with the telephone number and writes "Hello World" for you. If there already is a room with this telephone number, and you are participating, then "Hello World" will be sent to that room. +Create a room with you and `@smsBot:yourHomeServer.org` only. Now you can write `sms send --help` which gives you a +help, how to use this command. + +Example: `sms send -t 01749292923 "Hello World"` creates a new room with the telephone number and writes "Hello World" +for you. If there already is a room with this telephone number, and you are participating, then "Hello World" will be +sent to that room. ### Invite telephone number to matrix room + The virtual matrix users, which represents SMS numbers, have the following pattern: + ```text @sms_49123456789:yourHomeServer.org ``` + The number `49123456789` represents the international german telephone number `+49123456789`. -You can invite these users to every room, independently of the room members. So you can also invite more than one SMS number to rooms with more than one real matrix users. +You can invite these users to every room, independently of the room members. So you can also invite more than one SMS +number to rooms with more than one real matrix users. ### Write to telephone numbers -After a room invite the virtual matrix users automatically join the room and every message to this room will be sent as SMS to the telephone number. The SMS contains a token (e.g. "#3"), which can be used in the answer of the SMS to route it back to the matrix room. + +After a room invite the virtual matrix users automatically join the room and every message to this room will be sent as +SMS to the telephone number. The SMS contains a token (e.g. "#3"), which can be used in the answer of the SMS to route +it back to the matrix room. ### What if the SMS user has no token? -The bridge can be configured to route all SMS without a valid token to a default matrix room. Note that you must invite `@smsbot:yourHomeServer` to this room. + +The bridge can be configured to route all SMS without a valid token to a default matrix room. Note that you must +invite `@smsbot:yourHomeServer` to this room. ## Admin Guide + ### Configure Application Service + The Application Service gets configured with a yaml-file: + ```yaml matrix: bridge: @@ -87,13 +107,16 @@ matrix: ``` ### Configure HomeServer + Add this to your synapse `homeserver.yaml`: + ```yaml app_service_config_files: - /path/to/sms-bridge-appservice.yaml ``` `sms-bridge-appservice.yaml` looks like: + ```yaml id: "SMS Bridge" url: "http://url-to-sms-bridge:8080" @@ -111,10 +134,15 @@ namespaces: ``` ### Configure Provider -If you want your SMS gateway provider to be supported, look into the package [`provider`](./src/main/kotlin/net/folivo/matrix/bridge/sms/provider) to see how you can add your own provider to this bridge. + +If you want your SMS gateway provider to be supported, look into the +package [`provider`](./src/main/kotlin/net/folivo/matrix/bridge/sms/provider) to see how you can add your own provider +to this bridge. #### android-sms-gateway-server + You need to add some properties to the Application Service yaml-file: + ```yaml matrix: bridge: @@ -137,7 +165,9 @@ matrix: ``` #### Gammu + First you need to add some properties to the Application Service yaml-file: + ```yaml matrix: bridge: @@ -153,6 +183,7 @@ matrix: ``` Your `gammu-smsdrc` should look like this: + ```text [gammu] Device = /dev/ttyModem @@ -178,9 +209,11 @@ CheckBattery = 0 ``` ### Using Docker container + There are two types of docker-containers. One, that is bundled with Gammu and one without: * Default: `docker pull folivonet/matrix-sms-bridge:latest` -* Containers bundled with gammu use tags with the suffix `-gammu`: `docker pull folivonet/matrix-sms-bridge:latest-gammu` +* Containers bundled with gammu use tags with the + suffix `-gammu`: `docker pull folivonet/matrix-sms-bridge:latest-gammu` To see, how a docker setup of the bridge could look like, have a look at the [examples](./examples). diff --git a/build.gradle.kts b/build.gradle.kts index 165af4d..4f14b4f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,14 +17,14 @@ repositories { } group = "net.folivo" -version = "0.5.4" +version = "0.5.5" java.sourceCompatibility = JavaVersion.VERSION_11 tasks.withType() { manifest { attributes( - "Implementation-Title" to "matrix-sms-bridge", - "Implementation-Version" to project.version + "Implementation-Title" to "matrix-sms-bridge", + "Implementation-Version" to project.version ) } } @@ -96,17 +96,17 @@ tasks.getByName("bootBuildImage") { tasks.register("docker-gammu") { group = "build" commandLine( - "docker", - "build", - "--build-arg", - "JAR_FILE=./build/libs/*.jar", - "-t", - "folivonet/matrix-sms-bridge:latest-gammu", - "-t", - "folivonet/matrix-sms-bridge:${project.version}-gammu", - "-f", - "./src/main/docker/gammu/Dockerfile", - "." + "docker", + "build", + "--build-arg", + "JAR_FILE=./build/libs/*.jar", + "-t", + "folivonet/matrix-sms-bridge:latest-gammu", + "-t", + "folivonet/matrix-sms-bridge:${project.version}-gammu", + "-f", + "./src/main/docker/gammu/Dockerfile", + "." ) dependsOn("bootJar") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index acf1436..a89a5de 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -3,7 +3,8 @@ object Versions { const val kotlinRetry = "1.0.6" // https://github.com/michaelbull/kotlin-retry const val kotest = "4.3.1" // https://github.com/kotest/kotest/releases const val springBoot = "2.4.0" // https://spring.io/projects/spring-boot - const val springDependencyManagement = "1.0.10.RELEASE" // https://github.com/spring-gradle-plugins/dependency-management-plugin/releases + const val springDependencyManagement = + "1.0.10.RELEASE" // https://github.com/spring-gradle-plugins/dependency-management-plugin/releases const val springMockk = "2.0.3" // https://github.com/Ninja-Squad/springmockk/releases const val matrixSDK = "0.4.3" // https://github.com/benkuly/matrix-spring-boot-sdk/releases const val clikt = "3.0.1" // https://github.com/ajalt/clikt/releases diff --git a/examples/android/synapse/homeserver.yaml b/examples/android/synapse/homeserver.yaml index 4de445e..fafa364 100644 --- a/examples/android/synapse/homeserver.yaml +++ b/examples/android/synapse/homeserver.yaml @@ -216,7 +216,7 @@ listeners: x_forwarded: true resources: - - names: [client, federation] + - names: [ client, federation ] compress: false # example additional_resources: @@ -505,7 +505,7 @@ acme: # Again, you may want to change this if you are forwarding connections # through Apache/Nginx/etc. # - bind_addresses: ['::', '0.0.0.0'] + bind_addresses: [ '::', '0.0.0.0' ] # How many days remaining on a certificate before it is renewed. # diff --git a/examples/gammu/synapse/homeserver.yaml b/examples/gammu/synapse/homeserver.yaml index 4de445e..fafa364 100644 --- a/examples/gammu/synapse/homeserver.yaml +++ b/examples/gammu/synapse/homeserver.yaml @@ -216,7 +216,7 @@ listeners: x_forwarded: true resources: - - names: [client, federation] + - names: [ client, federation ] compress: false # example additional_resources: @@ -505,7 +505,7 @@ acme: # Again, you may want to change this if you are forwarding connections # through Apache/Nginx/etc. # - bind_addresses: ['::', '0.0.0.0'] + bind_addresses: [ '::', '0.0.0.0' ] # How many days remaining on a certificate before it is renewed. # diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/SmsBridgeProperties.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/SmsBridgeProperties.kt index 5f166d5..5f44d7a 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/SmsBridgeProperties.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/SmsBridgeProperties.kt @@ -7,44 +7,44 @@ import org.springframework.boot.context.properties.ConstructorBinding @ConfigurationProperties("matrix.bridge.sms") @ConstructorBinding data class SmsBridgeProperties( - val templates: SmsBridgeTemplateProperties = SmsBridgeTemplateProperties(), - val defaultRoomId: RoomId?, - val allowMappingWithoutToken: Boolean = true, - val singleModeEnabled: Boolean = false, - val defaultRegion: String, - val defaultTimeZone: String = "UTC" + val templates: SmsBridgeTemplateProperties = SmsBridgeTemplateProperties(), + val defaultRoomId: RoomId?, + val allowMappingWithoutToken: Boolean = true, + val singleModeEnabled: Boolean = false, + val defaultRegion: String, + val defaultTimeZone: String = "UTC" ) { data class SmsBridgeTemplateProperties( - val outgoingMessage: String = "{sender} wrote:\n\n{body}", - val outgoingMessageFromBot: String = "{body}",//FIXME bad - val outgoingMessageToken: String = "\n\nTo answer to this message add this token to your message: {token}", - val answerInvalidTokenWithDefaultRoom: String? = null, - val answerInvalidTokenWithoutDefaultRoom: String? = "Your message did not contain any valid token. Nobody can and will read your message.", - val sendSmsError: String = "Could not send SMS: {error}", - val sendSmsIncompatibleMessage: String = "Only text messages can be send to this SMS user.", - val defaultRoomIncomingMessage: String = "{sender} wrote:\n\n{body}", - val defaultRoomIncomingMessageWithSingleMode: String = "A message from {sender} was send to room {roomAlias}. Someone should join the room. Otherwise nobody will read the message.\n\nType `sms invite {roomAlias}` in a bot room to get invited to the room.", - val botHelp: String = "To use this bot, type 'sms'", - val botTooManyMembers: String = "Only rooms with two members are allowed to write with this bot.", - val botSmsError: String = "There was an error while using sms command. Reason: {error}", - val botSmsSendInvalidTelephoneNumber: String = "The telephone number is invalid.", - val botSmsSendNewRoomMessage: String = "{sender} wrote:\n\n{body}",//FIXME bad - val botSmsSendNoticeDelayedMessage: String = "A message will be sent for you at {sendAfter}.", - val botSmsSendCreatedRoomAndSendMessage: String = "You were invited to a new created room and (if given) the message to the telephone number(s) {receiverNumbers} was (or will be) sent for you.", - val botSmsSendCreatedRoomAndSendNoMessage: String = "You were invited to a new created room.", - val botSmsSendSendMessage: String = "The message was (or will be) sent for you into an existing room with the telephone number(s) {receiverNumbers}.", - val botSmsSendTooManyRooms: String = "No message was (or will be) sent, because there was more then one room with this telephone number(s) {receiverNumbers}. You can force room creation with the -c option.", - val botSmsSendNoMessage: String = "There was no message content to send.", - val botSmsSendDisabledRoomCreation: String = "No message was sent to telephone number(s) {receiverNumbers}, because either the bot wasn't invited to the room with the telephone number or creation was disabled by your command.", - val botSmsSendSingleModeOnlyOneTelephoneNumberAllowed: String = "Single mode is allowed with one telephone number only.", - val botSmsSendSingleModeDisabled: String = "Single mode was disabled by your admin.", - val botSmsSendError: String = "There was an error while sending message to the telephone number(s) {receiverNumbers}. Reason: {error}", - val botSmsInviteSuccess: String = "{sender} was invited to {roomAlias}.", - val botSmsInviteError: String = "There was an error while invite {sender} to {roomAlias}. Reason: {error}", - val botSmsAbortSuccess: String = "The deferred sending of messages in this room were aborted.", - val botSmsAbortError: String = "There was an error running this command. Reason: {error}", - val providerSendError: String = "Could not send sms to {receiver} with your provider. We will try to resend it and will notify you as soon as it was successful. Reason: {error}", - val providerResendSuccess: String = "The resend was successful for all messages.", - val providerReceiveError: String = "Could not receive messages through your configured provider. If this message does not appear again in the next few minutes, then retrying the receiving was successful. Reason: {error}" + val outgoingMessage: String = "{sender} wrote:\n\n{body}", + val outgoingMessageFromBot: String = "{body}",//FIXME bad + val outgoingMessageToken: String = "\n\nTo answer to this message add this token to your message: {token}", + val answerInvalidTokenWithDefaultRoom: String? = null, + val answerInvalidTokenWithoutDefaultRoom: String? = "Your message did not contain any valid token. Nobody can and will read your message.", + val sendSmsError: String = "Could not send SMS: {error}", + val sendSmsIncompatibleMessage: String = "Only text messages can be send to this SMS user.", + val defaultRoomIncomingMessage: String = "{sender} wrote:\n\n{body}", + val defaultRoomIncomingMessageWithSingleMode: String = "A message from {sender} was send to room {roomAlias}. Someone should join the room. Otherwise nobody will read the message.\n\nType `sms invite {roomAlias}` in a bot room to get invited to the room.", + val botHelp: String = "To use this bot, type 'sms'", + val botTooManyMembers: String = "Only rooms with two members are allowed to write with this bot.", + val botSmsError: String = "There was an error while using sms command. Reason: {error}", + val botSmsSendInvalidTelephoneNumber: String = "The telephone number is invalid.", + val botSmsSendNewRoomMessage: String = "{sender} wrote:\n\n{body}",//FIXME bad + val botSmsSendNoticeDelayedMessage: String = "A message will be sent for you at {sendAfter}.", + val botSmsSendCreatedRoomAndSendMessage: String = "You were invited to a new created room and (if given) the message to the telephone number(s) {receiverNumbers} was (or will be) sent for you.", + val botSmsSendCreatedRoomAndSendNoMessage: String = "You were invited to a new created room.", + val botSmsSendSendMessage: String = "The message was (or will be) sent for you into an existing room with the telephone number(s) {receiverNumbers}.", + val botSmsSendTooManyRooms: String = "No message was (or will be) sent, because there was more then one room with this telephone number(s) {receiverNumbers}. You can force room creation with the -c option.", + val botSmsSendNoMessage: String = "There was no message content to send.", + val botSmsSendDisabledRoomCreation: String = "No message was sent to telephone number(s) {receiverNumbers}, because either the bot wasn't invited to the room with the telephone number or creation was disabled by your command.", + val botSmsSendSingleModeOnlyOneTelephoneNumberAllowed: String = "Single mode is allowed with one telephone number only.", + val botSmsSendSingleModeDisabled: String = "Single mode was disabled by your admin.", + val botSmsSendError: String = "There was an error while sending message to the telephone number(s) {receiverNumbers}. Reason: {error}", + val botSmsInviteSuccess: String = "{sender} was invited to {roomAlias}.", + val botSmsInviteError: String = "There was an error while invite {sender} to {roomAlias}. Reason: {error}", + val botSmsAbortSuccess: String = "The deferred sending of messages in this room were aborted.", + val botSmsAbortError: String = "There was an error running this command. Reason: {error}", + val providerSendError: String = "Could not send sms to {receiver} with your provider. We will try to resend it and will notify you as soon as it was successful. Reason: {error}", + val providerResendSuccess: String = "The resend was successful for all messages.", + val providerReceiveError: String = "Could not receive messages through your configured provider. If this message does not appear again in the next few minutes, then retrying the receiving was successful. Reason: {error}" ) } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomService.kt index ccbcc6b..568a54d 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomService.kt @@ -16,23 +16,23 @@ import org.springframework.stereotype.Service @Service class SmsMatrixAppserviceRoomService( - roomService: MatrixRoomService, - helper: BotServiceHelper, - private val botProperties: MatrixBotProperties, - private val bridgeProperties: SmsBridgeProperties + roomService: MatrixRoomService, + helper: BotServiceHelper, + private val botProperties: MatrixBotProperties, + private val bridgeProperties: SmsBridgeProperties ) : DefaultAppserviceRoomService(roomService, helper) { override suspend fun getCreateRoomParameter(roomAlias: RoomAliasId): CreateRoomParameter { val invitedUser = UserId(roomAlias.localpart, botProperties.serverName) return CreateRoomParameter( - visibility = PRIVATE, - powerLevelContentOverride = PowerLevelsEventContent( - invite = 0, - kick = 0, - events = mapOf("m.room.name" to 0, "m.room.topic" to 0), - users = mapOf(invitedUser to 100, botProperties.botUserId to 100) - ), - invite = setOf(invitedUser) + visibility = PRIVATE, + powerLevelContentOverride = PowerLevelsEventContent( + invite = 0, + kick = 0, + events = mapOf("m.room.name" to 0, "m.room.topic" to 0), + users = mapOf(invitedUser to 100, botProperties.botUserId to 100) + ), + invite = setOf(invitedUser) ) } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceUserService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceUserService.kt index e8c170d..1e4ab26 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceUserService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceUserService.kt @@ -10,9 +10,9 @@ import org.springframework.stereotype.Service @Service class SmsMatrixAppserviceUserService( - userService: MatrixUserService, - helper: BotServiceHelper, - private val botProperties: MatrixBotProperties + userService: MatrixUserService, + helper: BotServiceHelper, + private val botProperties: MatrixBotProperties ) : DefaultAppserviceUserService(userService, helper, botProperties) { override suspend fun getRegisterUserParameter(userId: UserId): RegisterUserParameter { diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeService.kt index 3d0cc69..54bf8be 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeService.kt @@ -13,19 +13,19 @@ import org.springframework.stereotype.Service @Service class SmsMatrixMembershipChangeService( - private val roomService: MatrixRoomService, - membershipService: MatrixMembershipService, - userService: MatrixUserService, - membershipSyncService: MatrixMembershipSyncService, - matrixClient: MatrixClient, - private val botProperties: MatrixBotProperties + private val roomService: MatrixRoomService, + membershipService: MatrixMembershipService, + userService: MatrixUserService, + membershipSyncService: MatrixMembershipSyncService, + matrixClient: MatrixClient, + private val botProperties: MatrixBotProperties ) : DefaultMembershipChangeService( - roomService, - membershipService, - userService, - membershipSyncService, - matrixClient, - botProperties + roomService, + membershipService, + userService, + membershipSyncService, + matrixClient, + botProperties ) { override suspend fun shouldJoinRoom(userId: UserId, roomId: RoomId): Boolean { if (userId == botProperties.botUserId) return super.shouldJoinRoom(userId, roomId) diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandler.kt index ed222f8..ed955c3 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandler.kt @@ -16,23 +16,23 @@ import org.springframework.stereotype.Component @Component class MessageToBotHandler( - private val smsSendCommandHandler: SmsSendCommandHandler, - private val smsInviteCommandHandler: SmsInviteCommandHandler, - private val smsAbortCommandHandler: SmsAbortCommandHandler, - private val phoneNumberService: PhoneNumberService, - private val smsBridgeProperties: SmsBridgeProperties, - private val userService: MatrixUserService, - private val membershipService: MatrixMembershipService + private val smsSendCommandHandler: SmsSendCommandHandler, + private val smsInviteCommandHandler: SmsInviteCommandHandler, + private val smsAbortCommandHandler: SmsAbortCommandHandler, + private val phoneNumberService: PhoneNumberService, + private val smsBridgeProperties: SmsBridgeProperties, + private val userService: MatrixUserService, + private val membershipService: MatrixMembershipService ) { companion object { private val LOG = LoggerFactory.getLogger(this::class.java) } suspend fun handleMessage( - roomId: RoomId, - body: String, - senderId: UserId, - context: MessageContext + roomId: RoomId, + body: String, + senderId: UserId, + context: MessageContext ): Boolean { val sender = userService.getOrCreateUser(senderId) val membershipSize = membershipService.getMembershipsSizeByRoomId(roomId) @@ -55,23 +55,23 @@ class MessageToBotHandler( val args = Commandline.translateCommandline(body.removePrefix("sms")) SmsCommand().context { console = answerConsole } - .subcommands( - SmsSendCommand( - senderId, - smsSendCommandHandler, - phoneNumberService, - smsBridgeProperties - ), - SmsInviteCommand( - senderId, - smsInviteCommandHandler - ), - SmsAbortCommand( - roomId, - smsAbortCommandHandler - ) + .subcommands( + SmsSendCommand( + senderId, + smsSendCommandHandler, + phoneNumberService, + smsBridgeProperties + ), + SmsInviteCommand( + senderId, + smsInviteCommandHandler + ), + SmsAbortCommand( + roomId, + smsAbortCommandHandler ) - .parse(args) + ) + .parse(args) } catch (e: PrintHelpMessage) { answerConsole.print(e.command.getFormattedHelp(), false) } catch (e: PrintCompletionMessage) { @@ -86,8 +86,8 @@ class MessageToBotHandler( answerConsole.print("Aborted!", true) } catch (error: Throwable) { context.answer( - smsBridgeProperties.templates.botSmsError - .replace("{error}", error.message ?: "unknown") + smsBridgeProperties.templates.botSmsError + .replace("{error}", error.message ?: "unknown") ) } }.join() diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandler.kt index 3bb1739..0ea5c57 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandler.kt @@ -15,12 +15,12 @@ import org.springframework.stereotype.Service @Service class MessageToSmsHandler( - private val botProperties: MatrixBotProperties, - private val smsBridgeProperties: SmsBridgeProperties, - private val smsProvider: SmsProvider, - private val roomService: MatrixRoomService, - private val userService: MatrixUserService, - private val mappingService: MatrixSmsMappingService + private val botProperties: MatrixBotProperties, + private val smsBridgeProperties: SmsBridgeProperties, + private val smsProvider: SmsProvider, + private val roomService: MatrixRoomService, + private val userService: MatrixUserService, + private val mappingService: MatrixSmsMappingService ) { private val templates = smsBridgeProperties.templates @@ -30,65 +30,65 @@ class MessageToSmsHandler( } suspend fun handleMessage( - roomId: RoomId, - body: String, - senderId: UserId, - context: MessageContext, - isTextMessage: Boolean + roomId: RoomId, + body: String, + senderId: UserId, + context: MessageContext, + isTextMessage: Boolean ) { userService.getUsersByRoom(roomId) - .filter { it.isManaged && it.id != senderId && it.id != botProperties.botUserId } - .map { "+" + it.id.localpart.removePrefix("sms_") to it.id } - .collect { (receiverNumber, receiverId) -> - if (isTextMessage) { - LOG.debug("send SMS from $roomId to $receiverNumber") - val needsToken = !smsBridgeProperties.allowMappingWithoutToken - || !roomService.getOrCreateRoom(roomId).isManaged - && roomService.getRoomsByMembers(setOf(receiverId)).take(2).count() > 1 - val mappingToken = if (needsToken) - mappingService.getOrCreateMapping(receiverId, roomId).mappingToken else null + .filter { it.isManaged && it.id != senderId && it.id != botProperties.botUserId } + .map { "+" + it.id.localpart.removePrefix("sms_") to it.id } + .collect { (receiverNumber, receiverId) -> + if (isTextMessage) { + LOG.debug("send SMS from $roomId to $receiverNumber") + val needsToken = !smsBridgeProperties.allowMappingWithoutToken + || !roomService.getOrCreateRoom(roomId).isManaged + && roomService.getRoomsByMembers(setOf(receiverId)).take(2).count() > 1 + val mappingToken = if (needsToken) + mappingService.getOrCreateMapping(receiverId, roomId).mappingToken else null - try { - insertBodyAndSend( - sender = senderId, - receiverNumber = receiverNumber, - body = body, - mappingToken = mappingToken - ) - } catch (error: Throwable) { - LOG.error( - "Could not send sms from room $roomId and $senderId. " + + try { + insertBodyAndSend( + sender = senderId, + receiverNumber = receiverNumber, + body = body, + mappingToken = mappingToken + ) + } catch (error: Throwable) { + LOG.error( + "Could not send sms from room $roomId and $senderId. " + "This should be fixed.", error - ) - context.answer( - templates.sendSmsError.replace("{error}", error.message ?: "unknown"), - asUserId = receiverId - ) - } - } else { - LOG.debug("cannot send SMS from $roomId to $receiverNumber because of incompatible message type") - context.answer(templates.sendSmsIncompatibleMessage, asUserId = receiverId) + ) + context.answer( + templates.sendSmsError.replace("{error}", error.message ?: "unknown"), + asUserId = receiverId + ) } + } else { + LOG.debug("cannot send SMS from $roomId to $receiverNumber because of incompatible message type") + context.answer(templates.sendSmsIncompatibleMessage, asUserId = receiverId) } + } } private suspend fun insertBodyAndSend( - sender: UserId, - receiverNumber: String, - body: String, - mappingToken: Int? + sender: UserId, + receiverNumber: String, + body: String, + mappingToken: Int? ) { val messageTemplate = - if (sender == botProperties.botUserId) - templates.outgoingMessageFromBot - else templates.outgoingMessage + if (sender == botProperties.botUserId) + templates.outgoingMessageFromBot + else templates.outgoingMessage val completeTemplate = - if (mappingToken == null) messageTemplate - else messageTemplate + templates.outgoingMessageToken.replace("{token}", "#$mappingToken") + if (mappingToken == null) messageTemplate + else messageTemplate + templates.outgoingMessageToken.replace("{token}", "#$mappingToken") val templateBody = completeTemplate - .replace("{sender}", sender.full) - .replace("{body}", body) + .replace("{sender}", sender.full) + .replace("{body}", body) smsProvider.sendSms(receiver = receiverNumber, body = templateBody) } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsService.kt index f636cd0..2cac54d 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsService.kt @@ -16,13 +16,13 @@ import org.springframework.stereotype.Service @Service class ReceiveSmsService( - private val matrixClient: MatrixClient, - private val mappingService: MatrixSmsMappingService, - private val messageService: MatrixMessageService, - private val membershipService: MatrixMembershipService, - private val roomService: MatrixRoomService, - private val matrixBotProperties: MatrixBotProperties, - private val smsBridgeProperties: SmsBridgeProperties + private val matrixClient: MatrixClient, + private val mappingService: MatrixSmsMappingService, + private val messageService: MatrixMessageService, + private val membershipService: MatrixMembershipService, + private val roomService: MatrixRoomService, + private val matrixBotProperties: MatrixBotProperties, + private val smsBridgeProperties: SmsBridgeProperties ) { private val templates = smsBridgeProperties.templates @@ -34,11 +34,11 @@ class ReceiveSmsService( suspend fun receiveSms(body: String, sender: String): String? { val userIdLocalpart = "sms_${sender.substringAfter('+')}" val userId = - if (sender.matches(Regex("\\+[0-9]{6,15}"))) { - UserId(userIdLocalpart, matrixBotProperties.serverName) - } else { - throw IllegalArgumentException("The sender did not match our regex for international telephone numbers.") - } + if (sender.matches(Regex("\\+[0-9]{6,15}"))) { + UserId(userIdLocalpart, matrixBotProperties.serverName) + } else { + throw IllegalArgumentException("The sender did not match our regex for international telephone numbers.") + } val mappingTokenMatch = Regex("#[0-9]{1,9}").find(body) val mappingToken = mappingTokenMatch?.value?.substringAfter('#')?.toInt() @@ -46,36 +46,35 @@ class ReceiveSmsService( val cleanedBody = mappingTokenMatch?.let { body.removeRange(it.range) }?.trim() ?: body val roomIdFromMappingToken = mappingService.getRoomId( - userId = userId, - mappingToken = mappingToken + userId = userId, + mappingToken = mappingToken ) if (roomIdFromMappingToken != null) { LOG.debug("receive SMS from $sender to $roomIdFromMappingToken") matrixClient.roomsApi.sendRoomEvent( - roomIdFromMappingToken, - TextMessageEventContent(cleanedBody), - asUserId = userId + roomIdFromMappingToken, + TextMessageEventContent(cleanedBody), + asUserId = userId ) return null } else if (smsBridgeProperties.singleModeEnabled) { LOG.debug("receive SMS without or wrong mappingToken from $sender to single room") val roomAliasId = RoomAliasId(userIdLocalpart, matrixBotProperties.serverName) val roomIdFromAlias = roomService.getRoomAlias(roomAliasId)?.roomId - ?: matrixClient.roomsApi.getRoomAlias(roomAliasId).roomId + ?: matrixClient.roomsApi.getRoomAlias(roomAliasId).roomId messageService.sendRoomMessage( - MatrixMessage(roomIdFromAlias, cleanedBody, isNotice = false, asUserId = userId), - setOf(userId) + MatrixMessage(roomIdFromAlias, cleanedBody, isNotice = false, asUserId = userId) ) if (membershipService.hasRoomOnlyManagedUsersLeft(roomIdFromAlias)) { if (smsBridgeProperties.defaultRoomId != null) { val message = templates.defaultRoomIncomingMessageWithSingleMode - .replace("{sender}", sender) - .replace("{roomAlias}", roomAliasId.toString()) + .replace("{sender}", sender) + .replace("{roomAlias}", roomAliasId.toString()) matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - TextMessageEventContent(message) + smsBridgeProperties.defaultRoomId, + TextMessageEventContent(message) ) } else return templates.answerInvalidTokenWithoutDefaultRoom.takeIf { !it.isNullOrEmpty() } } @@ -85,12 +84,12 @@ class ReceiveSmsService( return if (smsBridgeProperties.defaultRoomId != null) { val message = templates.defaultRoomIncomingMessage - .replace("{sender}", sender) - .replace("{body}", cleanedBody) + .replace("{sender}", sender) + .replace("{body}", cleanedBody) matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - TextMessageEventContent(message) + smsBridgeProperties.defaultRoomId, + TextMessageEventContent(message) ) templates.answerInvalidTokenWithDefaultRoom.takeIf { !it.isNullOrEmpty() } } else templates.answerInvalidTokenWithoutDefaultRoom.takeIf { !it.isNullOrEmpty() } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommand.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommand.kt index 5d0823a..4100e91 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommand.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommand.kt @@ -5,8 +5,8 @@ import kotlinx.coroutines.runBlocking import net.folivo.matrix.core.model.MatrixId.RoomId class SmsAbortCommand( - private val roomId: RoomId, - private val handler: SmsAbortCommandHandler + private val roomId: RoomId, + private val handler: SmsAbortCommandHandler ) : CliktCommand(name = "abort") { override fun run() { diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandHandler.kt index 4a00ab1..7ebba72 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandHandler.kt @@ -10,8 +10,8 @@ import org.springframework.stereotype.Component @Component class SmsAbortCommandHandler( - private val messageService: MatrixMessageService, - smsBridgeProperties: SmsBridgeProperties, + private val messageService: MatrixMessageService, + smsBridgeProperties: SmsBridgeProperties, ) { private val templates: SmsBridgeTemplateProperties = smsBridgeProperties.templates @@ -21,7 +21,7 @@ class SmsAbortCommandHandler( } suspend fun handleCommand( - roomId: RoomId + roomId: RoomId ): String { return try { messageService.deleteByRoomId(roomId) @@ -29,7 +29,7 @@ class SmsAbortCommandHandler( } catch (ex: Throwable) { LOG.debug("got exception") templates.botSmsAbortError - .replace("{error}", ex.message ?: "unknown") + .replace("{error}", ex.message ?: "unknown") } } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsBotConsole.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsBotConsole.kt index e7758b6..64302ef 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsBotConsole.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsBotConsole.kt @@ -6,7 +6,7 @@ import net.folivo.matrix.bot.event.MessageContext import org.slf4j.LoggerFactory class SmsBotConsole( - private val messageContext: MessageContext + private val messageContext: MessageContext ) : CliktConsole { override val lineSeparator: String = "" diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommand.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommand.kt index 8b943e6..947be12 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommand.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommand.kt @@ -8,8 +8,8 @@ import net.folivo.matrix.core.model.MatrixId.RoomAliasId import net.folivo.matrix.core.model.MatrixId.UserId class SmsInviteCommand( - private val sender: UserId, - private val handler: SmsInviteCommandHandler + private val sender: UserId, + private val handler: SmsInviteCommandHandler ) : CliktCommand(name = "invite") { private val alias by argument("alias").convert { RoomAliasId(it) } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommandHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommandHandler.kt index ded2b18..a212a86 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommandHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsInviteCommandHandler.kt @@ -12,9 +12,9 @@ import org.springframework.stereotype.Component @Component class SmsInviteCommandHandler( - private val roomService: MatrixRoomService, - private val matrixClient: MatrixClient, - smsBridgeProperties: SmsBridgeProperties, + private val roomService: MatrixRoomService, + private val matrixClient: MatrixClient, + smsBridgeProperties: SmsBridgeProperties, ) { private val templates: SmsBridgeTemplateProperties = smsBridgeProperties.templates @@ -24,23 +24,22 @@ class SmsInviteCommandHandler( } suspend fun handleCommand( - sender: UserId, - alias: RoomAliasId + sender: UserId, + alias: RoomAliasId ): String { return try { val roomId = roomService.getRoomAlias(alias)?.roomId - ?: matrixClient.roomsApi.getRoomAlias(alias).roomId + ?: matrixClient.roomsApi.getRoomAlias(alias).roomId matrixClient.roomsApi.inviteUser(roomId, sender) templates.botSmsInviteSuccess - .replace("{roomAlias}", alias.full) - .replace("{sender}", sender.full) + .replace("{roomAlias}", alias.full) + .replace("{sender}", sender.full) } catch (ex: Throwable) { LOG.debug("got exception") templates.botSmsInviteError - .replace("{roomAlias}", alias.full) - .replace("{sender}", sender.full) - .replace("{error}", ex.message ?: "unknown") + .replace("{roomAlias}", alias.full) + .replace("{sender}", sender.full) + .replace("{error}", ex.message ?: "unknown") } } - } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandler.kt index 907e68d..aba1114 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandler.kt @@ -13,11 +13,11 @@ import org.springframework.stereotype.Component @Component class SmsMessageHandler( - private val messageToSmsHandler: MessageToSmsHandler, - private val messageToBotHandler: MessageToBotHandler, - private val membershipService: MatrixMembershipService, - private val botProperties: MatrixBotProperties, - private val smsBridgeProperties: SmsBridgeProperties + private val messageToSmsHandler: MessageToSmsHandler, + private val messageToBotHandler: MessageToBotHandler, + private val membershipService: MatrixMembershipService, + private val botProperties: MatrixBotProperties, + private val smsBridgeProperties: SmsBridgeProperties ) : MatrixMessageHandler { companion object { @@ -34,24 +34,24 @@ class SmsMessageHandler( return } else { val didHandleMessage = - membershipService.doesRoomContainsMembers(roomId, setOf(botProperties.botUserId)) - && messageToBotHandler.handleMessage( - roomId = roomId, - body = content.body, - senderId = senderId, - context = context - ) + membershipService.doesRoomContainsMembers(roomId, setOf(botProperties.botUserId)) + && messageToBotHandler.handleMessage( + roomId = roomId, + body = content.body, + senderId = senderId, + context = context + ) if (didHandleMessage) { LOG.debug("ignored message because it was for bot or only a notice message") return } else { messageToSmsHandler.handleMessage( - roomId = roomId, - body = content.body, - senderId = senderId, - context = context, - isTextMessage = content is TextMessageEventContent + roomId = roomId, + body = content.body, + senderId = senderId, + context = context, + isTextMessage = content is TextMessageEventContent ) } } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommand.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommand.kt index 2df17cd..4db5be4 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommand.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommand.kt @@ -15,10 +15,10 @@ import org.slf4j.LoggerFactory import java.time.LocalDateTime class SmsSendCommand( - private val sender: UserId, - private val handler: SmsSendCommandHandler, - private val phoneNumberService: PhoneNumberService, - private val smsBridgeProperties: SmsBridgeProperties + private val sender: UserId, + private val handler: SmsSendCommandHandler, + private val phoneNumberService: PhoneNumberService, + private val smsBridgeProperties: SmsBridgeProperties ) : CliktCommand(name = "send") { companion object { @@ -45,30 +45,30 @@ class SmsSendCommand( LOG.debug("use group and send message") echo(runBlocking { handler.handleCommand( - body = body, - senderId = sender, - receiverNumbers = receiverNumbers.toSet(), - inviteUserIds = inviteUserIds, - roomName = roomName, - roomCreationMode = roomCreationMode, - sendAfterLocal = sendAfter + body = body, + senderId = sender, + receiverNumbers = receiverNumbers.toSet(), + inviteUserIds = inviteUserIds, + roomName = roomName, + roomCreationMode = roomCreationMode, + sendAfterLocal = sendAfter ) }) } else { LOG.debug("use one room for each number and send message") receiverNumbers.forEach { number -> echo( - runBlocking { - handler.handleCommand( - body = body, - senderId = sender, - receiverNumbers = setOf(number), - inviteUserIds = inviteUserIds, - roomName = roomName, - roomCreationMode = roomCreationMode, - sendAfterLocal = sendAfter - ) - }) + runBlocking { + handler.handleCommand( + body = body, + senderId = sender, + receiverNumbers = setOf(number), + inviteUserIds = inviteUserIds, + roomName = roomName, + roomCreationMode = roomCreationMode, + sendAfterLocal = sendAfter + ) + }) } } } catch (ex: NumberParseException) { diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandler.kt index c56b764..714e32a 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandler.kt @@ -30,14 +30,14 @@ import java.time.temporal.ChronoUnit @Component class SmsSendCommandHandler( - private val userService: MatrixUserService, - private val roomService: MatrixRoomService, - private val membershipService: MatrixMembershipService, - private val messageService: MatrixMessageService, - private val appserviceHandlerHelper: AppserviceHandlerHelper, - private val matrixClient: MatrixClient, - private val botProperties: MatrixBotProperties, - private val smsBridgeProperties: SmsBridgeProperties, + private val userService: MatrixUserService, + private val roomService: MatrixRoomService, + private val membershipService: MatrixMembershipService, + private val messageService: MatrixMessageService, + private val appserviceHandlerHelper: AppserviceHandlerHelper, + private val matrixClient: MatrixClient, + private val botProperties: MatrixBotProperties, + private val smsBridgeProperties: SmsBridgeProperties, ) { private val templates: SmsBridgeTemplateProperties = smsBridgeProperties.templates @@ -47,13 +47,13 @@ class SmsSendCommandHandler( } suspend fun handleCommand( - body: String?, - senderId: UserId, - receiverNumbers: Set, - inviteUserIds: Set, - roomName: String?, - sendAfterLocal: LocalDateTime?, - roomCreationMode: RoomCreationMode + body: String?, + senderId: UserId, + receiverNumbers: Set, + inviteUserIds: Set, + roomName: String?, + sendAfterLocal: LocalDateTime?, + roomCreationMode: RoomCreationMode ): String { LOG.debug("handle command") val requiredManagedReceiverIds = receiverNumbers.map { @@ -61,49 +61,49 @@ class SmsSendCommandHandler( }.toSet() val membersWithoutBot = setOf(senderId, *requiredManagedReceiverIds.toTypedArray()) val rooms = roomService.getRoomsByMembers(membersWithoutBot) - .take(2) - .map { it.id } - .toSet() + .take(2) + .map { it.id } + .toSet() try { val answer = when (roomCreationMode) { - AUTO -> { + AUTO -> { if (smsBridgeProperties.singleModeEnabled && receiverNumbers.size == 1) { sendMessageToRoomAlias( - senderId, - body, - roomName, - requiredManagedReceiverIds.first(), - inviteUserIds, - sendAfterLocal + senderId, + body, + roomName, + requiredManagedReceiverIds.first(), + inviteUserIds, + sendAfterLocal ) } else when (rooms.size) { 0 -> createRoomAndSendMessage( - body, - senderId, - roomName, - requiredManagedReceiverIds, - inviteUserIds, - sendAfterLocal + body, + senderId, + roomName, + requiredManagedReceiverIds, + inviteUserIds, + sendAfterLocal ) 1 -> sendMessageToRoom( - rooms.first(), - senderId, - body, - requiredManagedReceiverIds, - sendAfterLocal + rooms.first(), + senderId, + body, + requiredManagedReceiverIds, + sendAfterLocal ) else -> templates.botSmsSendTooManyRooms } } ALWAYS -> { createRoomAndSendMessage( - body, - senderId, - roomName, - requiredManagedReceiverIds, - inviteUserIds, - sendAfterLocal + body, + senderId, + roomName, + requiredManagedReceiverIds, + inviteUserIds, + sendAfterLocal ) } SINGLE -> { @@ -111,26 +111,26 @@ class SmsSendCommandHandler( templates.botSmsSendSingleModeDisabled } else if (receiverNumbers.size == 1) { sendMessageToRoomAlias( - senderId, - body, - roomName, - requiredManagedReceiverIds.first(), - inviteUserIds, - sendAfterLocal + senderId, + body, + roomName, + requiredManagedReceiverIds.first(), + inviteUserIds, + sendAfterLocal ) } else { templates.botSmsSendSingleModeOnlyOneTelephoneNumberAllowed } } - NO -> { + NO -> { when (rooms.size) { 0 -> templates.botSmsSendDisabledRoomCreation 1 -> sendMessageToRoom( - rooms.first(), - senderId, - body, - requiredManagedReceiverIds, - sendAfterLocal + rooms.first(), + senderId, + body, + requiredManagedReceiverIds, + sendAfterLocal ) else -> templates.botSmsSendTooManyRooms } @@ -141,40 +141,40 @@ class SmsSendCommandHandler( } catch (error: Throwable) { LOG.warn("trying to create room, join room or send message failed: ${error.message}") return templates.botSmsSendError - .replace("{error}", error.message ?: "unknown") - .replace("{receiverNumbers}", receiverNumbers.joinToString()) + .replace("{error}", error.message ?: "unknown") + .replace("{receiverNumbers}", receiverNumbers.joinToString()) } } internal suspend fun sendMessageToRoomAlias( - senderId: UserId, - body: String?, - roomName: String?, - requiredManagedReceiverId: UserId, - inviteUserIds: Set, - sendAfterLocal: LocalDateTime? + senderId: UserId, + body: String?, + roomName: String?, + requiredManagedReceiverId: UserId, + inviteUserIds: Set, + sendAfterLocal: LocalDateTime? ): String { LOG.debug("send message to room alias") val aliasLocalpart = requiredManagedReceiverId.localpart val roomAliasId = RoomAliasId(aliasLocalpart, botProperties.serverName) val existingRoomId = roomService.getRoomAlias(roomAliasId)?.roomId val roomId = existingRoomId - ?: matrixClient.roomsApi.getRoomAlias(roomAliasId).roomId + ?: matrixClient.roomsApi.getRoomAlias(roomAliasId).roomId if (roomName != null && (existingRoomId == null || tryGetRoomName(roomId).isNullOrEmpty())) { matrixClient.roomsApi.sendStateEvent(roomId, NameEventContent(roomName)) } setOf(senderId, *inviteUserIds.toTypedArray()) - .filter { !membershipService.doesRoomContainsMembers(roomId, setOf(it)) } - .forEach { matrixClient.roomsApi.inviteUser(roomId, it) } - + .filter { !membershipService.doesRoomContainsMembers(roomId, setOf(it)) } + .forEach { matrixClient.roomsApi.inviteUser(roomId, it) } + return sendMessageToRoom( - roomId, - senderId, - body, - setOf(requiredManagedReceiverId), - sendAfterLocal, - denyBotInvite = true + roomId, + senderId, + body, + setOf(requiredManagedReceiverId), + sendAfterLocal, + denyBotInvite = true ) } @@ -187,12 +187,12 @@ class SmsSendCommandHandler( } internal suspend fun createRoomAndSendMessage( - body: String?, - senderId: UserId, - roomName: String?, - requiredManagedReceiverIds: Set, - inviteUserIds: Set, - sendAfterLocal: LocalDateTime? + body: String?, + senderId: UserId, + roomName: String?, + requiredManagedReceiverIds: Set, + inviteUserIds: Set, + sendAfterLocal: LocalDateTime? ): String { LOG.debug("ensure that users has already been created") requiredManagedReceiverIds.forEach { @@ -203,18 +203,18 @@ class SmsSendCommandHandler( LOG.debug("create room and send message") val roomId = matrixClient.roomsApi.createRoom( - name = roomName, - invite = setOf(senderId, *requiredManagedReceiverIds.toTypedArray(), *inviteUserIds.toTypedArray()), - visibility = PRIVATE, - powerLevelContentOverride = PowerLevelsEventContent( - invite = 0, - kick = 0, - events = mapOf("m.room.name" to 0, "m.room.topic" to 0), - users = mapOf( - botProperties.botUserId to 100, - *requiredManagedReceiverIds.map { it to 100 }.toTypedArray() - ) + name = roomName, + invite = setOf(senderId, *requiredManagedReceiverIds.toTypedArray(), *inviteUserIds.toTypedArray()), + visibility = PRIVATE, + powerLevelContentOverride = PowerLevelsEventContent( + invite = 0, + kick = 0, + events = mapOf("m.room.name" to 0, "m.room.topic" to 0), + users = mapOf( + botProperties.botUserId to 100, + *requiredManagedReceiverIds.map { it to 100 }.toTypedArray() ) + ) ) roomService.getOrCreateRoom(roomId) @@ -227,26 +227,26 @@ class SmsSendCommandHandler( } internal suspend fun sendMessageToRoom( - roomId: RoomId, - senderId: UserId, - body: String?, - requiredManagedReceiverIds: Set, - sendAfterLocal: LocalDateTime?, - denyBotInvite: Boolean = false + roomId: RoomId, + senderId: UserId, + body: String?, + requiredManagedReceiverIds: Set, + sendAfterLocal: LocalDateTime?, + denyBotInvite: Boolean = false ): String { if (body.isNullOrBlank()) { return templates.botSmsSendNoMessage } else { val botIsMember = denyBotInvite || membershipService.doesRoomContainsMembers( - roomId, - setOf(botProperties.botUserId) + roomId, + setOf(botProperties.botUserId) ) if (!botIsMember) { LOG.debug("try to invite sms bot user to room $roomId") matrixClient.roomsApi.inviteUser( - roomId = roomId, - userId = botProperties.botUserId, - asUserId = requiredManagedReceiverIds.first() + roomId = roomId, + userId = botProperties.botUserId, + asUserId = requiredManagedReceiverIds.first() ) } @@ -255,23 +255,23 @@ class SmsSendCommandHandler( if (sendAfter != null && Instant.now().until(sendAfter, ChronoUnit.SECONDS) > 15) { LOG.debug("notify room $roomId that message will be send later") messageService.sendRoomMessage( - MatrixMessage( - roomId = roomId, - body = templates.botSmsSendNoticeDelayedMessage - .replace("{sendAfter}", sendAfterLocal.toString()), - isNotice = true - ), requiredManagedReceiverIds.toSet() + MatrixMessage( + roomId = roomId, + body = templates.botSmsSendNoticeDelayedMessage + .replace("{sendAfter}", sendAfterLocal.toString()), + isNotice = true + ), requiredManagedReceiverIds.toSet() ) } LOG.debug("send message to room $roomId") messageService.sendRoomMessage( - MatrixMessage( - roomId = roomId, - body = templates.botSmsSendNewRoomMessage - .replace("{sender}", senderId.full) - .replace("{body}", body), - sendAfter = sendAfter ?: Instant.now() - ), requiredManagedReceiverIds.toSet() + MatrixMessage( + roomId = roomId, + body = templates.botSmsSendNewRoomMessage + .replace("{sender}", senderId.full) + .replace("{body}", body), + sendAfter = sendAfter ?: Instant.now() + ), requiredManagedReceiverIds.toSet() ) return templates.botSmsSendSendMessage diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMapping.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMapping.kt index 27e0ca8..8cb6b8b 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMapping.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMapping.kt @@ -8,12 +8,12 @@ import org.springframework.data.relational.core.mapping.Table @Table("matrix_sms_mapping") data class MatrixSmsMapping( - @Id - @Column("membership_id") - val membershipId: String, - @Column("mapping_token") - val mappingToken: Int, - @Version - @Column("version") - val version: Int = 0 + @Id + @Column("membership_id") + val membershipId: String, + @Column("mapping_token") + val mappingToken: Int, + @Version + @Column("version") + val version: Int = 0 ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepository.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepository.kt index 9f406bd..2b87eaa 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepository.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepository.kt @@ -10,7 +10,7 @@ import org.springframework.stereotype.Repository interface MatrixSmsMappingRepository : CoroutineCrudRepository { @Query( - """ + """ SELECT * from matrix_sms_mapping map JOIN matrix_membership mem ON mem.id = map.membership_id WHERE mem.user_id = :userId @@ -20,7 +20,7 @@ interface MatrixSmsMappingRepository : CoroutineCrudRepository @Query( - """ + """ SELECT * from matrix_sms_mapping map JOIN matrix_membership mem ON mem.id = map.membership_id WHERE map.mapping_token = :mappingToken AND mem.user_id = :userId diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingService.kt index ee1bd94..b78f12b 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingService.kt @@ -11,20 +11,20 @@ import org.springframework.stereotype.Service @Service class MatrixSmsMappingService( - private val mappingRepository: MatrixSmsMappingRepository, - private val membershipService: MatrixMembershipService, - private val smsBridgeProperties: SmsBridgeProperties + private val mappingRepository: MatrixSmsMappingRepository, + private val membershipService: MatrixMembershipService, + private val smsBridgeProperties: SmsBridgeProperties ) { suspend fun getOrCreateMapping( - userId: UserId, - roomId: RoomId + userId: UserId, + roomId: RoomId ): MatrixSmsMapping { val membership = membershipService.getOrCreateMembership(userId, roomId) val mapping = mappingRepository.findByMembershipId(membership.id) return if (mapping == null) { val lastMappingToken = mappingRepository.findByUserIdSortByMappingTokenDesc(userId) - .firstOrNull()?.mappingToken ?: 0 + .firstOrNull()?.mappingToken ?: 0 mappingRepository.save(MatrixSmsMapping(membership.id, lastMappingToken + 1)) } else mapping } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessage.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessage.kt index 8b2d97e..d6d0e6f 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessage.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessage.kt @@ -10,20 +10,20 @@ import java.time.Instant @Table("matrix_message") data class MatrixMessage( - @Column("room_id") - val roomId: RoomId, - @Column("body") - val body: String, - @Column("send_after") - val sendAfter: Instant = Instant.now(), - @Column("is_notice") - val isNotice: Boolean = false, - @Column("as_user_id") - val asUserId: UserId? = null, - @Id - @Column("id") - val id: Long? = null, - @Version - @Column("version") - val version: Int = 0 + @Column("room_id") + val roomId: RoomId, + @Column("body") + val body: String, + @Column("send_after") + val sendAfter: Instant = Instant.now(), + @Column("is_notice") + val isNotice: Boolean = false, + @Column("as_user_id") + val asUserId: UserId? = null, + @Id + @Column("id") + val id: Long? = null, + @Version + @Column("version") + val version: Int = 0 ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageReceiver.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageReceiver.kt index 5c6bcf4..437ca75 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageReceiver.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageReceiver.kt @@ -8,14 +8,14 @@ import org.springframework.data.relational.core.mapping.Table @Table("matrix_message_receiver") data class MatrixMessageReceiver( - @Column("room_message_id") - val roomMessageId: Long, - @Column("user_id") - val userId: UserId, - @Id - @Column("id") - val id: Long? = null, - @Version - @Column("version") - val version: Int = 0 + @Column("room_message_id") + val roomMessageId: Long, + @Column("user_id") + val userId: UserId, + @Id + @Column("id") + val id: Long? = null, + @Version + @Column("version") + val version: Int = 0 ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageService.kt index 072e100..0eb2055 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageService.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toSet import net.folivo.matrix.bot.membership.MatrixMembershipService +import net.folivo.matrix.bot.user.MatrixUserService import net.folivo.matrix.core.model.MatrixId.RoomId import net.folivo.matrix.core.model.MatrixId.UserId import net.folivo.matrix.core.model.events.m.room.message.NoticeMessageEventContent @@ -16,42 +17,46 @@ import java.time.temporal.ChronoUnit @Service class MatrixMessageService( - private val messageRepository: MatrixMessageRepository, - private val messageReceiverRepository: MatrixMessageReceiverRepository, - private val membershipService: MatrixMembershipService, - private val matrixClient: MatrixClient + private val messageRepository: MatrixMessageRepository, + private val messageReceiverRepository: MatrixMessageReceiverRepository, + private val membershipService: MatrixMembershipService, + private val userService: MatrixUserService, + private val matrixClient: MatrixClient ) { companion object { private val LOG = LoggerFactory.getLogger(this::class.java) } - suspend fun sendRoomMessage(message: MatrixMessage, requiredMembers: Set) { + suspend fun sendRoomMessage(message: MatrixMessage, requiredMembers: Set = setOf()) { val isNew = message.id == null if (Instant.now().isAfter(message.sendAfter)) { val roomId = message.roomId - val containsReceivers = membershipService.doesRoomContainsMembers(roomId, requiredMembers) - if (containsReceivers) { + val requiredMembersAndSender = + if (message.asUserId == null) requiredMembers + else setOf(*requiredMembers.toTypedArray(), message.asUserId) + val containsReceiversAndSender = membershipService.doesRoomContainsMembers(roomId, requiredMembersAndSender) + if (containsReceiversAndSender) { try { LOG.debug("send cached message to room $roomId and delete from db") matrixClient.roomsApi.sendRoomEvent( - roomId = roomId, - eventContent = if (message.isNotice) NoticeMessageEventContent(message.body) - else TextMessageEventContent(message.body), - asUserId = message.asUserId + roomId = roomId, + eventContent = if (message.isNotice) NoticeMessageEventContent(message.body) + else TextMessageEventContent(message.body), + asUserId = message.asUserId ) deleteMessage(message) } catch (error: Throwable) { LOG.debug( - "Could not send cached message to room $roomId. This happens e.g. when the bot was kicked " + - "out of the room, before the required receivers did join. Error: ${error.message}" + "Could not send cached message to room $roomId. This happens e.g. when the bot was kicked " + + "out of the room, before the required receivers did join. Error: ${error.message}" ) if (message.sendAfter.until(Instant.now(), ChronoUnit.DAYS) > 3) { LOG.warn( - "We have cached messages for the room $roomId, but sending the message " + - "didn't worked since 3 days. " + - "This usually should never happen! The message will now be deleted." + "We have cached messages for the room $roomId, but sending the message " + + "didn't worked since 3 days. " + + "This usually should never happen! The message will now be deleted." ) deleteMessage(message) // TODO directly notify user @@ -61,9 +66,9 @@ class MatrixMessageService( saveMessageAndReceivers(message.copy(sendAfter = Instant.now()), requiredMembers) } else if (message.sendAfter.until(Instant.now(), ChronoUnit.DAYS) > 3) { LOG.warn( - "We have cached messages for the room $roomId, but the required receivers " + - "${requiredMembers.joinToString()} didn't join since 3 days. " + - "This usually should never happen! The message will now be deleted." + "We have cached messages for the room $roomId, but the required receivers " + + "${requiredMembers.joinToString()} didn't join since 3 days. " + + "This usually should never happen! The message will now be deleted." ) deleteMessage(message) // TODO directly notify user @@ -76,10 +81,13 @@ class MatrixMessageService( } suspend fun saveMessageAndReceivers(message: MatrixMessage, requiredMembers: Set) { + if (message.asUserId != null) userService.getOrCreateUser(message.asUserId) val savedMessage = messageRepository.save(message) requiredMembers.forEach { - if (savedMessage.id != null) + if (savedMessage.id != null) { + userService.getOrCreateUser(it) messageReceiverRepository.save(MatrixMessageReceiver(savedMessage.id, it)) + } } } @@ -93,13 +101,13 @@ class MatrixMessageService( suspend fun processMessageQueue() { messageRepository.findAll() - .collect { message -> - if (message.id != null) { - val requiredReceivers = messageReceiverRepository.findByRoomMessageId(message.id) - .map { it.userId } - .toSet() - sendRoomMessage(message, requiredReceivers) - } + .collect { message -> + if (message.id != null) { + val requiredReceivers = messageReceiverRepository.findByRoomMessageId(message.id) + .map { it.userId } + .toSet() + sendRoomMessage(message, requiredReceivers) } + } } } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MessageQueueHandler.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MessageQueueHandler.kt index 5843da2..16ea097 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MessageQueueHandler.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/message/MessageQueueHandler.kt @@ -11,7 +11,8 @@ import org.springframework.stereotype.Component @Component @Profile("!initialsync") -class MessageQueueHandler(private val messageService: MatrixMessageService) : ApplicationListener { +class MessageQueueHandler(private val messageService: MatrixMessageService) : + ApplicationListener { companion object { private val LOG = LoggerFactory.getLogger(this::class.java) diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/PhoneNumberService.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/PhoneNumberService.kt index 89f6bc4..d35db3e 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/PhoneNumberService.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/PhoneNumberService.kt @@ -13,12 +13,12 @@ class PhoneNumberService(private val smsBridgeProperties: SmsBridgeProperties) { fun parseToInternationalNumber(raw: String): String { return phoneNumberUtil.parse(raw, smsBridgeProperties.defaultRegion) - .let { - if (!phoneNumberUtil.isValidNumber(it)) throw NumberParseException( - NOT_A_NUMBER, - "not a valid number" - ) - "+${it.countryCode}${it.nationalNumber}" - } + .let { + if (!phoneNumberUtil.isValidNumber(it)) throw NumberParseException( + NOT_A_NUMBER, + "not a valid number" + ) + "+${it.countryCode}${it.nationalNumber}" + } } } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessage.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessage.kt index bdcac2f..3084aa3 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessage.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessage.kt @@ -3,10 +3,10 @@ package net.folivo.matrix.bridge.sms.provider.android import com.fasterxml.jackson.annotation.JsonProperty data class AndroidInSmsMessage( - @JsonProperty("number") - val sender: String, - @JsonProperty("body") - val body: String, - @JsonProperty - val id: Int, + @JsonProperty("number") + val sender: String, + @JsonProperty("body") + val body: String, + @JsonProperty + val id: Int, ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessagesResponse.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessagesResponse.kt index e985cf9..2ea9b90 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessagesResponse.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidInSmsMessagesResponse.kt @@ -3,8 +3,8 @@ package net.folivo.matrix.bridge.sms.provider.android import com.fasterxml.jackson.annotation.JsonProperty data class AndroidInSmsMessagesResponse( - @JsonProperty("nextBatch") - val nextBatch: Int, - @JsonProperty("messages") - val messages: List + @JsonProperty("nextBatch") + val nextBatch: Int, + @JsonProperty("messages") + val messages: List ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessage.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessage.kt index 470332b..5cffe51 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessage.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessage.kt @@ -7,14 +7,14 @@ import org.springframework.data.relational.core.mapping.Table @Table("android_out_sms_message") data class AndroidOutSmsMessage( - @Column("receiver") - val receiver: String, - @Column("body") - val body: String, - @Id - @Column("id") - val id: Long? = null, - @Version - @Column("version") - var version: Int = 0 + @Column("receiver") + val receiver: String, + @Column("body") + val body: String, + @Id + @Column("id") + val id: Long? = null, + @Version + @Column("version") + var version: Int = 0 ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessageRequest.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessageRequest.kt index 567a46b..496c0db 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessageRequest.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidOutSmsMessageRequest.kt @@ -3,8 +3,8 @@ package net.folivo.matrix.bridge.sms.provider.android import com.fasterxml.jackson.annotation.JsonProperty data class AndroidOutSmsMessageRequest( - @JsonProperty("recipientPhoneNumber") - val receiver: String, - @JsonProperty("message") - val body: String + @JsonProperty("recipientPhoneNumber") + val receiver: String, + @JsonProperty("message") + val body: String ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProcessed.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProcessed.kt index d835d52..6c6f88a 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProcessed.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProcessed.kt @@ -7,12 +7,12 @@ import org.springframework.data.relational.core.mapping.Table @Table("android_sms_processed") data class AndroidSmsProcessed( - @Id - @Column("id") - val id: Long, - @Column("last_processed_id") - var lastProcessedId: Int, - @Version - @Column("version") - var version: Int = 0 + @Id + @Column("id") + val id: Long, + @Column("last_processed_id") + var lastProcessedId: Int, + @Version + @Column("version") + var version: Int = 0 ) \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProvider.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProvider.kt index 81cb0da..02e141e 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProvider.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProvider.kt @@ -15,13 +15,13 @@ import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.awaitBody class AndroidSmsProvider( - private val receiveSmsService: ReceiveSmsService, - private val phoneNumberService: PhoneNumberService, - private val processedRepository: AndroidSmsProcessedRepository, - private val outSmsMessageRepository: AndroidOutSmsMessageRepository, - private val webClient: WebClient, - private val matrixClient: MatrixClient, - private val smsBridgeProperties: SmsBridgeProperties + private val receiveSmsService: ReceiveSmsService, + private val phoneNumberService: PhoneNumberService, + private val processedRepository: AndroidSmsProcessedRepository, + private val outSmsMessageRepository: AndroidOutSmsMessageRepository, + private val webClient: WebClient, + private val matrixClient: MatrixClient, + private val smsBridgeProperties: SmsBridgeProperties ) : SmsProvider { companion object { @@ -39,12 +39,12 @@ class AndroidSmsProvider( outSmsMessageRepository.save(AndroidOutSmsMessage(receiver, body)) if (smsBridgeProperties.defaultRoomId != null) { matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - NoticeMessageEventContent( - smsBridgeProperties.templates.providerSendError - .replace("{error}", error.message ?: "unknown") - .replace("{receiver}", receiver) - ) + smsBridgeProperties.defaultRoomId, + NoticeMessageEventContent( + smsBridgeProperties.templates.providerSendError + .replace("{error}", error.message ?: "unknown") + .replace("{receiver}", receiver) + ) ) } } @@ -59,8 +59,8 @@ class AndroidSmsProvider( } if (smsBridgeProperties.defaultRoomId != null) { matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - NoticeMessageEventContent(smsBridgeProperties.templates.providerResendSuccess) + smsBridgeProperties.defaultRoomId, + NoticeMessageEventContent(smsBridgeProperties.templates.providerResendSuccess) ) } } @@ -69,7 +69,7 @@ class AndroidSmsProvider( private suspend fun sendOutSmsMessageRequest(message: AndroidOutSmsMessageRequest) { LOG.debug("start send out sms message via android") webClient.post().uri("/messages/out").bodyValue(message) - .retrieve().toBodilessEntity().awaitFirstOrNull() + .retrieve().toBodilessEntity().awaitFirstOrNull() LOG.debug("send out sms message via android was successful") } @@ -83,29 +83,29 @@ class AndroidSmsProvider( }.build() }.retrieve().awaitBody() response.messages - .sortedBy { it.id } - .fold(lastProcessed, { process, message -> - try { - receiveSmsService.receiveSms( - message.body, - phoneNumberService.parseToInternationalNumber(message.sender) - ) - } catch (error: NumberParseException) { - if (smsBridgeProperties.defaultRoomId != null) - matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - NoticeMessageEventContent( - smsBridgeProperties.templates.defaultRoomIncomingMessage - .replace("{sender}", message.sender) - .replace("{body}", message.body) - ) - ) - } - processedRepository.save( - process?.copy(lastProcessedId = message.id) - ?: AndroidSmsProcessed(1, message.id) + .sortedBy { it.id } + .fold(lastProcessed, { process, message -> + try { + receiveSmsService.receiveSms( + message.body, + phoneNumberService.parseToInternationalNumber(message.sender) ) - }) + } catch (error: NumberParseException) { + if (smsBridgeProperties.defaultRoomId != null) + matrixClient.roomsApi.sendRoomEvent( + smsBridgeProperties.defaultRoomId, + NoticeMessageEventContent( + smsBridgeProperties.templates.defaultRoomIncomingMessage + .replace("{sender}", message.sender) + .replace("{body}", message.body) + ) + ) + } + processedRepository.save( + process?.copy(lastProcessedId = message.id) + ?: AndroidSmsProcessed(1, message.id) + ) + }) LOG.debug("processed new messages") } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderConfiguration.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderConfiguration.kt index 03dfe47..fa4aca9 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderConfiguration.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderConfiguration.kt @@ -35,38 +35,38 @@ class AndroidSmsProviderConfiguration(private val properties: AndroidSmsProvider @Bean("androidSmsProviderWebClient") fun androidSmsProviderWebClient(webClientBuilder: WebClient.Builder): WebClient { val builder = webClientBuilder - .baseUrl(properties.baseUrl) - .defaultHeader( - HttpHeaders.AUTHORIZATION, - "Basic " + Base64.getEncoder() - .encodeToString("${properties.username}:${properties.password}".toByteArray()) - ) - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .filter(ExchangeFilterFunction.ofResponseProcessor { clientResponse: ClientResponse -> - val statusCode = clientResponse.statusCode() - if (clientResponse.statusCode().isError) { - clientResponse.bodyToMono(String::class.java) - .flatMap { - Mono.error(AndroidSmsProviderException(it, statusCode)) - } - } else { - Mono.just(clientResponse) - } - }) + .baseUrl(properties.baseUrl) + .defaultHeader( + HttpHeaders.AUTHORIZATION, + "Basic " + Base64.getEncoder() + .encodeToString("${properties.username}:${properties.password}".toByteArray()) + ) + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .filter(ExchangeFilterFunction.ofResponseProcessor { clientResponse: ClientResponse -> + val statusCode = clientResponse.statusCode() + if (clientResponse.statusCode().isError) { + clientResponse.bodyToMono(String::class.java) + .flatMap { + Mono.error(AndroidSmsProviderException(it, statusCode)) + } + } else { + Mono.just(clientResponse) + } + }) val trustStoreProps = properties.trustStore if (trustStoreProps != null) { val keyStore = KeyStore.getInstance(trustStoreProps.type) keyStore.load( - Files.newInputStream(Path.of(trustStoreProps.path)), - trustStoreProps.password.toCharArray() + Files.newInputStream(Path.of(trustStoreProps.path)), + trustStoreProps.password.toCharArray() ) val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) factory.init(keyStore) val sslContext = SslContextBuilder.forClient() - .trustManager(factory) - .build() + .trustManager(factory) + .build() val client = HttpClient.create().secure { spec -> spec.sslContext(sslContext) } builder.clientConnector(ReactorClientHttpConnector(client)) } @@ -76,31 +76,31 @@ class AndroidSmsProviderConfiguration(private val properties: AndroidSmsProvider @Bean fun androidSmsProvider( - receiveSmsService: ReceiveSmsService, - phoneNumberService: PhoneNumberService, - processedRepository: AndroidSmsProcessedRepository, - outSmsMessageRepository: AndroidOutSmsMessageRepository, - @Qualifier("androidSmsProviderWebClient") - webClient: WebClient, - matrixClient: MatrixClient, - smsBridgeProperties: SmsBridgeProperties + receiveSmsService: ReceiveSmsService, + phoneNumberService: PhoneNumberService, + processedRepository: AndroidSmsProcessedRepository, + outSmsMessageRepository: AndroidOutSmsMessageRepository, + @Qualifier("androidSmsProviderWebClient") + webClient: WebClient, + matrixClient: MatrixClient, + smsBridgeProperties: SmsBridgeProperties ): AndroidSmsProvider { return AndroidSmsProvider( - receiveSmsService, - phoneNumberService, - processedRepository, - outSmsMessageRepository, - webClient, - matrixClient, - smsBridgeProperties + receiveSmsService, + phoneNumberService, + processedRepository, + outSmsMessageRepository, + webClient, + matrixClient, + smsBridgeProperties ) } @Bean fun smsProviderLauncher( - androidSmsProvider: AndroidSmsProvider, - smsBridgeProperties: SmsBridgeProperties, - matrixClient: MatrixClient + androidSmsProvider: AndroidSmsProvider, + smsBridgeProperties: SmsBridgeProperties, + matrixClient: MatrixClient ): AndroidSmsProviderLauncher { return AndroidSmsProviderLauncher(androidSmsProvider, smsBridgeProperties, matrixClient) } diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncher.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncher.kt index 0fd0775..04f37b6 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncher.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncher.kt @@ -17,9 +17,9 @@ import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.context.event.EventListener class AndroidSmsProviderLauncher( - private val androidSmsProvider: AndroidSmsProvider, - private val smsBridgeProperties: SmsBridgeProperties, - private val matrixClient: MatrixClient + private val androidSmsProvider: AndroidSmsProvider, + private val smsBridgeProperties: SmsBridgeProperties, + private val matrixClient: MatrixClient ) { companion object { @@ -57,11 +57,11 @@ class AndroidSmsProviderLauncher( try { if (smsBridgeProperties.defaultRoomId != null) matrixClient.roomsApi.sendRoomEvent( - smsBridgeProperties.defaultRoomId, - NoticeMessageEventContent( - smsBridgeProperties.templates.providerReceiveError - .replace("{error}", reason.message ?: "unknown") - ) + smsBridgeProperties.defaultRoomId, + NoticeMessageEventContent( + smsBridgeProperties.templates.providerReceiveError + .replace("{error}", reason.message ?: "unknown") + ) ) } catch (error: Throwable) { LOG.error("could not warn user in default room: ${error.message}") diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderProperties.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderProperties.kt index d36e5eb..e7f2ec2 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderProperties.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderProperties.kt @@ -6,15 +6,15 @@ import org.springframework.boot.context.properties.ConstructorBinding @ConfigurationProperties("matrix.bridge.sms.provider.android") @ConstructorBinding data class AndroidSmsProviderProperties( - val enabled: Boolean = false, - val baseUrl: String, - val username: String, - val password: String, - val trustStore: TrustStore? = null + val enabled: Boolean = false, + val baseUrl: String, + val username: String, + val password: String, + val trustStore: TrustStore? = null ) { data class TrustStore( - val path: String, - val password: String, - val type: String + val path: String, + val password: String, + val type: String ) } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProvider.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProvider.kt index 94f48de..ecf96c7 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProvider.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProvider.kt @@ -31,9 +31,9 @@ import kotlin.text.Charsets.UTF_8 @ConditionalOnProperty(prefix = "matrix.bridge.sms.provider.gammu", name = ["enabled"], havingValue = "true") @EnableConfigurationProperties(GammuSmsProviderProperties::class) class GammuSmsProvider( - private val properties: GammuSmsProviderProperties, - private val receiveSmsService: ReceiveSmsService, - private val phoneNumberService: PhoneNumberService + private val properties: GammuSmsProviderProperties, + private val receiveSmsService: ReceiveSmsService, + private val phoneNumberService: PhoneNumberService ) : SmsProvider { companion object { @@ -49,71 +49,71 @@ class GammuSmsProvider( @EventListener(ApplicationReadyEvent::class) fun startNewMessageLookupLoop() { disposable = Mono.just(true) // TODO is there a less hacky way? Without that line, repeat does not work - .flatMapMany { Flux.fromStream(Files.list(Path.of(properties.inboxPath))) } - .map { it.toFile() } - .flatMap { file -> - val name = file.name - val sender = name.substringBeforeLast('_').substringAfterLast('_') - Flux.fromStream(Files.lines(file.toPath(), UTF_8)) - .skipUntil { it.startsWith("[SMSBackup000]") } - .filter { it.startsWith("; ") } - .map { it.removePrefix("; ") } - .collectList() - .map { Pair(sender, it.joinToString(separator = "")) } - .doOnSuccess { - Files.move( - file.toPath(), - Path.of(properties.inboxProcessedPath, file.name), - StandardCopyOption.REPLACE_EXISTING - ) - } - }.flatMap { message -> - receiveSms(message.first, message.second) - } - .doOnComplete { LOG.debug("read inbox") } - .doOnError { LOG.error("something happened while scanning directories for new sms", it) } - .delaySubscription(Duration.ofSeconds(10)) - .repeat() - .retry() - .subscribe() + .flatMapMany { Flux.fromStream(Files.list(Path.of(properties.inboxPath))) } + .map { it.toFile() } + .flatMap { file -> + val name = file.name + val sender = name.substringBeforeLast('_').substringAfterLast('_') + Flux.fromStream(Files.lines(file.toPath(), UTF_8)) + .skipUntil { it.startsWith("[SMSBackup000]") } + .filter { it.startsWith("; ") } + .map { it.removePrefix("; ") } + .collectList() + .map { Pair(sender, it.joinToString(separator = "")) } + .doOnSuccess { + Files.move( + file.toPath(), + Path.of(properties.inboxProcessedPath, file.name), + StandardCopyOption.REPLACE_EXISTING + ) + } + }.flatMap { message -> + receiveSms(message.first, message.second) + } + .doOnComplete { LOG.debug("read inbox") } + .doOnError { LOG.error("something happened while scanning directories for new sms", it) } + .delaySubscription(Duration.ofSeconds(10)) + .repeat() + .retry() + .subscribe() } override suspend fun sendSms(receiver: String, body: String) { var exitCode: Int val output = try { ProcessBuilder( - listOf( - "gammu-smsd-inject", - "TEXT", - receiver, - "-len", - body.length.toString(), - "-unicode", // TODO maybe don't sent everything in unicode (it allows more characters per sms) - "-text", - body - ) + listOf( + "gammu-smsd-inject", + "TEXT", + receiver, + "-len", + body.length.toString(), + "-unicode", // TODO maybe don't sent everything in unicode (it allows more characters per sms) + "-text", + body + ) ).directory(File(".")) - .redirectOutput(ProcessBuilder.Redirect.PIPE) - .redirectError(ProcessBuilder.Redirect.PIPE) - .start().apply { - waitFor(10, TimeUnit.SECONDS) - exitCode = exitValue() - } - .inputStream.bufferedReader().readText() + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start().apply { + waitFor(10, TimeUnit.SECONDS) + exitCode = exitValue() + } + .inputStream.bufferedReader().readText() } catch (error: Throwable) { LOG.error("some unhandled exception occurred during running send sms shell command", error) throw MatrixServerException( - INTERNAL_SERVER_ERROR, - ErrorResponse("NET.FOLIVO_UNKNOWN", error.message) + INTERNAL_SERVER_ERROR, + ErrorResponse("NET.FOLIVO_UNKNOWN", error.message) ) } if (exitCode != 0) { throw MatrixServerException( - INTERNAL_SERVER_ERROR, - ErrorResponse( - "NET.FOLIVO_INTERNAL_SERVER_ERROR", - "exitCode was $exitCode due to $output" - ) + INTERNAL_SERVER_ERROR, + ErrorResponse( + "NET.FOLIVO_INTERNAL_SERVER_ERROR", + "exitCode was $exitCode due to $output" + ) ) } else { LOG.debug(output) @@ -123,13 +123,13 @@ class GammuSmsProvider( } fun receiveSms( - sender: String, - body: String + sender: String, + body: String ): Mono { return mono { val phoneNumber = phoneNumberService.parseToInternationalNumber(sender) receiveSmsService.receiveSms(body = body, sender = phoneNumber) - ?.also { sendSms(receiver = phoneNumber, body = it) } + ?.also { sendSms(receiver = phoneNumber, body = it) } }.then() } } \ No newline at end of file diff --git a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProviderProperties.kt b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProviderProperties.kt index aa1b062..15e0158 100644 --- a/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProviderProperties.kt +++ b/src/main/kotlin/net/folivo/matrix/bridge/sms/provider/gammu/GammuSmsProviderProperties.kt @@ -6,7 +6,7 @@ import org.springframework.boot.context.properties.ConstructorBinding @ConfigurationProperties("matrix.bridge.sms.provider.gammu") @ConstructorBinding data class GammuSmsProviderProperties( - val enabled: Boolean = false, - val inboxPath: String = "/data/spool/inbox", - val inboxProcessedPath: String = "/data/spool/inbox_processed" + val enabled: Boolean = false, + val inboxPath: String = "/data/spool/inbox", + val inboxProcessedPath: String = "/data/spool/inbox_processed" ) \ No newline at end of file diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomServiceTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomServiceTest.kt index 9d3c66f..f61cff8 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomServiceTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixAppserviceRoomServiceTest.kt @@ -49,13 +49,13 @@ private fun testBody(): DescribeSpec.() -> Unit { result.powerLevelContentOverride?.kick.shouldBe(0) result.powerLevelContentOverride?.events.shouldNotBeNull() result.powerLevelContentOverride?.events?.shouldContainExactly( - mapOf("m.room.name" to 0, "m.room.topic" to 0) + mapOf("m.room.name" to 0, "m.room.topic" to 0) ) result.powerLevelContentOverride?.users.shouldBe( - mapOf( - botUserId to 100, - userId to 100 - ) + mapOf( + botUserId to 100, + userId to 100 + ) ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeServiceTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeServiceTest.kt index 3079066..dbf59b6 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeServiceTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/appservice/SmsMatrixMembershipChangeServiceTest.kt @@ -22,31 +22,31 @@ private fun testBody(): DescribeSpec.() -> Unit { } val cut = SmsMatrixMembershipChangeService( - roomServiceMock, - mockk(), - mockk(), - mockk(), - mockk(), - botPropertiesMock + roomServiceMock, + mockk(), + mockk(), + mockk(), + mockk(), + botPropertiesMock ) val roomId = RoomId("room", "server") describe(SmsMatrixMembershipChangeService::shouldJoinRoom.name) { it("user is bot") { cut.shouldJoinRoom(UserId("bot", "server"), roomId) - .shouldBeTrue() + .shouldBeTrue() } it("alias is that from user") { coEvery { roomServiceMock.getRoomAliasByRoomId(roomId) } - .returns(MatrixRoomAlias(RoomAliasId("sms_111111", "server"), roomId)) + .returns(MatrixRoomAlias(RoomAliasId("sms_111111", "server"), roomId)) cut.shouldJoinRoom(UserId("sms_111111", "server"), roomId) - .shouldBeTrue() + .shouldBeTrue() } it("alias is not that from user") { coEvery { roomServiceMock.getRoomAliasByRoomId(roomId) } - .returns(MatrixRoomAlias(RoomAliasId("sms_222222", "server"), roomId)) + .returns(MatrixRoomAlias(RoomAliasId("sms_222222", "server"), roomId)) cut.shouldJoinRoom(UserId("sms_111111", "server"), roomId) - .shouldBeFalse() + .shouldBeFalse() } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandlerTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandlerTest.kt index e22a0b3..6c15f42 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandlerTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToBotHandlerTest.kt @@ -29,13 +29,13 @@ private fun testBody(): DescribeSpec.() -> Unit { val membershipServiceMock: MatrixMembershipService = mockk() val cut = MessageToBotHandler( - smsSendCommandHandlerMock, - smsInviteCommandHandlerMock, - smsAbortCommandHandlerMock, - phoneNumberServiceMock, - smsBridgePropertiesMock, - userServiceMock, - membershipServiceMock + smsSendCommandHandlerMock, + smsInviteCommandHandlerMock, + smsAbortCommandHandlerMock, + phoneNumberServiceMock, + smsBridgePropertiesMock, + userServiceMock, + membershipServiceMock ) val contextMock: MessageContext = mockk() @@ -73,12 +73,12 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should accept sms abort command") { coEvery { smsAbortCommandHandlerMock.handleCommand(any()) } - .returns("aborted") + .returns("aborted") cut.handleMessage( - roomId, - "sms abort", - senderId, - contextMock + roomId, + "sms abort", + senderId, + contextMock ).shouldBeTrue() coVerify(exactly = 1) { @@ -93,14 +93,14 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should run sms send command") { coEvery { smsSendCommandHandlerMock.handleCommand(any(), any(), any(), any(), any(), any(), any()) } - .returns("message send") + .returns("message send") every { smsBridgePropertiesMock.defaultRegion }.returns("DE") every { phoneNumberServiceMock.parseToInternationalNumber(any()) }.returns("+4917392837462") cut.handleMessage( - roomId, - "sms send -t 017392837462 'some Text'", - senderId, - contextMock + roomId, + "sms send -t 017392837462 'some Text'", + senderId, + contextMock ).shouldBeTrue() coVerify(exactly = 1) { @@ -109,12 +109,12 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should run sms invite command") { coEvery { smsInviteCommandHandlerMock.handleCommand(any(), any()) } - .returns("invited") + .returns("invited") cut.handleMessage( - roomId, - "sms invite #sms_1739283746:server", - senderId, - contextMock + roomId, + "sms invite #sms_1739283746:server", + senderId, + contextMock ).shouldBeTrue() coVerify(exactly = 1) { @@ -150,12 +150,12 @@ private fun testBody(): DescribeSpec.() -> Unit { afterTest { clearMocks( - smsSendCommandHandlerMock, - smsInviteCommandHandlerMock, - phoneNumberServiceMock, - userServiceMock, - membershipServiceMock, - contextMock + smsSendCommandHandlerMock, + smsInviteCommandHandlerMock, + phoneNumberServiceMock, + userServiceMock, + membershipServiceMock, + contextMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandlerTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandlerTest.kt index c8a6339..4da8817 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandlerTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/MessageToSmsHandlerTest.kt @@ -35,12 +35,12 @@ private fun testBody(): DescribeSpec.() -> Unit { val mappingServiceMock: MatrixSmsMappingService = mockk() val cut = MessageToSmsHandler( - botPropertiesMock, - smsBridgePropertiesMock, - smsProviderMock, - roomServiceMock, - userServiceMock, - mappingServiceMock + botPropertiesMock, + smsBridgePropertiesMock, + smsProviderMock, + roomServiceMock, + userServiceMock, + mappingServiceMock ) val contextMock: MessageContext = mockk() @@ -57,17 +57,17 @@ private fun testBody(): DescribeSpec.() -> Unit { val userId2 = UserId("sms_22222", "server") beforeTest { coEvery { userServiceMock.getUsersByRoom(roomId) }.returns( - flowOf( - MatrixUser(botUserId, true), - MatrixUser(senderId, false), - MatrixUser(userId1, true), - MatrixUser(userId2, true) - ) + flowOf( + MatrixUser(botUserId, true), + MatrixUser(senderId, false), + MatrixUser(userId1, true), + MatrixUser(userId2, true) + ) ) coEvery { mappingServiceMock.getOrCreateMapping(userId1, roomId) } - .returns(MatrixSmsMapping("memId", 2)) + .returns(MatrixSmsMapping("memId", 2)) coEvery { mappingServiceMock.getOrCreateMapping(userId2, roomId) } - .returns(MatrixSmsMapping("memId", 3)) + .returns(MatrixSmsMapping("memId", 3)) } describe("mapping without token is allowed") { beforeTest { @@ -75,7 +75,7 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should ignore token when room is managed") { coEvery { roomServiceMock.getOrCreateRoom(roomId) } - .returns(MatrixRoom(roomId, true)) + .returns(MatrixRoom(roomId, true)) cut.handleMessage(roomId, "body", senderId, contextMock, true) coVerify { smsProviderMock.sendSms("+11111", "@sender:server wrote body") @@ -84,9 +84,9 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should ignore token when room is the only room") { coEvery { roomServiceMock.getOrCreateRoom(roomId) } - .returns(MatrixRoom(roomId, false)) + .returns(MatrixRoom(roomId, false)) coEvery { roomServiceMock.getRoomsByMembers(any()) } - .returns(flowOf(mockk())) + .returns(flowOf(mockk())) cut.handleMessage(roomId, "body", senderId, contextMock, true) coVerifyAll { smsProviderMock.sendSms("+11111", "@sender:server wrote body") @@ -95,11 +95,11 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should not ignore token when room is not managed and not the only room") { coEvery { roomServiceMock.getOrCreateRoom(roomId) } - .returns(MatrixRoom(roomId, false)) + .returns(MatrixRoom(roomId, false)) coEvery { roomServiceMock.getRoomsByMembers(any()) } - .returnsMany(flowOf(mockk(), mockk()), flowOf(mockk())) + .returnsMany(flowOf(mockk(), mockk()), flowOf(mockk())) coEvery { mappingServiceMock.getOrCreateMapping(any(), roomId).mappingToken } - .returns(2) + .returns(2) cut.handleMessage(roomId, "body", senderId, contextMock, true) coVerifyAll { smsProviderMock.sendSms("+11111", "@sender:server wrote body with #2") @@ -111,11 +111,11 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { smsBridgePropertiesMock.allowMappingWithoutToken }.returns(false) coEvery { roomServiceMock.getOrCreateRoom(roomId) } - .returns(MatrixRoom(roomId, false)) + .returns(MatrixRoom(roomId, false)) coEvery { roomServiceMock.getRoomsByMembers(any()) } - .returns(flowOf(mockk(), mockk())) + .returns(flowOf(mockk(), mockk())) coEvery { mappingServiceMock.getOrCreateMapping(any(), roomId).mappingToken } - .returns(2) + .returns(2) } it("should send sms") { cut.handleMessage(roomId, "body", senderId, contextMock, true) @@ -142,7 +142,7 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { smsBridgePropertiesMock.allowMappingWithoutToken }.returns(true) coEvery { roomServiceMock.getOrCreateRoom(roomId) } - .returns(MatrixRoom(roomId, true)) + .returns(MatrixRoom(roomId, true)) } it("when send sms fails") { coEvery { smsProviderMock.sendSms("+11111", any()) }.throws(RuntimeException("reason")) @@ -163,11 +163,11 @@ private fun testBody(): DescribeSpec.() -> Unit { } afterTest { clearMocks( - roomServiceMock, - userServiceMock, - smsProviderMock, - mappingServiceMock, - contextMock + roomServiceMock, + userServiceMock, + smsProviderMock, + mappingServiceMock, + contextMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsServiceTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsServiceTest.kt index 1f30080..f703d03 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsServiceTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/ReceiveSmsServiceTest.kt @@ -32,19 +32,19 @@ private fun testBody(): DescribeSpec.() -> Unit { every { templates.answerInvalidTokenWithoutDefaultRoom } returns "invalid token without default room" } val cut = ReceiveSmsService( - matrixClientMock, - mappingServiceMock, - messageServiceMock, - membershipServiceMock, - roomServiceMock, - matrixBotPropertiesMock, - smsBridgePropertiesMock + matrixClientMock, + mappingServiceMock, + messageServiceMock, + membershipServiceMock, + roomServiceMock, + matrixBotPropertiesMock, + smsBridgePropertiesMock ) beforeTest { every { matrixBotPropertiesMock.serverName } returns "server" coEvery { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) } - .returns(EventId("event", "server")) + .returns(EventId("event", "server")) coEvery { messageServiceMock.sendRoomMessage(any(), any()) } just Runs } @@ -56,10 +56,10 @@ private fun testBody(): DescribeSpec.() -> Unit { cut.receiveSms("message #3", "+111111").shouldBeNull() coVerify { matrixClientMock.roomsApi.sendRoomEvent( - roomId, - match { it.body == "message" }, - txnId = any(), - asUserId = UserId("sms_111111", "server") + roomId, + match { it.body == "message" }, + txnId = any(), + asUserId = UserId("sms_111111", "server") ) } } @@ -78,7 +78,7 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { coEvery { membershipServiceMock.hasRoomOnlyManagedUsersLeft(any()) }.returns(false) coEvery { roomServiceMock.getRoomAlias(roomAliasId)?.roomId } - .returns(null) + .returns(null) coEvery { matrixClientMock.roomsApi.getRoomAlias(roomAliasId).roomId }.returns(roomId) } it("should try create alias by using client-server-api") { @@ -92,12 +92,12 @@ private fun testBody(): DescribeSpec.() -> Unit { cut.receiveSms("body #123", "+111111").shouldBeNull() coVerify { messageServiceMock.sendRoomMessage( - match { - it.roomId == roomId - && it.body == "body" - && it.isNotice == false - && it.asUserId == UserId("sms_111111", "server") - }, setOf(UserId("sms_111111", "server")) + match { + it.roomId == roomId + && it.body == "body" + && it.isNotice == false + && it.asUserId == UserId("sms_111111", "server") + } ) } } @@ -107,15 +107,15 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("default room given") { beforeTest { coEvery { smsBridgePropertiesMock.defaultRoomId } - .returns(RoomId("default", "room")) + .returns(RoomId("default", "room")) } it("should send notification to default room") { cut.receiveSms("body #123", "+111111").shouldBe(null) coVerify { matrixClientMock.roomsApi.sendRoomEvent( - RoomId("default", "room"), - match { it.body == "+111111 wrote in #sms_111111:server" }, - txnId = any() + RoomId("default", "room"), + match { it.body == "+111111 wrote in #sms_111111:server" }, + txnId = any() ) } } @@ -141,9 +141,9 @@ private fun testBody(): DescribeSpec.() -> Unit { cut.receiveSms("body #123", "+111111").shouldBe("invalid token with default room") coVerify { matrixClientMock.roomsApi.sendRoomEvent( - RoomId("default", "room"), - match { it.body == "+111111 wrote body" }, - txnId = any() + RoomId("default", "room"), + match { it.body == "+111111 wrote body" }, + txnId = any() ) } } @@ -170,12 +170,12 @@ private fun testBody(): DescribeSpec.() -> Unit { } afterTest { clearMocks( - matrixClientMock, - mappingServiceMock, - messageServiceMock, - membershipServiceMock, - roomServiceMock, - smsBridgePropertiesMock + matrixClientMock, + mappingServiceMock, + messageServiceMock, + membershipServiceMock, + roomServiceMock, + smsBridgePropertiesMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandTest.kt index 969b107..3988dc2 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsAbortCommandTest.kt @@ -27,7 +27,7 @@ private fun testBody(): DescribeSpec.() -> Unit { coVerify { consoleMock.print("answer", false) } } } - + afterTest { clearMocks(consoleMock) } } } \ No newline at end of file diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandlerTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandlerTest.kt index fdebadb..fe68517 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandlerTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsMessageHandlerTest.kt @@ -26,11 +26,11 @@ private fun testBody(): DescribeSpec.() -> Unit { } val cut = SmsMessageHandler( - messageToSmsHandlerMock, - messageToBotHandlerMock, - membershipServiceMock, - botPropertiesMock, - smsBridgePropertiesMock + messageToSmsHandlerMock, + messageToBotHandlerMock, + membershipServiceMock, + botPropertiesMock, + smsBridgePropertiesMock ) val senderId = UserId("sender", "server") @@ -114,9 +114,9 @@ private fun testBody(): DescribeSpec.() -> Unit { afterTest { clearMocks( - messageToSmsHandlerMock, - messageToBotHandlerMock, - membershipServiceMock + messageToSmsHandlerMock, + messageToBotHandlerMock, + membershipServiceMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandlerTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandlerTest.kt index 5906adf..02df945 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandlerTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandHandlerTest.kt @@ -55,16 +55,16 @@ private fun testBody(): DescribeSpec.() -> Unit { } val cut = spyk( - SmsSendCommandHandler( - userServiceMock, - roomServiceMock, - membershipServiceMock, - messageServiceMock, - appserviceHandlerHelperMock, - matrixClientMock, - botPropertiesMock, - smsBridgePropertiesMock - ) + SmsSendCommandHandler( + userServiceMock, + roomServiceMock, + membershipServiceMock, + messageServiceMock, + appserviceHandlerHelperMock, + matrixClientMock, + botPropertiesMock, + smsBridgePropertiesMock + ) ) val senderId = UserId("sender", "server") @@ -87,11 +87,11 @@ private fun testBody(): DescribeSpec.() -> Unit { describe(SmsSendCommandHandler::handleCommand.name) { beforeTest { coEvery { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) } - .returns("alias {receiverNumbers}") + .returns("alias {receiverNumbers}") coEvery { cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) } - .returns("create {receiverNumbers}") + .returns("create {receiverNumbers}") coEvery { cut.sendMessageToRoom(any(), any(), any(), any(), any(), any()) } - .returns("send {receiverNumbers}") + .returns("send {receiverNumbers}") } describe("room creation mode is $AUTO") { describe("single mode is enabled and only one receiver") { @@ -101,15 +101,15 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should send message to room alias") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, AUTO) - .shouldBe("alias $tel1") + .shouldBe("alias $tel1") coVerify { cut.sendMessageToRoomAlias( - senderId, - "body", - "room name", - userId1, - setOf(), - sendAfter + senderId, + "body", + "room name", + userId1, + setOf(), + sendAfter ) } } @@ -122,19 +122,19 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf()) } it("should create room and send message") { cut.handleCommand( - "body", - senderId, - setOf(tel1, tel2), - setOf(), - "room name", - sendAfter, - AUTO + "body", + senderId, + setOf(tel1, tel2), + setOf(), + "room name", + sendAfter, + AUTO ) - .shouldBe("create $tel1, $tel2") + .shouldBe("create $tel1, $tel2") coVerify { cut.createRoomAndSendMessage( - "body", senderId, "room name", - setOf(userId1, userId2), setOf(), sendAfter + "body", senderId, "room name", + setOf(userId1, userId2), setOf(), sendAfter ) } } @@ -142,24 +142,24 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("one matching room found") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) } + mockk { every { id }.returns(roomId) } )) } it("should send message to room") { cut.handleCommand( - "body", - senderId, - setOf(tel1, tel2), - setOf(), - "room name", - sendAfter, - AUTO + "body", + senderId, + setOf(tel1, tel2), + setOf(), + "room name", + sendAfter, + AUTO ) - .shouldBe("send $tel1, $tel2") + .shouldBe("send $tel1, $tel2") coVerify { cut.sendMessageToRoom( - roomId, senderId, "body", - setOf(userId1, userId2), sendAfter + roomId, senderId, "body", + setOf(userId1, userId2), sendAfter ) } } @@ -167,21 +167,21 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("more then one matching room found") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) }, - mockk { every { id }.returns(RoomId("room2", "server")) } + mockk { every { id }.returns(roomId) }, + mockk { every { id }.returns(RoomId("room2", "server")) } )) } it("should do nothing") { cut.handleCommand( - "body", - senderId, - setOf(tel1, tel2), - setOf(), - "room name", - sendAfter, - AUTO + "body", + senderId, + setOf(tel1, tel2), + setOf(), + "room name", + sendAfter, + AUTO ) - .shouldBe("too many rooms $tel1, $tel2") + .shouldBe("too many rooms $tel1, $tel2") coVerify(exactly = 0) { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) @@ -194,16 +194,16 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("room creation mode is $ALWAYS") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) } + mockk { every { id }.returns(roomId) } )) } it("should create room and send message") { cut.handleCommand("body", senderId, setOf(tel1, tel2), setOf(), "room name", sendAfter, ALWAYS) - .shouldBe("create $tel1, $tel2") + .shouldBe("create $tel1, $tel2") coVerify { cut.createRoomAndSendMessage( - "body", senderId, "room name", - setOf(userId1, userId2), setOf(), sendAfter + "body", senderId, "room name", + setOf(userId1, userId2), setOf(), sendAfter ) } } @@ -211,7 +211,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("room creation mode is $SINGLE") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) } + mockk { every { id }.returns(roomId) } )) } describe("single mode is enabled and only one receiver") { @@ -219,15 +219,15 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("one receiver given") { it("should send message to room alias") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, SINGLE) - .shouldBe("alias $tel1") + .shouldBe("alias $tel1") coVerify { cut.sendMessageToRoomAlias( - senderId, - "body", - "room name", - userId1, - setOf(), - sendAfter + senderId, + "body", + "room name", + userId1, + setOf(), + sendAfter ) } } @@ -235,15 +235,15 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("more then one receiver given") { it("should do nothing") { cut.handleCommand( - "body", - senderId, - setOf(tel1, tel2), - setOf(), - "room name", - sendAfter, - SINGLE + "body", + senderId, + setOf(tel1, tel2), + setOf(), + "room name", + sendAfter, + SINGLE ) - .shouldBe("too many numbers $tel1, $tel2") + .shouldBe("too many numbers $tel1, $tel2") coVerify(exactly = 0) { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) @@ -256,7 +256,7 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { smsBridgePropertiesMock.singleModeEnabled }.returns(false) } it("should do nothing") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, SINGLE) - .shouldBe("single disabled $tel1") + .shouldBe("single disabled $tel1") coVerify(exactly = 0) { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) @@ -270,7 +270,7 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf()) } it("should do nothing") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, NO) - .shouldBe("disabled room creation $tel1") + .shouldBe("disabled room creation $tel1") coVerify(exactly = 0) { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) @@ -281,12 +281,12 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("one matching room found") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) } + mockk { every { id }.returns(roomId) } )) } it("should send message to room") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, NO) - .shouldBe("send $tel1") + .shouldBe("send $tel1") coVerify { cut.sendMessageToRoom(roomId, senderId, "body", setOf(userId1), sendAfter) } @@ -295,13 +295,13 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("more then one matching room found") { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf( - mockk { every { id }.returns(roomId) }, - mockk { every { id }.returns(RoomId("room2", "server")) } + mockk { every { id }.returns(roomId) }, + mockk { every { id }.returns(RoomId("room2", "server")) } )) } it("should do nothing") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, NO) - .shouldBe("too many rooms $tel1") + .shouldBe("too many rooms $tel1") coVerify(exactly = 0) { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) cut.createRoomAndSendMessage(any(), any(), any(), any(), any(), any()) @@ -316,23 +316,23 @@ private fun testBody(): DescribeSpec.() -> Unit { val roomAliasId = RoomAliasId("sms_111111", "server") beforeTest { coEvery { cut.sendMessageToRoom(any(), any(), any(), any(), any(), any()) } - .returns("send") + .returns("send") } describe("room alias does exist") { beforeTest { coEvery { roomServiceMock.getRoomAlias(roomAliasId)?.roomId } - .returns(roomId) + .returns(roomId) } describe("room name given") { beforeTest { coEvery { membershipServiceMock - .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) + .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) }.returns(true) } it("should set room name when currently not set") { coEvery { matrixClientMock.roomsApi.getStateEvent(roomId) } - .throws(MatrixServerException(NOT_FOUND, ErrorResponse("not found"))) + .throws(MatrixServerException(NOT_FOUND, ErrorResponse("not found"))) cut.sendMessageToRoomAlias(senderId, null, "room name", userId1, setOf(), null) coVerify { matrixClientMock.roomsApi.sendStateEvent(roomId, NameEventContent("room name")) @@ -340,7 +340,7 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should set room name when empty") { coEvery { matrixClientMock.roomsApi.getStateEvent(roomId) } - .returns(NameEventContent("")) + .returns(NameEventContent("")) cut.sendMessageToRoomAlias(senderId, null, "room name", userId1, setOf(), null) coVerify { matrixClientMock.roomsApi.sendStateEvent(roomId, NameEventContent("room name")) @@ -348,7 +348,7 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should not set room name when already set") { coEvery { matrixClientMock.roomsApi.getStateEvent(roomId) } - .returns(NameEventContent("existing name")) + .returns(NameEventContent("existing name")) cut.sendMessageToRoomAlias(senderId, null, "room name", userId1, setOf(), null) val roomsApi = matrixClientMock.roomsApi coVerify(exactly = 0) { @@ -366,21 +366,21 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { coEvery { membershipServiceMock - .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) + .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) }.returns(true) } it("should send message to room alias") { coEvery { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf()) cut.sendMessageToRoomAlias(senderId, "body", null, userId1, setOf(), sendAfter) - .shouldBe("send") + .shouldBe("send") coVerify { cut.sendMessageToRoom( - roomId, - senderId, - "body", - setOf(userId1), - sendAfter, - true + roomId, + senderId, + "body", + setOf(userId1), + sendAfter, + true ) } } @@ -389,26 +389,26 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { coEvery { membershipServiceMock - .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) + .doesRoomContainsMembers(roomId, match { it.containsAll(setOf(senderId)) }) }.returns(false) } it("should invite user and send message to room alias") { coEvery { roomServiceMock - .getRoomsByMembers(match { it.containsAll(setOf(userId1, senderId)) }) + .getRoomsByMembers(match { it.containsAll(setOf(userId1, senderId)) }) }.returns(flowOf()) cut.sendMessageToRoomAlias(senderId, "body", null, userId1, setOf(), sendAfter) - .shouldBe("send") + .shouldBe("send") coVerify { matrixClientMock.roomsApi.inviteUser(roomId, senderId) cut.sendMessageToRoom( - roomId, - senderId, - "body", - setOf(userId1), - sendAfter, - true + roomId, + senderId, + "body", + setOf(userId1), + sendAfter, + true ) } } @@ -417,17 +417,17 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("room alias does not exist") { beforeTest { coEvery { roomServiceMock.getRoomAlias(RoomAliasId("sms_111111", "server")) } - .returns(null) + .returns(null) coEvery { membershipServiceMock.doesRoomContainsMembers(roomId, any()) }.returns(false) coEvery { matrixClientMock.roomsApi.getRoomAlias(any()) } - .returns(GetRoomAliasResponse(roomId, listOf())) + .returns(GetRoomAliasResponse(roomId, listOf())) } it("should get room alias, invite users and send message") { cut.sendMessageToRoomAlias( - senderId, "body", "room name", userId1, - setOf(unmanagedUser1, unmanagedUser2), sendAfter + senderId, "body", "room name", userId1, + setOf(unmanagedUser1, unmanagedUser2), sendAfter ) - .shouldBe("send") + .shouldBe("send") coVerify { matrixClientMock.roomsApi.getRoomAlias(roomAliasId) matrixClientMock.roomsApi.inviteUser(roomId, senderId) @@ -455,7 +455,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe(SmsSendCommandHandler::createRoomAndSendMessage.name) { beforeTest { coEvery { cut.sendMessageToRoom(any(), any(), any(), any(), any(), any()) } - .returns("send") + .returns("send") coEvery { roomServiceMock.getOrCreateRoom(any()) }.returns(mockk()) coEvery { userServiceMock.existsUser(any()) }.returns(true) coEvery { matrixClientMock.roomsApi.createRoom(allAny()) }.returns(roomId) @@ -463,21 +463,21 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("body is null or empty") { it("should only create room") { cut.createRoomAndSendMessage( - null, senderId, "room name", setOf(userId1), - setOf(unmanagedUser1, unmanagedUser2), sendAfter + null, senderId, "room name", setOf(userId1), + setOf(unmanagedUser1, unmanagedUser2), sendAfter ) - .shouldBe("create room and send no message {receiverNumbers}") + .shouldBe("create room and send no message {receiverNumbers}") coVerify { matrixClientMock.roomsApi.createRoom( - name = "room name", - invite = setOf(senderId, userId1, unmanagedUser1, unmanagedUser2), - visibility = PRIVATE, - powerLevelContentOverride = PowerLevelsEventContent( - invite = 0, - kick = 0, - events = mapOf("m.room.name" to 0, "m.room.topic" to 0), - users = mapOf(botUserId to 100, userId1 to 100) - ) + name = "room name", + invite = setOf(senderId, userId1, unmanagedUser1, unmanagedUser2), + visibility = PRIVATE, + powerLevelContentOverride = PowerLevelsEventContent( + invite = 0, + kick = 0, + events = mapOf("m.room.name" to 0, "m.room.topic" to 0), + users = mapOf(botUserId to 100, userId1 to 100) + ) ) roomServiceMock.getOrCreateRoom(roomId) } @@ -486,21 +486,21 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("body contains message") { it("should create room and send message") { cut.createRoomAndSendMessage( - "body", senderId, "room name", setOf(userId1), - setOf(unmanagedUser1), sendAfter + "body", senderId, "room name", setOf(userId1), + setOf(unmanagedUser1), sendAfter ) - .shouldBe("create room and send message {receiverNumbers}") + .shouldBe("create room and send message {receiverNumbers}") coVerify { matrixClientMock.roomsApi.createRoom( - name = "room name", - invite = setOf(senderId, userId1, unmanagedUser1), - visibility = PRIVATE, - powerLevelContentOverride = PowerLevelsEventContent( - invite = 0, - kick = 0, - events = mapOf("m.room.name" to 0, "m.room.topic" to 0), - users = mapOf(botUserId to 100, userId1 to 100) - ) + name = "room name", + invite = setOf(senderId, userId1, unmanagedUser1), + visibility = PRIVATE, + powerLevelContentOverride = PowerLevelsEventContent( + invite = 0, + kick = 0, + events = mapOf("m.room.name" to 0, "m.room.topic" to 0), + users = mapOf(botUserId to 100, userId1 to 100) + ) ) roomServiceMock.getOrCreateRoom(roomId) cut.sendMessageToRoom(roomId, senderId, "body", setOf(userId1), sendAfter, true) @@ -512,14 +512,14 @@ private fun testBody(): DescribeSpec.() -> Unit { coEvery { userServiceMock.existsUser(userId2) }.returns(false) coEvery { appserviceHandlerHelperMock.registerManagedUser(any()) } just Runs cut.createRoomAndSendMessage( - null, - senderId, - "room name", - setOf(userId1, userId2), - setOf(), - sendAfter + null, + senderId, + "room name", + setOf(userId1, userId2), + setOf(), + sendAfter ) - .shouldBe("create room and send no message {receiverNumbers}") + .shouldBe("create room and send no message {receiverNumbers}") coVerify { appserviceHandlerHelperMock.registerManagedUser(userId2) } @@ -531,7 +531,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("body is null or blank") { it("should do nothing") { cut.sendMessageToRoom(roomId, senderId, null, setOf(userId1), null) - .shouldBe("no message {receiverNumbers}") + .shouldBe("no message {receiverNumbers}") coVerify { messageServiceMock wasNot Called } @@ -541,21 +541,21 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { coEvery { membershipServiceMock.doesRoomContainsMembers( - roomId, - match { it.containsAll(setOf(botUserId)) }) + roomId, + match { it.containsAll(setOf(botUserId)) }) }.returns(false) } it("should invite bot with first user and send message") { cut.sendMessageToRoom(roomId, senderId, "body", setOf(userId1, userId2), sendAfter) - .shouldBe("send message {receiverNumbers}") + .shouldBe("send message {receiverNumbers}") coVerify { matrixClientMock.roomsApi.inviteUser(roomId, botUserId, userId1) messageServiceMock.sendRoomMessage( - MatrixMessage( - roomId = roomId, - body = "message @sender:server body", - sendAfter = sendAfterInstant - ), setOf(userId1, userId2) + MatrixMessage( + roomId = roomId, + body = "message @sender:server body", + sendAfter = sendAfterInstant + ), setOf(userId1, userId2) ) } } @@ -564,51 +564,51 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { coEvery { membershipServiceMock.doesRoomContainsMembers( - roomId, - match { it.containsAll(setOf(botUserId)) }) + roomId, + match { it.containsAll(setOf(botUserId)) }) }.returns(true) } it("should send message") { cut.sendMessageToRoom(roomId, senderId, "body", setOf(userId1, userId2), sendAfter) - .shouldBe("send message {receiverNumbers}") + .shouldBe("send message {receiverNumbers}") coVerify { messageServiceMock.sendRoomMessage( - MatrixMessage( - roomId = roomId, - body = "message @sender:server body", - sendAfter = sendAfterInstant - ), setOf(userId1, userId2) + MatrixMessage( + roomId = roomId, + body = "message @sender:server body", + sendAfter = sendAfterInstant + ), setOf(userId1, userId2) ) } } describe("send after is more then 15 seconds in future") { it("should notify user about this") { val sendAfterStatic = LocalDateTime.ofInstant( - Instant.ofEpochMilli(4104433464000), - ZoneId.of("Europe/Berlin") + Instant.ofEpochMilli(4104433464000), + ZoneId.of("Europe/Berlin") ) cut.sendMessageToRoom( - roomId, - senderId, - "body", - setOf(userId1, userId2), - sendAfterStatic + roomId, + senderId, + "body", + setOf(userId1, userId2), + sendAfterStatic ).shouldBe("send message {receiverNumbers}") coVerify { messageServiceMock.sendRoomMessage( - match { - it.roomId == roomId - && it.body == "notice at 2100-01-24T01:24:24" - && it.isNotice == true - && it.sendAfter.until(Instant.now(), ChronoUnit.SECONDS) < 2424 - }, setOf(userId1, userId2) + match { + it.roomId == roomId + && it.body == "notice at 2100-01-24T01:24:24" + && it.isNotice == true + && it.sendAfter.until(Instant.now(), ChronoUnit.SECONDS) < 2424 + }, setOf(userId1, userId2) ) messageServiceMock.sendRoomMessage( - MatrixMessage( - roomId = roomId, - body = "message @sender:server body", - sendAfter = Instant.ofEpochMilli(4104433464000) - ), setOf(userId1, userId2) + MatrixMessage( + roomId = roomId, + body = "message @sender:server body", + sendAfter = Instant.ofEpochMilli(4104433464000) + ), setOf(userId1, userId2) ) } } @@ -620,25 +620,25 @@ private fun testBody(): DescribeSpec.() -> Unit { beforeTest { every { roomServiceMock.getRoomsByMembers(any()) }.returns(flowOf()) coEvery { cut.sendMessageToRoomAlias(any(), any(), any(), any(), any(), any()) } - .throws(RuntimeException("mimimi")) + .throws(RuntimeException("mimimi")) every { smsBridgePropertiesMock.singleModeEnabled }.returns(true) } it("should catch exception and notify user") { cut.handleCommand("body", senderId, setOf(tel1), setOf(), "room name", sendAfter, AUTO) - .shouldBe("error mimimi +111111") + .shouldBe("error mimimi +111111") } } afterTest { clearMocks( - cut, - userServiceMock, - roomServiceMock, - membershipServiceMock, - messageServiceMock, - appserviceHandlerHelperMock, - matrixClientMock, - smsBridgePropertiesMock + cut, + userServiceMock, + roomServiceMock, + membershipServiceMock, + messageServiceMock, + appserviceHandlerHelperMock, + matrixClientMock, + smsBridgePropertiesMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandTest.kt index 93dc745..05ed61c 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/handler/SmsSendCommandTest.kt @@ -55,22 +55,22 @@ class SmsSendCommandTest { coVerifyAll { handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917331111111"), - inviteUserIds = setOf(), - roomName = null, - roomCreationMode = AUTO, - sendAfterLocal = null + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917331111111"), + inviteUserIds = setOf(), + roomName = null, + roomCreationMode = AUTO, + sendAfterLocal = null ) handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917332222222"), - inviteUserIds = setOf(), - roomName = null, - roomCreationMode = AUTO, - sendAfterLocal = null + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917332222222"), + inviteUserIds = setOf(), + roomName = null, + roomCreationMode = AUTO, + sendAfterLocal = null ) } } @@ -81,13 +81,13 @@ class SmsSendCommandTest { coVerifyAll { handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917331111111"), - inviteUserIds = setOf(), - roomName = null, - roomCreationMode = AUTO, - sendAfterLocal = LocalDateTime.of(1955, 11, 9, 12, 0) + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917331111111"), + inviteUserIds = setOf(), + roomName = null, + roomCreationMode = AUTO, + sendAfterLocal = LocalDateTime.of(1955, 11, 9, 12, 0) ) } } @@ -98,13 +98,13 @@ class SmsSendCommandTest { coVerify { handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917331111111", "+4917332222222"), - inviteUserIds = setOf(), - roomName = "some name", - roomCreationMode = AUTO, - sendAfterLocal = null + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917331111111", "+4917332222222"), + inviteUserIds = setOf(), + roomName = "some name", + roomCreationMode = AUTO, + sendAfterLocal = null ) } } @@ -115,13 +115,13 @@ class SmsSendCommandTest { coVerify { handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917331111111"), - inviteUserIds = setOf(), - roomName = null, - roomCreationMode = ALWAYS, - sendAfterLocal = null + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917331111111"), + inviteUserIds = setOf(), + roomName = null, + roomCreationMode = ALWAYS, + sendAfterLocal = null ) } } @@ -132,13 +132,13 @@ class SmsSendCommandTest { coVerify { handler.handleCommand( - body = "some text", - senderId = senderId, - receiverNumbers = setOf("+4917331111111"), - inviteUserIds = setOf(UserId("test1", "test"), UserId("test2", "test")), - roomName = null, - roomCreationMode = AUTO, - sendAfterLocal = null + body = "some text", + senderId = senderId, + receiverNumbers = setOf("+4917331111111"), + inviteUserIds = setOf(UserId("test1", "test"), UserId("test2", "test")), + roomName = null, + roomCreationMode = AUTO, + sendAfterLocal = null ) } } @@ -154,10 +154,10 @@ class SmsSendCommandTest { @Test fun `should fail and echo when wrong telephone number`() { every { phoneNumberServiceMock.parseToInternationalNumber(any()) }.throws( - NumberParseException( - NOT_A_NUMBER, - "not a valid number" - ) + NumberParseException( + NOT_A_NUMBER, + "not a valid number" + ) ) cut.parse(listOf("some text", "-t", "012345678 DINO")) diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepositoryTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepositoryTest.kt index bb5c3c0..1279fcf 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepositoryTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingRepositoryTest.kt @@ -22,8 +22,8 @@ import org.springframework.data.r2dbc.core.delete @DataR2dbcTest @ImportAutoConfiguration(value = [MatrixBotDatabaseAutoconfiguration::class, SmsBridgeDatabaseConfiguration::class]) class MatrixSmsMappingRepositoryTest( - cut: MatrixSmsMappingRepository, - db: R2dbcEntityTemplate + cut: MatrixSmsMappingRepository, + db: R2dbcEntityTemplate ) : DescribeSpec(testBody(cut, db)) private fun testBody(cut: MatrixSmsMappingRepository, db: R2dbcEntityTemplate): DescribeSpec.() -> Unit { @@ -60,24 +60,24 @@ private fun testBody(cut: MatrixSmsMappingRepository, db: R2dbcEntityTemplate): describe(MatrixSmsMappingRepository::findByUserIdSortByMappingTokenDesc.name) { it("should find and sort mapping tokens") { cut.findByUserIdSortByMappingTokenDesc(user1).toList() - .shouldContainInOrder(map3, map1, map4) + .shouldContainInOrder(map3, map1, map4) } it("should not find and sort mapping tokens") { cut.findByUserIdSortByMappingTokenDesc(user3).toList() - .shouldBeEmpty() + .shouldBeEmpty() } } describe(MatrixSmsMappingRepository::findByUserIdAndMappingToken.name) { it("should find by user id and mapping token") { cut.findByUserIdAndMappingToken(user2, 1) - .shouldBe(map5) + .shouldBe(map5) } it("should not find by user id and mapping token") { cut.findByUserIdAndMappingToken(user2, 5) - .shouldBeNull() + .shouldBeNull() cut.findByUserIdAndMappingToken(user3, 1) - .shouldBeNull() + .shouldBeNull() } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingServiceTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingServiceTest.kt index 8bfea56..b1f937d 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingServiceTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/mapping/MatrixSmsMappingServiceTest.kt @@ -30,7 +30,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe(MatrixSmsMappingService::getOrCreateMapping.name) { beforeTest { coEvery { membershipServiceMock.getOrCreateMembership(userId, roomId) } - .returns(membership) + .returns(membership) } describe("mapping in database") { beforeTest { coEvery { mappingRepositoryMock.findByMembershipId(membership.id) }.returns(mapping) } @@ -44,24 +44,24 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("no last mapping token found") { beforeTest { coEvery { mappingRepositoryMock.findByUserIdSortByMappingTokenDesc(userId) } - .returns(flowOf()) + .returns(flowOf()) } it("should create and save new entity and start with 1 as token") { val savedMapping = MatrixSmsMapping(membership.id, 1, 2) coEvery { mappingRepositoryMock.save(MatrixSmsMapping(membership.id, 1)) } - .returns(savedMapping) + .returns(savedMapping) cut.getOrCreateMapping(userId, roomId).shouldBe(savedMapping) } } describe("last mapping token found") { beforeTest { coEvery { mappingRepositoryMock.findByUserIdSortByMappingTokenDesc(userId) } - .returns(flowOf(MatrixSmsMapping(membership.id, 14, 2))) + .returns(flowOf(MatrixSmsMapping(membership.id, 14, 2))) } it("should create and save new entity and start with 1 as token") { val savedMapping = MatrixSmsMapping(membership.id, 15, 2) coEvery { mappingRepositoryMock.save(MatrixSmsMapping(membership.id, 15)) } - .returns(savedMapping) + .returns(savedMapping) cut.getOrCreateMapping(userId, roomId).shouldBe(savedMapping) } } @@ -81,7 +81,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("user is in one room") { beforeTest { coEvery { membershipServiceMock.getMembershipsByUserId(userId) } - .returns(flowOf(membership)) + .returns(flowOf(membership)) } it("should return room id") { cut.getRoomId(userId, null).shouldBe(membership.roomId) @@ -90,7 +90,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("user is in more then one room") { beforeTest { coEvery { membershipServiceMock.getMembershipsByUserId(userId) } - .returns(flowOf(mockk(), mockk())) + .returns(flowOf(mockk(), mockk())) } it("should return null") { cut.getRoomId(userId, null).shouldBeNull() @@ -110,9 +110,9 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("mapping token in database") { beforeTest { coEvery { mappingRepositoryMock.findByUserIdAndMappingToken(userId, 2) } - .returns(mapping) + .returns(mapping) coEvery { membershipServiceMock.getMembership(mapping.membershipId) } - .returns(membership) + .returns(membership) } it("should return room id from database") { cut.getRoomId(userId, 2).shouldBe(membership.roomId) @@ -121,7 +121,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("mapping token not in database") { beforeTest { coEvery { mappingRepositoryMock.findByUserIdAndMappingToken(userId, 2) } - .returns(null) + .returns(null) } include(testFindSingleRoomIdMapping("a")) } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageRepositoryTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageRepositoryTest.kt index d3c550a..d46e2fc 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageRepositoryTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageRepositoryTest.kt @@ -15,8 +15,8 @@ import org.springframework.data.r2dbc.core.delete @DataR2dbcTest @ImportAutoConfiguration(value = [MatrixBotDatabaseAutoconfiguration::class, SmsBridgeDatabaseConfiguration::class]) class MatrixMessageRepositoryTest( - cut: MatrixMessageRepository, - db: R2dbcEntityTemplate + cut: MatrixMessageRepository, + db: R2dbcEntityTemplate ) : DescribeSpec(testBody(cut, db)) private fun testBody(cut: MatrixMessageRepository, db: R2dbcEntityTemplate): DescribeSpec.() -> Unit { diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageServiceTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageServiceTest.kt index 636c5ba..a0cf6e4 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageServiceTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/message/MatrixMessageServiceTest.kt @@ -4,6 +4,7 @@ import io.kotest.core.spec.style.DescribeSpec import io.mockk.* import kotlinx.coroutines.flow.flowOf import net.folivo.matrix.bot.membership.MatrixMembershipService +import net.folivo.matrix.bot.user.MatrixUserService import net.folivo.matrix.core.model.MatrixId.* import net.folivo.matrix.core.model.events.m.room.message.NoticeMessageEventContent import net.folivo.matrix.core.model.events.m.room.message.TextMessageEventContent @@ -18,15 +19,17 @@ private fun testBody(): DescribeSpec.() -> Unit { val messageRepositoryMock: MatrixMessageRepository = mockk() val messageReceiverRepositoryMock: MatrixMessageReceiverRepository = mockk() val membershipServiceMock: MatrixMembershipService = mockk() + val userServiceMock: MatrixUserService = mockk() val matrixClientMock: MatrixClient = mockk() val cut = spyk( - MatrixMessageService( - messageRepositoryMock, - messageReceiverRepositoryMock, - membershipServiceMock, - matrixClientMock - ) + MatrixMessageService( + messageRepositoryMock, + messageReceiverRepositoryMock, + membershipServiceMock, + userServiceMock, + matrixClientMock + ) ) val roomId = RoomId("room", "server") @@ -38,23 +41,38 @@ private fun testBody(): DescribeSpec.() -> Unit { coEvery { cut.deleteMessage(any()) } just Runs coEvery { cut.saveMessageAndReceivers(any(), any()) } just Runs } + describe("check required users") { + beforeTest { coEvery { membershipServiceMock.doesRoomContainsMembers(any(), any()) }.returns(false) } + it("should use set of required users and sender when sender is given") { + val message = + MatrixMessage(roomId, "body", Instant.now().minusSeconds(400000), asUserId = userId1) + cut.sendRoomMessage(message, setOf(userId2)) + coVerify { membershipServiceMock.doesRoomContainsMembers(roomId, setOf(userId1, userId2)) } + } + it("should use set of required users when sender is not given") { + val message = + MatrixMessage(roomId, "body", Instant.now().minusSeconds(400000)) + cut.sendRoomMessage(message, setOf(userId2)) + coVerify { membershipServiceMock.doesRoomContainsMembers(roomId, setOf(userId2)) } + } + } describe("message send after is after now") { describe("room contains receivers") { beforeTest { coEvery { membershipServiceMock.doesRoomContainsMembers(any(), any()) } - .returns(true) + .returns(true) } describe("sending message fails") { beforeTest { coEvery { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) } - .throws(RuntimeException()) + .throws(RuntimeException()) } describe("message is older then three days") { val message = MatrixMessage( - roomId, - "body", - sendAfter = Instant.now().minusSeconds(400000), - id = 2 + roomId, + "body", + sendAfter = Instant.now().minusSeconds(400000), + id = 2 ) it("should delete message") { cut.sendRoomMessage(message, setOf(userId1)) @@ -73,20 +91,20 @@ private fun testBody(): DescribeSpec.() -> Unit { } describe("message is notice") { val message = MatrixMessage( - roomId, - "body", - isNotice = true, - sendAfter = Instant.now().minusSeconds(2424) + roomId, + "body", + isNotice = true, + sendAfter = Instant.now().minusSeconds(2424) ) it("should send message and delete message from database") { coEvery { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) } - .returns(EventId("event", "server")) + .returns(EventId("event", "server")) cut.sendRoomMessage(message, setOf(userId1)) coVerify { matrixClientMock.roomsApi.sendRoomEvent( - roomId, - match { it.body == "body" }, - txnId = any() + roomId, + match { it.body == "body" }, + txnId = any() ) cut.deleteMessage(message) } @@ -94,20 +112,20 @@ private fun testBody(): DescribeSpec.() -> Unit { } describe("message is not notice") { val message = MatrixMessage( - roomId, - "body", - isNotice = false, - sendAfter = Instant.now().minusSeconds(2424) + roomId, + "body", + isNotice = false, + sendAfter = Instant.now().minusSeconds(2424) ) it("should send message and delete message from database") { coEvery { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) } - .returns(EventId("event", "server")) + .returns(EventId("event", "server")) cut.sendRoomMessage(message, setOf(userId1)) coVerify { matrixClientMock.roomsApi.sendRoomEvent( - roomId, - match { it.body == "body" }, - txnId = any() + roomId, + match { it.body == "body" }, + txnId = any() ) cut.deleteMessage(message) } @@ -117,7 +135,7 @@ private fun testBody(): DescribeSpec.() -> Unit { describe("room does not contain receivers") { beforeTest { coEvery { membershipServiceMock.doesRoomContainsMembers(any(), any()) } - .returns(false) + .returns(false) } describe("message is new") { val message = MatrixMessage(roomId, "body", sendAfter = Instant.now().minusSeconds(400000)) @@ -125,21 +143,21 @@ private fun testBody(): DescribeSpec.() -> Unit { cut.sendRoomMessage(message, setOf(userId1)) coVerify { cut.saveMessageAndReceivers( - match { - it.body == "body" - && it.sendAfter.until(Instant.now(), ChronoUnit.MINUTES) < 24 - }, - setOf(userId1) + match { + it.body == "body" + && it.sendAfter.until(Instant.now(), ChronoUnit.MINUTES) < 24 + }, + setOf(userId1) ) } } } describe("message is older then three days and not new") { val message = MatrixMessage( - roomId, - "body", - sendAfter = Instant.now().minusSeconds(400000), - id = 2 + roomId, + "body", + sendAfter = Instant.now().minusSeconds(400000), + id = 2 ) it("should delete message") { cut.sendRoomMessage(message, setOf(userId1)) @@ -172,13 +190,18 @@ private fun testBody(): DescribeSpec.() -> Unit { } describe(MatrixMessageService::saveMessageAndReceivers.name) { it("should save message and its receivers") { - val message = MatrixMessage(roomId, "body") + val senderId = UserId("sender", "server") + val message = MatrixMessage(roomId, "body", asUserId = senderId) coEvery { messageRepositoryMock.save(message) }.returns(message.copy(id = 24)) coEvery { messageReceiverRepositoryMock.save(any()) }.returns(mockk()) + coEvery { userServiceMock.getOrCreateUser(any()) }.returns(mockk()) cut.saveMessageAndReceivers(message, setOf(userId1, userId2)) coVerifyAll { messageReceiverRepositoryMock.save(MatrixMessageReceiver(24, userId1)) messageReceiverRepositoryMock.save(MatrixMessageReceiver(24, userId2)) + userServiceMock.getOrCreateUser(senderId) + userServiceMock.getOrCreateUser(userId1) + userServiceMock.getOrCreateUser(userId2) } } } @@ -201,9 +224,9 @@ private fun testBody(): DescribeSpec.() -> Unit { val message2 = MatrixMessage(roomId, "body", id = 2) every { messageRepositoryMock.findAll() }.returns(flowOf(message1, message2)) every { messageReceiverRepositoryMock.findByRoomMessageId(1) } - .returns(flowOf(MatrixMessageReceiver(1, userId1))) + .returns(flowOf(MatrixMessageReceiver(1, userId1))) every { messageReceiverRepositoryMock.findByRoomMessageId(2) } - .returns(flowOf(MatrixMessageReceiver(2, userId1), MatrixMessageReceiver(2, userId2))) + .returns(flowOf(MatrixMessageReceiver(2, userId1), MatrixMessageReceiver(2, userId2))) coEvery { cut.sendRoomMessage(any(), any()) } just Runs cut.processMessageQueue() coVerify { @@ -215,11 +238,11 @@ private fun testBody(): DescribeSpec.() -> Unit { afterTest { clearMocks( - cut, - messageRepositoryMock, - messageReceiverRepositoryMock, - membershipServiceMock, - matrixClientMock + cut, + messageRepositoryMock, + messageReceiverRepositoryMock, + membershipServiceMock, + matrixClientMock ) } } diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncherTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncherTest.kt index 41f581f..44537dd 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncherTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderLauncherTest.kt @@ -19,7 +19,7 @@ private fun testBody(): DescribeSpec.() -> Unit { } val matrixClientMock: MatrixClient = mockk { coEvery { roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) } - .returns(EventId("event", "server")) + .returns(EventId("event", "server")) } val cut = AndroidSmsProviderLauncher(androidSmsProviderMock, smsBridgePropertiesMock, matrixClientMock) @@ -33,12 +33,12 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should notify default room") { coEvery { androidSmsProviderMock.getAndProcessNewMessages() } - .throws(RuntimeException("meteor")) + .throws(RuntimeException("meteor")) val job = cut.startReceiveLoop() coVerify(timeout = 100) { matrixClientMock.roomsApi.sendRoomEvent( - defaultRoom, match { it.body == "error meteor" }, - any(), any(), any() + defaultRoom, match { it.body == "error meteor" }, + any(), any(), any() ) } job.cancelAndJoin() @@ -50,7 +50,7 @@ private fun testBody(): DescribeSpec.() -> Unit { } it("should not notify default room") { coEvery { androidSmsProviderMock.getAndProcessNewMessages() } - .throws(RuntimeException("meteor")) + .throws(RuntimeException("meteor")) val job = cut.startReceiveLoop() coVerify(exactly = 0, timeout = 100) { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any(), any()) diff --git a/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderTest.kt b/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderTest.kt index 22aa9ca..cc1b6b0 100644 --- a/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderTest.kt +++ b/src/test/kotlin/net/folivo/matrix/bridge/sms/provider/android/AndroidSmsProviderTest.kt @@ -36,30 +36,30 @@ import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus @SpringBootTest( - properties = [ - "matrix.bridge.sms.provider.android.enabled=true", - "matrix.bridge.sms.provider.android.baseUrl=http://localhost:5100", - "matrix.bridge.sms.provider.android.username=username", - "matrix.bridge.sms.provider.android.password=password" - ] + properties = [ + "matrix.bridge.sms.provider.android.enabled=true", + "matrix.bridge.sms.provider.android.baseUrl=http://localhost:5100", + "matrix.bridge.sms.provider.android.username=username", + "matrix.bridge.sms.provider.android.password=password" + ] ) class AndroidSmsProviderTest( - db: R2dbcEntityTemplate, - @MockkBean(relaxed = true) - private val receiveSmsServiceMock: ReceiveSmsService, - @MockkBean - private val matrixClientMock: MatrixClient, - @SpykBean - private val smsBridgeProperties: SmsBridgeProperties, - cut: AndroidSmsProvider + db: R2dbcEntityTemplate, + @MockkBean(relaxed = true) + private val receiveSmsServiceMock: ReceiveSmsService, + @MockkBean + private val matrixClientMock: MatrixClient, + @SpykBean + private val smsBridgeProperties: SmsBridgeProperties, + cut: AndroidSmsProvider ) : DescribeSpec(testBody(cut, db, receiveSmsServiceMock, matrixClientMock, smsBridgeProperties)) private fun testBody( - cut: AndroidSmsProvider, - db: R2dbcEntityTemplate, - receiveSmsServiceMock: ReceiveSmsService, - matrixClientMock: MatrixClient, - smsBridgeProperties: SmsBridgeProperties + cut: AndroidSmsProvider, + db: R2dbcEntityTemplate, + receiveSmsServiceMock: ReceiveSmsService, + matrixClientMock: MatrixClient, + smsBridgeProperties: SmsBridgeProperties ): DescribeSpec.() -> Unit { return { @@ -69,21 +69,21 @@ private fun testBody( beforeTest { mockServerClient.reset() coEvery { matrixClientMock.roomsApi.sendRoomEvent(any(), any(), any(), any()) } - .returns(EventId("event", "server")) + .returns(EventId("event", "server")) } describe(AndroidSmsProvider::getAndProcessNewMessages.name) { beforeTest { mockServerClient - .`when`( - HttpRequest.request() - .withMethod(HttpMethod.GET.name) - .withPath("/messages/in"), - Times.exactly(1) - ).respond( - HttpResponse.response() - .withBody( - """ + .`when`( + HttpRequest.request() + .withMethod(HttpMethod.GET.name) + .withPath("/messages/in"), + Times.exactly(1) + ).respond( + HttpResponse.response() + .withBody( + """ { "nextBatch":"2", "messages":[ @@ -100,19 +100,19 @@ private fun testBody( ] } """.trimIndent(), MediaType.APPLICATION_JSON - ) - ) + ) + ) mockServerClient - .`when`( - HttpRequest.request() - .withMethod(HttpMethod.GET.name) - .withPath("/messages/in") - .withQueryStringParameter("after", "2"), - Times.exactly(1) - ).respond( - HttpResponse.response() - .withBody( - """ + .`when`( + HttpRequest.request() + .withMethod(HttpMethod.GET.name) + .withPath("/messages/in") + .withQueryStringParameter("after", "2"), + Times.exactly(1) + ).respond( + HttpResponse.response() + .withBody( + """ { "nextBatch":"3", "messages":[ @@ -124,8 +124,8 @@ private fun testBody( ] } """.trimIndent(), MediaType.APPLICATION_JSON - ) - ) + ) + ) } it("should get new messages") { cut.getAndProcessNewMessages() @@ -138,40 +138,40 @@ private fun testBody( cut.getAndProcessNewMessages() cut.getAndProcessNewMessages() mockServerClient - .verify( - HttpRequest.request() - .withMethod(HttpMethod.GET.name) - .withPath("/messages/in"), - HttpRequest.request() - .withMethod(HttpMethod.GET.name) - .withPath("/messages/in") - .withQueryStringParameter("after", "2") - ) + .verify( + HttpRequest.request() + .withMethod(HttpMethod.GET.name) + .withPath("/messages/in"), + HttpRequest.request() + .withMethod(HttpMethod.GET.name) + .withPath("/messages/in") + .withQueryStringParameter("after", "2") + ) } it("should save last processed message") { db.delete().all().awaitFirstOrNull() db.select().first().awaitFirstOrNull() - ?.shouldBeNull() + ?.shouldBeNull() cut.getAndProcessNewMessages() db.select().first().awaitFirstOrNull() - ?.lastProcessedId.shouldBe(2) + ?.lastProcessedId.shouldBe(2) cut.getAndProcessNewMessages() db.select().first().awaitFirstOrNull() - ?.lastProcessedId.shouldBe(3) + ?.lastProcessedId.shouldBe(3) } describe("handle unparsable telephone numbers") { beforeTest { mockServerClient - .`when`( - HttpRequest.request() - .withMethod(HttpMethod.GET.name) - .withPath("/messages/in") - .withQueryStringParameter("after", "3"), - Times.exactly(1) - ).respond( - HttpResponse.response() - .withBody( - """ + .`when`( + HttpRequest.request() + .withMethod(HttpMethod.GET.name) + .withPath("/messages/in") + .withQueryStringParameter("after", "3"), + Times.exactly(1) + ).respond( + HttpResponse.response() + .withBody( + """ { "nextBatch":"4", "messages":[ @@ -183,8 +183,8 @@ private fun testBody( ] } """.trimIndent(), MediaType.APPLICATION_JSON - ) - ) + ) + ) } it("should send to default room, when present") { val defaultRoomId = RoomId("default", "server") @@ -212,48 +212,48 @@ private fun testBody( } it("should handle exceptions while processing message") { coEvery { receiveSmsServiceMock.receiveSms(any(), "+4917332222222") } - .throws(RuntimeException()) + .throws(RuntimeException()) shouldThrow { cut.getAndProcessNewMessages() } db.select().first().awaitFirstOrNull() - ?.lastProcessedId.shouldBe(1) + ?.lastProcessedId.shouldBe(1) } } describe(AndroidSmsProvider::sendSms.name) { it("should call android device to send message") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond(HttpResponse.response()) cut.sendSms("+491234567", "some body") mockServerClient.verify( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") - .withBody( - JsonBody.json( - """ + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") + .withBody( + JsonBody.json( + """ { "recipientPhoneNumber":"+491234567", "message":"some body" } """.trimIndent(), STRICT - ) - ) + ) + ) ) } describe("on error BadRequest") { it("should rethrow error") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond( - HttpResponse.response() - .withStatusCode(HttpStatus.BAD_REQUEST.value()) - .withBody("wrong telephone number") + HttpResponse.response() + .withStatusCode(HttpStatus.BAD_REQUEST.value()) + .withBody("wrong telephone number") ) try { cut.sendSms("+491234567", "some body") @@ -266,13 +266,13 @@ private fun testBody( describe("on other error") { beforeTest { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond( - HttpResponse.response() - .withStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) - .withBody("no network") + HttpResponse.response() + .withStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .withBody("no network") ) } it("should save message to send later") { @@ -324,38 +324,38 @@ private fun testBody( } it("should send all messages and delete messages") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond(HttpResponse.response()) cut.sendOutFailedMessages() mockServerClient.verify( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") - .withBody( - JsonBody.json( - """ + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") + .withBody( + JsonBody.json( + """ { "recipientPhoneNumber":"+491234511", "message":"some body 1" } """.trimIndent(), STRICT - ) - ), - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") - .withBody( - JsonBody.json( - """ + ) + ), + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") + .withBody( + JsonBody.json( + """ { "recipientPhoneNumber":"+491234522", "message":"some body 2" } """.trimIndent(), STRICT - ) - ) + ) + ) ) db.select().all().asFlow().count().shouldBe(0) } @@ -364,9 +364,9 @@ private fun testBody( beforeTest { every { smsBridgeProperties.defaultRoomId }.returns(defaultRoomId) } it("should notify about all resend messages") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond(HttpResponse.response()) cut.sendOutFailedMessages() coVerify { @@ -377,13 +377,13 @@ private fun testBody( } it("should not notify when sending failed") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond( - HttpResponse.response() - .withStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) - .withBody("no network") + HttpResponse.response() + .withStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .withBody("no network") ) shouldThrow { cut.sendOutFailedMessages() @@ -395,9 +395,9 @@ private fun testBody( beforeTest { every { smsBridgeProperties.defaultRoomId }.returns(null) } it("should not notify") { mockServerClient.`when`( - HttpRequest.request() - .withMethod(HttpMethod.POST.name) - .withPath("/messages/out") + HttpRequest.request() + .withMethod(HttpMethod.POST.name) + .withPath("/messages/out") ).respond(HttpResponse.response()) cut.sendOutFailedMessages() coVerify { matrixClientMock wasNot Called }