Commit 49673262 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt
parents 83d4375d 08bdf821
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
开发版本. 频繁更新, 不保证高稳定性 开发版本. 频繁更新, 不保证高稳定性
## `0.15.2` 2020/2/18
### mirai-core
- 尝试修复 `atomicfu` 编译错误的问题
### mirai-core-qqandroid
- 查询群信息失败后重试
## `0.15.1` 2020/2/15 ## `0.15.1` 2020/2/15
### mirai-core ### mirai-core
......
...@@ -57,6 +57,10 @@ TIM PC (2.3.2 版本,2019 年 8 月)协议的实现,相较于 core,仅 ...@@ -57,6 +57,10 @@ TIM PC (2.3.2 版本,2019 年 8 月)协议的实现,相较于 core,仅
## Use as a library ## Use as a library
**mirai-core 为独立设计, 可以作为库内置于任意 Java(JVM)/Android 项目中使用.** **mirai-core 为独立设计, 可以作为库内置于任意 Java(JVM)/Android 项目中使用.**
请将 `VERSION` 替换为最新的版本(如 `0.15.0`):
[![Download](https://api.bintray.com/packages/him188moe/mirai/mirai-core/images/download.svg)](https://bintray.com/him188moe/mirai/mirai-core/)
**Mirai 目前还处于实验性阶段, 我们无法保证任何稳定性, API 也可能会随时修改.**
### Maven ### Maven
Kotlin 在 Maven 上只支持 JVM 平台. Kotlin 在 Maven 上只支持 JVM 平台.
```xml ```xml
...@@ -71,7 +75,7 @@ Kotlin 在 Maven 上只支持 JVM 平台. ...@@ -71,7 +75,7 @@ Kotlin 在 Maven 上只支持 JVM 平台.
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>net.mamoe</groupId> <groupId>net.mamoe</groupId>
<artifactId>mirai-core-qqandroid-jvm</artifactId> <artifactId>mirai-core-qqandroid</artifactId>
<version>0.15.1</version> <!-- 替换版本为最新版本 --> <version>0.15.1</version> <!-- 替换版本为最新版本 -->
</dependency> </dependency>
</dependencies> </dependencies>
...@@ -85,24 +89,20 @@ repositories{ ...@@ -85,24 +89,20 @@ repositories{
} }
``` ```
若您需要使用在跨平台项目, 则要对各个目标平台添加不同的依赖,这与 kotlin 相关多平台库的依赖是类似的。 若您需要使用在跨平台项目, 则要对各个目标平台添加不同的依赖,这与 kotlin 相关多平台库的依赖是类似的。
**若您只需要使用在单一平台, 则只需要添加一项该平台的依赖. 如只在 JVM 运行则只需要`-jvm`的依赖** **若您只需要使用在单一平台, 则只需要添加一项该平台的依赖.**
请将 `VERSION` 替换为最新的版本(如 `0.15.0`):
[![Download](https://api.bintray.com/packages/him188moe/mirai/mirai-core/images/download.svg)](https://bintray.com/him188moe/mirai/mirai-core/)
**Mirai 目前还处于实验性阶段, 我们无法保证任何稳定性, API 也可能会随时修改.**
**注意:** **注意:**
Mirai 核心由 API 模块(`mirai-core`)和协议模块组成。 Mirai 核心由 API 模块(`mirai-core`)和协议模块组成。
只添加 API 模块将无法正常工作。 只添加 API 模块将无法正常工作。
现在只推荐使用 QQAndroid 协议,请参照下文选择对应目标平台的依赖添加。 现在只推荐使用 QQAndroid 协议,请参照下文选择对应目标平台的依赖添加。
**common** (通用平台) **jvm** (JVM 平台)
```kotlin ```kotlin
implementation("net.mamoe:mirai-core-qqandroid-common:VERSION") implementation("net.mamoe:mirai-core-qqandroid:VERSION")
``` ```
**jvm** (JVM 平台) **common** (通用平台)
```kotlin ```kotlin
implementation("net.mamoe:mirai-core-qqandroid-jvm:VERSION") implementation("net.mamoe:mirai-core-qqandroid-common:VERSION")
``` ```
**android** (Android 平台) **android** (Android 平台)
```kotlin ```kotlin
......
# style guide # style guide
kotlin.code.style=official kotlin.code.style=official
# config # config
mirai_version=0.15.1 mirai_version=0.15.2
mirai_japt_version=1.0.1 mirai_japt_version=1.0.1
kotlin.incremental.multiplatform=true kotlin.incremental.multiplatform=true
kotlin.parallel.tasks.in.project=true kotlin.parallel.tasks.in.project=true
......
// 部分源码来自 kotlinx.coroutines // 部分源码来自 kotlinx.coroutines
// Source code from kotlinx.coroutines
def pomConfig = { def pomConfig = {
licenses { licenses {
...@@ -12,6 +13,7 @@ def pomConfig = { ...@@ -12,6 +13,7 @@ def pomConfig = {
developer { developer {
id "mamoe" id "mamoe"
name "Mamoe Technologies" name "Mamoe Technologies"
email "support@mamoe.net"
} }
} }
scm { scm {
......
...@@ -6,7 +6,7 @@ plugins { ...@@ -6,7 +6,7 @@ plugins {
} }
javafx { javafx {
version = "11" version = "13.0.2"
modules = listOf("javafx.controls") modules = listOf("javafx.controls")
//mainClassName = "Application" //mainClassName = "Application"
} }
......
...@@ -24,8 +24,8 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { ...@@ -24,8 +24,8 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
val botList = observableListOf<BotModel>() val botList = observableListOf<BotModel>()
val consoleInfo = ConsoleInfo() val consoleInfo = ConsoleInfo()
fun login(qq: String, psd: String) { suspend fun login(qq: String, psd: String) {
MiraiConsole.CommandListener.commandChannel.offer("/login $qq $psd") MiraiConsole.CommandListener.commandChannel.send("/login $qq $psd")
} }
override fun pushLog(identity: Long, message: String) = Platform.runLater { override fun pushLog(identity: Long, message: String) = Platform.runLater {
......
package net.mamoe.mirai.console.graphical.view package net.mamoe.mirai.console.graphical.view
import com.jfoenix.controls.JFXTextField
import javafx.beans.property.SimpleStringProperty import javafx.beans.property.SimpleStringProperty
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
import net.mamoe.mirai.console.graphical.util.jfxButton import net.mamoe.mirai.console.graphical.util.jfxButton
import net.mamoe.mirai.console.graphical.util.jfxPasswordfield import net.mamoe.mirai.console.graphical.util.jfxPasswordfield
...@@ -24,7 +24,9 @@ class LoginFragment : Fragment() { ...@@ -24,7 +24,9 @@ class LoginFragment : Fragment() {
} }
} }
jfxButton("登录").action { jfxButton("登录").action {
runBlocking {
controller.login(qq.value, psd.value) controller.login(qq.value, psd.value)
}
close() close()
} }
} }
......
...@@ -10,7 +10,6 @@ import com.googlecode.lanterna.terminal.DefaultTerminalFactory ...@@ -10,7 +10,6 @@ import com.googlecode.lanterna.terminal.DefaultTerminalFactory
import com.googlecode.lanterna.terminal.Terminal import com.googlecode.lanterna.terminal.Terminal
import com.googlecode.lanterna.terminal.TerminalResizeListener import com.googlecode.lanterna.terminal.TerminalResizeListener
import com.googlecode.lanterna.terminal.swing.SwingTerminal import com.googlecode.lanterna.terminal.swing.SwingTerminal
import com.googlecode.lanterna.terminal.swing.SwingTerminalFontConfiguration
import com.googlecode.lanterna.terminal.swing.SwingTerminalFrame import com.googlecode.lanterna.terminal.swing.SwingTerminalFrame
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.io.close import kotlinx.coroutines.io.close
...@@ -23,7 +22,6 @@ import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs ...@@ -23,7 +22,6 @@ import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs
import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.LoginSolver
import net.mamoe.mirai.utils.createCharImg import net.mamoe.mirai.utils.createCharImg
import net.mamoe.mirai.utils.writeChannel import net.mamoe.mirai.utils.writeChannel
import java.awt.Font
import java.io.File import java.io.File
import java.io.OutputStream import java.io.OutputStream
import java.io.PrintStream import java.io.PrintStream
...@@ -126,12 +124,12 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI { ...@@ -126,12 +124,12 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
} }
fun provideInput(input: String) { suspend fun provideInput(input: String) {
if (requesting) { if (requesting) {
requestResult = input requestResult = input
requesting = false requesting = false
} else { } else {
MiraiConsole.CommandListener.commandChannel.offer( MiraiConsole.CommandListener.commandChannel.send(
commandBuilder.toString() commandBuilder.toString()
) )
} }
...@@ -336,7 +334,9 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI { ...@@ -336,7 +334,9 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
update() update()
} }
KeyType.Enter -> { KeyType.Enter -> {
runBlocking {
provideInput(commandBuilder.toString()) provideInput(commandBuilder.toString())
}
emptyCommand() emptyCommand()
} }
KeyType.Escape -> { KeyType.Escape -> {
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
| 名字 | 介绍 | | 名字 | 介绍 |
| --- | --- | | --- | --- |
| Mirai-Console-Pure | 最纯净版, CLI环境, 通过标准输入与标准输出 交互 | | Mirai-Console-Pure | 最纯净版, CLI环境, 通过标准输入与标准输出 交互 |
| Mirai-Console-Terminal | (UNIX)Terminal环境 提供简介好用的富文本控制台 | | Mirai-Console-Terminal | (UNIX)Terminal环境 提供简的富文本控制台 |
| Mirai-Console-Android | 安卓APP (TODO) | | Mirai-Console-Android | 安卓APP (TODO) |
| Mirai-Console-Graphical | JavaFX的图形化界面, 有Native版本(.jar/.exe/.dmg) | | Mirai-Console-Graphical | JavaFX的图形化界面 (.jar/.exe/.dmg) |
| Mirai-Console-WebPanel | Web Panel操作(TODO) | | Mirai-Console-WebPanel | Web Panel操作(TODO) |
| Mirai-Console-Ios | IOS APP (TODO) | | Mirai-Console-Ios | IOS APP (TODO) |
......
...@@ -42,7 +42,7 @@ object CommandManager { ...@@ -42,7 +42,7 @@ object CommandManager {
registeredCommand.remove(commandName) registeredCommand.remove(commandName)
} }
fun runCommand(fullCommand: String): Boolean { suspend fun runCommand(fullCommand: String): Boolean {
val blocks = fullCommand.split(" ") val blocks = fullCommand.split(" ")
val commandHead = blocks[0].replace("/", "") val commandHead = blocks[0].replace("/", "")
if (!registeredCommand.containsKey(commandHead)) { if (!registeredCommand.containsKey(commandHead)) {
...@@ -66,7 +66,7 @@ interface ICommand { ...@@ -66,7 +66,7 @@ interface ICommand {
val name: String val name: String
val alias: List<String> val alias: List<String>
val description: String val description: String
fun onCommand(args: List<String>): Boolean suspend fun onCommand(args: List<String>): Boolean
fun register() fun register()
} }
...@@ -77,9 +77,9 @@ abstract class Command( ...@@ -77,9 +77,9 @@ abstract class Command(
) : ICommand { ) : ICommand {
/** /**
* 最高优先级监听器 * 最高优先级监听器
* 如果return [false] 这次指令不会被[PluginBase]的全局onCommand监听器监听 * 如果 return `false` 这次指令不会被 [PluginBase] 的全局 onCommand 监听器监听
* */ * */
open override fun onCommand(args: List<String>): Boolean { open override suspend fun onCommand(args: List<String>): Boolean {
return true return true
} }
...@@ -92,9 +92,9 @@ class AnonymousCommand internal constructor( ...@@ -92,9 +92,9 @@ class AnonymousCommand internal constructor(
override val name: String, override val name: String,
override val alias: List<String>, override val alias: List<String>,
override val description: String, override val description: String,
val onCommand: ICommand.(args: List<String>) -> Boolean val onCommand: suspend ICommand.(args: List<String>) -> Boolean
) : ICommand { ) : ICommand {
override fun onCommand(args: List<String>): Boolean { override suspend fun onCommand(args: List<String>): Boolean {
return onCommand.invoke(this, args) return onCommand.invoke(this, args)
} }
...@@ -107,9 +107,9 @@ class CommandBuilder internal constructor() { ...@@ -107,9 +107,9 @@ class CommandBuilder internal constructor() {
var name: String? = null var name: String? = null
var alias: List<String>? = null var alias: List<String>? = null
var description: String = "" var description: String = ""
var onCommand: (ICommand.(args: List<String>) -> Boolean)? = null var onCommand: (suspend ICommand.(args: List<String>) -> Boolean)? = null
fun onCommand(commandProcess: ICommand.(args: List<String>) -> Boolean) { fun onCommand(commandProcess: suspend ICommand.(args: List<String>) -> Boolean) {
onCommand = commandProcess onCommand = commandProcess
} }
......
...@@ -9,20 +9,20 @@ package net.mamoe.mirai.console ...@@ -9,20 +9,20 @@ package net.mamoe.mirai.console
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.api.http.MiraiHttpAPIServer import net.mamoe.mirai.api.http.MiraiHttpAPIServer
import net.mamoe.mirai.api.http.generateSessionKey import net.mamoe.mirai.api.http.generateSessionKey
import net.mamoe.mirai.console.MiraiConsole.CommandListener.processNextCommandLine
import net.mamoe.mirai.console.plugins.PluginManager import net.mamoe.mirai.console.plugins.PluginManager
import net.mamoe.mirai.console.plugins.loadAsConfig import net.mamoe.mirai.console.plugins.loadAsConfig
import net.mamoe.mirai.console.plugins.withDefaultWrite import net.mamoe.mirai.console.plugins.withDefaultWrite
import net.mamoe.mirai.console.plugins.withDefaultWriteSave import net.mamoe.mirai.console.plugins.withDefaultWriteSave
import net.mamoe.mirai.contact.sendMessage import net.mamoe.mirai.contact.sendMessage
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.SimpleLogger
import java.io.File import java.io.File
import java.util.* import java.util.*
import java.util.concurrent.LinkedBlockingQueue
import kotlin.concurrent.thread
object MiraiConsole { object MiraiConsole {
...@@ -130,7 +130,6 @@ object MiraiConsole { ...@@ -130,7 +130,6 @@ object MiraiConsole {
val qqPassword = it[1] val qqPassword = it[1]
logger("[Bot Login]", 0, "login...") logger("[Bot Login]", 0, "login...")
try { try {
runBlocking {
frontEnd.prePushBot(qqNumber) frontEnd.prePushBot(qqNumber)
val bot = Bot(qqNumber, qqPassword) { val bot = Bot(qqNumber, qqPassword) {
this.loginSolver = frontEnd.createLoginSolver() this.loginSolver = frontEnd.createLoginSolver()
...@@ -160,7 +159,6 @@ object MiraiConsole { ...@@ -160,7 +159,6 @@ object MiraiConsole {
"$qqNumber login successes" "$qqNumber login successes"
) )
frontEnd.pushBot(bot) frontEnd.pushBot(bot)
}
} catch (e: Exception) { } catch (e: Exception) {
logger( logger(
"[Bot Login]", "[Bot Login]",
...@@ -288,20 +286,19 @@ object MiraiConsole { ...@@ -288,20 +286,19 @@ object MiraiConsole {
} }
} }
object CommandListener { object CommandListener : Job by {
val commandChannel: Queue<String> = LinkedBlockingQueue<String>() GlobalScope.launch(start = CoroutineStart.LAZY) {
fun start() {
thread {
processNextCommandLine() processNextCommandLine()
} }
} }() {
val commandChannel: Channel<String> = Channel()
tailrec fun processNextCommandLine() { suspend fun processNextCommandLine() {
if (allDown) { if (allDown) {
return return
} }
var fullCommand = commandChannel.take(1)[0] for (command in commandChannel) {
if (fullCommand != null) { var fullCommand = command
if (!fullCommand.startsWith("/")) { if (!fullCommand.startsWith("/")) {
fullCommand = "/$fullCommand" fullCommand = "/$fullCommand"
} }
...@@ -309,7 +306,6 @@ object MiraiConsole { ...@@ -309,7 +306,6 @@ object MiraiConsole {
logger("未知指令 $fullCommand") logger("未知指令 $fullCommand")
} }
} }
processNextCommandLine();
} }
} }
......
package net.mamoe.mirai.console package net.mamoe.mirai.console
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.utils.DefaultLoginSolver import net.mamoe.mirai.utils.DefaultLoginSolver
import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.LoginSolver
import net.mamoe.mirai.utils.LoginSolverInputReader import net.mamoe.mirai.utils.LoginSolverInputReader
import kotlin.concurrent.thread import kotlin.concurrent.thread
class MiraiConsoleUIPure() : MiraiConsoleUI { class MiraiConsoleUIPure : MiraiConsoleUI {
var requesting = false var requesting = false
var requestStr = "" var requestStr = ""
init { init {
thread { thread {
while (true) { while (true) {
val input = readLine() ?: "" val input = readLine() ?: return@thread
if (requesting) { if (requesting) {
requestStr = input requestStr = input
requesting = false requesting = false
} else { } else {
MiraiConsole.CommandListener.commandChannel.offer(input) runBlocking {
MiraiConsole.CommandListener.commandChannel.send(input)
}
} }
} }
} }
......
...@@ -118,5 +118,9 @@ kotlin { ...@@ -118,5 +118,9 @@ kotlin {
} }
} }
} }
//
//tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
// kotlinOptions.jvmTarget = "1.8"
//}
apply(from = rootProject.file("gradle/publish.gradle")) apply(from = rootProject.file("gradle/publish.gradle"))
...@@ -215,11 +215,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -215,11 +215,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2) .sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2)
troopListData.groups.forEach { troopNum -> troopListData.groups.forEach { troopNum ->
launch { // 别用 fun, 别 val, 编译失败警告
try { lateinit var loadGroup: suspend () -> Unit
loadGroup = suspend {
tryNTimesOrException(3) {
bot.groups.delegate.addLast( bot.groups.delegate.addLast(
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
GroupImpl( (GroupImpl(
bot = bot, bot = bot,
coroutineContext = bot.coroutineContext, coroutineContext = bot.coroutineContext,
id = troopNum.groupCode, id = troopNum.groupCode,
...@@ -241,12 +244,20 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -241,12 +244,20 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
this.delegate.groupCode = troopNum.groupCode this.delegate.groupCode = troopNum.groupCode
}, },
members = bot.queryGroupMemberList(troopNum.groupUin, troopNum.groupCode, troopNum.dwGroupOwnerUin) members = bot.queryGroupMemberList(troopNum.groupUin, troopNum.groupCode, troopNum.dwGroupOwnerUin)
))
) )
) }?.let {
} catch (e: Exception) {
logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试") logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试")
logger.error(e) logger.error(it)
this@QQAndroidBotNetworkHandler.launch {
delay(10_000)
loadGroup()
}
} }
Unit // 别删, 编译失败警告
}
launch {
loadGroup()
} }
} }
logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个") logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个")
......
...@@ -150,5 +150,9 @@ kotlin { ...@@ -150,5 +150,9 @@ kotlin {
} }
} }
} }
//
//tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
// kotlinOptions.jvmTarget = "1.8"
//}
apply(from = rootProject.file("gradle/publish.gradle")) apply(from = rootProject.file("gradle/publish.gradle"))
package net.mamoe.mirai.utils
private var isAddSuppressedSupported: Boolean = true
@MiraiInternalAPI
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
actual fun Throwable.addSuppressed(e: Throwable) {
if (!isAddSuppressedSupported) {
return
}
try {
this.addSuppressed(e)
} catch (e: Exception) {
isAddSuppressedSupported = false
}
}
\ No newline at end of file
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
@file:Suppress("EXPERIMENTAL_API_USAGE") @file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
...@@ -14,6 +17,8 @@ package net.mamoe.mirai.message.data ...@@ -14,6 +17,8 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.groupCardOrNick import net.mamoe.mirai.contact.groupCardOrNick
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/** /**
......
...@@ -7,8 +7,14 @@ ...@@ -7,8 +7,14 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/** /**
* "@全体成员" * "@全体成员"
* *
......
...@@ -7,8 +7,13 @@ ...@@ -7,8 +7,13 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
/** /**
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
@file:Suppress("EXPERIMENTAL_API_USAGE") @file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
...@@ -14,13 +17,18 @@ package net.mamoe.mirai.message.data ...@@ -14,13 +17,18 @@ package net.mamoe.mirai.message.data
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
import net.mamoe.mirai.utils.io.chunkedHexToBytes import net.mamoe.mirai.utils.io.chunkedHexToBytes
import kotlin.js.JsName
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
/** /**
* 自定义表情 (收藏的表情), 图片 * 自定义表情 (收藏的表情), 图片
*/ */
sealed class Image : Message { sealed class Image : Message {
companion object Key : Message.Key<Image> { companion object Key : Message.Key<Image> {
@JvmStatic
@JsName("fromId")
@JvmName("fromId") @JvmName("fromId")
operator fun invoke(imageId: String): Image = when (imageId.length) { operator fun invoke(imageId: String): Image = when (imageId.length) {
37 -> NotOnlineImageFromFile(imageId) // /f8f1ab55-bf8e-4236-b55e-955848d7069f 37 -> NotOnlineImageFromFile(imageId) // /f8f1ab55-bf8e-4236-b55e-955848d7069f
......
...@@ -13,6 +13,7 @@ package net.mamoe.mirai.message.data ...@@ -13,6 +13,7 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.sendMessage import net.mamoe.mirai.contact.sendMessage
import kotlin.jvm.JvmSynthetic
/** /**
* 可发送的或从服务器接收的消息. * 可发送的或从服务器接收的消息.
...@@ -82,6 +83,7 @@ interface Message { ...@@ -82,6 +83,7 @@ interface Message {
* println(c)// "Hello world!" * println(c)// "Hello world!"
* ``` * ```
*/ */
@JvmSynthetic // in java they should use `plus` instead
fun followedBy(tail: Message): MessageChain { fun followedBy(tail: Message): MessageChain {
require(tail !is SingleOnly) { "SingleOnly Message cannot follow another message" } require(tail !is SingleOnly) { "SingleOnly Message cannot follow another message" }
require(this !is SingleOnly) { "SingleOnly Message cannot be followed" } require(this !is SingleOnly) { "SingleOnly Message cannot be followed" }
...@@ -92,6 +94,7 @@ interface Message { ...@@ -92,6 +94,7 @@ interface Message {
override fun toString(): String override fun toString(): String
operator fun plus(another: Message): MessageChain = this.followedBy(another) operator fun plus(another: Message): MessageChain = this.followedBy(another)
operator fun plus(another: String): MessageChain = this.followedBy(another.toMessage()) operator fun plus(another: String): MessageChain = this.followedBy(another.toMessage())
// `+ ""` will be resolved to `plus(String)` instead of `plus(CharSeq)` // `+ ""` will be resolved to `plus(String)` instead of `plus(CharSeq)`
operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage()) operator fun plus(another: CharSequence): MessageChain = this.followedBy(another.toString().toMessage())
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.message.data.NullMessageChain.toString import net.mamoe.mirai.message.data.NullMessageChain.toString
...@@ -14,6 +17,9 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI ...@@ -14,6 +17,9 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.js.JsName import kotlin.js.JsName
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.jvm.Volatile import kotlin.jvm.Volatile
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
...@@ -35,10 +41,12 @@ interface MessageChain : Message, MutableList<Message> { ...@@ -35,10 +41,12 @@ interface MessageChain : Message, MutableList<Message> {
override fun followedBy(tail: Message): MessageChain override fun followedBy(tail: Message): MessageChain
// endregion // endregion
@JvmSynthetic
operator fun plusAssign(message: Message) { operator fun plusAssign(message: Message) {
this.followedBy(message) this.followedBy(message)
} }
@JvmSynthetic // make java user happier
operator fun plusAssign(plain: String) { operator fun plusAssign(plain: String) {
this.plusAssign(plain.toMessage()) this.plusAssign(plain.toMessage())
} }
...@@ -53,7 +61,7 @@ interface MessageChain : Message, MutableList<Message> { ...@@ -53,7 +61,7 @@ interface MessageChain : Message, MutableList<Message> {
operator fun <M : Message> get(key: Message.Key<M>): M = first(key) operator fun <M : Message> get(key: Message.Key<M>): M = first(key)
override fun eq(other: Message): Boolean { override fun eq(other: Message): Boolean {
if(other is MessageChain && other.size != this.size) if (other is MessageChain && other.size != this.size)
return false return false
return this.toString() == other.toString() return this.toString() == other.toString()
} }
...@@ -67,13 +75,16 @@ inline operator fun <reified T : Message> MessageChain.getValue(thisRef: Any?, p ...@@ -67,13 +75,16 @@ inline operator fun <reified T : Message> MessageChain.getValue(thisRef: Any?, p
/** /**
* 构造无初始元素的可修改的 [MessageChain]. 初始大小将会被设定为 8 * 构造无初始元素的可修改的 [MessageChain]. 初始大小将会被设定为 8
*/ */
@JsName("emptyMessageChain") @JvmName("newChain")
@JsName("newChain")
@Suppress("FunctionName") @Suppress("FunctionName")
fun MessageChain(): MessageChain = EmptyMessageChain() fun MessageChain(): MessageChain = EmptyMessageChain()
/** /**
* 构造无初始元素的可修改的 [MessageChain]. 初始大小将会被设定为 [initialCapacity] * 构造无初始元素的可修改的 [MessageChain]. 初始大小将会被设定为 [initialCapacity]
*/ */
@JvmName("newChain")
@JsName("newChain")
@Suppress("FunctionName") @Suppress("FunctionName")
fun MessageChain(initialCapacity: Int): MessageChain = fun MessageChain(initialCapacity: Int): MessageChain =
if (initialCapacity == 0) EmptyMessageChain() if (initialCapacity == 0) EmptyMessageChain()
...@@ -83,6 +94,8 @@ fun MessageChain(initialCapacity: Int): MessageChain = ...@@ -83,6 +94,8 @@ fun MessageChain(initialCapacity: Int): MessageChain =
* 构造 [MessageChain] * 构造 [MessageChain]
* 若仅提供一个参数, 请考虑使用 [Message.toChain] 以优化性能 * 若仅提供一个参数, 请考虑使用 [Message.toChain] 以优化性能
*/ */
@JvmName("newChain")
@JsName("newChain")
@Suppress("FunctionName") @Suppress("FunctionName")
fun MessageChain(vararg messages: Message): MessageChain = fun MessageChain(vararg messages: Message): MessageChain =
if (messages.isEmpty()) EmptyMessageChain() if (messages.isEmpty()) EmptyMessageChain()
...@@ -91,6 +104,8 @@ fun MessageChain(vararg messages: Message): MessageChain = ...@@ -91,6 +104,8 @@ fun MessageChain(vararg messages: Message): MessageChain =
/** /**
* 构造 [MessageChain] * 构造 [MessageChain]
*/ */
@JvmName("newChain")
@JsName("newChain")
@Suppress("FunctionName") @Suppress("FunctionName")
fun MessageChain(messages: Iterable<Message>): MessageChain = fun MessageChain(messages: Iterable<Message>): MessageChain =
MessageChainImpl(messages.toMutableList()) MessageChainImpl(messages.toMutableList())
...@@ -106,6 +121,8 @@ fun MessageChain(messages: Iterable<Message>): MessageChain = ...@@ -106,6 +121,8 @@ fun MessageChain(messages: Iterable<Message>): MessageChain =
* *
* @see Message.toChain receiver 模式 * @see Message.toChain receiver 模式
*/ */
@JvmName("newSingleMessageChain")
@JsName("newChain")
@MiraiExperimentalAPI @MiraiExperimentalAPI
@UseExperimental(ExperimentalContracts::class) @UseExperimental(ExperimentalContracts::class)
@Suppress("FunctionName") @Suppress("FunctionName")
...@@ -352,6 +369,7 @@ internal inline class SingleMessageChainImpl( ...@@ -352,6 +369,7 @@ internal inline class SingleMessageChainImpl(
// region Message override // region Message override
override operator fun contains(sub: String): Boolean = delegate.contains(sub) override operator fun contains(sub: String): Boolean = delegate.contains(sub)
override fun followedBy(tail: Message): MessageChain { override fun followedBy(tail: Message): MessageChain {
require(tail !is SingleOnly) { "SingleOnly Message cannot follow another message" } require(tail !is SingleOnly) { "SingleOnly Message cannot follow another message" }
return if (tail is MessageChain) tail.apply { followedBy(delegate) } return if (tail is MessageChain) tail.apply { followedBy(delegate) }
......
...@@ -7,8 +7,14 @@ ...@@ -7,8 +7,14 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/** /**
* 消息源, 用于被引用. 它将由协议模块实现. * 消息源, 用于被引用. 它将由协议模块实现.
* 消息源只用于 [QuoteReply] * 消息源只用于 [QuoteReply]
...@@ -18,7 +24,7 @@ package net.mamoe.mirai.message.data ...@@ -18,7 +24,7 @@ package net.mamoe.mirai.message.data
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain] * @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
*/ */
interface MessageSource : Message { interface MessageSource : Message {
companion object : Message.Key<MessageSource> companion object Key : Message.Key<MessageSource>
/** /**
* 实际上是个随机数, 但服务器确实是用它当做 uid * 实际上是个随机数, 但服务器确实是用它当做 uid
......
...@@ -7,9 +7,19 @@ ...@@ -7,9 +7,19 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* 纯文本. 可含 emoji 表情.
*
* 一般不需要主动构造 [PlainText], [Message] 可直接与 [String] 相加. Java 用户请使用 [MessageChain.plus]
*/
inline class PlainText(val stringValue: String) : Message { inline class PlainText(val stringValue: String) : Message {
override operator fun contains(sub: String): Boolean = sub in stringValue override operator fun contains(sub: String): Boolean = sub in stringValue
override fun toString(): String = stringValue override fun toString(): String = stringValue
...@@ -17,7 +27,7 @@ inline class PlainText(val stringValue: String) : Message { ...@@ -17,7 +27,7 @@ inline class PlainText(val stringValue: String) : Message {
companion object Key : Message.Key<PlainText> companion object Key : Message.Key<PlainText>
override fun eq(other: Message): Boolean { override fun eq(other: Message): Boolean {
if(other is MessageChain){ if (other is MessageChain) {
return other eq this.toString() return other eq this.toString()
} }
return other is PlainText && other.stringValue == this.stringValue return other is PlainText && other.stringValue == this.stringValue
......
...@@ -7,10 +7,15 @@ ...@@ -7,10 +7,15 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/** /**
......
...@@ -7,10 +7,17 @@ ...@@ -7,10 +7,17 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
@file:Suppress("MemberVisibilityCanBePrivate") @file:Suppress("MemberVisibilityCanBePrivate")
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/** /**
* XML 消息, 如分享, 卡片等. * XML 消息, 如分享, 卡片等.
* *
...@@ -30,6 +37,7 @@ inline class XMLMessage(val stringValue: String) : Message, ...@@ -30,6 +37,7 @@ inline class XMLMessage(val stringValue: String) : Message,
* 构造一条 XML 消息 * 构造一条 XML 消息
*/ */
@XMLDsl @XMLDsl
@MiraiExperimentalAPI("还未支持")
inline fun buildXMLMessage(block: @XMLDsl XMLMessageBuilder.() -> Unit): XMLMessage = inline fun buildXMLMessage(block: @XMLDsl XMLMessageBuilder.() -> Unit): XMLMessage =
XMLMessage(XMLMessageBuilder().apply(block).text) XMLMessage(XMLMessageBuilder().apply(block).text)
......
/*
* Copyright 2020 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/master/LICENSE
*/
package net.mamoe.mirai.utils
@MiraiInternalAPI
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
expect fun Throwable.addSuppressed(e: Throwable)
@MiraiInternalAPI
@Suppress("DuplicatedCode")
inline fun <R> tryNTimes(repeat: Int, block: () -> R): R {
var lastException: Throwable? = null
repeat(repeat) {
try {
return block()
} catch (e: Throwable) {
if (lastException == null) {
lastException = e
}
lastException!!.addSuppressed(e)
}
}
throw lastException!!
}
@MiraiInternalAPI
@Suppress("DuplicatedCode")
inline fun <R> tryNTimesOrNull(repeat: Int, block: () -> R): R? {
var lastException: Throwable? = null
repeat(repeat) {
try {
return block()
} catch (e: Throwable) {
if (lastException == null) {
lastException = e
}
lastException!!.addSuppressed(e)
}
}
return null
}
@MiraiInternalAPI
@Suppress("DuplicatedCode")
inline fun <R> tryNTimesOrException(repeat: Int, block: () -> R): Throwable? {
var lastException: Throwable? = null
repeat(repeat) {
try {
block()
return null
} catch (e: Throwable) {
if (lastException == null) {
lastException = e
}
lastException!!.addSuppressed(e)
}
}
return lastException!!
}
\ No newline at end of file
package net.mamoe.mirai.utils
private var isAddSuppressedSupported: Boolean = true
@MiraiInternalAPI
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
actual fun Throwable.addSuppressed(e: Throwable) {
if (!isAddSuppressedSupported) {
return
}
try {
this.addSuppressed(e)
} catch (e: Exception) {
isAddSuppressedSupported = false
}
}
\ No newline at end of file
...@@ -2,9 +2,9 @@ apply plugin: "kotlin" ...@@ -2,9 +2,9 @@ apply plugin: "kotlin"
apply plugin: "java" apply plugin: "java"
dependencies { dependencies {
implementation files("../../mirai-core/build/classes/kotlin/jvm/main") // IDE bug runtimeOnly files("../../mirai-core/build/classes/kotlin/jvm/main") // IDE bug
implementation files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug runtimeOnly files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug
implementation project(":mirai-core-qqandroid") implementation project(":mirai-core-qqandroid")
api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion api group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
......
...@@ -2,9 +2,9 @@ apply plugin: "java" ...@@ -2,9 +2,9 @@ apply plugin: "java"
apply plugin: "kotlin" apply plugin: "kotlin"
dependencies { dependencies {
implementation files("../../mirai-core/build/classes/kotlin/jvm/main") // IDE bug runtimeOnly files("../../mirai-core/build/classes/kotlin/jvm/main") // IDE bug
implementation files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug runtimeOnly files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug
implementation project(":mirai-core-qqandroid") implementation project(":mirai-core-qqandroid")
implementation project(":mirai-japt") implementation project(":mirai-japt")
} }
......
...@@ -5,6 +5,9 @@ import net.mamoe.mirai.japt.BlockingContacts; ...@@ -5,6 +5,9 @@ import net.mamoe.mirai.japt.BlockingContacts;
import net.mamoe.mirai.japt.BlockingQQ; import net.mamoe.mirai.japt.BlockingQQ;
import net.mamoe.mirai.japt.Events; import net.mamoe.mirai.japt.Events;
import net.mamoe.mirai.message.GroupMessage; import net.mamoe.mirai.message.GroupMessage;
import net.mamoe.mirai.message.data.At;
import net.mamoe.mirai.message.data.Image;
import net.mamoe.mirai.message.data.MessageUtils;
class BlockingTest { class BlockingTest {
...@@ -19,8 +22,14 @@ class BlockingTest { ...@@ -19,8 +22,14 @@ class BlockingTest {
Events.subscribeAlways(GroupMessage.class, (GroupMessage message) -> { Events.subscribeAlways(GroupMessage.class, (GroupMessage message) -> {
final BlockingQQ sender = BlockingContacts.createBlocking(message.getSender()); final BlockingQQ sender = BlockingContacts.createBlocking(message.getSender());
sender.sendMessage("Hello World!");
sender.sendMessage("Hello"); System.out.println("发送完了");
sender.sendMessage(MessageUtils.newChain()
.plus(new At(message.getSender()))
.plus(Image.fromId("{xxxx}.jpg"))
.plus("123465")
);
}); });
Thread.sleep(999999999); Thread.sleep(999999999);
......
...@@ -32,7 +32,7 @@ Mirai Java Apt ...@@ -32,7 +32,7 @@ Mirai Java Apt
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>net.mamoe</groupId> <groupId>net.mamoe</groupId>
<artifactId>mirai-core-qqandroid-jvm</artifactId> <artifactId>mirai-core-qqandroid</artifactId>
<version>CORE_VERSION</version> <!-- 替换版本为最新版本 --> <version>CORE_VERSION</version> <!-- 替换版本为最新版本 -->
</dependency> </dependency>
...@@ -51,7 +51,7 @@ repositories { ...@@ -51,7 +51,7 @@ repositories {
} }
dependencies { dependencies {
implementation("net.mamoe:mirai-core-qqandroid-jvm:CORE_VERSION") implementation("net.mamoe:mirai-core-qqandroid:CORE_VERSION")
implementation("net.mamoe:mirai-japt:JAPT_VERSION") implementation("net.mamoe:mirai-japt:JAPT_VERSION")
} }
``` ```
......
...@@ -18,9 +18,9 @@ buildscript { ...@@ -18,9 +18,9 @@ buildscript {
plugins { plugins {
kotlin("jvm") kotlin("jvm")
java java
id("com.jfrog.bintray") version "1.8.0"
`maven-publish` `maven-publish`
// maven // maven
id("com.jfrog.bintray") version "1.8.0"
} }
val kotlinVersion: String by rootProject.ext val kotlinVersion: String by rootProject.ext
...@@ -77,6 +77,10 @@ tasks.withType<JavaCompile>() { ...@@ -77,6 +77,10 @@ tasks.withType<JavaCompile>() {
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
bintray { bintray {
val keyProps = Properties() val keyProps = Properties()
val keyFile = file("../keys.properties") val keyFile = file("../keys.properties")
......
...@@ -65,11 +65,11 @@ try{ ...@@ -65,11 +65,11 @@ try{
println("jdk版本为 "+ javaVersionNum) println("jdk版本为 "+ javaVersionNum)
include(':mirai-console-graphical') include(':mirai-console-graphical')
} else { } else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`") println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-console-graphical`")
} }
} }
}catch(Exception ignored){ }catch(Exception ignored){
println("无法确定 JDK 版本, 将不会引入 `:mirai-console-graphical`")
} }
enableFeaturePreview('GRADLE_METADATA') enableFeaturePreview('GRADLE_METADATA')
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment