Skip to content

Commit 9631c31

Browse files
committed
1
1 parent 6ccfd7d commit 9631c31

7 files changed

Lines changed: 208 additions & 167 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
}
88

99
group = "cn.mpsmc"
10-
version = "0.1.0"
10+
version = "0.2.1"
1111

1212
repositories {
1313
maven("https://maven.aliyun.com/repository/public")

src/main/kotlin/API.kt

Lines changed: 0 additions & 102 deletions
This file was deleted.

src/main/kotlin/Assistants.kt

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package cn.mpsmc
2+
3+
import io.ktor.client.*
4+
import io.ktor.client.call.*
5+
import io.ktor.client.engine.*
6+
import io.ktor.client.engine.okhttp.*
7+
import io.ktor.client.plugins.*
8+
import io.ktor.client.plugins.contentnegotiation.*
9+
import io.ktor.client.request.*
10+
import io.ktor.http.*
11+
import io.ktor.serialization.kotlinx.json.*
12+
import kotlinx.coroutines.runBlocking
13+
import kotlinx.serialization.Serializable
14+
15+
16+
@Serializable
17+
data class RequestObject(
18+
val model: String,
19+
val messages: List<Message>
20+
)
21+
22+
@Serializable
23+
data class ReceivedObject(
24+
val id: String,
25+
val `object`: String,
26+
val created: Long,
27+
val model: String,
28+
val usage: Usage,
29+
val choices: List<Choice>,
30+
)
31+
32+
@Serializable
33+
data class Usage(
34+
val prompt_tokens: Long,
35+
val completion_tokens: Long,
36+
val total_tokens: Long,
37+
)
38+
39+
@Serializable
40+
data class Choice(
41+
val message: Message,
42+
val finish_reason: String,
43+
val index: Long,
44+
)
45+
46+
@Serializable
47+
data class Message(
48+
val role: String,
49+
val content: String,
50+
)
51+
52+
53+
class UserDataHandler(private val source: String) {
54+
init {
55+
if (Data.lastChatTime[source] != null)
56+
if (Config.expirationTime != -1 && ((System.currentTimeMillis() / 1000)) - Data.lastChatTime[source]!! >= Config.expirationTime)
57+
Data.historicalMessages.remove(source)
58+
}
59+
60+
val cooldown: Long
61+
get() = if (Data.lastChatTime[source] != null && Config.cooldown != -1) (Config.cooldown - ((System.currentTimeMillis() / 1000) - Data.lastChatTime[source]!!)) else -1
62+
63+
fun updateLastChatTime() {
64+
Data.lastChatTime[source] = System.currentTimeMillis() / 1000
65+
}
66+
67+
fun removeAllFromHistoricalMessages(): Boolean = Data.historicalMessages.remove(source) != null
68+
fun getHistoricalMessages() = Data.historicalMessages[source] ?: mutableListOf()
69+
fun addElementToHistoricalMessages(msg: Message) {
70+
if (Data.historicalMessages[source] != null)
71+
Data.historicalMessages[source]?.add(msg)
72+
else
73+
Data.historicalMessages[source] = mutableListOf(msg)
74+
val msgs = Data.historicalMessages[source]!!
75+
var contentBytes = 0
76+
msgs.forEach {
77+
contentBytes += it.content.length
78+
}
79+
while (contentBytes > Config.maxCharacters) {
80+
contentBytes -= msgs.removeAt(0).content.length
81+
}
82+
Data.historicalMessages[source] = msgs
83+
}
84+
}
85+
86+
87+
object Client {
88+
private lateinit var client: HttpClient
89+
90+
fun close() = client.close()
91+
fun load() {
92+
client = HttpClient(OkHttp) {
93+
install(ContentNegotiation) {
94+
json()
95+
}
96+
install(HttpTimeout) {
97+
requestTimeoutMillis = Config.client.timeout
98+
socketTimeoutMillis = Config.client.timeout
99+
}
100+
engine {
101+
if (Config.client.httpProxyUrl != "")
102+
proxy = ProxyBuilder.http(Config.client.httpProxyUrl)
103+
if (Config.client.socksProxyUrl != "")
104+
proxy = ProxyBuilder.socks(Config.client.socksProxyUrl, Config.client.socksProxyPort)
105+
}
106+
}
107+
}
108+
109+
fun sendRequest(requestObject: RequestObject): ReceivedObject {
110+
return runBlocking {
111+
return@runBlocking client.post(Config.openAI.apiUrl) {
112+
headers {
113+
headers {
114+
append(HttpHeaders.Authorization, "Bearer ${Config.openAI.token}")
115+
}
116+
}
117+
contentType(ContentType.Application.Json)
118+
setBody(requestObject)
119+
}.body() as ReceivedObject
120+
}
121+
}
122+
}
123+
124+
125+

src/main/kotlin/BotGPT.kt

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,38 @@ import net.mamoe.mirai.event.GlobalEventChannel
1010
import net.mamoe.mirai.event.events.FriendMessageEvent
1111
import net.mamoe.mirai.event.events.GroupMessageEvent
1212
import net.mamoe.mirai.message.data.At
13-
import net.mamoe.mirai.message.data.MessageSource.Key.quote
1413
import net.mamoe.mirai.message.data.PlainText
1514
import net.mamoe.mirai.utils.info
1615

1716
object BotGPT : KotlinPlugin(
1817
JvmPluginDescription(
1918
id = "cn.mpsmc.botgpt",
2019
name = "BotGPT",
21-
version = "0.1.0",
20+
version = "0.2.1",
2221
) {
2322
author("sectly")
2423
}
2524
) {
2625

2726

2827
override fun onEnable() {
28+
logger.info { "MPSMC BotGPT 加载中" }
2929
Config.reload()
3030
Data.reload()
3131
Client.load()
32-
logger.info { "MPSMC BotGPT loaded" }
3332
val chatPermission = PermissionService.INSTANCE.register(permissionId("botgpt.chat"), "BotGPT聊天权限")
33+
logger.info { " _____ _ _____ _____ _____ " }
34+
logger.info { "| __ | ___ | |_ | __|| _ ||_ _|" }
35+
logger.info { "| __ -|| . || _|| | || __| | | " }
36+
logger.info { "|_____||___||_| |_____||__| |_| " }
37+
logger.info { "MPSMC BotGPT 已加载" }
3438
launch {
3539
GlobalEventChannel.parentScope(this).subscribeAlways<GroupMessageEvent> { event ->
3640
run {
37-
if (event.group.permitteeId.hasPermission(chatPermission) && (event.message[1] is At) && ((event.message[1] as At).target == event.bot.id) && (event.message[2] is PlainText)) {
41+
if (event.group.permitteeId.hasPermission(chatPermission) && (event.message[1] is At) && ((event.message[1] as At).target == event.bot.id) && event.message.size >= 3 && (event.message[2] is PlainText)) {
3842
event.group.sendMessage(
3943
chatEventHandler(
40-
sender.id,
41-
event.message.contentToString().removeRange(0 until event.bot.id.toString().length + 2),
42-
event.message.quote()
44+
event.group, event
4345
)
4446
)
4547
}
@@ -50,9 +52,7 @@ object BotGPT : KotlinPlugin(
5052
if (sender.permitteeId.hasPermission(chatPermission) && (event.message[1] is PlainText)) {
5153
event.sender.sendMessage(
5254
chatEventHandler(
53-
sender.id,
54-
event.message.contentToString(),
55-
event.message.quote()
55+
sender, event
5656
)
5757
)
5858
}
@@ -63,8 +63,6 @@ object BotGPT : KotlinPlugin(
6363

6464
override fun onDisable() {
6565
Client.close()
66-
logger.info { "MPSMC BotGPT unloaded" }
66+
logger.info { "MPSMC BotGPT 已卸载" }
6767
}
68-
}
69-
70-
68+
}

src/main/kotlin/Command.kt

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,53 @@
11
package cn.mpsmc
22

3-
import net.mamoe.mirai.message.data.MessageChain
4-
import net.mamoe.mirai.message.data.MessageChainBuilder
5-
import net.mamoe.mirai.message.data.PlainText
6-
import net.mamoe.mirai.message.data.QuoteReply
7-
import kotlin.math.absoluteValue
3+
import net.mamoe.mirai.contact.Contact
4+
import net.mamoe.mirai.contact.User
5+
import net.mamoe.mirai.event.events.MessageEvent
6+
import net.mamoe.mirai.message.data.*
7+
import net.mamoe.mirai.message.data.MessageSource.Key.quote
88

9-
fun chatEventHandler(idL: Long, message: String, quote: QuoteReply): MessageChain {
10-
val id = idL.toString()
11-
if (Data.lastChatTime[id] != null)
12-
if (Config.expirationTime != -1 && ((System.currentTimeMillis() / 1000)) - Data.lastChatTime[id]!! >= Config.expirationTime)
13-
Data.historicalMessages.remove(id)
14-
if (message == "清空会话")
15-
return MessageChainBuilder().append(quote)
16-
.append(if (Data.historicalMessages.remove(id) != null) "清空成功" else "清空失败").build()
9+
fun chatHandler(source: String, message: String): List<String> {
10+
val userData = UserDataHandler(source)
11+
if (message == Config.clearCommand)
12+
return listOf(if (userData.removeAllFromHistoricalMessages()) "清空成功" else "清空失败")
1713
else {
18-
val cd = checkCoolDown(id)
19-
BotGPT.logger.info(cd.toString())
20-
if (cd >= 0) {
21-
var finalMessage = ""
22-
var finalMessages: MutableList<String> = mutableListOf()
23-
val historicalMessages = Data.historicalMessages[id]
24-
Data.historicalMessages.remove(id)
25-
finalMessages.add(message)
26-
if (historicalMessages != null) {
27-
finalMessages = (historicalMessages + message).toMutableList()
28-
}
29-
for (i in finalMessages) {
30-
finalMessage += i + Config.separator
31-
}
32-
finalMessage = finalMessage.substring(0 until finalMessage.length - Config.separator.length)
33-
Data.lastChatTime[id] = System.currentTimeMillis() / 1000
34-
Data.historicalMessages[id] = finalMessages
35-
BotGPT.logger.info("$id -> $finalMessage")
36-
return try {
14+
return if (userData.cooldown <= 0) {
15+
userData.updateLastChatTime()
16+
userData.addElementToHistoricalMessages(Message("user", message))
17+
try {
3718
val response =
38-
Client.sendRequest(RequestObject(Config.model, listOf(Messages("user", finalMessage))))
39-
val content = (response.choices[0].message.content).trim()
40-
MessageChainBuilder().append(quote).append(PlainText(content)).build()
19+
Client.sendRequest(RequestObject(Config.openAI.model, userData.getHistoricalMessages().toList()))
20+
val c = (response.choices[0].message.content).trim()
21+
userData.addElementToHistoricalMessages(Message("assistant", c))
22+
userData.updateLastChatTime()
23+
c.split('\n')
4124
} catch (e: Exception) {
4225
BotGPT.logger.warning(e.message)
43-
MessageChainBuilder().append(quote).append(PlainText("内部错误")).build()
26+
userData.removeAllFromHistoricalMessages()
27+
listOf(Config.messages.errorMessage)
4428
}
4529
} else
46-
return MessageChainBuilder().append(quote).append(PlainText("冷却中 [${checkCoolDown(id).absoluteValue}]"))
47-
.build()
30+
return listOf(Config.messages.cooldownMessage.replace("%cd%", userData.cooldown.toString()))
31+
}
32+
}
33+
34+
fun chatEventHandler(context: Contact, event: MessageEvent): MessageChain {
35+
val message: String
36+
val source: String
37+
if (context is User) {
38+
message = event.message.contentToString()
39+
source = 'u' + context.id.toString()
40+
} else {
41+
message = event.message.contentToString().removeRange(0 until event.bot.id.toString().length + 2)
42+
source = 'g' + context.id.toString()
4843
}
44+
val apiReply = chatHandler(source, message)
45+
return if (apiReply.size > 1)
46+
buildForwardMessage(context, ForwardMessage.DisplayStrategy.Default) {
47+
for (i in apiReply)
48+
if (i.isNotEmpty())
49+
event.bot says PlainText(i)
50+
}.toMessageChain()
51+
else
52+
event.message.quote() + PlainText(apiReply[0]).toMessageChain()
4953
}

0 commit comments

Comments
 (0)