Files
JChatGPT/src/test/kotlin/profile/ProfileHistoryReaderTest.kt
T

165 lines
7.1 KiB
Kotlin

package top.jie65535.mirai.profile
import net.mamoe.mirai.message.data.MessageSourceKind
import java.nio.file.Files
import java.sql.DriverManager
import kotlin.io.path.absolutePathString
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class ProfileHistoryReaderTest {
@Test
fun keepsEqualTimestampTargetMessagesTogetherAndLoadsGroupContext() {
val directory = Files.createTempDirectory("jchatgpt-profile-history-test-")
val database = directory.resolve("history.sqlite")
try {
DriverManager.getConnection("jdbc:sqlite:${database.absolutePathString()}").use { connection ->
connection.createStatement().use { statement ->
statement.executeUpdate(
"""
CREATE TABLE message_record(
id INTEGER PRIMARY KEY AUTOINCREMENT,
bot_id INTEGER NOT NULL,
from_id INTEGER NOT NULL,
target_id INTEGER NOT NULL,
ids TEXT,
internal_ids TEXT,
time INTEGER NOT NULL,
kind INTEGER NOT NULL,
code TEXT NOT NULL,
recalled INTEGER NOT NULL DEFAULT 0
)
""".trimIndent()
)
}
connection.prepareStatement(
"INSERT INTO message_record(" +
"bot_id, from_id, target_id, time, kind, code, recalled" +
") VALUES (1, ?, ?, ?, ?, ?, ?)"
).use { statement ->
fun insert(
fromId: Long,
groupId: Long,
time: Int,
text: String,
kind: MessageSourceKind = MessageSourceKind.GROUP,
recalled: Int = 0,
) {
statement.setLong(1, fromId)
statement.setLong(2, groupId)
statement.setInt(3, time)
statement.setInt(4, kind.ordinal)
statement.setString(5, """[{"type":"PlainText","content":"$text"}]""")
statement.setInt(6, recalled)
statement.executeUpdate()
}
insert(TARGET, 10, 100, "目标发言一")
insert(OTHER, 10, 110, "用于理解语境的回复")
insert(OTHER, 10, 110, "同一秒的补充回复")
insert(TARGET, 10, 130, "目标发言二")
insert(TARGET, 20, 130, "同一秒的另一群发言")
insert(OTHER, 20, 140, "后续上下文")
insert(TARGET, 10, 200, "下一批目标发言")
insert(TARGET, 30, 300, "私聊消息", kind = MessageSourceKind.FRIEND)
insert(TARGET, 40, 400, "已撤回群消息", recalled = 1)
}
}
val reader = ProfileHistoryReader(database.toFile())
assertEquals(listOf(10L, 20L), reader.listGroupTimeBounds().map { it.groupId })
val bounds = assertNotNull(reader.findUserTimeBounds(TARGET))
assertEquals(100, bounds.startTime)
assertEquals(201, bounds.endTime)
val first = assertNotNull(
reader.loadNextBatch(
userId = TARGET,
startTime = bounds.startTime,
snapshotEndTime = bounds.endTime,
targetMessageLimit = 2,
maxEpisodes = 1,
episodeGapSeconds = 60,
contextBeforeMessages = 2,
contextAfterMessages = 2,
contextCoreMessages = 20,
maxMessageChars = 200,
)
)
assertEquals(131, first.endTime)
assertEquals(3, first.evidenceByRef.values.count { it.record.fromId == TARGET })
assertTrue(first.messages.any { it.record.fromId == OTHER })
assertEquals("TARGET", first.aliases[TARGET])
val second = assertNotNull(
reader.loadNextBatch(
userId = TARGET,
startTime = first.endTime,
snapshotEndTime = bounds.endTime,
targetMessageLimit = 2,
maxEpisodes = 10,
episodeGapSeconds = 60,
contextBeforeMessages = 2,
contextAfterMessages = 2,
contextCoreMessages = 20,
maxMessageChars = 200,
)
)
assertEquals(201, second.endTime)
assertEquals(1, second.evidenceByRef.values.count { it.record.fromId == TARGET })
val conversation = assertNotNull(
reader.loadConversationBatch(
botId = 1,
groupId = 10,
startTime = 90,
endTime = 150,
messageLimit = 10,
maxMessageChars = 200,
)
)
assertTrue(conversation.authoredTextCharsByUser.getValue(TARGET) > 0)
assertTrue(conversation.messages.all { it.record.targetId == 10L })
assertTrue(conversation.messages.all { it.record.time in 90 until 150 })
val groupBounds = assertNotNull(reader.findGroupTimeBounds(10))
assertEquals(1, groupBounds.botId)
assertEquals(10L, groupBounds.groupId)
assertEquals(100, groupBounds.startTime)
assertEquals(201, groupBounds.endTime)
val firstGroupBatch = assertNotNull(
reader.loadNextConversationBatch(
botId = groupBounds.botId,
groupId = 10,
startTime = groupBounds.startTime,
snapshotEndTime = groupBounds.endTime,
messageLimit = 2,
maxMessageChars = 200,
)
)
assertEquals(111, firstGroupBatch.endTime)
assertEquals(listOf(100, 110, 110), firstGroupBatch.messages.map { it.record.time })
val secondGroupBatch = assertNotNull(
reader.loadNextConversationBatch(
botId = groupBounds.botId,
groupId = 10,
startTime = firstGroupBatch.endTime,
snapshotEndTime = groupBounds.endTime,
messageLimit = 2,
maxMessageChars = 200,
)
)
assertEquals(201, secondGroupBatch.endTime)
assertEquals(listOf(130, 200), secondGroupBatch.messages.map { it.record.time })
} finally {
directory.toFile().deleteRecursively()
}
}
companion object {
private const val TARGET = 100L
private const val OTHER = 200L
}
}