Implement multiplatform modules

This commit is contained in:
Him188 2022-05-18 20:54:47 +01:00
parent ce87400998
commit ff2a8acb0c
555 changed files with 10181 additions and 3918 deletions

View File

@ -16,15 +16,10 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPI
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import java.io.File
private val miraiPlatform = Attribute.of(
"net.mamoe.mirai.platform",
@ -35,6 +30,9 @@ private val miraiPlatform = Attribute.of(
fun Project.configureHMPPJvm() {
extensions.getByType(KotlinMultiplatformExtension::class.java).apply {
jvm("jvmBase") {
compilations.all {
this.compileKotlinTask.enabled = false // IDE complain
}
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) // avoid resolving by others
// attributes.attribute(miraiPlatform, "jvmBase")
}
@ -57,16 +55,18 @@ fun Project.configureHMPPJvm() {
val nativeMainSets = mutableListOf<KotlinSourceSet>()
val nativeTestSets = mutableListOf<KotlinSourceSet>()
val nativeTargets = mutableListOf<KotlinNativeTarget>()
if (ideaActive) {
when {
val target = when {
Os.isFamily(Os.FAMILY_MAC) -> if (Os.isArch("aarch64")) macosArm64("native") else macosX64("native")
Os.isFamily(Os.FAMILY_WINDOWS) -> mingwX64("native")
else -> linuxX64("native")
}
nativeTargets.add(target)
} else {
// 1.6.0
val nativeTargets: List<String> = arrayOf(
val nativeTargetNames: List<String> = arrayOf(
// serialization doesn't support those commented targets
// "androidNativeArm32, androidNativeArm64, androidNativeX86, androidNativeX64",
"iosArm32, iosArm64, iosX64, iosSimulatorArm64",
@ -77,11 +77,12 @@ fun Project.configureHMPPJvm() {
"mingwX64",
// "wasm32" // linuxArm32Hfp, mingwX86
).flatMap { it.split(",") }.map { it.trim() }
presets.filter { it.name in nativeTargets }
presets.filter { it.name in nativeTargetNames }
.forEach { preset ->
val target = targetFromPreset(preset, preset.name)
val target = targetFromPreset(preset, preset.name) as KotlinNativeTarget
nativeMainSets.add(target.compilations[MAIN_COMPILATION_NAME].kotlinSourceSets.first())
nativeTestSets.add(target.compilations[TEST_COMPILATION_NAME].kotlinSourceSets.first())
nativeTargets.add(target)
}
if (!ideaActive) {
@ -95,31 +96,8 @@ fun Project.configureHMPPJvm() {
}
}
// nativeTarget.apply {
// val myrust by compilations.getByName("main").cinterops.creating {
// headers(project.projectDir.resolve("untitled/myrust.h"))
// }
//
// binaries {
// sharedLib {
// linkerOpts("-v")
// linkerOpts("-L${project.projectDir.resolve("untitled/target/debug/").absolutePath}")
//// linkerOpts("-lmyrust")
// linkerOpts("-Wl,-undefined,dynamic_lookup") // resolve symbols in runtime
// baseName = "mykotlin"
// }
//
// executable {
//
// linkerOpts("-v")
// linkerOpts("-L${project.projectDir.resolve("untitled/target/debug/").absolutePath}")
//// linkerOpts("-lmyrust")
// linkerOpts("-Wl,-undefined,dynamic_lookup") // resolve symbols in runtime
// baseName = "KotlinExecutable"
// entryPoint = "main.main"
// }
// }
// }
configureNativeInterop("main", projectDir.resolve("src/nativeMainInterop"), nativeTargets)
configureNativeInterop("test", projectDir.resolve("src/nativeTestInterop"), nativeTargets)
val sourceSets = kotlinSourceSets.orEmpty()
@ -143,9 +121,181 @@ fun Project.configureHMPPJvm() {
androidMain.dependsOn(jvmBaseMain)
jvmTest.dependsOn(jvmBaseTest)
androidTest.dependsOn(commonTest)
androidTest.dependsOn(jvmBaseTest)
nativeMain.dependsOn(commonMain)
nativeTest.dependsOn(commonTest)
}
}
private fun Project.linkerDirs(): List<String> {
return listOf(
":mirai-core",
":mirai-core-api",
":mirai-core-utils",
).map {
rootProject.project(it).projectDir.resolve("src/nativeMainInterop/target/debug/").absolutePath
}
}
private fun Project.includeDirs(): List<String> {
return listOf(
":mirai-core",
":mirai-core-api",
":mirai-core-utils",
).map {
rootProject.project(it).projectDir.resolve("src/nativeMainInterop/").absolutePath
}
}
private fun Project.configureNativeInterop(
compilationName: String,
nativeInteropDir: File,
nativeTargets: MutableList<KotlinNativeTarget>
) {
val crateName = project.name.replace("-", "_") + "_i"
configure(nativeTargets) {
binaries {
for (buildType in NativeBuildType.values()) {
findTest(buildType)?.apply {
linkerOpts("-v")
linkerOpts(*linkerDirs().map { "-L$it" }.toTypedArray())
linkerOpts("-undefined", "dynamic_lookup") // resolve symbol in runtime
}
}
}
}
if (nativeInteropDir.exists() && nativeInteropDir.isDirectory && nativeInteropDir.resolve("build.rs").exists()) {
val kotlinDylibName = project.name.replace("-", "_") + "_i"
val kotlinDylibName = project.name.replace("-", "_")
val headerName = "$crateName.h"
val rustLibDir = nativeInteropDir.resolve("target/debug/")
var interopTaskName = ""
configure(nativeTargets) {
interopTaskName = compilations.getByName(compilationName).cinterops.create(compilationName) {
defFile(nativeInteropDir.resolve("interop.def"))
val headerFile = nativeInteropDir.resolve(headerName)
if (headerFile.exists()) headers(headerFile)
}.interopProcessingTaskName
binaries {
sharedLib {
linkerOpts("-v")
linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
// linkerOpts("-lmirai_core_utils_i")
linkerOpts("-undefined", "dynamic_lookup")
baseName = project.name
}
getTest(NativeBuildType.DEBUG).apply {
linkerOpts("-v")
linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
linkerOpts("-lmirai_core_utils_i")
// linkerOpts("-undefined", "dynamic_lookup")
}
}
}
val cbindgen = tasks.register("cbindgen${compilationName.titlecase()}") {
group = "mirai"
description = "Generate C Headers from Rust"
inputs.files(
project.objects.fileTree().from(nativeInteropDir.resolve("src"))
.filterNot { it.name == "bindings.rs" }
)
outputs.file(nativeInteropDir.resolve(headerName))
doLast {
exec {
workingDir(nativeInteropDir)
commandLine(
"cbindgen",
"--config", "cbindgen.toml",
"--crate", crateName,
"--output", headerName
)
}
}
}
val generateRustBindings = tasks.register("generateRustBindings${compilationName.titlecase()}") {
group = "mirai"
description = "Generates Rust bindings for Kotlin"
dependsOn(cbindgen)
}
afterEvaluate {
val cinteropTask = tasks.getByName(interopTaskName)
cinteropTask.mustRunAfter(cbindgen)
generateRustBindings.get().dependsOn(cinteropTask)
}
val bindgen = tasks.register("bindgen${compilationName.titlecase()}") {
group = "mirai"
val bindingsPath = nativeInteropDir.resolve("src/bindings.rs")
val headerFile = buildDir.resolve("bin/native/debugShared/lib${kotlinDylibName}_api.h")
inputs.files(headerFile)
outputs.file(bindingsPath)
mustRunAfter(tasks.findByName("linkDebugSharedNative"))
doLast {
exec {
workingDir(nativeInteropDir)
// bindgen input.h -o bindings.rs
commandLine(
"bindgen",
headerFile,
"-o", bindingsPath,
)
}
}
}
val generateKotlinBindings = tasks.register("generateKotlinBindings${compilationName.titlecase()}") {
group = "mirai"
description = "Generates Kotlin bindings for Rust"
dependsOn(bindgen)
dependsOn(tasks.findByName("linkDebugSharedNative"))
}
var targetCompilation: KotlinNativeCompilation? = null
configure(nativeTargets) {
val compilations = compilations.filter { nativeInteropDir.name.contains(it.name, ignoreCase = true) }
check(compilations.isNotEmpty()) { "Should be at lease one corresponding native compilation, but found 0" }
targetCompilation = compilations.single()
// targetCompilation!!.compileKotlinTask.dependsOn(cbindgen)
// tasks.getByName("cinteropNative$name").dependsOn(cbindgen)
}
targetCompilation!!
val compileRust = tasks.register("compileRust${compilationName.titlecase()}") {
group = "mirai"
inputs.files(nativeInteropDir.resolve("src"))
outputs.file(rustLibDir.resolve("lib$crateName.dylib"))
// dependsOn(targetCompilation!!.compileKotlinTask)
dependsOn(bindgen)
dependsOn(tasks.findByName("linkDebugSharedNative")) // dylib to link
doLast {
exec {
workingDir(nativeInteropDir)
commandLine(
"cargo",
"build",
"--color", "always",
"--all",
// "--", "--color", "always", "2>&1"
)
}
}
}
tasks.getByName("assemble").dependsOn(compileRust)
}
}
fun String.titlecase(): String {
if (this.isEmpty()) return this
val c = get(0)
return replaceFirst(c, Character.toTitleCase(c))
}

View File

@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
fun Project.useIr() {
@ -41,7 +42,6 @@ fun Project.preConfigureJvmTarget() {
val defaultVer = jvmVersion()
tasks.withType(KotlinJvmCompile::class.java) {
kotlinOptions.languageVersion = "1.6"
kotlinOptions.jvmTarget = defaultVer.toString()
kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
@ -61,8 +61,8 @@ fun Project.preConfigureJvmTarget() {
fun Project.configureJvmTarget() {
val defaultVer = jvmVersion()
tasks.withType(KotlinJvmCompile::class)
.filter { it.name.startsWith("compileTestKotlin") }
tasks.withType(KotlinCompile::class)
.filter { it.name.contains("test", ignoreCase = true) }
.forEach { task ->
task.kotlinOptions.freeCompilerArgs += "-Xopt-in=net.mamoe.mirai.utils.TestOnly"
}

View File

@ -22,11 +22,11 @@ object Versions {
val consoleIntellij = "221-$project-162-1" // idea-mirai-kotlin-patch
val consoleTerminal = project
const val kotlinCompiler = "1.6.21"
const val kotlinCompiler = "1.7.0-RC"
const val kotlinStdlib = kotlinCompiler
const val dokka = "1.6.20"
const val dokka = "1.6.21"
const val kotlinCompilerForIdeaPlugin = "1.6.20"
const val kotlinCompilerForIdeaPlugin = "1.7.0-RC"
const val coroutines = "1.6.1"
const val atomicFU = "0.17.2"
@ -38,8 +38,8 @@ object Versions {
const val io = "0.1.16"
const val coroutinesIo = "0.1.16"
const val blockingBridge = "2.1.0-162.1"
const val dynamicDelegation = "0.3.0-162.4"
const val blockingBridge = "2.1.0-170.1"
const val dynamicDelegation = "0.3.0-170.1"
const val androidGradlePlugin = "4.1.1"
const val android = "4.1.1.4"
@ -106,13 +106,13 @@ val `kotlinx-coroutines-io` = kotlinx("coroutines-io", Versions.coroutinesIo)
val `ktor-serialization` = ktor("serialization", Versions.ktor)
val `ktor-client-core` = ktor("client-core-jvm", Versions.ktor)
val `ktor-client-cio` = ktor("client-cio-jvm", Versions.ktor)
val `ktor-client-core` = ktor("client-core", Versions.ktor)
val `ktor-client-cio` = ktor("client-cio", Versions.ktor)
val `ktor-client-okhttp` = ktor("client-okhttp", Versions.ktor)
val `ktor-client-android` = ktor("client-android", Versions.ktor)
val `ktor-client-logging` = ktor("client-logging-jvm", Versions.ktor)
val `ktor-client-logging` = ktor("client-logging", Versions.ktor)
val `ktor-network` = ktor("network-jvm", Versions.ktor)
val `ktor-client-serialization` = ktor("client-serialization-jvm", Versions.ktor)
val `ktor-client-serialization` = ktor("client-serialization", Versions.ktor)
const val `logback-classic` = "ch.qos.logback:logback-classic:" + Versions.logback

View File

@ -13,6 +13,7 @@ org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 --illegal-access=permit -Dkot
org.gradle.parallel=true
org.gradle.vfs.watch=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.binary.memoryModel=experimental
kotlin.native.enableDependencyPropagation=false
#kotlin.mpp.enableCompatibilityMetadataVariant=true
#kotlin.mpp.enableGranularSourceSetsMetadata=true
@ -21,4 +22,5 @@ gnsp.disableApplyOnlyOnRootProjectEnforcement=true
# We may target 15 with Kotlin 1.5 IR
mirai.android.target.api.level=24
# Enable if you want to use mavenLocal for both Gradle plugin and project dependencies resolutions.
systemProp.use.maven.local=false
systemProp.use.maven.local=false
org.gradle.caching=true

11
install.sh Normal file
View File

@ -0,0 +1,11 @@
#
# Copyright 2019-2022 Mamoe Technologies and contributors.
#
# 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
# Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
#
# https://github.com/mamoe/mirai/blob/dev/LICENSE
#
cargo install --force cbindgen
cargo install bindgen

View File

@ -10,7 +10,6 @@
package net.mamoe.console.integrationtest
import net.mamoe.console.integrationtest.testpoints.MCITBSelfAssertions
import org.junit.jupiter.api.Test
import org.objectweb.asm.ClassReader
import java.io.File
import java.lang.management.ManagementFactory
@ -22,6 +21,7 @@ import kotlin.io.path.inputStream
import kotlin.io.path.isDirectory
import kotlin.io.path.name
import kotlin.reflect.KClass
import kotlin.test.Test
import kotlin.test.assertTrue

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -17,7 +17,6 @@ import net.mamoe.mirai.console.data.value
import net.mamoe.mirai.console.extension.PluginComponentStorage
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import net.mamoe.mirai.utils.touch
import java.io.File
import kotlin.test.assertEquals
@ -40,13 +39,14 @@ internal object PluginDataRenameToIdTest : AbstractTestPointAsPlugin() {
}
override fun beforeConsoleStartup() {
File("config/PluginDataRenameToIdTest/test.txt").touch()
File("config/PluginDataRenameToIdTest").mkdirs()
File("config/PluginDataRenameToIdTest/test.txt").createNewFile()
File("config/PluginDataRenameToIdTest/testconf.yml").writeText(
"""
test: a
""".trimIndent()
)
File("data/PluginDataRenameToIdTest/test.txt").touch()
File("data/PluginDataRenameToIdTest/test.txt").createNewFile()
File("data/PluginDataRenameToIdTest/testdata.yml").writeText(
"""
test: a

View File

@ -28,9 +28,6 @@ import net.mamoe.mirai.console.internal.command.flattenCommandComponents
import net.mamoe.mirai.console.permission.PermissionService.Companion.permit
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import net.mamoe.mirai.message.data.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import java.time.*
import java.time.temporal.TemporalAccessor
import kotlin.reflect.KClass
@ -158,7 +155,6 @@ class TestTemporalArgCommand : CompositeCommand(owner, "testtemporal") {
private val sender get() = ConsoleCommandSender
private val owner get() = ConsoleCommandOwner
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@OptIn(ExperimentalCommandDescriptors::class)
internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
private val manager by lazy { MiraiConsoleImplementation.getBridge().commandManager as CommandManagerImpl }
@ -167,7 +163,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
private val rawCommand by lazy { TestRawCommand() }
private val compositeCommand by lazy { TestCompositeCommand() }
@BeforeEach
@BeforeTest
fun grantPermission() {
ConsoleCommandSender.permit(simpleCommand.permission)
ConsoleCommandSender.permit(compositeCommand.permission)

View File

@ -12,6 +12,7 @@
package net.mamoe.mirai.console.command
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.runBlocking
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
@ -23,7 +24,7 @@ import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.Pa
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.utils.md5
import net.mamoe.mirai.utils.toUHexString
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
@ -32,7 +33,7 @@ import kotlin.test.assertEquals
internal class LoginCommandTest : AbstractCommandTest() {
@Test
suspend fun `login with provided password`() {
fun `login with provided password`() = runBlocking {
val myId = 123L
val myPwd = "password001"
@ -52,7 +53,7 @@ internal class LoginCommandTest : AbstractCommandTest() {
}
@Test
suspend fun `login with saved plain password`() {
fun `login with saved plain password`() = runBlocking {
val myId = 123L
val myPwd = "password001"
@ -81,7 +82,7 @@ internal class LoginCommandTest : AbstractCommandTest() {
}
@Test
suspend fun `login with saved md5 password`() {
fun `login with saved md5 password`() = runBlocking {
val myId = 123L
val myPwd = "password001"

View File

@ -17,7 +17,7 @@ import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.globalEventChannel
import net.mamoe.mirai.utils.BotConfiguration
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
class AutoLoginTest : AbstractConsoleInstanceTest() {

View File

@ -13,7 +13,7 @@ import net.mamoe.mirai.console.data.java.JavaAutoSavePluginData
import net.mamoe.mirai.console.plugin.jvm.reloadPluginData
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import net.mamoe.mirai.console.util.JavaFriendlyApi
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -19,9 +19,9 @@ import net.mamoe.mirai.message.data.PlainText
import net.mamoe.mirai.message.data.SingleMessage
import net.mamoe.mirai.message.data.messageChainOf
import net.mamoe.mirai.utils.mapPrimitive
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.nio.file.Path
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertSame

View File

@ -18,7 +18,7 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import org.junit.jupiter.api.Test
import kotlin.test.Test
class PluginMovingTests : AbstractConsoleInstanceTest() {
private val mockPluginWithName = object : KotlinPlugin(JvmPluginDescription("org.test1.test1", "1.0.0", "test1")) {}

View File

@ -12,7 +12,7 @@ package net.mamoe.mirai.console.extension
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorageImpl
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
internal class GlobalComponentStorageTest : AbstractConsoleInstanceTest() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -9,7 +9,7 @@
package net.mamoe.mirai.console.logging
import org.junit.jupiter.api.Test
import kotlin.test.Test
@Suppress("ClassName")
internal class TestALC_PathBased {

View File

@ -11,7 +11,6 @@ package net.mamoe.mirai.console.permission
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
import net.mamoe.mirai.console.internal.permission.PermissionImpl
import org.junit.jupiter.api.Test
import kotlin.test.*
internal class PermissionServiceTest {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -9,7 +9,7 @@
package net.mamoe.mirai.console.permission
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertFails
internal class PermissionsBasicsTest {

View File

@ -19,14 +19,14 @@ import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import kotlin.test.BeforeTest
abstract class AbstractConsoleInstanceTest {
val mockPlugin by lazy { mockKotlinPlugin() }
private lateinit var implementation: MiraiConsoleImplementation
val consoleImplementation: MiraiConsoleImplementation by ::implementation
@BeforeEach
@BeforeTest
protected open fun initializeConsole() {
this.implementation = MockConsoleImplementation().apply { start() }
CommandManager

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -9,9 +9,9 @@
package net.mamoe.mirai.console.testFramework.test
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import net.mamoe.mirai.console.plugin.PluginManager
import org.junit.jupiter.api.Test
import net.mamoe.mirai.console.testFramework.AbstractConsoleInstanceTest
import kotlin.test.Test
import kotlin.test.assertEquals
class FrameworkInstanceTest : AbstractConsoleInstanceTest() {

View File

@ -1,17 +1,17 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.console.util
//import kotlinx.coroutines.*
//import org.junit.jupiter.api.Test
//import kotlin.test.Test
//import java.util.concurrent.atomic.AtomicInteger
//import kotlin.coroutines.resume
//import kotlin.test.assertEquals

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -14,7 +14,7 @@
package net.mamoe.mirai.console.util
import net.mamoe.mirai.console.util.SemVersion.Companion.test
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertFails
internal class TestSemVersion {

View File

@ -20,7 +20,7 @@ description = "Mirai Console compiler annotations"
kotlin {
explicitApi()
configureHMPPJvm()
configureHMPP()
}
configureMppPublishing()

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -58,10 +58,12 @@ abstract class AbstractTest {
File(tempDir, "gradle.properties").apply {
delete()
writeText("""
writeText(
"""
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
""".trimIndent())
""".trimIndent()
)
}
buildFile = File(tempDir, "build.gradle")

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -11,11 +11,11 @@ package net.mamoe.mirai.console.gradle
import org.gradle.testkit.runner.GradleRunner
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintWriter
import kotlin.test.Test
class KotlinTransitiveDependenciesIntegrationTest {
@Test

View File

@ -12,9 +12,9 @@
package net.mamoe.mirai.console.gradle
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.io.File
import java.util.zip.ZipFile
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertNull

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -9,7 +9,7 @@
package net.mamoe.mirai.console.gradle
import org.junit.jupiter.api.Test
import kotlin.test.Test
class TestPluginApply : AbstractTest() {

View File

@ -45,8 +45,10 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
try {
languageSettings.optIn("kotlin.RequiresOptIn")
} catch (e: NoSuchMethodError) {
@Suppress("DEPRECATION")
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
// User is using < 1.6
target.compilations.forEach { compilation ->
compilation.kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
}
}
dependencies { configureDependencies(project, this@configureSourceSet, target) }
}

View File

@ -9,7 +9,7 @@
package creator
import net.mamoe.mirai.console.intellij.wizard.sortVersionsDescending
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
class MiraiVersionKindTest {

View File

@ -13,7 +13,7 @@ import net.mamoe.mirai.console.intellij.diagnostics.adjustToClassName
import net.mamoe.mirai.console.intellij.diagnostics.isValidPackageName
import net.mamoe.mirai.console.intellij.diagnostics.isValidQualifiedClassName
import net.mamoe.mirai.console.intellij.diagnostics.isValidSimpleClassName
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

View File

@ -26,7 +26,7 @@ description = "Mirai API module"
kotlin {
explicitApi()
configureHMPPJvm()
configureHMPP()
sourceSets {
@ -36,6 +36,7 @@ kotlin {
api(`kotlinx-serialization-core`)
api(`kotlinx-serialization-json`)
api(`kotlinx-coroutines-core`) // don't remove it, otherwise IDE will complain
implementation(`ktor-client-core`)
implementation(project(":mirai-core-utils"))
implementation(project(":mirai-console-compiler-annotations"))

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("unused", "NOTHING_TO_INLINE")
@ -12,6 +12,7 @@
package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import kotlin.jvm.JvmSynthetic
/**
* 构造 [Bot] 的工厂. 这是 [Bot] 唯一的构造方式.

View File

@ -15,7 +15,6 @@
package net.mamoe.mirai
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.UserProfile
@ -30,8 +29,9 @@ import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.data.Image.Key.queryUrl
import net.mamoe.mirai.message.data.MessageSource.Key.recall
import net.mamoe.mirai.utils.*
import java.util.ServiceLoader
import kotlin.reflect.full.companionObjectInstance
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* [IMirai] 实例.
@ -336,11 +336,10 @@ public suspend inline fun IMirai.recallMessage(bot: Bot, message: MessageChain):
@PublishedApi // for tests and potential public uses.
@Suppress("ClassName")
internal object _MiraiInstance {
private var instance: IMirai? = null
@JvmStatic
fun set(instance: IMirai) {
this.instance = instance
miraiInstance = instance
}
/**
@ -348,15 +347,14 @@ internal object _MiraiInstance {
*/
@JvmStatic
fun get(): IMirai {
return instance ?: findMiraiInstance().also { instance = it }
return miraiInstance ?: findMiraiInstance().also { miraiInstance = it }
}
}
// to overcome native gc issue
private var miraiInstance: IMirai? = null
@JvmSynthetic
internal fun findMiraiInstance(): IMirai {
ServiceLoader.load(IMirai::class.java).firstOrNull()?.let { return it }
val implClass = Class.forName("net.mamoe.mirai.internal.MiraiImpl")
(implClass.kotlin.companionObjectInstance as? IMirai)?.let { return it }
return implClass.asSubclass(IMirai::class.java).getConstructor().newInstance()
return loadService(IMirai::class, "net.mamoe.mirai.internal.MiraiImpl")
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -17,7 +17,6 @@ import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.*
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.WeakRef
import kotlin.annotation.AnnotationTarget.*
/**
@ -52,7 +51,7 @@ public interface LowLevelApiAccessor {
public suspend fun refreshKeys(bot: Bot)
/**
* 构造一个 [Friend] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
* 构造一个 [Friend] 对象.
*
* [Bot] 无法管理这个对象, 但这个对象会以 [Bot] [Job] 作为父 Job.
* 因此, [Bot] 被关闭后, 这个对象也会被关闭.
@ -61,7 +60,7 @@ public interface LowLevelApiAccessor {
public fun newFriend(bot: Bot, friendInfo: FriendInfo): Friend
/**
* 构造一个 [Stranger] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
* 构造一个 [Stranger] 对象.
*
* [Bot] 无法管理这个对象, 但这个对象会以 [Bot] [Job] 作为父 Job.
* 因此, [Bot] 被关闭后, 这个对象也会被关闭.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -23,16 +23,16 @@ import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.recallMessage
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.ExternalResource.Companion.sendAsImageTo
import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage
import java.io.File
import java.io.InputStream
import kotlin.coroutines.cancellation.CancellationException
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 联系对象, 即可以与 [Bot] 互动的对象. 包含 [用户][User], [][Group].
*/
@NotStableForInheritance
public interface Contact : ContactOrBot, CoroutineScope {
public expect interface Contact : ContactOrBot, CoroutineScope {
/**
* 这个联系对象所属 [Bot].
*/
@ -67,7 +67,7 @@ public interface Contact : ContactOrBot, CoroutineScope {
* 发送纯文本消息
* @see sendMessage
*/
public suspend fun sendMessage(message: String): MessageReceipt<Contact> = this.sendMessage(message.toPlainText())
public open suspend fun sendMessage(message: String): MessageReceipt<Contact>
/**
* 上传一个 [资源][ExternalResource] 作为图片以备发送.
@ -90,81 +90,23 @@ public interface Contact : ContactOrBot, CoroutineScope {
@JvmBlockingBridge
public companion object {
/**
* 读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
*
* 注意此函数不会关闭 [imageStream]
*
* @param formatName 查看 [ExternalResource.formatName]
* @throws OverFileSizeMaxException
* @see FileCacheStrategy
*/
@JvmStatic
@JvmOverloads
public suspend fun <C : Contact> C.sendImage(
imageStream: InputStream,
formatName: String? = null
): MessageReceipt<C> = imageStream.sendAsImageTo(this, formatName)
/**
* 将文件作为图片发送到指定联系人
* @param formatName 查看 [ExternalResource.formatName]
* @throws OverFileSizeMaxException
* @see FileCacheStrategy
*/
@JvmStatic
@JvmOverloads
public suspend fun <C : Contact> C.sendImage(
file: File,
formatName: String? = null
): MessageReceipt<C> = file.sendAsImageTo(this, formatName)
/**
* 将资源作为单独的图片消息发送给 [this]
*
* @see Contact.sendMessage 最终调用, 发送消息.
*/
@JvmStatic
public suspend fun <C : Contact> C.sendImage(resource: ExternalResource): MessageReceipt<C> =
resource.sendAsImageTo(this)
/**
* 读取 [InputStream] 到临时文件并将其作为图片上传, 但不发送
*
* 注意本函数不会关闭流
*
* @param formatName 查看 [ExternalResource.formatName]
* @throws OverFileSizeMaxException
*/
@JvmStatic
@JvmOverloads
public suspend fun Contact.uploadImage(
imageStream: InputStream,
formatName: String? = null
): Image = imageStream.uploadAsImage(this@uploadImage, formatName)
/**
* 将文件作为图片上传, 但不发送
* @param formatName 查看 [ExternalResource.formatName]
* @throws OverFileSizeMaxException
*/
@JvmStatic
@JvmOverloads
public suspend fun Contact.uploadImage(
file: File,
formatName: String? = null
): Image = file.uploadAsImage(this, formatName)
public suspend fun <C : Contact> C.sendImage(resource: ExternalResource): MessageReceipt<C>
/**
* 将文件作为图片上传, 但不发送
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
@Throws(OverFileSizeMaxException::class, CancellationException::class)
@JvmStatic
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXTENSION_SHADOWED_BY_MEMBER")
@kotlin.internal.LowPriorityInOverloadResolution // for better Java API
public suspend fun Contact.uploadImage(resource: ExternalResource): Image = this.uploadImage(resource)
public suspend fun Contact.uploadImage(resource: ExternalResource): Image
}
}

View File

@ -1,18 +1,19 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
package net.mamoe.mirai.contact
import net.mamoe.mirai.utils.ConcurrentLinkedDeque
import net.mamoe.mirai.utils.MiraiInternalApi
import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.jvm.JvmField
/**
@ -26,7 +27,7 @@ public class ContactList<out C : Contact>
Collection<C> by delegate {
@MiraiInternalApi
public constructor() : this(ConcurrentLinkedQueue())
public constructor() : this(ConcurrentLinkedDeque())
/**
* 获取一个 [Contact.id] [id] 的元素. 在不存在时返回 `null`.

View File

@ -12,6 +12,7 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot
import net.mamoe.mirai.utils.NotStableForInheritance
import kotlin.jvm.JvmName
/**
* 拥有 [id] 的对象.

View File

@ -23,6 +23,8 @@ import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.NotStableForInheritance
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* .

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -20,8 +20,8 @@ import net.mamoe.mirai.message.action.Nudge
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.isContentEmpty
import net.mamoe.mirai.message.data.toPlainText
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.NotStableForInheritance
import kotlin.jvm.JvmName
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -16,6 +16,9 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.contact.announcement.Announcement.Companion.publishAnnouncement
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -11,6 +11,8 @@ package net.mamoe.mirai.contact.announcement
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.mamoe.mirai.utils.isSameClass
import kotlin.jvm.JvmStatic
/**
@ -47,9 +49,7 @@ public class AnnouncementImage private constructor(
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AnnouncementImage
if (other !is AnnouncementImage || !isSameClass(this, other)) return false
if (id != other.id) return false
if (height != other.height) return false

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -12,6 +12,9 @@ package net.mamoe.mirai.contact.announcement
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.mamoe.mirai.contact.announcement.AnnouncementParameters.Companion.DEFAULT
import net.mamoe.mirai.utils.isSameClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
/**
* 群公告的附加参数.
@ -65,9 +68,7 @@ public class AnnouncementParameters internal constructor(
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AnnouncementParameters
if (other !is AnnouncementParameters || !isSameClass(this, other)) return false
if (image != other.image) return false
if (sendToNewMember != other.sendToNewMember) return false

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -13,6 +13,9 @@ package net.mamoe.mirai.contact.announcement
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
/**

View File

@ -21,6 +21,9 @@ import net.mamoe.mirai.utils.map
import net.mamoe.mirai.utils.safeCast
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 表示在本地构建的 [Announcement].

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -18,7 +18,6 @@ import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.utils.NotStableForInheritance
import java.time.Instant
/**
@ -65,7 +64,7 @@ public interface OnlineAnnouncement : Announcement {
/**
* 公告发出的时间 EpochSecond ( 1970-01-01T000000Z 的秒数)
*
* @see Instant.ofEpochSecond
* @see java.time.Instant.ofEpochSecond
*/
public val publicationTime: Long

View File

@ -17,7 +17,7 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.contact.FileSupported
import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.utils.NotStableForInheritance
import java.io.File
import kotlin.jvm.JvmStatic
/**
* 绝对文件或目录标识. 精确表示一个远程文件. 不会受同名文件或目录的影响.
@ -174,7 +174,7 @@ public sealed interface AbsoluteFileFolder {
*
* 不会包含 `:*?"<>|/\` 任一字符.
*
* @see File.extension
* @see java.io.File.extension
*/
@get:JvmStatic
public val AbsoluteFileFolder.extension: String

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -16,10 +16,9 @@ import kotlinx.coroutines.flow.Flow
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.JavaFriendlyAPI
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.ProgressionCallback
import java.util.stream.Stream
import kotlin.jvm.JvmOverloads
/**
* 绝对目录标识. 精确表示一个远程目录. 不会受同名文件或目录的影响.
@ -30,7 +29,7 @@ import java.util.stream.Stream
* @see AbsoluteFileFolder
*/
@NotStableForInheritance
public interface AbsoluteFolder : AbsoluteFileFolder {
public expect interface AbsoluteFolder : AbsoluteFileFolder {
/**
* 当前快照中文件数量, 当有文件更新时(上传/删除文件) 该属性不会更新.
*
@ -43,7 +42,7 @@ public interface AbsoluteFolder : AbsoluteFileFolder {
/**
* 当该目录为空时返回 `true`.
*/
public fun isEmpty(): Boolean = contentsCount == 0
public open fun isEmpty(): Boolean
/**
* 返回更新了文件或目录信息 ([lastModifiedTime] ) , 指向相同文件的 [AbsoluteFileFolder].
@ -64,42 +63,18 @@ public interface AbsoluteFolder : AbsoluteFileFolder {
*/
public suspend fun folders(): Flow<AbsoluteFolder>
/**
* 获取该目录下所有子目录列表.
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [folders], 因此不建议在 Kotlin 使用. Kotlin 请使用 [folders].
*/
@JavaFriendlyAPI
public suspend fun foldersStream(): Stream<AbsoluteFolder>
/**
* 获取该目录下所有文件列表.
*/
public suspend fun files(): Flow<AbsoluteFile>
/**
* 获取该目录下所有文件列表.
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [files], 因此不建议在 Kotlin 使用. Kotlin 请使用 [files].
*/
@JavaFriendlyAPI
public suspend fun filesStream(): Stream<AbsoluteFile>
/**
* 获取该目录下所有文件和子目录列表.
*/
public suspend fun children(): Flow<AbsoluteFileFolder>
/**
* 获取该目录下所有文件和子目录列表.
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [children], 因此不建议在 Kotlin 使用. Kotlin 请使用 [children].
*/
@JavaFriendlyAPI
public suspend fun childrenStream(): Stream<AbsoluteFileFolder>
///////////////////////////////////////////////////////////////////////////
// resolve and upload
///////////////////////////////////////////////////////////////////////////
@ -144,16 +119,6 @@ public interface AbsoluteFolder : AbsoluteFileFolder {
path: String
): Flow<AbsoluteFile>
/**
* 根据路径获取指向的所有路径为 [path] 的文件列表. 同时支持相对路径和绝对路径. 支持获取子目录内的文件.
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [resolveFiles], 因此不建议在 Kotlin 使用. Kotlin 请使用 [resolveFiles].
*/
@JavaFriendlyAPI
public suspend fun resolveFilesStream(
path: String
): Stream<AbsoluteFile>
/**
* 根据路径获取指向的所有路径为 [path] 的文件和目录列表. 同时支持相对路径和绝对路径. 支持获取子目录内的文件和目录.
*/
@ -161,16 +126,6 @@ public interface AbsoluteFolder : AbsoluteFileFolder {
path: String
): Flow<AbsoluteFileFolder>
/**
* 根据路径获取指向的所有路径为 [path] 的文件和目录列表. 同时支持相对路径和绝对路径. 支持获取子目录内的文件和目录.
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [resolveAll], 因此不建议在 Kotlin 使用. Kotlin 请使用 [resolveAll].
*/
@JavaFriendlyAPI
public suspend fun resolveAllStream(
path: String
): Stream<AbsoluteFileFolder>
/**
* 上传一个文件到该目录, 返回上传成功的文件标识.
*
@ -200,6 +155,7 @@ public interface AbsoluteFolder : AbsoluteFileFolder {
* 根目录 folder ID.
* @see id
*/
public const val ROOT_FOLDER_ID: String = "/"
@Suppress("CONST_VAL_WITHOUT_INITIALIZER") // compiler bug
public const val ROOT_FOLDER_ID: String
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -19,8 +19,7 @@ import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.ProgressionCallback
import java.io.File
import java.util.stream.Stream
import kotlin.jvm.JvmOverloads
/**
* 表示远程文件列表 (管理器).
@ -46,7 +45,7 @@ import java.util.stream.Stream
*
* # 绝对路径与相对路径
*
* mirai 文件系统的绝对路径与相对路径与 Java [File] 实现的相同.
* mirai 文件系统的绝对路径与相对路径与 Java [java.io.File] 实现的相同.
*
* `/` 起始的路径表示绝对路径, 基于根目录 [root] 处理. 其他路径均表示相对路径.
*
@ -64,11 +63,11 @@ import java.util.stream.Stream
*
* 一个目录 ([AbsoluteFolder]) 可以包含多个子文件, 根目录还可以包含多个子目录 (详见下文 '目录结构限制').
*
* 使用 [AbsoluteFolder.children] 可以获得其内子目录和文件列表 [Flow]. [AbsoluteFolder.childrenStream] 提供适合 Java [Stream] 实现.
* 使用 [AbsoluteFolder.children] 可以获得其内子目录和文件列表 [Flow]. [AbsoluteFolder.childrenStream] 提供适合 Java [java.util.stream.Stream] 实现.
* 使用 [AbsoluteFolder.folders] [AbsoluteFolder.files] 可以特定地只获取子目录或文件列表. 这些函数也有其 `*Stream` 实现.
*
* 若要根据确定的文件或目录名称获取其 [AbsoluteFileFolder] 实例, 可使用 [AbsoluteFolder.resolveFiles] [AbsoluteFolder.resolveFiles].
* 注意 [AbsoluteFolder.resolveFiles] 返回 [Flow] ( Stream 版返回 [Stream]), 因为服务器允许多个文件有相同名称. (详见下文 '允许重名').
* 注意 [AbsoluteFolder.resolveFiles] 返回 [Flow] ( Stream 版返回 [java.util.stream.Stream]), 因为服务器允许多个文件有相同名称. (详见下文 '允许重名').
*
* 若已知文件 [AbsoluteFile.id], 可通过 [AbsoluteFolder.resolveFileById] 获得该文件.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -12,6 +12,7 @@ package net.mamoe.mirai.contact.roaming
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.message.data.MessageSource
import kotlin.jvm.JvmField
/**
* @since 2.8

View File

@ -16,8 +16,6 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.utils.JavaFriendlyAPI
import java.util.stream.Stream
/**
* 漫游消息记录管理器. 可通过 [RoamingSupported.roamingMessages] 获得. 目前仅 [Friend] 实现 [RoamingSupported].
@ -25,13 +23,13 @@ import java.util.stream.Stream
* @since 2.8
* @see RoamingSupported
*/
public interface RoamingMessages {
public expect interface RoamingMessages {
///////////////////////////////////////////////////////////////////////////
// Get list
///////////////////////////////////////////////////////////////////////////
/**
* 查询指定时间段内的漫游消息记录. Java Stream 方法查看 [getMessagesStream].
* 查询指定时间段内的漫游消息记录.
*
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
@ -55,7 +53,7 @@ public interface RoamingMessages {
): Flow<MessageChain>
/**
* 查询所有漫游消息记录. Java Stream 方法查看 [getAllMessagesStream].
* 查询所有漫游消息记录.
*
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
@ -70,57 +68,7 @@ public interface RoamingMessages {
*
* @param filter 过滤器.
*/
public suspend fun getAllMessages(
public open suspend fun getAllMessages(
filter: RoamingMessageFilter? = null
): Flow<MessageChain> = getMessagesIn(0, Long.MAX_VALUE, filter)
/**
* 查询指定时间段内的漫游消息记录. Kotlin Flow 版本查看 [getMessagesIn].
*
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
*
* 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息.
* 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.get(MessageSource.Key)`), 判断 [MessageSource.fromId] (发送人).
* 消息的其他*元数据*信息也要通过 [MessageSource] 获取 ( [MessageSource.time] 获取时间).
*
* 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递.
*
* 性能提示: 请在 [filter] 执行筛选, [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
*
* @param timeStart 起始时间, UTC+8 时间戳, 单位为秒. 可以为 `0`, 即表示从可以获取的最早的消息起. 负数将会被看是 `0`.
* @param timeEnd 结束时间, UTC+8 时间戳, 单位为秒. 可以为 [Long.MAX_VALUE], 即表示到可以获取的最晚的消息为止. 低于 [timeStart] 的值将会被看作是 [timeStart] 的值.
* @param filter 过滤器.
*/
@Suppress("OVERLOADS_INTERFACE")
@JvmOverloads
@JavaFriendlyAPI
public suspend fun getMessagesStream(
timeStart: Long,
timeEnd: Long,
filter: RoamingMessageFilter? = null
): Stream<MessageChain>
/**
* 查询所有漫游消息记录. Kotlin Flow 版本查看 [getAllMessages].
*
* 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息.
* 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回.
*
* 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息.
* 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.get(MessageSource.Key)`), 判断 [MessageSource.fromId] (发送人).
* 消息的其他*元数据*信息也要通过 [MessageSource] 获取 ( [MessageSource.time] 获取时间).
*
* 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递.
*
* 性能提示: 请在 [filter] 执行筛选, [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响.
*
* @param filter 过滤器.
*/
@Suppress("OVERLOADS_INTERFACE")
@JvmOverloads
@JavaFriendlyAPI
public suspend fun getAllMessagesStream(
filter: RoamingMessageFilter? = null
): Stream<MessageChain> = getMessagesStream(0, Long.MAX_VALUE, filter)
): Flow<MessageChain>
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -19,6 +19,7 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.jvm.JvmStatic
/**
* 群荣誉信息

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -20,6 +20,9 @@ import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
@Serializable
@SerialName("RequestEventData")

View File

@ -18,6 +18,8 @@ import net.mamoe.mirai.Mirai
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmField
import kotlin.jvm.Volatile
/**
* 表示一个事件.
@ -152,6 +154,7 @@ public interface CancellableEvent : Event {
* [EventChannel.filter] [Listener.onEvent] 时产生的异常只会由监听方处理.
*/
@JvmBlockingBridge
@Suppress("TOP_LEVEL_FUNCTIONS_NOT_SUPPORTED") // compiler bug
public suspend fun <E : Event> E.broadcast(): E {
Mirai.broadcastEvent(this)
return this

View File

@ -25,12 +25,14 @@ import net.mamoe.mirai.IMirai
import net.mamoe.mirai.event.ConcurrencyKind.CONCURRENT
import net.mamoe.mirai.event.ConcurrencyKind.LOCKED
import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.internal.event.registerEventHandler
import net.mamoe.mirai.utils.*
import org.jetbrains.annotations.Contract
import java.util.function.Consumer
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.context
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
/**
@ -54,7 +56,7 @@ import kotlin.reflect.KClass
*
* ### 对通道的操作
* - 过滤通道: 通过 [EventChannel.filter]. 例如 `filter { it is BotEvent }` 得到一个只能监听到 [BotEvent] 的事件通道.
* - 转换为 Kotlin 协程 [Channel]: [EventChannel.asChannel]
* - 转换为 Kotlin 协程 [Channel]: [EventChannel.forwardToChannel]
* - 添加 [CoroutineContext]: [context], [parentJob], [parentScope], [exceptionHandler]
*
* ### 创建事件监听
@ -80,38 +82,17 @@ import kotlin.reflect.KClass
* 使用 [EventChannel.forwardToChannel] 可将事件转发到指定 [SendChannel].
*/
@NotStableForInheritance // since 2.12, before it was `final class`.
public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi public constructor(
public val baseEventClass: KClass<out BaseEvent>,
public expect abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi public constructor(
baseEventClass: KClass<out BaseEvent>,
defaultCoroutineContext: CoroutineContext,
) {
/**
* 此事件通道的默认 [CoroutineScope.coroutineContext]. 将会被添加给所有注册的事件监听器.
*/
public val defaultCoroutineContext: CoroutineContext,
) {
/**
* 创建事件监听并将监听结果发送在 [Channel]. 将返回值 [Channel] [关闭][Channel.close] 时将会同时关闭事件监听.
*
* @param capacity Channel 容量. 详见 [Channel] 构造.
*
* @see subscribeAlways
* @see Channel
*/
@Deprecated(
"Please use forwardToChannel instead.",
replaceWith = ReplaceWith(
"Channel<BaseEvent>(capacity).apply { forwardToChannel(this, coroutineContext, priority) }",
"kotlinx.coroutines.channels.Channel"
),
level = DeprecationLevel.ERROR,
)
@DeprecatedSinceMirai(warningSince = "2.10", errorSince = "2.12")
@MiraiExperimentalApi
public fun asChannel(
capacity: Int = Channel.RENDEZVOUS,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
@Suppress("UNUSED_PARAMETER") concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
): Channel<out BaseEvent> =
Channel<BaseEvent>(capacity).apply { forwardToChannel(this, coroutineContext, priority) }
public val defaultCoroutineContext: CoroutineContext
public val baseEventClass: KClass<out BaseEvent>
/**
* 创建事件监听并将监听结果转发到 [channel]. [Channel.send] 抛出 [ClosedSendChannelException] 时停止 [Listener] 监听和转发.
@ -139,16 +120,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
channel: SendChannel<@UnsafeVariance BaseEvent>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: EventPriority = EventPriority.MONITOR,
): Listener<@UnsafeVariance BaseEvent> {
return subscribe(baseEventClass, coroutineContext, priority = priority) {
try {
channel.send(it)
ListeningStatus.LISTENING
} catch (_: ClosedSendChannelException) {
ListeningStatus.STOPPED
}
}
}
): Listener<@UnsafeVariance BaseEvent>
/**
* 通过 [Flow] 接收此通道内的所有事件.
@ -216,9 +188,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
* @see filterIsInstance 过滤指定类型的事件
*/
@JvmSynthetic
public fun filter(filter: suspend (event: BaseEvent) -> Boolean): EventChannel<BaseEvent> {
return FilterEventChannel(this, filter)
}
public fun filter(filter: suspend (event: BaseEvent) -> Boolean): EventChannel<BaseEvent>
/**
* [EventChannel.filter] Java 版本.
@ -258,32 +228,20 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun filter(filter: (event: BaseEvent) -> Boolean): EventChannel<BaseEvent> {
return filter { runBIO { filter(it) } }
}
public fun filter(filter: (event: BaseEvent) -> Boolean): EventChannel<BaseEvent>
/**
* 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel]
* @see filter 获取更多信息
*/
@JvmSynthetic
public inline fun <reified E : Event> filterIsInstance(): EventChannel<E> =
filterIsInstance(E::class)
public inline fun <reified E : Event> filterIsInstance(): EventChannel<E>
/**
* 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel]
* @see filter 获取更多信息
*/
public fun <E : Event> filterIsInstance(kClass: KClass<out E>): EventChannel<E> {
return filter { kClass.isInstance(it) }.cast()
}
/**
* 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel]
* @see filter 获取更多信息
*/
public fun <E : Event> filterIsInstance(clazz: Class<out E>): EventChannel<E> =
filterIsInstance(clazz.kotlin)
public fun <E : Event> filterIsInstance(kClass: KClass<out E>): EventChannel<E>
/**
@ -300,19 +258,13 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun exceptionHandler(coroutineExceptionHandler: CoroutineExceptionHandler): EventChannel<BaseEvent> {
return context(coroutineExceptionHandler)
}
public fun exceptionHandler(coroutineExceptionHandler: CoroutineExceptionHandler): EventChannel<BaseEvent>
/**
* 创建一个新的 [EventChannel], [EventChannel] 包含 [`this.coroutineContext`][defaultCoroutineContext] 和添加的 [coroutineExceptionHandler]
* @see context
*/
public fun exceptionHandler(coroutineExceptionHandler: (exception: Throwable) -> Unit): EventChannel<BaseEvent> {
return context(CoroutineExceptionHandler { _, throwable ->
coroutineExceptionHandler(throwable)
})
}
public fun exceptionHandler(coroutineExceptionHandler: (exception: Throwable) -> Unit): EventChannel<BaseEvent>
/**
* 创建一个新的 [EventChannel], [EventChannel] 包含 [`this.coroutineContext`][defaultCoroutineContext] 和添加的 [coroutineExceptionHandler]
@ -337,9 +289,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
*
* @see CoroutineScope.globalEventChannel `GlobalEventChannel.parentScope()` 的扩展
*/
public fun parentScope(coroutineScope: CoroutineScope): EventChannel<BaseEvent> {
return context(coroutineScope.coroutineContext)
}
public fun parentScope(coroutineScope: CoroutineScope): EventChannel<BaseEvent>
/**
* 指定协程父 [Job]. 之后在此 [EventChannel] 下创建的事件监听器都会成为 [job] 的子任务, [job] 被取消时, 所有的事件监听器都会被取消.
@ -349,9 +299,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
* @see parentScope
* @see context
*/
public fun parentJob(job: Job): EventChannel<BaseEvent> {
return context(job)
}
public fun parentJob(job: Job): EventChannel<BaseEvent>
// endregion
@ -452,7 +400,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
concurrency: ConcurrencyKind = LOCKED,
priority: EventPriority = EventPriority.NORMAL,
noinline handler: suspend E.(E) -> ListeningStatus,
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority, handler)
): Listener<E>
/**
* [subscribe] 的区别是接受 [eventClass] 参数, 而不使用 `reified` 泛型. 通常推荐使用具体化类型参数.
@ -467,10 +415,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
concurrency: ConcurrencyKind = LOCKED,
priority: EventPriority = EventPriority.NORMAL,
handler: suspend E.(E) -> ListeningStatus,
): Listener<E> = subscribeInternal(
eventClass,
createListener(coroutineContext, concurrency, priority) { it.handler(it); }
)
): Listener<E>
/**
* 创建一个事件监听器, 监听事件通道中所有 [E] 及其子类事件.
@ -492,7 +437,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
noinline handler: suspend E.(E) -> Unit,
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority, handler)
): Listener<E>
/**
@ -506,10 +451,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
handler: suspend E.(E) -> Unit,
): Listener<E> = subscribeInternal(
eventClass,
createListener(coroutineContext, concurrency, priority) { it.handler(it); ListeningStatus.LISTENING }
)
): Listener<E>
/**
* 创建一个事件监听器, 监听事件通道中所有 [E] 及其子类事件, 只监听一次.
@ -527,7 +469,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: EventPriority = EventPriority.NORMAL,
noinline handler: suspend E.(E) -> Unit,
): Listener<E> = subscribeOnce(E::class, coroutineContext, priority, handler)
): Listener<E>
/**
* @see subscribeOnce
@ -537,155 +479,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: EventPriority = EventPriority.NORMAL,
handler: suspend E.(E) -> Unit,
): Listener<E> = subscribeInternal(
eventClass,
createListener(coroutineContext, LOCKED, priority) { it.handler(it); ListeningStatus.STOPPED }
)
// endregion
/**
* 注册 [ListenerHost] 中的所有 [EventHandler] 标注的方法到这个 [EventChannel]. 查看 [EventHandler].
*
* @param coroutineContext [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext]
*
* @see subscribe
* @see EventHandler
* @see ListenerHost
*/
@JvmOverloads
public fun registerListenerHost(
host: ListenerHost,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
) {
val jobOfListenerHost: Job?
val coroutineContext0 = if (host is SimpleListenerHost) {
val listenerCoroutineContext = host.coroutineContext
val listenerJob = listenerCoroutineContext[Job]
val rsp = listenerCoroutineContext.minusKey(Job) +
coroutineContext +
(listenerCoroutineContext[CoroutineExceptionHandler] ?: EmptyCoroutineContext)
val registerCancelHook = when {
listenerJob === null -> false
// Registering cancellation hook is needless
// if [Job] of [EventChannel] is same as [Job] of [SimpleListenerHost]
(rsp[Job] ?: this.defaultCoroutineContext[Job]) === listenerJob -> false
else -> true
}
jobOfListenerHost = if (registerCancelHook) {
listenerCoroutineContext[Job]
} else {
null
}
rsp
} else {
jobOfListenerHost = null
coroutineContext
}
for (method in host.javaClass.declaredMethods) {
method.getAnnotation(EventHandler::class.java)?.let {
val listener = method.registerEventHandler(host, this, it, coroutineContext0)
// For [SimpleListenerHost.cancelAll]
jobOfListenerHost?.invokeOnCompletion { exception ->
listener.cancel(
when (exception) {
is CancellationException -> exception
is Throwable -> CancellationException(null, exception)
else -> null
}
)
}
}
}
}
// region Java API
/**
* Java API. 查看 [subscribeAlways] 获取更多信息.
*
* ```java
* eventChannel.subscribeAlways(GroupMessageEvent.class, (event) -> { });
* ```
*
* @see subscribe
* @see subscribeAlways
*/
@JvmOverloads
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun <E : Event> subscribeAlways(
eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
handler: Consumer<E>,
): Listener<E> = subscribeInternal(
eventClass.kotlin,
createListener(coroutineContext, concurrency, priority) { event ->
runInterruptible(Dispatchers.IO) { handler.accept(event) }
ListeningStatus.LISTENING
}
)
/**
* Java API. 查看 [subscribe] 获取更多信息.
*
* ```java
* eventChannel.subscribe(GroupMessageEvent.class, (event) -> {
* return ListeningStatus.LISTENING;
* });
* ```
*
* @see subscribe
*/
@JvmOverloads
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun <E : Event> subscribe(
eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
handler: java.util.function.Function<E, ListeningStatus>,
): Listener<E> = subscribeInternal(
eventClass.kotlin,
createListener(coroutineContext, concurrency, priority) { event ->
runInterruptible(Dispatchers.IO) { handler.apply(event) }
}
)
/**
* Java API. 查看 [subscribeOnce] 获取更多信息.
*
* ```java
* eventChannel.subscribeOnce(GroupMessageEvent.class, (event) -> { });
* ```
*
* @see subscribe
* @see subscribeOnce
*/
@JvmOverloads
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun <E : Event> subscribeOnce(
eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL,
handler: Consumer<E>,
): Listener<E> = subscribeInternal(
eventClass.kotlin,
createListener(coroutineContext, concurrency, priority) { event ->
runInterruptible(Dispatchers.IO) { handler.accept(event) }
ListeningStatus.STOPPED
}
)
): Listener<E>
// endregion
@ -697,19 +491,12 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
protected abstract fun <E : Event> registerListener(eventClass: KClass<out E>, listener: Listener<E>)
// to overcome visibility issue
internal fun <E : Event> registerListener0(eventClass: KClass<out E>, listener: Listener<E>) {
return registerListener(eventClass, listener)
}
private fun <L : Listener<E>, E : Event> subscribeInternal(eventClass: KClass<out E>, listener: L): L {
registerListener(eventClass, listener)
return listener
}
internal fun <E : Event> registerListener0(eventClass: KClass<out E>, listener: Listener<E>)
/**
* Creates [Listener] instance using the [listenerBlock] action.
*/
@Contract("_ -> new") // always creates new instance
// @Contract("_ -> new") // always creates new instance
@MiraiInternalApi
protected abstract fun <E : Event> createListener(
coroutineContext: CoroutineContext,
@ -724,7 +511,7 @@ public abstract class EventChannel<out BaseEvent : Event> @MiraiInternalApi publ
concurrencyKind: ConcurrencyKind,
priority: EventPriority,
listenerBlock: suspend (E) -> ListeningStatus,
): Listener<E> = createListener(coroutineContext, concurrencyKind, priority, listenerBlock)
): Listener<E>
// endregion
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@ -14,7 +14,8 @@ package net.mamoe.mirai.event
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**

View File

@ -19,6 +19,9 @@ import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.loadService
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
/**

View File

@ -18,6 +18,8 @@ import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.event.EventPriority.*
import net.mamoe.mirai.utils.NotStableForInheritance
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* 订阅者的状态

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress(
@ -22,6 +22,9 @@ import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.data.MessageSource.Key.quote
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import kotlin.annotation.AnnotationTarget.CONSTRUCTOR
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
/**

View File

@ -17,6 +17,8 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import kotlin.coroutines.resume
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass

View File

@ -17,6 +17,8 @@ import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**

View File

@ -16,6 +16,8 @@ import kotlinx.coroutines.*
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
/**

View File

@ -23,6 +23,8 @@ import net.mamoe.mirai.internal.event.VerboseEvent
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**

View File

@ -24,6 +24,8 @@ import net.mamoe.mirai.message.data.source
import net.mamoe.mirai.message.isContextIdenticalWith
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**

View File

@ -22,6 +22,9 @@ import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**

View File

@ -20,6 +20,8 @@ import net.mamoe.mirai.internal.event.VerboseEvent
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
@ -105,7 +107,7 @@ public data class GroupTempMessagePreSendEvent @MiraiInternalApi constructor(
public override val target: NormalMember,
/** 待发送的消息. 修改后将会同时应用于发送. */
public override var message: Message
) : @kotlin.Suppress("DEPRECATION_ERROR") TempMessagePreSendEvent(target, message) {
) : @Suppress("DEPRECATION_ERROR") TempMessagePreSendEvent(target, message) {
public override val group: Group get() = target.group
}

View File

@ -18,6 +18,9 @@ import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.isSameClass
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
@ -78,9 +81,7 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
@Suppress("DuplicatedCode")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as FriendRecall
if (other !is FriendRecall || !isSameClass(this, other)) return false
if (bot != other.bot) return false
if (!messageIds.contentEquals(other.messageIds)) return false
@ -123,9 +124,7 @@ public sealed class MessageRecallEvent : BotEvent, AbstractEvent() {
@Suppress("DuplicatedCode")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as GroupRecall
if (other !is GroupRecall || !isSameClass(this, other)) return false
if (bot != other.bot) return false
if (authorId != other.authorId) return false

View File

@ -18,6 +18,8 @@ import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.message.data.OnlineMessageSource
import net.mamoe.mirai.message.data.source
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**

View File

@ -17,6 +17,8 @@ import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("unused", "FunctionName")
@ -18,6 +18,8 @@ import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
// note: 若你使用 IntelliJ IDEA, 按 alt + 7 可打开结构

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -13,6 +13,8 @@
package net.mamoe.mirai.event.events
import kotlinx.atomicfu.AtomicBoolean
import kotlinx.atomicfu.atomic
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.Bot
import net.mamoe.mirai.Mirai
@ -23,7 +25,9 @@ import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.internal.event.VerboseEvent
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.MiraiInternalApi
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.jvm.JvmField
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
@ -80,7 +84,7 @@ public data class NewFriendRequestEvent @MiraiInternalApi public constructor(
public val fromNick: String,
) : BotEvent, Packet, AbstractEvent(), FriendInfoChangeEvent {
@JvmField
internal val responded: AtomicBoolean = AtomicBoolean(false)
internal val responded: AtomicBoolean = atomic(false)
/**
* @return 申请人来自的群. 当申请人来自其他途径申请时为 `null`

View File

@ -16,6 +16,8 @@
package net.mamoe.mirai.event.events
import kotlinx.atomicfu.AtomicBoolean
import kotlinx.atomicfu.atomic
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.Bot
import net.mamoe.mirai.Mirai
@ -27,7 +29,7 @@ import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.jvm.*
/**
* 机器人被踢出群或在其他客户端主动退出一个群. 在事件广播前 [Bot.groups] 就已删除这个群.
@ -353,7 +355,7 @@ public data class BotInvitedJoinGroupRequestEvent @MiraiInternalApi constructor(
public val invitor: Friend? get() = this.bot.getFriend(invitorId)
@JvmField
internal val responded: AtomicBoolean = AtomicBoolean(false)
internal val responded: AtomicBoolean = atomic(false)
@JvmBlockingBridge
public suspend fun accept(): Unit = Mirai.acceptInvitedJoinGroupRequest(this)
@ -403,7 +405,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor(
@JvmField
@PublishedApi
internal val responded: AtomicBoolean = AtomicBoolean(false)
internal val responded: AtomicBoolean = atomic(false)
/**
* 同意这个请求
@ -445,7 +447,7 @@ public data class MemberJoinRequestEvent @MiraiInternalApi constructor(
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
@JvmStatic
@JvmName("copy\$default") // avoid being mangled
fun `copy$default`(
fun copy_default(
var0: MemberJoinRequestEvent, var1: Bot, var2: Long, var4: String, var5: Long, var7: Long,
var9: String, var10: String, var11: Int, @Suppress("UNUSED_PARAMETER") var12: Any
): MemberJoinRequestEvent {

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -17,6 +17,9 @@ import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 有关一个 [Bot] 的事件

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("DuplicatedCode")
@ -19,6 +19,9 @@ import net.mamoe.mirai.message.data.PlainText
import net.mamoe.mirai.message.isContextIdenticalWith
import net.mamoe.mirai.message.nextMessage
import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.jvm.JvmInline
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
@ -404,7 +407,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@Suppress("unused")
@JvmName("invoke-RNyhSv4")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public fun MessageSelectionTimeoutChecker.invoke000(block: suspend () -> R): Void? {
public fun MessageSelectionTimeoutChecker.invoke000(block: suspend () -> R): Nothing? {
invoke(block)
return null
}
@ -417,7 +420,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("reply-RNyhSv4")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.reply000(block: suspend () -> Any?): Void? {
public infix fun MessageSelectionTimeoutChecker.reply000(block: suspend () -> Any?): Nothing? {
reply(block)
return null
}
@ -430,7 +433,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("reply-sCZ5gAI")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.reply000(message: String): Void? {
public infix fun MessageSelectionTimeoutChecker.reply000(message: String): Nothing? {
reply(message)
return null
}
@ -443,7 +446,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("reply-AVDwu3U")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.reply000(message: Message): Void? {
public infix fun MessageSelectionTimeoutChecker.reply000(message: Message): Nothing? {
reply(message)
return null
}
@ -457,7 +460,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("quoteReply-RNyhSv4")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.quoteReply000(block: suspend () -> Any?): Void? {
public infix fun MessageSelectionTimeoutChecker.quoteReply000(block: suspend () -> Any?): Nothing? {
reply(block)
return null
}
@ -470,7 +473,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("quoteReply-sCZ5gAI")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.quoteReply000(message: String): Void? {
public infix fun MessageSelectionTimeoutChecker.quoteReply000(message: String): Nothing? {
reply(message)
return null
}
@ -483,7 +486,7 @@ public abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedAp
@JvmName("quoteReply-AVDwu3U")
@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN)
public infix fun MessageSelectionTimeoutChecker.quoteReply000(message: Message): Void? {
public infix fun MessageSelectionTimeoutChecker.quoteReply000(message: Message): Nothing? {
reply(message)
return null
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -25,6 +25,8 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
public typealias MessageEventSubscribersBuilder = MessageSubscribersBuilder<MessageEvent, Listener<MessageEvent>, Unit, Unit>

View File

@ -13,7 +13,10 @@ import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.modules.*
import kotlinx.serialization.modules.PolymorphicModuleBuilder
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.overwriteWith
import kotlinx.serialization.modules.polymorphic
import net.mamoe.mirai.Mirai
import net.mamoe.mirai.message.MessageSerializers
import net.mamoe.mirai.message.data.*
@ -21,9 +24,8 @@ import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.lateinitMutableProperty
import net.mamoe.mirai.utils.map
import net.mamoe.mirai.utils.takeElementsFrom
import kotlin.jvm.Synchronized
import kotlin.reflect.KClass
import kotlin.reflect.full.allSuperclasses
import kotlin.reflect.full.isSubclassOf
@MiraiInternalApi
public open class MessageSourceSerializerImpl(serialName: String) :
@ -208,37 +210,25 @@ internal object MessageSerializersImpl : MessageSerializers {
}
}
internal fun <M : Any> SerializersModule.overwritePolymorphicWith(
internal expect fun <M : Any> SerializersModule.overwritePolymorphicWith(
type: KClass<M>,
serializer: KSerializer<M>
): SerializersModule {
return overwriteWith(SerializersModule {
// contextual(type, serializer)
for (superclass in type.allSuperclasses) {
if (superclass.isFinal) continue
if (!superclass.isSubclassOf(SingleMessage::class)) continue
@Suppress("UNCHECKED_CAST")
polymorphic(superclass as KClass<Any>) {
subclass(type, serializer)
}
}
})
}
): SerializersModule
private inline fun <reified M : SingleMessage> SerializersModuleBuilder.hierarchicallyPolymorphic(serializer: KSerializer<M>) =
hierarchicallyPolymorphic(M::class, serializer)
private fun <M : SingleMessage> SerializersModuleBuilder.hierarchicallyPolymorphic(
type: KClass<M>,
serializer: KSerializer<M>
) {
// contextual(type, serializer)
for (superclass in type.allSuperclasses) {
if (superclass.isFinal) continue
if (!superclass.isSubclassOf(SingleMessage::class)) continue
@Suppress("UNCHECKED_CAST")
polymorphic(superclass as KClass<Any>) {
subclass(type, serializer)
}
}
}
//private inline fun <reified M : SingleMessage> SerializersModuleBuilder.hierarchicallyPolymorphic(serializer: KSerializer<M>) =
// hierarchicallyPolymorphic(M::class, serializer)
//
//private fun <M : SingleMessage> SerializersModuleBuilder.hierarchicallyPolymorphic(
// type: KClass<M>,
// serializer: KSerializer<M>
//) {
// // contextual(type, serializer)
// for (superclass in type.allSuperclasses) {
// if (superclass.isFinal) continue
// if (!superclass.isSubclassOf(SingleMessage::class)) continue
// @Suppress("UNCHECKED_CAST")
// polymorphic(superclass as KClass<Any>) {
// subclass(type, serializer)
// }
// }
//}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -10,8 +10,6 @@
package net.mamoe.mirai.internal.utils
import net.mamoe.mirai.utils.MiraiLogger
import org.apache.logging.log4j.Marker
import org.apache.logging.log4j.MarkerManager
/**
* 内部添加 [Marker] 支持, 并兼容旧 [MiraiLogger] API.

View File

@ -0,0 +1,15 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.utils
internal expect interface Marker {
fun addParents(vararg parent: Marker)
}

View File

@ -0,0 +1,14 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.utils
internal expect object MarkerManager {
fun getMarker(name: String): Marker
}

View File

@ -10,8 +10,6 @@
package net.mamoe.mirai.internal.utils
import net.mamoe.mirai.utils.*
import java.text.SimpleDateFormat
import java.util.*
/**
@ -101,11 +99,8 @@ internal open class StdoutLogger constructor(
else debug(message.toString())
}
protected open val timeFormat: SimpleDateFormat by threadLocal {
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
}
private val currentTimeFormatted get() = timeFormat.format(Date())
private val currentTimeFormatted get() = currentTimeFormatted(null)
@MiraiExperimentalApi("This is subject to change.")
protected enum class Color(private val format: String) {

View File

@ -8,85 +8,41 @@
*/
@file:Suppress("MemberVisibilityCanBePrivate", "unused")
@file:JvmBlockingBridge
package net.mamoe.mirai.message.action
import kotlinx.coroutines.*
import kotlinx.coroutines.Deferred
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.message.data.MessageSource.Key.recallIn
import java.util.concurrent.CompletableFuture
/**
* [MessageSource.recallIn] 的结果.
*
* @see MessageSource.recallIn
*/
public class AsyncRecallResult internal constructor(
public expect class AsyncRecallResult internal constructor(
/**
* 撤回时产生的异常. Kotlin [Deferred] API.
* 撤回时产生的异常.
*/
public val exception: Deferred<Throwable?>,
exception: Deferred<Throwable?>,
) {
/**
* 撤回时产生的异常. Java [CompletableFuture] API.
*/
public val exceptionFuture: CompletableFuture<Throwable?> by lazy { exception.asCompletableFuture() }
public val exception: Deferred<Throwable?>
/**
* 撤回是否成功. Kotlin [Deferred] API.
* 撤回是否成功.
*/
public val isSuccess: Deferred<Boolean> by lazy {
CompletableDeferred<Boolean>().apply {
exception.invokeOnCompletion {
complete(it == null)
}
}
}
/**
* 撤回是否成功. Java [CompletableFuture] API.
*/
public val isSuccessFuture: CompletableFuture<Boolean> by lazy { isSuccess.asCompletableFuture() }
public val isSuccess: Deferred<Boolean>
/**
* 等待撤回完成, 返回撤回时产生的异常.
*/
@JvmBlockingBridge
public suspend fun awaitException(): Throwable? {
return exception.await()
}
public suspend fun awaitException(): Throwable?
/**
* 等待撤回完成, 返回撤回的结果.
*/
@JvmBlockingBridge
public suspend fun awaitIsSuccess(): Boolean {
return isSuccess.await()
}
public suspend fun awaitIsSuccess(): Boolean
}
// copied from kotlinx-coroutines-jdk8
private fun <T> Deferred<T>.asCompletableFuture(): CompletableFuture<T> {
val future = CompletableFuture<T>()
setupCancellation(future)
invokeOnCompletion {
@OptIn(ExperimentalCoroutinesApi::class)
try {
future.complete(getCompleted())
} catch (t: Throwable) {
future.completeExceptionally(t)
}
}
return future
}
// copied from kotlinx-coroutines-jdk8
private fun Job.setupCancellation(future: CompletableFuture<*>) {
future.whenComplete { _, exception ->
cancel(exception?.let {
it as? CancellationException ?: CancellationException("CompletableFuture was completed exceptionally", it)
})
}
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.message.action
@ -16,6 +16,8 @@ import net.mamoe.mirai.event.events.NudgeEvent
import net.mamoe.mirai.message.data.PokeMessage
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.BotConfiguration.MiraiProtocol
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 一个 "戳一戳" 动作.

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("unused", "NOTHING_TO_INLINE")
@ -17,6 +17,10 @@ import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageChain.Companion.deserializeFromMiraiCode
import net.mamoe.mirai.utils.safeCast
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* Mirai 码相关操作.

View File

@ -24,6 +24,9 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**

View File

@ -19,6 +19,9 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* "@全体成员".

View File

@ -22,6 +22,10 @@ import net.mamoe.mirai.message.MessageSerializers
import net.mamoe.mirai.message.data.MessageChain.Companion.serializeToJsonString
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds

View File

@ -1,22 +1,20 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress(
"MemberVisibilityCanBePrivate", "unused", "EXPERIMENTAL_API_USAGE",
"NOTHING_TO_INLINE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE",
"INAPPLICABLE_JVM_NAME"
)
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* 约束一个 [MessageChain] 中只存在这一种类型的元素. 新元素将会替换旧元素, 保持原顺序.
*

View File

@ -7,8 +7,6 @@
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:OptIn(MiraiInternalApi::class)
package net.mamoe.mirai.message.data
import io.ktor.utils.io.core.*
@ -19,9 +17,9 @@ import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.protobuf.ProtoNumber
import net.mamoe.mirai.message.MessageSerializers
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.ConcurrentLinkedDeque
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import java.util.concurrent.ConcurrentLinkedQueue
/**
* 自定义消息
@ -117,7 +115,7 @@ public sealed class CustomMessage : SingleMessage {
}
public companion object {
private val factories: ConcurrentLinkedQueue<Factory<*>> = ConcurrentLinkedQueue()
private val factories: MutableCollection<Factory<*>> = ConcurrentLinkedDeque()
internal fun register(factory: Factory<out CustomMessage>) {
factories.removeAll { it::class == factory::class }

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@ -19,7 +19,10 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.mamoe.mirai.IMirai
import net.mamoe.mirai.utils.DeprecatedSinceMirai
import net.mamoe.mirai.utils.isSameClass
import net.mamoe.mirai.utils.safeCast
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
@ -81,10 +84,7 @@ constructor(
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@Suppress("DEPRECATION_ERROR")
other as RichMessageOrigin
if (other !is RichMessageOrigin || !isSameClass(this, other)) return false
if (origin != other.origin) return false
if (resourceId != other.resourceId) return false

View File

@ -19,8 +19,11 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.annotations.Range
import net.mamoe.mirai.utils.safeCast
import org.jetbrains.annotations.Range
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.random.Random
import kotlin.random.nextInt

View File

@ -19,6 +19,9 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.jvm.JvmField
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* QQ 自带表情

View File

@ -25,6 +25,10 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.code.internal.appendStringAsMiraiCode
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 文件消息.

View File

@ -18,6 +18,8 @@ import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.safeCast
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 闪照. 闪照的内容取决于 [image] 代表的图片.

View File

@ -19,7 +19,8 @@ import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.message.data.ForwardMessage.DisplayStrategy
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
/**
* 未通过 [DisplayStrategy] 渲染的合并转发消息. [RawForwardMessage] 仅作为一个中间件, 用于 [ForwardMessageBuilder].

View File

@ -18,6 +18,8 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.castOrNull
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* 一些特殊的消息

View File

@ -7,13 +7,9 @@
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress(
"MemberVisibilityCanBePrivate", "unused", "EXPERIMENTAL_API_USAGE",
"NOTHING_TO_INLINE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE",
"INAPPLICABLE_JVM_NAME"
)
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
@file:Suppress("NOTHING_TO_INLINE")
package net.mamoe.mirai.message.data
@ -27,7 +23,9 @@ import net.mamoe.mirai.message.code.MiraiCode.serializeToMiraiCode
import net.mamoe.mirai.message.data.MessageChain.Companion.serializeToJsonString
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 可发送的或从服务器接收的消息.
@ -200,7 +198,8 @@ public interface Message {
*
* @param ignoreCase `true` 时忽略大小写
*/
@LowPriorityInOverloadResolution
@kotlin.internal.LowPriorityInOverloadResolution
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun contentEquals(another: Message, ignoreCase: Boolean = false): Boolean =
contentEquals(another, ignoreCase, false)
@ -281,6 +280,7 @@ public interface Message {
/** 将 [another] 按顺序连接到这个消息的尾部. */
@JvmName("plusIterableString")
@Suppress("INAPPLICABLE_JVM_NAME")
public operator fun plus(another: Iterable<String>): MessageChain =
another.fold(this, Message::plus).toMessageChain()
@ -360,7 +360,7 @@ public inline fun Message.repeat(count: Int): MessageChain {
return this.toMessageChain()
}
return buildMessageChain(count) {
repeat(count) {
repeat(count) l@{
add(this@repeat)
}
}

View File

@ -34,9 +34,8 @@ import net.mamoe.mirai.message.data.MessageSource.Key.recall
import net.mamoe.mirai.message.data.MessageSource.Key.recallIn
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.*
import java.util.stream.Stream
import kotlin.jvm.*
import kotlin.reflect.KProperty
import kotlin.streams.asSequence
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.RESTRICTED_ABSTRACT_MESSAGE_KEYS as RAMK
/**
@ -492,12 +491,6 @@ public inline fun messageChainOf(vararg messages: Message): MessageChain = messa
public fun Sequence<Message>.toMessageChain(): MessageChain =
LinearMessageChainImpl.create(ConstrainSingleHelper.constrainSingleMessages(this))
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public fun Stream<Message>.toMessageChain(): MessageChain = this.asSequence().toMessageChain()
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/

View File

@ -15,6 +15,9 @@ package net.mamoe.mirai.message.data
import kotlin.contracts.InvocationKind.EXACTLY_ONCE
import kotlin.contracts.contract
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 构建一个 [MessageChain]. 用法查看 [MessageChainBuilder].

View File

@ -1,14 +1,16 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.message.data
import kotlin.jvm.JvmField
/**
* 类型 Key. 由伴生对象实现, 表示一个 [Message] 对象的类型.
*

View File

@ -18,6 +18,7 @@ import net.mamoe.mirai.IMirai
import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.isSameClass
import net.mamoe.mirai.utils.safeCast
/**
@ -71,9 +72,7 @@ public class MessageOrigin(
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MessageOrigin
if (other !is MessageOrigin || !isSameClass(this, other)) return false
if (origin != other.origin) return false
if (resourceId != other.resourceId) return false

View File

@ -32,6 +32,10 @@ import net.mamoe.mirai.message.data.visitor.MessageVisitor
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.safeCast
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 消息源. 消息源存在于 [MessageChain] , 用于表示这个消息的来源, 也可以用来分辨 [MessageChain].

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -20,6 +20,9 @@ import net.mamoe.mirai.contact.ContactOrBot
import net.mamoe.mirai.message.data.MessageSource.Key.quote
import net.mamoe.mirai.message.data.MessageSource.Key.recall
import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 将在线消息源转换为离线消息源.

Some files were not shown because too many files have changed in this diff Show More