Skip to content

Commit

Permalink
build: 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cssxsh committed Mar 18, 2023
1 parent 44a0e78 commit a41a241
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 29 deletions.
Binary file added .github/afdian.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# [Mirai New Bing](https://github.com/cssxsh/mirai-new-bing)

> 基于 Mirai Console 的 New Bing Chat Bot 插件
[![maven-central](https://img.shields.io/maven-central/v/xyz.cssxsh.mirai/mirai-new-bing)](https://search.maven.org/artifact/xyz.cssxsh.mirai/mirai-new-bing)
[![test](https://github.com/cssxsh/mirai-new-bing/actions/workflows/test.yml/badge.svg)](https://github.com/cssxsh/mirai-new-bing/actions/workflows/test.yml)

## 安装

### MCL 指令安装

**请确认 mcl.jar 的版本是 2.1.0+**
`./mcl --update-package xyz.cssxsh.mirai:mirai-new-bing --channel maven-stable --type plugins`

### 手动安装

1.[Releases](https://github.com/cssxsh/mirai-new-bing/releases) 或者 [Maven](https://repo1.maven.org/maven2/xyz/cssxsh/mirai/mirai-new-bing/) 下载 `mirai2.jar`
2. 将其放入 `plugins` 文件夹中

## [爱发电](https://afdian.net/@cssxsh)

![afdian](.github/afdian.jpg)
50 changes: 23 additions & 27 deletions src/main/kotlin/xyz/cssxsh/bing/NewBingClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import kotlinx.serialization.*
import kotlinx.serialization.json.*
import org.slf4j.*
import java.util.*
import kotlin.coroutines.*

public open class NewBingClient(@PublishedApi internal val config: NewBingConfig) : CoroutineScope {
public open class NewBingClient(@PublishedApi internal val config: NewBingConfig) {
public companion object {
public const val RS: String = "\u001E"
}
Expand All @@ -45,7 +44,6 @@ public open class NewBingClient(@PublishedApi internal val config: NewBingConfig
}
}
}
public override val coroutineContext: CoroutineContext = EmptyCoroutineContext
protected open val format: Json = Json
protected val shared: MutableSharedFlow<Pair<String, JsonObject>> = MutableSharedFlow()
@PublishedApi internal val uuid: UUID = UUID.randomUUID()
Expand Down Expand Up @@ -91,23 +89,40 @@ public open class NewBingClient(@PublishedApi internal val config: NewBingConfig
when (val frame = incoming.receive()) {
is Frame.Binary -> {
// TODO
logger.warn("Frame.Binary")
}
is Frame.Text -> {
for (text in frame.readText().splitToSequence(RS)) {
if (text.isEmpty()) continue
val item = format.decodeFromString(JsonObject.serializer(), text)
if (logger.isTraceEnabled) logger.trace(item.toString())
when (item["type"]?.jsonPrimitive?.int) {
1 -> {
// TODO
if (logger.isTraceEnabled) logger.trace(item.toString())
}
2 -> {
if (logger.isDebugEnabled) logger.debug(item.toString())
launch {
shared.emit(chat.clientId to item)
}
}
3 -> return
null -> Unit
3 -> {
if (logger.isDebugEnabled) logger.debug(item.toString())
return
}
6 -> {
if (logger.isDebugEnabled) logger.debug(item.toString())
// echo
launch {
sendJson {
put("type", 6)
}
}
continue
}
else -> {
if (item.isEmpty().not()) logger.warn(item.toString())
continue
}
}
}
}
Expand Down Expand Up @@ -139,36 +154,17 @@ public open class NewBingClient(@PublishedApi internal val config: NewBingConfig
for (option in config.options) {
add(option)
}
listOf(
"deepleo",
"nlu_direct_response_filter",
"disable_emoji_spoken_text",
"responsible_ai_policy_235",
"enablemm",
"dtappid",
"rai253",
"dv3sugg",
"harmonyv3"
).forEach {
add(it)
}
}
putJsonArray("allowedMessageTypes") {
for (type in config.allowed) {
add(type)
}
listOf(
"Chat",
"InternalSearchQuery"
).forEach {
add(it)
}
}
putJsonArray("sliceIds") {
// TODO
}
// XXX: traceId
put("isStartOfSession", true)
put("isStartOfSession", chat.index == 0)
put("conversationId", chat.conversationId)
put("conversationSignature", chat.conversationSignature)
putJsonObject("participant") {
Expand Down
28 changes: 28 additions & 0 deletions src/main/kotlin/xyz/cssxsh/mirai/bing/MiraiBingPermissions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package xyz.cssxsh.mirai.bing

import net.mamoe.mirai.console.permission.*
import net.mamoe.mirai.event.*
import kotlin.properties.*
import kotlin.reflect.*

@PublishedApi
internal object MiraiBingPermissions : ReadOnlyProperty<SimpleListenerHost, Permission> {
private val records: MutableMap<String, Permission> = HashMap()

@Synchronized
override fun getValue(thisRef: SimpleListenerHost, property: KProperty<*>): Permission {
return records[property.name] ?: kotlin.run {
val permission = PermissionService.INSTANCE.register(
id = MiraiNewBing.permissionId(property.name),
description = "触发 ${property}_prefix",
parent = MiraiNewBing.parentPermission
)

records[property.name] = permission

MiraiNewBing.logger.info("${property.name}_prefix 权限 ${permission.id}")

permission
}
}
}
24 changes: 22 additions & 2 deletions src/main/kotlin/xyz/cssxsh/mirai/bing/MiraiNewBing.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package xyz.cssxsh.mirai.bing

import kotlinx.coroutines.*
import net.mamoe.mirai.console.data.*
import net.mamoe.mirai.console.plugin.jvm.*
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.console.util.*
import net.mamoe.mirai.event.*

public object MiraiNewBing : KotlinPlugin(
JvmPluginDescription(
Expand All @@ -13,6 +16,23 @@ public object MiraiNewBing : KotlinPlugin(
}
) {
override fun onEnable() {
logger.info { "Plugin loaded" }
MiraiNewBingConfig.reload()
if (MiraiNewBingConfig.cookie.isEmpty()) {
val token = runBlocking { ConsoleInput.requestInput(hint = "请输入 New Bing Cookie") }

@OptIn(ConsoleExperimentalApi::class)
@Suppress("UNCHECKED_CAST")
val value = MiraiNewBingConfig.findBackingFieldValue<String>("cookie") as Value<String>
value.value = token

}
MiraiNewBingConfig.save()

MiraiNewBingListener.chat
MiraiNewBingListener.registerTo(globalEventChannel())
}

override fun onDisable() {
MiraiNewBingListener.cancel()
}
}
46 changes: 46 additions & 0 deletions src/main/kotlin/xyz/cssxsh/mirai/bing/MiraiNewBingConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package xyz.cssxsh.mirai.bing

import net.mamoe.mirai.console.data.*
import xyz.cssxsh.bing.*

public object MiraiNewBingConfig : ReadOnlyPluginConfig("openai"), NewBingConfig {
@ValueName("proxy")
override val proxy: String by value("socks://127.0.0.1:7890")

@ValueName("doh")
override val doh: String by value("https://public.dns.iij.jp/dns-query")

@ValueName("ipv6")
override val ipv6: Boolean by value(true)

@ValueName("timeout")
override val timeout: Long by value(30_000L)

@ValueName("cookie")
override val cookie: String by value("")

@ValueName("device")
override val device: String by value("azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/MacIntel")

@ValueName("options")
override val options: List<String> by value(listOf(
"deepleo",
"nlu_direct_response_filter",
"disable_emoji_spoken_text",
"responsible_ai_policy_235",
"enablemm",
"dtappid",
"rai253",
"dv3sugg",
"harmonyv3"
))

@ValueName("allowed_message_types")
override val allowed: List<String> by value(listOf(
"Chat",
"InternalSearchQuery"
))

@ValueName("chat_prefix")
public val prefix: String by value("bing")
}
68 changes: 68 additions & 0 deletions src/main/kotlin/xyz/cssxsh/mirai/bing/MiraiNewBingListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package xyz.cssxsh.mirai.bing

import kotlinx.coroutines.*
import kotlinx.serialization.json.*
import net.mamoe.mirai.console.command.CommandSender.Companion.toCommandSender
import net.mamoe.mirai.console.permission.*
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.*
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.utils.*
import xyz.cssxsh.bing.*
import kotlin.coroutines.*

@PublishedApi
internal object MiraiNewBingListener : SimpleListenerHost() {
private val client = object : NewBingClient(config = MiraiNewBingConfig) {
init {
launch {
shared.collect { (clientId, data) ->
val item = data["item"] as? JsonObject ?: return@collect
val messages = item["messages"] as? JsonArray ?: return@collect
for (message in messages) {
message as? JsonObject ?: continue
val author = message["author"]?.jsonPrimitive?.content ?: continue
if ("bot" != author) continue
val (id, _) = chats.entries.find { it.value.clientId == clientId } ?: continue
val subject = contacts[id] ?: continue
val text = message["text"]?.jsonPrimitive?.content ?: continue

launch {
subject.sendMessage(text)
}
}
}
}
}
}
private val logger = MiraiLogger.Factory.create(this::class)
internal val chat: Permission by MiraiBingPermissions
private val chats: MutableMap<String, NewBingChat> = java.util.concurrent.ConcurrentHashMap()
private val contacts: MutableMap<String, Contact> = java.util.concurrent.ConcurrentHashMap()

override fun handleException(context: CoroutineContext, exception: Throwable) {
when (exception) {
is CancellationException -> {
// ...
}
is ExceptionInEventHandlerException -> {
logger.warning({ "MiraiNewBingListener with ${exception.event}" }, exception.cause)
}
else -> Unit
}
}

@EventHandler(concurrency = ConcurrencyKind.CONCURRENT)
suspend fun MessageEvent.handle() {
val content = message.contentToString()
if (content.startsWith(MiraiNewBingConfig.prefix).not()) return

val id = toCommandSender().permitteeId.asString()
val cache = chats[id] ?: client.create()
chats[id] = cache
contacts[id] = subject
launch {
client.send(cache, content.removePrefix(MiraiNewBingConfig.prefix))
}
}
}

0 comments on commit a41a241

Please sign in to comment.