Skip to content

Commit

Permalink
implemented #3
Browse files Browse the repository at this point in the history
  • Loading branch information
benkuly committed Nov 27, 2020
1 parent 1ba1c93 commit fea21bc
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 19 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/dockerimage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ jobs:
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: build image
run: gradle bootBuildImage
- name: tag to latest
run: docker tag folivonet/matrix-sms-bridge:${GITHUB_REF:11} folivonet/matrix-sms-bridge:latest
- name: tag to version
run: docker tag folivonet/matrix-sms-bridge:latest folivonet/matrix-sms-bridge:${GITHUB_REF:11}
- name: Publish version tagged image to DockerHub
run: docker push folivonet/matrix-sms-bridge:${GITHUB_REF:11}
- name: Publish latest image to DockerHub
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repositories {
}

group = "net.folivo"
version = "0.5.3"
version = "0.5.4"
java.sourceCompatibility = JavaVersion.VERSION_11

tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar>() {
Expand Down Expand Up @@ -90,7 +90,7 @@ tasks.withType<KotlinCompile> {
}

tasks.getByName<BootBuildImage>("bootBuildImage") {
imageName = "folivonet/matrix-sms-bridge:${project.version}"
imageName = "folivonet/matrix-sms-bridge:latest"
}

tasks.register<Exec>("docker-gammu") {
Expand Down
2 changes: 1 addition & 1 deletion examples/android/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.3'
services:
matrix-sms-bridge:
image: folivonet/matrix-sms-bridge:0.5.3
image: folivonet/matrix-sms-bridge:latest
volumes:
- type: bind
source: ./config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ data class SmsBridgeProperties(
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}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.springframework.stereotype.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,
Expand All @@ -39,8 +40,9 @@ class MessageToBotHandler(
LOG.debug("ignore message from managed user")
false
} else if (body.startsWith("sms")) {
if (membershipSize > 2) {
LOG.debug("to many members in room form sms command")
// TODO is there a less hacky way for "sms abort"? Maybe completely switch to non-console?
if (membershipSize > 2 && !body.startsWith("sms abort")) {
LOG.debug("to many members in room for sms command")
context.answer(smsBridgeProperties.templates.botTooManyMembers)
true
} else {
Expand All @@ -63,6 +65,10 @@ class MessageToBotHandler(
SmsInviteCommand(
senderId,
smsInviteCommandHandler
),
SmsAbortCommand(
roomId,
smsAbortCommandHandler
)
)
.parse(args)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package net.folivo.matrix.bridge.sms.handler

import com.github.ajalt.clikt.core.CliktCommand
import kotlinx.coroutines.runBlocking
import net.folivo.matrix.core.model.MatrixId.RoomId

class SmsAbortCommand(
private val roomId: RoomId,
private val handler: SmsAbortCommandHandler
) : CliktCommand(name = "abort") {

override fun run() {
echo(runBlocking { handler.handleCommand(roomId) })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.folivo.matrix.bridge.sms.handler

import net.folivo.matrix.bridge.sms.SmsBridgeProperties
import net.folivo.matrix.bridge.sms.SmsBridgeProperties.SmsBridgeTemplateProperties
import net.folivo.matrix.bridge.sms.message.MatrixMessageService
import net.folivo.matrix.core.model.MatrixId.RoomId
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component


@Component
class SmsAbortCommandHandler(
private val messageService: MatrixMessageService,
smsBridgeProperties: SmsBridgeProperties,
) {

private val templates: SmsBridgeTemplateProperties = smsBridgeProperties.templates

companion object {
private val LOG = LoggerFactory.getLogger(this::class.java)
}

suspend fun handleCommand(
roomId: RoomId
): String {
return try {
messageService.deleteByRoomId(roomId)
templates.botSmsAbortSuccess
} catch (ex: Throwable) {
LOG.debug("got exception")
templates.botSmsAbortError
.replace("{error}", ex.message ?: "unknown")
}
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package net.folivo.matrix.bridge.sms.message

import net.folivo.matrix.core.model.MatrixId.RoomId
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
import org.springframework.stereotype.Repository

@Repository
interface MatrixMessageRepository : CoroutineCrudRepository<MatrixMessage, Long> {
suspend fun deleteByRoomId(roomId: RoomId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.core.model.MatrixId.RoomId
import net.folivo.matrix.core.model.MatrixId.UserId
import net.folivo.matrix.core.model.events.m.room.message.NoticeMessageEventContent
import net.folivo.matrix.core.model.events.m.room.message.TextMessageEventContent
Expand Down Expand Up @@ -74,18 +75,22 @@ class MatrixMessageService(
}
}

internal suspend fun saveMessageAndReceivers(message: MatrixMessage, requiredMembers: Set<UserId>) {
suspend fun saveMessageAndReceivers(message: MatrixMessage, requiredMembers: Set<UserId>) {
val savedMessage = messageRepository.save(message)
requiredMembers.forEach {
if (savedMessage.id != null)
messageReceiverRepository.save(MatrixMessageReceiver(savedMessage.id, it))
}
}

internal suspend fun deleteMessage(message: MatrixMessage) {
suspend fun deleteMessage(message: MatrixMessage) {
if (message.id != null) messageRepository.delete(message)
}

suspend fun deleteByRoomId(roomId: RoomId) {
messageRepository.deleteByRoomId(roomId)
}

suspend fun processMessageQueue() {
messageRepository.findAll()
.collect { message ->
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/banner.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
\ \ __< \ \ __< \ \ \ \ \ \/\ \ \ \ \__ \ \ \ __\
\ \_____\ \ \_\ \_\ \ \_\ \ \____- \ \_____\ \ \_____\
\/_____/ \/_/ /_/ \/_/ \/____/ \/_____/ \/_____/

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private fun testBody(): DescribeSpec.() -> Unit {
return {
val smsSendCommandHandlerMock: SmsSendCommandHandler = mockk()
val smsInviteCommandHandlerMock: SmsInviteCommandHandler = mockk()
val smsAbortCommandHandlerMock: SmsAbortCommandHandler = mockk()
val phoneNumberServiceMock: PhoneNumberService = mockk()
val smsBridgePropertiesMock: SmsBridgeProperties = mockk {
every { templates.botHelp }.returns("help")
Expand All @@ -30,6 +31,7 @@ private fun testBody(): DescribeSpec.() -> Unit {
val cut = MessageToBotHandler(
smsSendCommandHandlerMock,
smsInviteCommandHandlerMock,
smsAbortCommandHandlerMock,
phoneNumberServiceMock,
smsBridgePropertiesMock,
userServiceMock,
Expand Down Expand Up @@ -57,16 +59,32 @@ private fun testBody(): DescribeSpec.() -> Unit {
}
}
describe("to many members in room") {
it("should warn user and return true") {
coEvery { userServiceMock.getOrCreateUser(senderId) }.returns(MatrixUser(senderId))
beforeTest {
coEvery { membershipServiceMock.getMembershipsSizeByRoomId(roomId) }.returns(3L)
coEvery { userServiceMock.getOrCreateUser(senderId) }.returns(MatrixUser(senderId))
}
it("should warn user and return true") {
cut.handleMessage(roomId, "sms", senderId, contextMock).shouldBeTrue()
coVerifyAll {
smsSendCommandHandlerMock wasNot Called
smsInviteCommandHandlerMock wasNot Called
contextMock.answer("toMany")
}
}
it("should accept sms abort command") {
coEvery { smsAbortCommandHandlerMock.handleCommand(any()) }
.returns("aborted")
cut.handleMessage(
roomId,
"sms abort",
senderId,
contextMock
).shouldBeTrue()

coVerify(exactly = 1) {
contextMock.answer("aborted")
}
}
}
describe("valid sms command") {
beforeTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.folivo.matrix.bridge.sms.handler

import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.shouldBe
import io.mockk.*
import net.folivo.matrix.bridge.sms.SmsBridgeProperties
import net.folivo.matrix.bridge.sms.message.MatrixMessageService
import net.folivo.matrix.core.model.MatrixId.RoomId

class SmsAbortCommandHandlerTest : DescribeSpec(testBody())

private fun testBody(): DescribeSpec.() -> Unit {
return {
val messageServiceMock: MatrixMessageService = mockk()
val smsBridgePropertiesMock: SmsBridgeProperties = mockk {
every { templates.botSmsAbortSuccess }.returns("success")
every { templates.botSmsAbortError }.returns("error:{error}")
}
val cut = SmsAbortCommandHandler(messageServiceMock, smsBridgePropertiesMock)

val roomId = RoomId("room", "server")

describe(SmsAbortCommandHandler::handleCommand.name) {
it("should delete messages") {
coEvery { messageServiceMock.deleteByRoomId(roomId) } just Runs
cut.handleCommand(roomId).shouldBe("success")
coVerify { messageServiceMock.deleteByRoomId(roomId) }
}
it("should catch error") {
coEvery { messageServiceMock.deleteByRoomId(roomId) }.throws(RuntimeException("meteor"))
cut.handleCommand(roomId).shouldBe("error:meteor")
}
}

afterTest { clearMocks(messageServiceMock) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.folivo.matrix.bridge.sms.handler

import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.output.CliktConsole
import io.kotest.core.spec.style.DescribeSpec
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import net.folivo.matrix.core.model.MatrixId.RoomId

class SmsAbortCommandTest : DescribeSpec(testBody())

private fun testBody(): DescribeSpec.() -> Unit {
return {
val roomId = RoomId("room", "server")
val handlerMock: SmsAbortCommandHandler = mockk()
val consoleMock: CliktConsole = mockk(relaxed = true)
val cut = SmsAbortCommand(roomId, handlerMock)
cut.context { console = consoleMock }

describe("run command") {
it("should run command") {
coEvery { handlerMock.handleCommand(roomId) }.returns("answer")
cut.parse(listOf())
coVerify { handlerMock.handleCommand(roomId) }
coVerify { consoleMock.print("answer", false) }
}
}

afterTest { clearMocks(consoleMock) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,25 @@ private fun testBody(): DescribeSpec.() -> Unit {
cut.context { console = consoleMock }

describe("alias was given") {
coEvery { handlerMock.handleCommand(sender, roomAliasId) }.returns("answer")
cut.parse(listOf("#alias:server"))
coVerify { handlerMock.handleCommand(sender, roomAliasId) }
coVerify { consoleMock.print("answer", false) }
it("should run") {
coEvery { handlerMock.handleCommand(sender, roomAliasId) }.returns("answer")
cut.parse(listOf("#alias:server"))
coVerify { handlerMock.handleCommand(sender, roomAliasId) }
coVerify { consoleMock.print("answer", false) }
}
}
describe("alias was not given") {
shouldThrow<MissingArgument> {
cut.parse(listOf())
it("should throw missing argument") {
shouldThrow<MissingArgument> {
cut.parse(listOf())
}
}
}
describe("alias was no alias") {
shouldThrow<BadParameterValue> {
cut.parse(listOf("!noAlias:server"))
it("should throw bad parameter") {
shouldThrow<BadParameterValue> {
cut.parse(listOf("!noAlias:server"))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package net.folivo.matrix.bridge.sms.message

import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.shouldBe
import kotlinx.coroutines.reactive.awaitFirst
import net.folivo.matrix.bot.config.MatrixBotDatabaseAutoconfiguration
import net.folivo.matrix.bot.room.MatrixRoom
import net.folivo.matrix.bridge.sms.SmsBridgeDatabaseConfiguration
import net.folivo.matrix.core.model.MatrixId.RoomId
import org.springframework.boot.autoconfigure.ImportAutoConfiguration
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate
import org.springframework.data.r2dbc.core.delete

@DataR2dbcTest
@ImportAutoConfiguration(value = [MatrixBotDatabaseAutoconfiguration::class, SmsBridgeDatabaseConfiguration::class])
class MatrixMessageRepositoryTest(
cut: MatrixMessageRepository,
db: R2dbcEntityTemplate
) : DescribeSpec(testBody(cut, db))

private fun testBody(cut: MatrixMessageRepository, db: R2dbcEntityTemplate): DescribeSpec.() -> Unit {
return {
val room1 = RoomId("room1", "server")
val room2 = RoomId("room2", "server")

val message1 = MatrixMessage(room1, "some body 1")
val message2 = MatrixMessage(room1, "some body 2")
val message3 = MatrixMessage(room2, "some body 3")

beforeSpec {
db.insert(MatrixRoom(room1)).awaitFirst()
db.insert(MatrixRoom(room2)).awaitFirst()
db.insert(message1).awaitFirst()
db.insert(message2).awaitFirst()
db.insert(message3).awaitFirst()
}

describe(MatrixMessageRepository::deleteByRoomId.name) {
it("should delete all matching rooms") {
cut.count().shouldBe(3)
cut.deleteByRoomId(room1)
cut.count().shouldBe(1)
}
}

afterSpec {
db.delete<MatrixMessage>().all().awaitFirst()
db.delete<MatrixRoom>().all().awaitFirst()
}
}
}

0 comments on commit fea21bc

Please sign in to comment.