-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* module: AI 데이터 명세를 정의하는 :data:ai 모듈 추가 * feature: 쿠링봇 메시지 domain 객체 추가 * feature: 쿠링봇 로직에 필요한 유틸 코드 추가 * feature: 쿠링봇 메시지 domain - entity 변환 코드 추가 * feature: 쿠링봇 메시지 repository 인터페이스 작성 * refactor: KuringBotClient에 특정 프로토콜을 명시하지 않음 * feature: 쿠링봇 메시지 repository 구현체 작성 * test: 쿠링봇 메시지 repository 구현체 테스트 코드 작성 * refactor: 쿠링봇 메시지 repository의 hilt 모듈 작성 * test: 테스트 코드의 람다식 이름 변경 Co-authored-by: HyunWoo Lee (Nunu Lee) <[email protected]> --------- Co-authored-by: HyunWoo Lee (Nunu Lee) <[email protected]>
- Loading branch information
Showing
16 changed files
with
256 additions
and
9 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
core/util/src/main/java/com/ku_stacks/ku_ring/util/DateTimeUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.ku_stacks.ku_ring.util | ||
|
||
import java.time.Instant | ||
import java.time.LocalDate | ||
import java.time.LocalDateTime | ||
import java.time.YearMonth | ||
import java.time.ZoneOffset | ||
|
||
val LocalDateTime.yearMonth: YearMonth | ||
get() = YearMonth.of(this.year, this.monthValue) | ||
|
||
fun Long.toLocalDateTime(): LocalDateTime = | ||
LocalDateTime.ofInstant(Instant.ofEpochSecond(this), ZoneOffset.systemDefault()) | ||
|
||
fun LocalDateTime.toEpochSecond() = atZone(ZoneOffset.systemDefault()).toEpochSecond() | ||
|
||
fun LocalDate.toEpochSecond() = atStartOfDay(ZoneOffset.systemDefault()).toEpochSecond() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import com.ku_stacks.ku_ring.buildlogic.dsl.setNameSpace | ||
|
||
plugins { | ||
kuring("feature") | ||
kuringPrimitive("room") | ||
kuringPrimitive("ktor") | ||
kuringPrimitive("test") | ||
} | ||
|
||
android { | ||
setNameSpace("ai") | ||
|
||
testOptions { | ||
unitTests { | ||
isIncludeAndroidResources = true | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation(projects.core.util) | ||
implementation(projects.data.domain) | ||
implementation(projects.data.remote) | ||
implementation(projects.data.local) | ||
|
||
testImplementation(libs.kotlinx.coroutines.test) | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest> | ||
|
||
</manifest> |
17 changes: 17 additions & 0 deletions
17
data/ai/src/main/java/com/ku_stacks/ku_ring/ai/di/RepositoryModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.ku_stacks.ku_ring.ai.di | ||
|
||
import com.ku_stacks.ku_ring.ai.repository.KuringBotRepository | ||
import com.ku_stacks.ku_ring.ai.repository.KuringBotRepositoryImpl | ||
import dagger.Binds | ||
import dagger.Module | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
abstract class RepositoryModule { | ||
@Binds | ||
@Singleton | ||
abstract fun bindKuringBotMessageRepository(repositoryImpl: KuringBotRepositoryImpl): KuringBotRepository | ||
} |
14 changes: 14 additions & 0 deletions
14
data/ai/src/main/java/com/ku_stacks/ku_ring/ai/mapper/DomainToEntityMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.ai.mapper | ||
|
||
import com.ku_stacks.ku_ring.domain.KuringBotMessage | ||
import com.ku_stacks.ku_ring.local.entity.KuringBotMessageEntity | ||
import com.ku_stacks.ku_ring.util.toEpochSecond | ||
|
||
internal fun KuringBotMessage.toEntity() = KuringBotMessageEntity( | ||
id = id, | ||
message = message, | ||
postedEpochSeconds = postedDate.toEpochSecond(), | ||
isQuery = isQuery, | ||
) | ||
|
||
internal fun List<KuringBotMessage>.toEntity() = map { it.toEntity() } |
14 changes: 14 additions & 0 deletions
14
data/ai/src/main/java/com/ku_stacks/ku_ring/ai/mapper/EntityToDomainMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.ku_stacks.ku_ring.ai.mapper | ||
|
||
import com.ku_stacks.ku_ring.domain.KuringBotMessage | ||
import com.ku_stacks.ku_ring.local.entity.KuringBotMessageEntity | ||
import com.ku_stacks.ku_ring.util.toLocalDateTime | ||
|
||
internal fun KuringBotMessageEntity.toDomain() = KuringBotMessage( | ||
id = id, | ||
message = message, | ||
postedDate = postedEpochSeconds.toLocalDateTime(), | ||
isQuery = isQuery, | ||
) | ||
|
||
internal fun List<KuringBotMessageEntity>.toDomain() = map { it.toDomain() } |
51 changes: 51 additions & 0 deletions
51
data/ai/src/main/java/com/ku_stacks/ku_ring/ai/repository/KuringBotRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.ku_stacks.ku_ring.ai.repository | ||
|
||
import com.ku_stacks.ku_ring.domain.KuringBotMessage | ||
import java.time.LocalDate | ||
|
||
interface KuringBotRepository { | ||
/** | ||
* 쿠링봇 메시지 세션을 열고, 서버로부터 데이터가 주어졌을 때 작업을 실행한다. | ||
* | ||
* @param query 질문 내용 | ||
* @param token 사용자 FCM 토큰 | ||
* @param onReceived 데이터를 수신했을 때 실행할 작업 | ||
*/ | ||
suspend fun openKuringBotSession( | ||
query: String, | ||
token: String, | ||
onReceived: (String) -> Unit, | ||
) | ||
|
||
/** | ||
* 로컬 DB에 저장된 쿠링봇 메시지를 모두 반환한다. | ||
* | ||
* @return 로컬에 저장된 모든 쿠링봇 메시지 | ||
*/ | ||
suspend fun getAllMessages(): List<KuringBotMessage> | ||
|
||
/** | ||
* 로컬 DB에 쿠링봇 메시지 여러 개를 저장한다. | ||
* 이미 저장되어 있는 메시지는 중복으로 저장되지 않는다. | ||
* | ||
* @param messages 로컬에 저장할 메시지 | ||
*/ | ||
suspend fun insertMessages(messages: List<KuringBotMessage>) | ||
|
||
/** | ||
* 로컬 DB에 쿠링봇 메시지를 저장한다. | ||
* 이미 저장되어 있는 메시지라면, 아무 일도 일어나지 않는다. | ||
* | ||
* @param message 로컬에 저장할 메시지 | ||
*/ | ||
suspend fun insertMessage(message: KuringBotMessage) | ||
|
||
/** | ||
* 지정된 기간 동안에 전송한 질문의 수를 반환한다. | ||
* | ||
* @param from 기간의 시작 | ||
* @param to 기간의 끝 | ||
* @return [from]부터 [to]까지 전송한 질문의 수 (inclusive) | ||
*/ | ||
suspend fun getQueryCount(from: LocalDate, to: LocalDate): Int | ||
} |
48 changes: 48 additions & 0 deletions
48
data/ai/src/main/java/com/ku_stacks/ku_ring/ai/repository/KuringBotRepositoryImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.ku_stacks.ku_ring.ai.repository | ||
|
||
import com.ku_stacks.ku_ring.ai.mapper.toDomain | ||
import com.ku_stacks.ku_ring.ai.mapper.toEntity | ||
import com.ku_stacks.ku_ring.domain.KuringBotMessage | ||
import com.ku_stacks.ku_ring.local.room.KuringBotMessageDao | ||
import com.ku_stacks.ku_ring.remote.kuringbot.KuringBotClient | ||
import com.ku_stacks.ku_ring.util.toEpochSecond | ||
import java.time.LocalDate | ||
import javax.inject.Inject | ||
|
||
class KuringBotRepositoryImpl @Inject constructor( | ||
private val kuringBotClient: KuringBotClient, | ||
private val kuringBotMessageDao: KuringBotMessageDao, | ||
) : KuringBotRepository { | ||
|
||
override suspend fun openKuringBotSession( | ||
query: String, | ||
token: String, | ||
onReceived: (String) -> Unit, | ||
) { | ||
try { | ||
kuringBotClient.openKuringBotConnection(query, token, onReceived) | ||
} catch (e: Exception) { | ||
onReceived(UNKNOWN_ERROR) | ||
} | ||
} | ||
|
||
override suspend fun getAllMessages(): List<KuringBotMessage> { | ||
return kuringBotMessageDao.getAllMessages().toDomain() | ||
} | ||
|
||
override suspend fun insertMessages(messages: List<KuringBotMessage>) { | ||
kuringBotMessageDao.insertMessages(messages.toEntity()) | ||
} | ||
|
||
override suspend fun insertMessage(message: KuringBotMessage) { | ||
kuringBotMessageDao.insertMessage(message.toEntity()) | ||
} | ||
|
||
override suspend fun getQueryCount(from: LocalDate, to: LocalDate): Int { | ||
return kuringBotMessageDao.getQueryCount(from.toEpochSecond(), to.toEpochSecond()) | ||
} | ||
|
||
companion object { | ||
internal const val UNKNOWN_ERROR = "예상치 못한 오류가 발생했어요. 다음에 다시 시도해 주세요." | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
data/ai/src/test/java/com/ku_stacks/ku_ring/ai/KuringBotRepositoryImplTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.ku_stacks.ku_ring.ai | ||
|
||
import com.ku_stacks.ku_ring.ai.repository.KuringBotRepository | ||
import com.ku_stacks.ku_ring.ai.repository.KuringBotRepositoryImpl | ||
import com.ku_stacks.ku_ring.local.room.KuringBotMessageDao | ||
import com.ku_stacks.ku_ring.remote.kuringbot.KuringBotClient | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.mockito.Mockito | ||
import org.mockito.exceptions.base.MockitoException | ||
|
||
class KuringBotRepositoryImplTest { | ||
private val kuringBotClient = Mockito.mock(KuringBotClient::class.java) | ||
private val dao = Mockito.mock(KuringBotMessageDao::class.java) | ||
private lateinit var repository: KuringBotRepository | ||
|
||
private val query = "교내,외 장학금 및 학자금 대출 관련 전화번호들을 안내를 해줘" | ||
|
||
@Before | ||
fun setup() { | ||
repository = KuringBotRepositoryImpl(kuringBotClient, dao) | ||
} | ||
|
||
@Test | ||
fun `test when exception is thrown`() = runTest { | ||
val tokens = mutableListOf<String>() | ||
val onReceived: (String) -> Unit = { data -> | ||
tokens.add(data) | ||
} | ||
|
||
// given | ||
val token = System.currentTimeMillis().toString() | ||
Mockito.`when`(kuringBotClient.openKuringBotConnection(query, token, onReceived)) | ||
.thenThrow(MockitoException("test exception")) | ||
|
||
// when | ||
repository.openKuringBotSession(query, token, onReceived) | ||
|
||
// then | ||
assert(tokens.size == 1) | ||
assert(tokens.contains(KuringBotRepositoryImpl.UNKNOWN_ERROR)) | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
data/domain/src/main/java/com/ku_stacks/ku_ring/domain/KuringBotMessage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.ku_stacks.ku_ring.domain | ||
|
||
import java.time.LocalDateTime | ||
|
||
data class KuringBotMessage( | ||
val id: Int, | ||
val message: String, | ||
val postedDate: LocalDateTime, | ||
val isQuery: Boolean, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters