Skip to content

Commit

Permalink
feat: receiving messages about new conversations and new messages fro…
Browse files Browse the repository at this point in the history
…m Awala (#55)

Receiving new messages about messages & conversations, storing &
displaying them in the database
  • Loading branch information
migulyaev authored Sep 19, 2023
1 parent 5b58eb7 commit 5a2df50
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 0 deletions.
6 changes: 6 additions & 0 deletions app/src/main/java/tech/relaycorp/letro/di/AwalaModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import tech.relaycorp.letro.awala.message.MessageType
import tech.relaycorp.letro.awala.processor.AwalaMessageProcessor
import tech.relaycorp.letro.awala.processor.AwalaMessageProcessorImpl
import tech.relaycorp.letro.awala.processor.UnknownMessageProcessor
import tech.relaycorp.letro.messages.processor.NewConversationProcessor
import tech.relaycorp.letro.messages.processor.NewMessageProcessor
import tech.relaycorp.letro.onboarding.registration.processor.RegistrationMessageProcessor
import tech.relaycorp.letro.pairing.processor.ContactPairingAuthorizationProcessor
import tech.relaycorp.letro.pairing.processor.ContactPairingMatchProcessor
Expand All @@ -27,12 +29,16 @@ object AwalaModule {
registrationMessageProcessor: RegistrationMessageProcessor,
contactPairingMatchProcessor: ContactPairingMatchProcessor,
contactPairingAuthorizationProcessor: ContactPairingAuthorizationProcessor,
newConversationProcessor: NewConversationProcessor,
newMessageProcessor: NewMessageProcessor,
unknownMessageProcessor: UnknownMessageProcessor,
): AwalaMessageProcessor {
val processors = mapOf(
MessageType.AccountCreationCompleted to registrationMessageProcessor,
MessageType.ContactPairingMatch to contactPairingMatchProcessor,
MessageType.ContactPairingAuthorization to contactPairingAuthorizationProcessor,
MessageType.NewConversation to newConversationProcessor,
MessageType.NewMessage to newMessageProcessor,
MessageType.Unknown to unknownMessageProcessor,
)
return AwalaMessageProcessorImpl(processors)
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/tech/relaycorp/letro/di/ConversationsModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ import tech.relaycorp.letro.messages.converter.ExtendedConversationConverter
import tech.relaycorp.letro.messages.converter.ExtendedConversationConverterImpl
import tech.relaycorp.letro.messages.converter.MessageTimestampConverter
import tech.relaycorp.letro.messages.converter.MessageTimestampConverterImpl
import tech.relaycorp.letro.messages.parser.NewConversationMessageParser
import tech.relaycorp.letro.messages.parser.NewConversationMessageParserImpl
import tech.relaycorp.letro.messages.parser.NewMessageMessageParser
import tech.relaycorp.letro.messages.parser.NewMessageMessageParserImpl
import tech.relaycorp.letro.messages.parser.OutgoingConversationMessageEncoder
import tech.relaycorp.letro.messages.parser.OutgoingConversationMessageEncoderImpl
import tech.relaycorp.letro.messages.processor.NewConversationProcessor
import tech.relaycorp.letro.messages.processor.NewConversationProcessorImpl
import tech.relaycorp.letro.messages.processor.NewMessageProcessor
import tech.relaycorp.letro.messages.processor.NewMessageProcessorImpl
import tech.relaycorp.letro.messages.repository.ConversationsRepository
import tech.relaycorp.letro.messages.repository.ConversationsRepositoryImpl
import tech.relaycorp.letro.messages.storage.ConversationsDao
Expand Down Expand Up @@ -56,5 +64,25 @@ object ConversationsModule {
fun bindOutgoingConversationMessageEncoder(
impl: OutgoingConversationMessageEncoderImpl,
): OutgoingConversationMessageEncoder

@Binds
fun bindNewConversationProcessor(
impl: NewConversationProcessorImpl,
): NewConversationProcessor

@Binds
fun bindNewConversationParser(
imp: NewConversationMessageParserImpl,
): NewConversationMessageParser

@Binds
fun bindNewMessageProcessor(
impl: NewMessageProcessorImpl,
): NewMessageProcessor

@Binds
fun bindNewMessageParser(
impl: NewMessageMessageParserImpl,
): NewMessageMessageParser
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tech.relaycorp.letro.messages.dto

import tech.relaycorp.letro.awala.message.AwalaIncomingMessage
import tech.relaycorp.letro.awala.message.MessageType
import tech.relaycorp.letro.messages.storage.entity.Conversation
import tech.relaycorp.letro.messages.storage.entity.Message

data class NewConversationIncomingMessageContent(
val conversation: Conversation,
val message: Message,
)

data class NewConversationIncomingMessage(
override val content: NewConversationIncomingMessageContent,
) : AwalaIncomingMessage<NewConversationIncomingMessageContent> {
override val type: MessageType
get() = MessageType.NewConversation
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tech.relaycorp.letro.messages.dto

import tech.relaycorp.letro.awala.message.AwalaIncomingMessage
import tech.relaycorp.letro.awala.message.MessageType
import tech.relaycorp.letro.messages.storage.entity.Message

data class NewMessageIncomingMessage(
override val content: Message,
) : AwalaIncomingMessage<Message> {
override val type: MessageType
get() = MessageType.NewMessage
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package tech.relaycorp.letro.messages.parser

import tech.relaycorp.letro.awala.parser.AwalaMessageParser
import tech.relaycorp.letro.messages.dto.NewConversationIncomingMessage
import tech.relaycorp.letro.messages.dto.NewConversationIncomingMessageContent
import tech.relaycorp.letro.messages.storage.entity.Conversation
import java.util.UUID
import javax.inject.Inject

interface NewConversationMessageParser : AwalaMessageParser

class NewConversationMessageParserImpl @Inject constructor() : NewConversationMessageParser {

override fun parse(content: ByteArray): NewConversationIncomingMessage {
val conversation = mockConversation() // TODO: parse conversation
val message = mockMessage(conversation.conversationId)
return NewConversationIncomingMessage(
content = NewConversationIncomingMessageContent(
conversation = conversation,
message = message,
),
)
}

private fun mockConversation() = Conversation(
ownerVeraId = "[email protected]",
contactVeraId = "[email protected]",
subject = "Test subject",
conversationId = MOCK_CONVERSATION_ID,
)
}

private val MOCK_CONVERSATION_ID = UUID.randomUUID()
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package tech.relaycorp.letro.messages.parser

import tech.relaycorp.letro.awala.parser.AwalaMessageParser
import tech.relaycorp.letro.messages.dto.NewMessageIncomingMessage
import tech.relaycorp.letro.messages.storage.entity.Message
import java.time.LocalDateTime
import java.util.UUID
import javax.inject.Inject

interface NewMessageMessageParser : AwalaMessageParser

class NewMessageMessageParserImpl @Inject constructor() : NewMessageMessageParser {

override fun parse(content: ByteArray): NewMessageIncomingMessage {
val message = mockMessage(UUID.randomUUID()) // TODO: parse message here
return NewMessageIncomingMessage(
content = message,
)
}
}

internal fun mockMessage(conversationId: UUID) = Message(
conversationId = conversationId,
text = "Hello, how are you?",
ownerVeraId = "[email protected]",
recipientVeraId = "[email protected]",
senderVeraId = "[email protected]",
sentAt = LocalDateTime.now(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package tech.relaycorp.letro.messages.processor

import tech.relaycorp.awaladroid.messaging.IncomingMessage
import tech.relaycorp.letro.awala.AwalaManager
import tech.relaycorp.letro.awala.processor.AwalaMessageProcessor
import tech.relaycorp.letro.messages.dto.NewConversationIncomingMessage
import tech.relaycorp.letro.messages.parser.NewConversationMessageParser
import tech.relaycorp.letro.messages.storage.ConversationsDao
import tech.relaycorp.letro.messages.storage.MessagesDao
import javax.inject.Inject

interface NewConversationProcessor : AwalaMessageProcessor

class NewConversationProcessorImpl @Inject constructor(
private val newConversationMessageParser: NewConversationMessageParser,
private val conversationsDao: ConversationsDao,
private val messagesDao: MessagesDao,
) : NewConversationProcessor {

override suspend fun process(message: IncomingMessage, awalaManager: AwalaManager) {
val content = (newConversationMessageParser.parse(message.content) as NewConversationIncomingMessage).content
conversationsDao.createNewConversation(content.conversation)
messagesDao.insert(content.message)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package tech.relaycorp.letro.messages.processor

import tech.relaycorp.awaladroid.messaging.IncomingMessage
import tech.relaycorp.letro.awala.AwalaManager
import tech.relaycorp.letro.awala.processor.AwalaMessageProcessor
import tech.relaycorp.letro.messages.dto.NewMessageIncomingMessage
import tech.relaycorp.letro.messages.parser.NewMessageMessageParser
import tech.relaycorp.letro.messages.storage.MessagesDao
import javax.inject.Inject

interface NewMessageProcessor : AwalaMessageProcessor

class NewMessageProcessorImpl @Inject constructor(
private val parser: NewMessageMessageParser,
private val messagesDao: MessagesDao,
) : NewMessageProcessor {
override suspend fun process(message: IncomingMessage, awalaManager: AwalaManager) {
val parsedMessage = (parser.parse(message.content) as NewMessageIncomingMessage).content
messagesDao.insert(parsedMessage)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ const val TABLE_NAME_CONVERSATIONS = "conversations"
@Entity(
tableName = TABLE_NAME_CONVERSATIONS,
)
/**
* @param keyId - primary key for the conversations table. Autogenerated.
* @param conversationId - Unique ID of a conversation
* @param ownerVeraId - ID of the account, which this conversation belongs (for display this conversation only for a particular account)
* @param contactVeraId - ID of the contact
* @param subject - the subject of the conversation
*/
data class Conversation(
@PrimaryKey(autoGenerate = true)
val keyId: Long = 0L,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ const val TABLE_NAME_MESSAGES = "messages"
@Entity(
tableName = TABLE_NAME_MESSAGES,
)
/**
* @param id - primary key for the messages table. Autogenerated.
* @param conversationId - Unique ID of a conversation, which the message belongs to
* @param text - text of the message
* @param ownerVeraId - ID of the account, which this conversation belongs to (for display this message only for a particular account)
* @param recipientVeraId - the ID of the recipient of the message
* @param senderVeraId - the ID of the sender of the message
* @param sentAt - timestamp where this message was sent (or received)
*/
data class Message(
@PrimaryKey(autoGenerate = true)
val id: Long = 0L,
Expand Down

0 comments on commit 5a2df50

Please sign in to comment.