Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
3eab26a5
Commit
3eab26a5
authored
Feb 15, 2020
by
jiahua.liu
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
b7fd77b6
35e9138c
Changes
47
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
47 changed files
with
948 additions
and
301 deletions
+948
-301
CHANGELOG.md
CHANGELOG.md
+23
-0
gradle.properties
gradle.properties
+1
-1
gradle/wrapper/gradle-wrapper.properties
gradle/wrapper/gradle-wrapper.properties
+1
-1
mirai-api-http/README_CH.md
mirai-api-http/README_CH.md
+68
-1
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
...kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
+10
-1
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
...ain/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
+16
-1
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt
.../net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt
+10
-2
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt
...ttp/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt
+3
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+57
-43
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/OnlinePushPack.kt
...rai/qqandroid/network/protocol/data/jce/OnlinePushPack.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
...ndroid/network/protocol/packet/chat/receive/OnlinePush.kt
+13
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
.../mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
+28
-18
mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
...d/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
+1
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt
...n/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt
+118
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformLoggerAndroid.kt
...ain/kotlin/net/mamoe/mirai/utils/PlatformLoggerAndroid.kt
+10
-10
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
...roidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+30
-2
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
...oidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
+5
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
+69
-42
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
+3
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt
...onMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
...rc/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
+6
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
...mmonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
+16
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
.../net.mamoe.mirai/event/internal/InternalEventListeners.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt
...c/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
...nMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
+1
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
...Main/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
+2
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
...monMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
+9
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
...nMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
+11
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
...n/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
+3
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/LoginFailedException.kt
...in/kotlin/net.mamoe.mirai/network/LoginFailedException.kt
+22
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Annotations.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/Annotations.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
...mmonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
+31
-16
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
...src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
+43
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt
+81
-80
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/SystemDeviceInfo.kt
...mmonMain/kotlin/net.mamoe.mirai/utils/SystemDeviceInfo.kt
+6
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
...c/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
+4
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
...monMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
+2
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/event/internal/EventInternalJvm.kt
...kotlin/net/mamoe/mirai/event/internal/EventInternalJvm.kt
+30
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt
...mMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt
+97
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
...rc/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
+7
-6
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+55
-25
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
...jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+1
-1
mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
...i-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
+2
-1
mirai-japt/src/main/java/net/mamoe/mirai/japt/Events.java
mirai-japt/src/main/java/net/mamoe/mirai/japt/Events.java
+39
-0
mirai-japt/src/main/kotlin/net/mamoe/mirai/japt/internal/EventsImpl.kt
...c/main/kotlin/net/mamoe/mirai/japt/internal/EventsImpl.kt
+5
-11
No files found.
CHANGELOG.md
View file @
3eab26a5
...
@@ -2,11 +2,34 @@
...
@@ -2,11 +2,34 @@
开发版本. 频繁更新, 不保证高稳定性
开发版本. 频繁更新, 不保证高稳定性
## `0.15.0` 2020/2/14
### mirai-core
-
新增事件:
`BotReloginEvent`
和
`BotOfflineEvent.Dropped`
-
`AtAll`
现在实现
`Message.Key`
-
新增
`BotConfiguration`
DSL, 支持自动将设备信息存储在文件系统等
-
新增
`MessageSource.quote(Member)`
-
更好的网络层连接逻辑
-
密码错误后不再重试登录
-
掉线后尝试快速重连, 失败则普通重连 (#47)
-
有原因的登录失败时将抛出特定异常:
`LoginFailedException`
-
默认心跳时间调整为 60s
### mirai-core-qqandroid
-
解决一些验证码无法识别的问题
-
忽略一些不需要处理的事件(机器人主动操作触发的事件)
## `0.14.0` 2020/2/13
## `0.14.0` 2020/2/13
### mirai-core
### mirai-core
-
**支持 at 全体成员: `AtAll`**
-
**支持 at 全体成员: `AtAll`**
### mirai-core-qqandroid
### mirai-core-qqandroid
-
**支持 `AtAll` 的发送和解析**
-
**支持 `AtAll` 的发送和解析**
-
**修复某些情况下禁言处理异常**
-
**修复某些情况下禁言处理异常**
...
...
gradle.properties
View file @
3eab26a5
# style guide
# style guide
kotlin.code.style
=
official
kotlin.code.style
=
official
# config
# config
mirai_version
=
0.1
4
.0
mirai_version
=
0.1
5
.0
kotlin.incremental.multiplatform
=
true
kotlin.incremental.multiplatform
=
true
kotlin.parallel.tasks.in.project
=
true
kotlin.parallel.tasks.in.project
=
true
# kotlin
# kotlin
...
...
gradle/wrapper/gradle-wrapper.properties
View file @
3eab26a5
#Thu Feb 06 14:10:33 CST 2020
#Thu Feb 06 14:10:33 CST 2020
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-
5.4
.1-all.zip
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-
6.1
.1-all.zip
distributionBase
=
GRADLE_USER_HOME
distributionBase
=
GRADLE_USER_HOME
distributionPath
=
wrapper/dists
distributionPath
=
wrapper/dists
zipStorePath
=
wrapper/dists
zipStorePath
=
wrapper/dists
...
...
mirai-api-http/README_CH.md
View file @
3eab26a5
...
@@ -220,6 +220,44 @@ fun main() {
...
@@ -220,6 +220,44 @@ fun main() {
### 发送引用回复消息(仅支持群消息)
```
[POST] /sendQuoteMessage
```
使用此方法向指定的消息进行引用回复
#### 请求
```
json5
{
"sessionKey": "YourSession",
"target": 987654321,
"messageChain": [
{ "type": "Plain", "text":"hello\n" },
{ "type": "Plain", "text":"world" }
]
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | -------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| target | Long | false | 987654321 | 引用消息的Message Source的Uid |
| messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 发送图片消息(通过URL)
### 发送图片消息(通过URL)
```
```
...
@@ -308,6 +346,9 @@ Content-Type:multipart/form-data
...
@@ -308,6 +346,9 @@ Content-Type:multipart/form-data
[{
[{
"type": "GroupMessage", // 消息类型:GroupMessage或FriendMessage
"type": "GroupMessage", // 消息类型:GroupMessage或FriendMessage
"messageChain": [{ // 消息链,是一个消息对象构成的数组
"messageChain": [{ // 消息链,是一个消息对象构成的数组
"type": "Source",
"uid": 123456
},{
"type": "Plain",
"type": "Plain",
"text": "Miral牛逼"
"text": "Miral牛逼"
}],
}],
...
@@ -343,12 +384,26 @@ Content-Type:multipart/form-data
...
@@ -343,12 +384,26 @@ Content-Type:multipart/form-data
#### 消息是构成消息链的基本对象,目前支持的消息类型有
#### 消息是构成消息链的基本对象,目前支持的消息类型有
+
[x] At,@消息
+
[x] At,@消息
+
[x] AtAll,@全体成员
+
[x] Face,表情消息
+
[x] Face,表情消息
+
[x] Plain,文字消息
+
[x] Plain,文字消息
+
[
] Image,图片消息
+
[
x
] Image,图片消息
+
[ ] Xml,Xml卡片消息
+
[ ] Xml,Xml卡片消息
+
[ ] 敬请期待
+
[ ] 敬请期待
#### Source
```
json5
{
"type": "Source",
"uid": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ------------------------------------------------------------ |
| uid | Long | 消息的识别号,用于引用回复(Source类型只在群消息中返回,且永远为chain的第一个元素) |
#### At
#### At
```
json5
```
json5
...
@@ -364,6 +419,18 @@ Content-Type:multipart/form-data
...
@@ -364,6 +419,18 @@ Content-Type:multipart/form-data
| target | Long | 群员QQ号 |
| target | Long | 群员QQ号 |
| display | String | @时显示的文本如:"@Mirai" |
| display | String | @时显示的文本如:"@Mirai" |
#### AtAll
```
json5
{
"type": "AtAll"
}
```
| 名字 | 类型 | 说明 |
| ------- | ------ | ------------------------- |
| - | - | - |
#### Face
#### Face
```
json5
```
json5
...
...
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
View file @
3eab26a5
...
@@ -36,9 +36,15 @@ data class UnKnownMessagePacketDTO(val msg: String) : MessagePacketDTO()
...
@@ -36,9 +36,15 @@ data class UnKnownMessagePacketDTO(val msg: String) : MessagePacketDTO()
// Message
// Message
@Serializable
@Serializable
@SerialName
(
"Source"
)
data class
MessageSourceDTO
(
val
uid
:
Long
)
:
MessageDTO
()
@Serializable
@SerialName
(
"At"
)
@SerialName
(
"At"
)
data class
AtDTO
(
val
target
:
Long
,
val
display
:
String
)
:
MessageDTO
()
data class
AtDTO
(
val
target
:
Long
,
val
display
:
String
)
:
MessageDTO
()
@Serializable
@Serializable
@SerialName
(
"AtAll"
)
data class
AtAllDTO
(
val
target
:
Long
=
0
)
:
MessageDTO
()
// target为保留字段
@Serializable
@SerialName
(
"Face"
)
@SerialName
(
"Face"
)
data class
FaceDTO
(
val
faceId
:
Int
)
:
MessageDTO
()
data class
FaceDTO
(
val
faceId
:
Int
)
:
MessageDTO
()
@Serializable
@Serializable
...
@@ -82,7 +88,9 @@ fun MessageChainDTO.toMessageChain() =
...
@@ -82,7 +88,9 @@ fun MessageChainDTO.toMessageChain() =
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
fun
Message
.
toDTO
()
=
when
(
this
)
{
fun
Message
.
toDTO
()
=
when
(
this
)
{
is
MessageSource
->
MessageSourceDTO
(
messageUid
)
is
At
->
AtDTO
(
target
,
display
)
is
At
->
AtDTO
(
target
,
display
)
is
AtAll
->
AtAllDTO
(
0L
)
is
Face
->
FaceDTO
(
id
.
value
.
toInt
())
is
Face
->
FaceDTO
(
id
.
value
.
toInt
())
is
PlainText
->
PlainDTO
(
stringValue
)
is
PlainText
->
PlainDTO
(
stringValue
)
is
Image
->
ImageDTO
(
imageId
)
is
Image
->
ImageDTO
(
imageId
)
...
@@ -93,11 +101,12 @@ fun Message.toDTO() = when (this) {
...
@@ -93,11 +101,12 @@ fun Message.toDTO() = when (this) {
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
fun
MessageDTO
.
toMessage
()
=
when
(
this
)
{
fun
MessageDTO
.
toMessage
()
=
when
(
this
)
{
is
AtDTO
->
At
(
target
,
display
)
is
AtDTO
->
At
(
target
,
display
)
is
AtAllDTO
->
AtAll
is
FaceDTO
->
Face
(
FaceId
(
faceId
.
toUByte
()))
is
FaceDTO
->
Face
(
FaceId
(
faceId
.
toUByte
()))
is
PlainDTO
->
PlainText
(
text
)
is
PlainDTO
->
PlainText
(
text
)
is
ImageDTO
->
Image
(
imageId
)
is
ImageDTO
->
Image
(
imageId
)
is
XmlDTO
->
XMLMessage
(
xml
)
is
XmlDTO
->
XMLMessage
(
xml
)
is
UnknownMessageDTO
->
PlainText
(
"assert cannot reach"
)
is
MessageSourceDTO
,
is
UnknownMessageDTO
->
PlainText
(
"assert cannot reach"
)
}
}
...
...
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
View file @
3eab26a5
...
@@ -9,17 +9,32 @@
...
@@ -9,17 +9,32 @@
package
net.mamoe.mirai.api.http.queue
package
net.mamoe.mirai.api.http.queue
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.message.data.MessageSource
import
java.util.concurrent.ConcurrentHashMap
import
java.util.concurrent.ConcurrentLinkedDeque
import
java.util.concurrent.ConcurrentLinkedDeque
class
MessageQueue
:
ConcurrentLinkedDeque
<
MessagePacket
<
*
,
*
>>()
{
class
MessageQueue
:
ConcurrentLinkedDeque
<
MessagePacket
<
*
,
*
>>()
{
val
quoteCache
=
ConcurrentHashMap
<
Long
,
GroupMessage
>()
fun
fetch
(
size
:
Int
):
List
<
MessagePacket
<
*
,
*
>>
{
fun
fetch
(
size
:
Int
):
List
<
MessagePacket
<
*
,
*
>>
{
var
count
=
size
var
count
=
size
quoteCache
.
clear
()
val
ret
=
ArrayList
<
MessagePacket
<
*
,
*
>>(
count
)
val
ret
=
ArrayList
<
MessagePacket
<
*
,
*
>>(
count
)
while
(!
this
.
isEmpty
()
&&
count--
>
0
)
{
while
(!
this
.
isEmpty
()
&&
count--
>
0
)
{
ret
.
add
(
this
.
pop
())
val
packet
=
pop
()
ret
.
add
(
packet
)
if
(
packet
is
GroupMessage
)
{
addCache
(
packet
)
}
}
}
return
ret
return
ret
}
}
private
fun
addCache
(
msg
:
GroupMessage
)
{
quoteCache
[
msg
.
message
[
MessageSource
].
messageUid
]
=
msg
}
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt
View file @
3eab26a5
...
@@ -52,6 +52,12 @@ fun Application.messageModule() {
...
@@ -52,6 +52,12 @@ fun Application.messageModule() {
call
.
respondStateCode
(
StateCode
.
Success
)
call
.
respondStateCode
(
StateCode
.
Success
)
}
}
miraiVerify
<
SendDTO
>(
"/quoteMessage"
)
{
it
.
session
.
messageQueue
.
quoteCache
[
it
.
target
]
?.
quoteReply
(
it
.
messageChain
.
toMessageChain
())
?:
throw
NoSuchElementException
()
call
.
respondStateCode
(
StateCode
.
Success
)
}
miraiVerify
<
SendImageDTO
>(
"sendImageMessage"
)
{
miraiVerify
<
SendImageDTO
>(
"sendImageMessage"
)
{
val
bot
=
it
.
session
.
bot
val
bot
=
it
.
session
.
bot
val
contact
=
when
{
val
contact
=
when
{
...
@@ -72,12 +78,14 @@ fun Application.messageModule() {
...
@@ -72,12 +78,14 @@ fun Application.messageModule() {
if
(!
SessionManager
.
containSession
(
sessionKey
))
throw
IllegalSessionException
if
(!
SessionManager
.
containSession
(
sessionKey
))
throw
IllegalSessionException
val
session
=
try
{
val
session
=
try
{
SessionManager
[
sessionKey
]
as
AuthedSession
SessionManager
[
sessionKey
]
as
AuthedSession
}
catch
(
e
:
TypeCastException
)
{
throw
NotVerifiedSessionException
}
}
catch
(
e
:
TypeCastException
)
{
throw
NotVerifiedSessionException
}
val
type
=
parts
.
value
(
"type"
)
val
type
=
parts
.
value
(
"type"
)
parts
.
file
(
"img"
)
?.
apply
{
parts
.
file
(
"img"
)
?.
apply
{
val
image
=
streamProvider
().
use
{
val
image
=
streamProvider
().
use
{
when
(
type
)
{
when
(
type
)
{
"group"
->
session
.
bot
.
groups
.
toList
().
random
().
uploadImage
(
it
)
"group"
->
session
.
bot
.
groups
.
toList
().
random
().
uploadImage
(
it
)
"friend"
->
session
.
bot
.
qqs
.
toList
().
random
().
uploadImage
(
it
)
"friend"
->
session
.
bot
.
qqs
.
toList
().
random
().
uploadImage
(
it
)
else
->
null
else
->
null
...
...
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt
View file @
3eab26a5
...
@@ -13,6 +13,7 @@ import kotlinx.serialization.*
...
@@ -13,6 +13,7 @@ import kotlinx.serialization.*
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.modules.SerializersModule
import
kotlinx.serialization.modules.SerializersModule
import
net.mamoe.mirai.api.http.data.common.*
import
net.mamoe.mirai.api.http.data.common.*
import
net.mamoe.mirai.message.data.MessageSource
// 解析失败时直接返回null,由路由判断响应400状态
// 解析失败时直接返回null,由路由判断响应400状态
@UseExperimental
(
ImplicitReflectionSerializer
::
class
)
@UseExperimental
(
ImplicitReflectionSerializer
::
class
)
...
@@ -50,7 +51,9 @@ object MiraiJson {
...
@@ -50,7 +51,9 @@ object MiraiJson {
UnKnownMessagePacketDTO
::
class
with
UnKnownMessagePacketDTO
.
serializer
()
UnKnownMessagePacketDTO
::
class
with
UnKnownMessagePacketDTO
.
serializer
()
}
}
polymorphic
(
MessageDTO
.
serializer
())
{
polymorphic
(
MessageDTO
.
serializer
())
{
MessageSourceDTO
::
class
with
MessageSourceDTO
.
serializer
()
AtDTO
::
class
with
AtDTO
.
serializer
()
AtDTO
::
class
with
AtDTO
.
serializer
()
AtAllDTO
::
class
with
AtAllDTO
.
serializer
()
FaceDTO
::
class
with
FaceDTO
.
serializer
()
FaceDTO
::
class
with
FaceDTO
.
serializer
()
PlainDTO
::
class
with
PlainDTO
.
serializer
()
PlainDTO
::
class
with
PlainDTO
.
serializer
()
ImageDTO
::
class
with
ImageDTO
.
serializer
()
ImageDTO
::
class
with
ImageDTO
.
serializer
()
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
3eab26a5
...
@@ -20,9 +20,13 @@ import kotlinx.io.core.buildPacket
...
@@ -20,9 +20,13 @@ import kotlinx.io.core.buildPacket
import
kotlinx.io.core.use
import
kotlinx.io.core.use
import
net.mamoe.mirai.data.MultiPacket
import
net.mamoe.mirai.data.MultiPacket
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.event.*
import
net.mamoe.mirai.event.BroadcastControllable
import
net.mamoe.mirai.event.CancellableEvent
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.WrongPasswordException
import
net.mamoe.mirai.qqandroid.FriendInfoImpl
import
net.mamoe.mirai.qqandroid.FriendInfoImpl
import
net.mamoe.mirai.qqandroid.GroupImpl
import
net.mamoe.mirai.qqandroid.GroupImpl
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.QQAndroidBot
...
@@ -37,7 +41,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.Heartbeat
...
@@ -37,7 +41,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.Heartbeat
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.WtLogin
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.WtLogin
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.PlatformSocket
import
net.mamoe.mirai.utils.io.readPacket
import
net.mamoe.mirai.utils.io.useBytes
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
kotlin.jvm.Volatile
import
kotlin.jvm.Volatile
import
kotlin.time.ExperimentalTime
import
kotlin.time.ExperimentalTime
...
@@ -55,13 +62,48 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -55,13 +62,48 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
private
lateinit
var
channel
:
PlatformSocket
private
lateinit
var
channel
:
PlatformSocket
override
suspend
fun
login
()
{
private
var
_packetReceiverJob
:
Job
?
=
null
private
var
heartbeatJob
:
Job
?
=
null
private
val
packetReceiveLock
:
Mutex
=
Mutex
()
private
fun
startPacketReceiverJobOrKill
(
cancelCause
:
CancellationException
?
=
null
):
Job
{
_packetReceiverJob
?.
cancel
(
cancelCause
)
return
this
.
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
while
(
channel
.
isOpen
)
{
val
rawInput
=
try
{
channel
.
read
()
}
catch
(
e
:
CancellationException
)
{
return
@
launch
}
catch
(
e
:
Throwable
)
{
BotOfflineEvent
.
Dropped
(
bot
).
broadcast
()
return
@
launch
}
packetReceiveLock
.
withLock
{
processPacket
(
rawInput
)
}
}
}.
also
{
_packetReceiverJob
=
it
}
}
override
suspend
fun
relogin
()
{
heartbeatJob
?.
cancel
()
if
(
::
channel
.
isInitialized
)
{
if
(
::
channel
.
isInitialized
)
{
if
(
channel
.
isOpen
)
{
kotlin
.
runCatching
{
registerClientOnline
()
}.
exceptionOrNull
()
?:
return
logger
.
info
(
"Cannot do fast relogin. Trying slow relogin"
)
}
channel
.
close
()
channel
.
close
()
}
}
channel
=
PlatformSocket
()
channel
=
PlatformSocket
()
channel
.
connect
(
"113.96.13.208"
,
8080
)
// TODO: 2020/2/14 连接多个服务器
this
.
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
processReceive
()
}
withTimeoutOrNull
(
3000
)
{
channel
.
connect
(
"113.96.13.208"
,
8080
)
}
?:
error
(
"timeout connecting server"
)
startPacketReceiverJobOrKill
(
CancellationException
(
"reconnect"
))
// logger.info("Trying login")
// logger.info("Trying login")
var
response
:
WtLogin
.
Login
.
LoginPacketResponse
=
WtLogin
.
Login
.
SubCommand9
(
bot
.
client
).
sendAndExpect
()
var
response
:
WtLogin
.
Login
.
LoginPacketResponse
=
WtLogin
.
Login
.
SubCommand9
(
bot
.
client
).
sendAndExpect
()
...
@@ -94,7 +136,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -94,7 +136,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
}
}
}
is
WtLogin
.
Login
.
LoginPacketResponse
.
Error
->
error
(
response
.
toString
())
is
WtLogin
.
Login
.
LoginPacketResponse
.
Error
->
throw
WrongPasswordException
(
response
.
toString
())
is
WtLogin
.
Login
.
LoginPacketResponse
.
DeviceLockLogin
->
{
is
WtLogin
.
Login
.
LoginPacketResponse
.
DeviceLockLogin
->
{
response
=
WtLogin
.
Login
.
SubCommand20
(
response
=
WtLogin
.
Login
.
SubCommand20
(
...
@@ -112,18 +155,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -112,18 +155,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
}
// println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
// println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
StatSvc
.
Register
(
bot
.
client
).
sendAndExpect
<
StatSvc
.
Register
.
Response
>(
6000
)
// it's slow
registerClientOnline
()
}
private
suspend
fun
registerClientOnline
()
{
StatSvc
.
Register
(
bot
.
client
).
sendAndExpect
<
StatSvc
.
Register
.
Response
>()
}
}
@UseExperimental
(
MiraiExperimentalAPI
::
class
,
ExperimentalTime
::
class
)
@UseExperimental
(
MiraiExperimentalAPI
::
class
,
ExperimentalTime
::
class
)
override
suspend
fun
init
():
Unit
=
coroutineScope
{
override
suspend
fun
init
():
Unit
=
coroutineScope
{
this
@QQAndroidBotNetworkHandler
.
subscribeAlways
<
BotOfflineEvent
>
{
if
(
this
@QQAndroidBotNetworkHandler
.
bot
==
this
.
bot
)
{
logger
.
error
(
"被挤下线"
)
close
()
}
}
MessageSvc
.
PbGetMsg
(
bot
.
client
,
MsgSvc
.
SyncFlag
.
START
,
currentTimeSeconds
).
sendWithoutExpect
()
MessageSvc
.
PbGetMsg
(
bot
.
client
,
MsgSvc
.
SyncFlag
.
START
,
currentTimeSeconds
).
sendWithoutExpect
()
bot
.
qqs
.
delegate
.
clear
()
bot
.
qqs
.
delegate
.
clear
()
...
@@ -172,6 +212,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -172,6 +212,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
launch
{
launch
{
try
{
try
{
bot
.
groups
.
delegate
.
addLast
(
bot
.
groups
.
delegate
.
addLast
(
@Suppress
(
"DuplicatedCode"
)
GroupImpl
(
GroupImpl
(
bot
=
bot
,
bot
=
bot
,
coroutineContext
=
bot
.
coroutineContext
,
coroutineContext
=
bot
.
coroutineContext
,
...
@@ -211,14 +252,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -211,14 +252,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
joinAll
(
friendListJob
,
groupJob
)
joinAll
(
friendListJob
,
groupJob
)
this
@QQAndroidBotNetworkHandler
.
launch
(
CoroutineName
(
"Heartbeat"
))
{
heartbeatJob
=
this
@QQAndroidBotNetworkHandler
.
launch
(
CoroutineName
(
"Heartbeat"
))
{
while
(
this
.
isActive
)
{
while
(
this
.
isActive
)
{
delay
(
bot
.
configuration
.
heartbeatPeriodMillis
)
delay
(
bot
.
configuration
.
heartbeatPeriodMillis
)
val
failException
=
doHeartBeat
()
val
failException
=
doHeartBeat
()
if
(
failException
!=
null
)
{
if
(
failException
!=
null
)
{
delay
(
bot
.
configuration
.
firstReconnectDelayMillis
)
delay
(
bot
.
configuration
.
firstReconnectDelayMillis
)
close
()
close
()
bot
.
tryReinitializeNetworkHandler
(
failException
)
BotOfflineEvent
.
Dropped
(
bot
).
broadcast
(
)
}
}
}
}
}
}
...
@@ -408,33 +449,6 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -408,33 +449,6 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
}
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
private
suspend
fun
processReceive
()
{
while
(
channel
.
isOpen
)
{
val
rawInput
=
try
{
channel
.
read
()
}
catch
(
e
:
ClosedChannelException
)
{
bot
.
tryReinitializeNetworkHandler
(
e
)
return
}
catch
(
e
:
ReadPacketInternalException
)
{
logger
.
error
(
"Socket channel read failed: ${e.message}"
)
bot
.
tryReinitializeNetworkHandler
(
e
)
return
}
catch
(
e
:
CancellationException
)
{
return
}
catch
(
e
:
Throwable
)
{
logger
.
error
(
"Caught unexpected exceptions"
,
e
)
bot
.
tryReinitializeNetworkHandler
(
e
)
return
}
packetReceiveLock
.
withLock
{
processPacket
(
rawInput
)
}
}
}
private
val
packetReceiveLock
:
Mutex
=
Mutex
()
/**
/**
* 发送一个包, 但不期待任何返回.
* 发送一个包, 但不期待任何返回.
*/
*/
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/OnlinePushPack.kt
View file @
3eab26a5
...
@@ -13,7 +13,7 @@ import kotlinx.serialization.SerialId
...
@@ -13,7 +13,7 @@ import kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.qqandroid.io.JceStruct
import
net.mamoe.mirai.qqandroid.io.JceStruct
class
OnlinePushPack
{
internal
class
OnlinePushPack
{
@Serializable
@Serializable
internal
class
DelMsgInfo
(
internal
class
DelMsgInfo
(
@SerialId
(
0
)
val
fromUin
:
Long
,
@SerialId
(
0
)
val
fromUin
:
Long
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
View file @
3eab26a5
...
@@ -35,6 +35,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
...
@@ -35,6 +35,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildResponseUniPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildResponseUniPacket
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.debug
import
net.mamoe.mirai.utils.io.discardExact
import
net.mamoe.mirai.utils.io.discardExact
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.utils.io.readString
import
net.mamoe.mirai.utils.io.readString
...
@@ -157,6 +158,8 @@ internal class OnlinePush {
...
@@ -157,6 +158,8 @@ internal class OnlinePush {
val
reqPushMsg
=
decodeUniPacket
(
OnlinePushPack
.
SvcReqPushMsg
.
serializer
(),
"req"
)
val
reqPushMsg
=
decodeUniPacket
(
OnlinePushPack
.
SvcReqPushMsg
.
serializer
(),
"req"
)
reqPushMsg
.
vMsgInfos
.
forEach
{
msgInfo
:
MsgInfo
->
reqPushMsg
.
vMsgInfos
.
forEach
{
msgInfo
:
MsgInfo
->
msgInfo
.
vMsg
!!
.
read
{
msgInfo
.
vMsg
!!
.
read
{
// TODO: 2020/2/13 可能会同时收到多个事件. 使用 map 而不要直接 return
when
{
when
{
msgInfo
.
shMsgType
.
toInt
()
==
732
->
{
msgInfo
.
shMsgType
.
toInt
()
==
732
->
{
val
group
=
bot
.
getGroup
(
this
.
readUInt
().
toLong
())
val
group
=
bot
.
getGroup
(
this
.
readUInt
().
toLong
())
...
@@ -164,7 +167,11 @@ internal class OnlinePush {
...
@@ -164,7 +167,11 @@ internal class OnlinePush {
when
(
val
internalType
=
this
.
readShort
().
toInt
())
{
when
(
val
internalType
=
this
.
readShort
().
toInt
())
{
3073
->
{
// mute
3073
->
{
// mute
val
operator
=
group
[
this
.
readUInt
().
toLong
()]
val
operatorUin
=
this
.
readUInt
().
toLong
()
if
(
operatorUin
==
bot
.
uin
)
{
return
NoPacket
}
val
operator
=
group
[
operatorUin
]
this
.
readUInt
().
toLong
()
// time
this
.
readUInt
().
toLong
()
// time
this
.
discardExact
(
2
)
this
.
discardExact
(
2
)
val
target
=
this
.
readUInt
().
toLong
()
val
target
=
this
.
readUInt
().
toLong
()
...
@@ -215,7 +222,7 @@ internal class OnlinePush {
...
@@ -215,7 +222,7 @@ internal class OnlinePush {
4096
->
{
4096
->
{
val
dataBytes
=
this
.
readBytes
(
26
)
val
dataBytes
=
this
.
readBytes
(
26
)
val
message
=
this
.
readString
(
this
.
readByte
().
toInt
())
val
message
=
this
.
readString
(
this
.
readByte
().
toInt
())
println
(
dataBytes
.
toUHexString
())
//
println(dataBytes.toUHexString())
if
(
dataBytes
[
0
].
toInt
()
!=
59
)
{
if
(
dataBytes
[
0
].
toInt
()
!=
59
)
{
return
GroupNameChangeEvent
(
return
GroupNameChangeEvent
(
...
@@ -244,7 +251,7 @@ internal class OnlinePush {
...
@@ -244,7 +251,7 @@ internal class OnlinePush {
)
)
}
}
else
->
{
else
->
{
println
(
"Unknown server messages $message"
)
bot
.
network
.
logger
.
debug
{
"Unknown server messages $message"
}
return
NoPacket
return
NoPacket
}
}
}
}
...
@@ -255,17 +262,17 @@ internal class OnlinePush {
...
@@ -255,17 +262,17 @@ internal class OnlinePush {
// println(msgInfo.vMsg.toUHexString())
// println(msgInfo.vMsg.toUHexString())
// }
// }
else
->
{
else
->
{
println
(
"unknown group internal type $internalType , data: "
+
this
.
readBytes
().
toUHexString
()
+
" "
)
bot
.
network
.
logger
.
debug
{
"unknown group internal type $internalType , data: "
+
this
.
readBytes
().
toUHexString
()
+
" "
}
}
}
}
}
}
}
msgInfo
.
shMsgType
.
toInt
()
==
528
->
{
msgInfo
.
shMsgType
.
toInt
()
==
528
->
{
println
(
"unknown shtype ${msgInfo.shMsgType.toInt()}"
)
bot
.
network
.
logger
.
debug
{
"unknown shtype ${msgInfo.shMsgType.toInt()}"
}
// val content = msgInfo.vMsg.loadAs(OnlinePushPack.MsgType0x210.serializer())
// val content = msgInfo.vMsg.loadAs(OnlinePushPack.MsgType0x210.serializer())
// println(content.contentToString())
// println(content.contentToString())
}
}
else
->
{
else
->
{
println
(
"unknown shtype ${msgInfo.shMsgType.toInt()}"
)
bot
.
network
.
logger
.
debug
{
"unknown shtype ${msgInfo.shMsgType.toInt()}"
}
}
}
}
}
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
View file @
3eab26a5
This diff is collapsed.
Click to expand it.
mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
View file @
3eab26a5
...
@@ -124,7 +124,7 @@ fun ByteReadPacket.decodeMultiClientToServerPackets() {
...
@@ -124,7 +124,7 @@ fun ByteReadPacket.decodeMultiClientToServerPackets() {
}
}
fun
Map
<
Int
,
ByteArray
>.
printTLVMap
(
name
:
String
=
""
,
keyLength
:
Int
=
2
)
=
fun
Map
<
Int
,
ByteArray
>.
printTLVMap
(
name
:
String
=
""
,
keyLength
:
Int
=
2
)
=
debugPrintln
(
"TLVMap $name= "
+
this
.
mapValues
{
(
_
,
value
)
->
value
.
toUHexString
()
}.
mapKeys
{
DebugLogger
.
debug
(
"TLVMap $name= "
+
this
.
mapValues
{
(
_
,
value
)
->
value
.
toUHexString
()
}.
mapKeys
{
when
(
keyLength
)
{
when
(
keyLength
)
{
1
->
it
.
key
.
toUByte
().
contentToString
()
1
->
it
.
key
.
toUByte
().
contentToString
()
2
->
it
.
key
.
toUShort
().
contentToString
()
2
->
it
.
key
.
toUShort
().
contentToString
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt
0 → 100644
View file @
3eab26a5
/*
* 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
import
kotlinx.io.core.IoBuffer
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
/**
* 在各平台实现的默认的验证码处理器.
*/
actual
var
defaultLoginSolver
:
LoginSolver
=
object
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
{
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
{
error
(
"should be implemented manually by you"
)
}
}
@Suppress
(
"ClassName"
,
"PropertyName"
)
actual
open
class
BotConfiguration
actual
constructor
()
{
/**
* 日志记录器
*/
actual
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Bot(${it.uin})"
)
}
/**
* 网络层日志构造器
*/
actual
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Network(${it.bot.uin})"
)
}
/**
* 设备信息覆盖. 默认使用随机的设备信息.
*/
actual
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
=
null
/**
* 父 [CoroutineContext]
*/
actual
var
parentCoroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
/**
* 心跳周期. 过长会导致被服务器断开连接.
*/
actual
var
heartbeatPeriodMillis
:
Long
=
60
.
secondsToMillis
/**
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/
actual
var
heartbeatTimeoutMillis
:
Long
=
2
.
secondsToMillis
/**
* 心跳失败后的第一次重连前的等待时间.
*/
actual
var
firstReconnectDelayMillis
:
Long
=
5
.
secondsToMillis
/**
* 重连失败后, 继续尝试的每次等待时间
*/
actual
var
reconnectPeriodMillis
:
Long
=
60
.
secondsToMillis
/**
* 最多尝试多少次重连
*/
actual
var
reconnectionRetryTimes
:
Int
=
3
/**
* 验证码处理器
*/
actual
var
loginSolver
:
LoginSolver
=
defaultLoginSolver
actual
companion
object
{
/**
* 默认的配置实例
*/
@JvmStatic
actual
val
Default
=
BotConfiguration
()
}
actual
operator
fun
_NoNetworkLog
.
unaryPlus
()
{
networkLoggerSupplier
=
supplier
}
/**
* 不记录网络层的 log.
* 网络层 log 包含包接收, 包发送, 和一些调试用的记录.
*/
@BotConfigurationDsl
actual
val
NoNetworkLog
:
_NoNetworkLog
get
()
=
_NoNetworkLog
@BotConfigurationDsl
actual
object
_
NoNetworkLog
{
internal
val
supplier
=
{
_
:
BotNetworkHandler
->
SilentLogger
}
}
}
/**
* 使用文件系统存储设备信息.
*/
@BotConfigurationDsl
inline
class
FileBasedDeviceInfo
@BotConfigurationDsl
constructor
(
val
filepath
:
String
)
{
/**
* 使用 "device.json" 存储设备信息
*/
@BotConfigurationDsl
companion
object
ByDeviceDotJson
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformLoggerAndroid.kt
View file @
3eab26a5
...
@@ -16,40 +16,40 @@ import android.util.Log
...
@@ -16,40 +16,40 @@ import android.util.Log
* 不应该直接构造这个类的实例. 需使用 [DefaultLogger]
* 不应该直接构造这个类的实例. 需使用 [DefaultLogger]
*/
*/
actual
open
class
PlatformLogger
actual
constructor
(
override
val
identity
:
String
?)
:
MiraiLoggerPlatformBase
()
{
actual
open
class
PlatformLogger
actual
constructor
(
override
val
identity
:
String
?)
:
MiraiLoggerPlatformBase
()
{
override
fun
verbose0
(
any
:
Any
?)
{
override
fun
verbose0
(
message
:
String
?)
{
Log
.
v
(
identity
,
any
?.
toString
()
?:
""
)
Log
.
v
(
identity
,
message
?:
""
)
}
}
override
fun
verbose0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
verbose0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
v
(
identity
,
message
?:
""
,
e
)
Log
.
v
(
identity
,
message
?:
""
,
e
)
}
}
override
fun
debug0
(
any
:
Any
?)
{
override
fun
debug0
(
message
:
String
?)
{
Log
.
d
(
identity
,
any
?.
toString
()
?:
""
)
Log
.
d
(
identity
,
message
?:
""
)
}
}
override
fun
debug0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
debug0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
d
(
identity
,
message
?:
""
,
e
)
Log
.
d
(
identity
,
message
?:
""
,
e
)
}
}
override
fun
info0
(
any
:
Any
?)
{
override
fun
info0
(
message
:
String
?)
{
Log
.
i
(
identity
,
any
?.
toString
()
?:
""
)
Log
.
i
(
identity
,
message
?:
""
)
}
}
override
fun
info0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
info0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
i
(
identity
,
message
?:
""
,
e
)
Log
.
i
(
identity
,
message
?:
""
,
e
)
}
}
override
fun
warning0
(
any
:
Any
?)
{
override
fun
warning0
(
message
:
String
?)
{
Log
.
w
(
identity
,
any
?.
toString
()
?:
""
)
Log
.
w
(
identity
,
message
?:
""
)
}
}
override
fun
warning0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
warning0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
w
(
identity
,
message
?:
""
,
e
)
Log
.
w
(
identity
,
message
?:
""
,
e
)
}
}
override
fun
error0
(
any
:
Any
?)
{
override
fun
error0
(
message
:
String
?)
{
Log
.
e
(
identity
,
any
?.
toString
()
?:
""
)
Log
.
e
(
identity
,
message
?:
""
)
}
}
override
fun
error0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
error0
(
message
:
String
?,
e
:
Throwable
?)
{
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
3eab26a5
...
@@ -14,13 +14,40 @@ import android.net.wifi.WifiManager
...
@@ -14,13 +14,40 @@ import android.net.wifi.WifiManager
import
android.os.Build
import
android.os.Build
import
android.telephony.TelephonyManager
import
android.telephony.TelephonyManager
import
kotlinx.io.core.toByteArray
import
kotlinx.io.core.toByteArray
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.UnstableDefault
import
kotlinx.serialization.json.Json
import
java.io.File
import
java.io.File
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
*/
@UseExperimental
(
UnstableDefault
::
class
)
fun
File
.
loadAsDeviceInfo
(
context
:
Context
):
DeviceInfo
{
if
(!
this
.
exists
()
||
this
.
length
()
==
0L
)
{
return
SystemDeviceInfo
(
context
).
also
{
this
.
writeText
(
Json
.
plain
.
stringify
(
SystemDeviceInfo
.
serializer
(),
it
))
}
}
return
Json
.
nonstrict
.
parse
(
DeviceInfoData
.
serializer
(),
this
.
readText
()).
also
{
it
.
context
=
context
}
}
/**
/**
* 部分引用指向 [Build].
* 部分引用指向 [Build].
* 部分需要权限, 若无权限则会使用默认值.
* 部分需要权限, 若无权限则会使用默认值.
*/
*/
actual
open
class
SystemDeviceInfo
actual
constructor
(
context
:
Context
)
:
DeviceInfo
(
context
)
{
@Serializable
actual
open
class
SystemDeviceInfo
actual
constructor
()
:
DeviceInfo
()
{
actual
constructor
(
context
:
Context
)
:
this
()
{
this
.
context
=
context
}
@Transient
final
override
lateinit
var
context
:
Context
override
val
display
:
ByteArray
get
()
=
Build
.
DISPLAY
.
toByteArray
()
override
val
display
:
ByteArray
get
()
=
Build
.
DISPLAY
.
toByteArray
()
override
val
product
:
ByteArray
get
()
=
Build
.
PRODUCT
.
toByteArray
()
override
val
product
:
ByteArray
get
()
=
Build
.
PRODUCT
.
toByteArray
()
override
val
device
:
ByteArray
get
()
=
Build
.
DEVICE
.
toByteArray
()
override
val
device
:
ByteArray
get
()
=
Build
.
DEVICE
.
toByteArray
()
...
@@ -88,7 +115,8 @@ actual open class SystemDeviceInfo actual constructor(context: Context) : Device
...
@@ -88,7 +115,8 @@ actual open class SystemDeviceInfo actual constructor(context: Context) : Device
override
val
androidId
:
ByteArray
get
()
=
Build
.
ID
.
toByteArray
()
override
val
androidId
:
ByteArray
get
()
=
Build
.
ID
.
toByteArray
()
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
object
Version
:
DeviceInfo
.
Version
{
@Serializable
actual
object
Version
:
DeviceInfo
.
Version
{
override
val
incremental
:
ByteArray
get
()
=
Build
.
VERSION
.
INCREMENTAL
.
toByteArray
()
override
val
incremental
:
ByteArray
get
()
=
Build
.
VERSION
.
INCREMENTAL
.
toByteArray
()
override
val
release
:
ByteArray
get
()
=
Build
.
VERSION
.
RELEASE
.
toByteArray
()
override
val
release
:
ByteArray
get
()
=
Build
.
VERSION
.
RELEASE
.
toByteArray
()
override
val
codename
:
ByteArray
get
()
=
Build
.
VERSION
.
CODENAME
.
toByteArray
()
override
val
codename
:
ByteArray
get
()
=
Build
.
VERSION
.
CODENAME
.
toByteArray
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
View file @
3eab26a5
...
@@ -32,7 +32,7 @@ actual class PlatformSocket : Closeable {
...
@@ -32,7 +32,7 @@ actual class PlatformSocket : Closeable {
actual
val
isOpen
:
Boolean
actual
val
isOpen
:
Boolean
get
()
=
socket
.
isConnected
get
()
=
socket
.
isConnected
override
fun
close
()
=
socket
.
close
()
actual
override
fun
close
()
=
socket
.
close
()
@PublishedApi
@PublishedApi
internal
lateinit
var
writeChannel
:
BufferedOutputStream
internal
lateinit
var
writeChannel
:
BufferedOutputStream
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
View file @
3eab26a5
...
@@ -24,6 +24,7 @@ import net.mamoe.mirai.data.GroupInfo
...
@@ -24,6 +24,7 @@ import net.mamoe.mirai.data.GroupInfo
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.LoginFailedException
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.transferTo
import
net.mamoe.mirai.utils.io.transferTo
...
@@ -175,9 +176,11 @@ abstract class Bot : CoroutineScope {
...
@@ -175,9 +176,11 @@ abstract class Bot : CoroutineScope {
/**
/**
* 登录, 或重新登录.
* 登录, 或重新登录.
*
不建议调用这个函数
.
*
重新登录时不会再次拉取联系人列表
.
*
*
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.login]
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.relogin]
*
* @throws LoginFailedException
*/
*/
abstract
suspend
fun
login
()
abstract
suspend
fun
login
()
// endregion
// endregion
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
View file @
3eab26a5
...
@@ -12,10 +12,15 @@
...
@@ -12,10 +12,15 @@
package
net.mamoe.mirai
package
net.mamoe.mirai
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
import
net.mamoe.mirai.event.Listener
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.event.events.BotReloginEvent
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.ForceOfflineException
import
net.mamoe.mirai.network.LoginFailedException
import
net.mamoe.mirai.network.closeAndJoin
import
net.mamoe.mirai.network.closeAndJoin
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.logStacktrace
import
net.mamoe.mirai.utils.io.logStacktrace
...
@@ -33,7 +38,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
...
@@ -33,7 +38,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
private
val
botJob
=
SupervisorJob
(
configuration
.
parentCoroutineContext
[
Job
])
private
val
botJob
=
SupervisorJob
(
configuration
.
parentCoroutineContext
[
Job
])
override
val
coroutineContext
:
CoroutineContext
=
override
val
coroutineContext
:
CoroutineContext
=
configuration
.
parentCoroutineContext
+
botJob
+
(
configuration
.
parentCoroutineContext
[
CoroutineExceptionHandler
]
configuration
.
parentCoroutineContext
+
botJob
+
(
configuration
.
parentCoroutineContext
[
CoroutineExceptionHandler
]
?:
CoroutineExceptionHandler
{
_
,
e
->
e
.
logStacktrace
(
"An exception was thrown under a coroutine of Bot"
)
})
?:
CoroutineExceptionHandler
{
_
,
e
->
logger
.
error
(
"An exception was thrown under a coroutine of Bot"
,
e
)
})
@Suppress
(
"CanBePrimaryConstructorProperty"
)
// for logger
@Suppress
(
"CanBePrimaryConstructorProperty"
)
// for logger
final
override
val
account
:
BotAccount
=
account
final
override
val
account
:
BotAccount
=
account
...
@@ -78,60 +83,70 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
...
@@ -78,60 +83,70 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
@Suppress
(
"PropertyName"
)
@Suppress
(
"PropertyName"
)
internal
lateinit
var
_network
:
N
internal
lateinit
var
_network
:
N
final
override
suspend
fun
login
()
=
reinitializeNetworkHandler
(
null
)
@Suppress
(
"unused"
)
private
val
offlineListener
:
Listener
<
BotOfflineEvent
>
=
this
.
subscribeAlways
{
event
->
// shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close
when
(
event
)
{
fun
tryReinitializeNetworkHandler
(
is
BotOfflineEvent
.
Dropped
->
{
cause
:
Throwable
?
bot
.
logger
.
info
(
"Connection dropped or lost by server, retrying login"
)
):
Job
=
launch
{
var
lastFailedException
:
Throwable
?
=
null
var
lastFailedException
:
Throwable
?
=
null
repeat
(
configuration
.
reconnectionRetryTimes
)
{
repeat
(
configuration
.
reconnectionRetryTimes
)
{
try
{
try
{
reinitializeNetworkHandler
(
cause
)
network
.
relogin
()
logger
.
info
(
"Reconnected successfully"
)
logger
.
info
(
"Reconnected successfully"
)
return
@
launch
return
@
subscribeAlways
}
catch
(
e
:
Throwable
)
{
}
catch
(
e
:
Throwable
)
{
lastFailedException
=
e
lastFailedException
=
e
delay
(
configuration
.
reconnectPeriodMillis
)
delay
(
configuration
.
reconnectPeriodMillis
)
}
}
if
(
lastFailedException
!=
null
)
{
throw
lastFailedException
!!
}
}
is
BotOfflineEvent
.
Active
->
{
val
msg
=
if
(
event
.
cause
==
null
)
{
""
}
else
{
" with exception: "
+
event
.
cause
.
message
}
bot
.
logger
.
info
(
"Bot is closed manually$msg"
)
close
(
CancellationException
(
event
.
toString
()))
}
is
BotOfflineEvent
.
Force
->
{
bot
.
logger
.
info
(
"Connection occupied by another android device: ${event.message}"
)
close
(
ForceOfflineException
(
event
.
toString
()))
}
}
}
if
(
lastFailedException
!=
null
)
{
throw
lastFailedException
!!
}
}
}
}
final
override
suspend
fun
login
()
=
reinitializeNetworkHandler
(
null
)
private
suspend
fun
reinitializeNetworkHandler
(
private
suspend
fun
reinitializeNetworkHandler
(
cause
:
Throwable
?
cause
:
Throwable
?
)
{
)
{
logger
.
info
(
"BotAccount: $uin"
)
suspend
fun
doRelogin
()
{
logger
.
info
(
"Initializing BotNetworkHandler"
)
while
(
true
)
{
try
{
_network
=
createNetworkHandler
(
this
.
coroutineContext
)
if
(
::
_network
.
isInitialized
)
{
try
{
BotOfflineEvent
.
Active
(
this
,
cause
).
broadcast
()
_network
.
relogin
()
_network
.
closeAndJoin
(
cause
)
return
}
}
catch
(
e
:
LoginFailedException
)
{
}
catch
(
e
:
Exception
)
{
throw
e
logger
.
error
(
"Cannot close network handler"
,
e
)
}
catch
(
e
:
Exception
)
{
}
network
.
logger
.
error
(
e
)
_network
.
closeAndJoin
(
e
)
loginLoop
@
while
(
true
)
{
}
_network
=
createNetworkHandler
(
this
.
coroutineContext
)
logger
.
warning
(
"Login failed. Retrying in 3s..."
)
try
{
delay
(
3000
)
_network
.
login
()
break
@
loginLoop
}
catch
(
e
:
Exception
)
{
e
.
logStacktrace
()
_network
.
closeAndJoin
(
e
)
}
}
logger
.
warning
(
"Login failed. Retrying in 3s..."
)
delay
(
3000
)
}
}
repeat
(
1
)
block
@
{
suspend
fun
doInit
()
{
repeat
(
2
)
{
repeat
(
2
)
{
try
{
try
{
_network
.
init
()
_network
.
init
()
return
@
block
return
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Exception
)
{
e
.
logStacktrace
()
e
.
logStacktrace
()
}
}
...
@@ -141,6 +156,16 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
...
@@ -141,6 +156,16 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
logger
.
error
(
"cannot init. some features may be affected"
)
logger
.
error
(
"cannot init. some features may be affected"
)
}
}
logger
.
info
(
"Initializing BotNetworkHandler"
)
if
(
::
_network
.
isInitialized
)
{
BotReloginEvent
(
this
,
cause
).
broadcast
()
doRelogin
()
return
}
doRelogin
()
doInit
()
}
}
protected
abstract
fun
createNetworkHandler
(
coroutineContext
:
CoroutineContext
):
N
protected
abstract
fun
createNetworkHandler
(
coroutineContext
:
CoroutineContext
):
N
...
@@ -153,9 +178,11 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
...
@@ -153,9 +178,11 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
if
(
cause
==
null
)
{
if
(
cause
==
null
)
{
network
.
close
()
network
.
close
()
this
.
botJob
.
complete
()
this
.
botJob
.
complete
()
offlineListener
.
complete
()
}
else
{
}
else
{
network
.
close
(
cause
)
network
.
close
(
cause
)
this
.
botJob
.
completeExceptionally
(
cause
)
this
.
botJob
.
completeExceptionally
(
cause
)
offlineListener
.
completeExceptionally
(
cause
)
}
}
}
}
groups
.
delegate
.
clear
()
groups
.
delegate
.
clear
()
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
View file @
3eab26a5
...
@@ -98,4 +98,6 @@ suspend inline fun Member.mute(duration: Duration): Boolean {
...
@@ -98,4 +98,6 @@ suspend inline fun Member.mute(duration: Duration): Boolean {
require
(
duration
.
inDays
<=
30
)
{
"duration must be at most 1 month"
}
require
(
duration
.
inDays
<=
30
)
{
"duration must be at most 1 month"
}
require
(
duration
.
inSeconds
>
0
)
{
"duration must be greater than 0 second"
}
require
(
duration
.
inSeconds
>
0
)
{
"duration must be greater than 0 second"
}
return
this
.
mute
(
duration
.
inSeconds
.
toInt
())
return
this
.
mute
(
duration
.
inSeconds
.
toInt
())
}
}
\ No newline at end of file
suspend
inline
fun
Member
.
mute
(
durationSeconds
:
Long
)
=
this
.
mute
(
durationSeconds
.
toInt
())
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/MessageSubscribers.kt
View file @
3eab26a5
...
@@ -631,4 +631,4 @@ class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
...
@@ -631,4 +631,4 @@ class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
@Retention
(
AnnotationRetention
.
SOURCE
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@Target
(
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
TYPE
)
@Target
(
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
TYPE
)
@DslMarker
@DslMarker
internal
annotation
class
MessageDsl
annotation
class
MessageDsl
\ No newline at end of file
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
View file @
3eab26a5
...
@@ -16,6 +16,7 @@ import kotlinx.coroutines.GlobalScope
...
@@ -16,6 +16,7 @@ import kotlinx.coroutines.GlobalScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.internal.Handler
import
net.mamoe.mirai.event.internal.Handler
import
net.mamoe.mirai.event.internal.subscribeInternal
import
net.mamoe.mirai.event.internal.subscribeInternal
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
/*
/*
...
@@ -96,6 +97,7 @@ interface Listener<in E : Event> : CompletableJob {
...
@@ -96,6 +97,7 @@ interface Listener<in E : Event> : CompletableJob {
*
@
see
subscribeGroupMessages
监听群消息
DSL
*
@
see
subscribeGroupMessages
监听群消息
DSL
*
@
see
subscribeFriendMessages
监听好友消息
DSL
*
@
see
subscribeFriendMessages
监听好友消息
DSL
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribe
(
crossinline
handler
:
suspend
E
.(
E
)
->
ListeningStatus
):
Listener
<
E
>
=
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribe
(
crossinline
handler
:
suspend
E
.(
E
)
->
ListeningStatus
):
Listener
<
E
>
=
E
::
class
.
subscribeInternal
(
Handler
{
it
.
handler
(
it
);
})
E
::
class
.
subscribeInternal
(
Handler
{
it
.
handler
(
it
);
})
...
@@ -107,6 +109,7 @@ inline fun <reified E : Event> CoroutineScope.subscribe(crossinline handler: sus
...
@@ -107,6 +109,7 @@ inline fun <reified E : Event> CoroutineScope.subscribe(crossinline handler: sus
*
*
* @see subscribe 获取更多说明
* @see subscribe 获取更多说明
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribeAlways
(
crossinline
listener
:
suspend
E
.(
E
)
->
Unit
):
Listener
<
E
>
=
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribeAlways
(
crossinline
listener
:
suspend
E
.(
E
)
->
Unit
):
Listener
<
E
>
=
E
::
class
.
subscribeInternal
(
Handler
{
it
.
listener
(
it
);
ListeningStatus
.
LISTENING
})
E
::
class
.
subscribeInternal
(
Handler
{
it
.
listener
(
it
);
ListeningStatus
.
LISTENING
})
...
@@ -118,6 +121,7 @@ inline fun <reified E : Event> CoroutineScope.subscribeAlways(crossinline listen
...
@@ -118,6 +121,7 @@ inline fun <reified E : Event> CoroutineScope.subscribeAlways(crossinline listen
*
*
* @see subscribe 获取更多说明
* @see subscribe 获取更多说明
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribeOnce
(
crossinline
listener
:
suspend
E
.(
E
)
->
Unit
):
Listener
<
E
>
=
inline
fun
<
reified
E
:
Event
>
CoroutineScope
.
subscribeOnce
(
crossinline
listener
:
suspend
E
.(
E
)
->
Unit
):
Listener
<
E
>
=
E
::
class
.
subscribeInternal
(
Handler
{
it
.
listener
(
it
);
ListeningStatus
.
STOPPED
})
E
::
class
.
subscribeInternal
(
Handler
{
it
.
listener
(
it
);
ListeningStatus
.
STOPPED
})
...
@@ -129,6 +133,7 @@ inline fun <reified E : Event> CoroutineScope.subscribeOnce(crossinline listener
...
@@ -129,6 +133,7 @@ inline fun <reified E : Event> CoroutineScope.subscribeOnce(crossinline listener
*
*
* @see subscribe 获取更多说明
* @see subscribe 获取更多说明
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
inline
fun
<
reified
E
:
Event
,
T
>
CoroutineScope
.
subscribeUntil
(
valueIfStop
:
T
,
crossinline
listener
:
suspend
E
.(
E
)
->
T
):
Listener
<
E
>
=
inline
fun
<
reified
E
:
Event
,
T
>
CoroutineScope
.
subscribeUntil
(
valueIfStop
:
T
,
crossinline
listener
:
suspend
E
.(
E
)
->
T
):
Listener
<
E
>
=
E
::
class
.
subscribeInternal
(
Handler
{
if
(
it
.
listener
(
it
)
==
valueIfStop
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
E
::
class
.
subscribeInternal
(
Handler
{
if
(
it
.
listener
(
it
)
==
valueIfStop
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
...
@@ -141,6 +146,7 @@ inline fun <reified E : Event, T> CoroutineScope.subscribeUntil(valueIfStop: T,
...
@@ -141,6 +146,7 @@ inline fun <reified E : Event, T> CoroutineScope.subscribeUntil(valueIfStop: T,
*
*
* @see subscribe 获取更多说明
* @see subscribe 获取更多说明
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
inline
fun
<
reified
E
:
Event
,
T
>
CoroutineScope
.
subscribeWhile
(
valueIfContinue
:
T
,
crossinline
listener
:
suspend
E
.(
E
)
->
T
):
Listener
<
E
>
=
inline
fun
<
reified
E
:
Event
,
T
>
CoroutineScope
.
subscribeWhile
(
valueIfContinue
:
T
,
crossinline
listener
:
suspend
E
.(
E
)
->
T
):
Listener
<
E
>
=
E
::
class
.
subscribeInternal
(
Handler
{
if
(
it
.
listener
(
it
)
!=
valueIfContinue
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
E
::
class
.
subscribeInternal
(
Handler
{
if
(
it
.
listener
(
it
)
!=
valueIfContinue
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
View file @
3eab26a5
...
@@ -42,19 +42,32 @@ data class BotOnlineEvent(override val bot: Bot) : BotActiveEvent
...
@@ -42,19 +42,32 @@ data class BotOnlineEvent(override val bot: Bot) : BotActiveEvent
/**
/**
* [Bot] 离线.
* [Bot] 离线.
*/
*/
sealed
class
BotOfflineEvent
:
Bot
Active
Event
{
sealed
class
BotOfflineEvent
:
BotEvent
{
/**
/**
* 主动离线
* 主动离线
*/
*/
data class
Active
(
override
val
bot
:
Bot
,
val
cause
:
Throwable
?)
:
BotOfflineEvent
()
data class
Active
(
override
val
bot
:
Bot
,
val
cause
:
Throwable
?)
:
BotOfflineEvent
()
,
BotActiveEvent
/**
/**
* 被挤下线
* 被挤下线
*/
*/
data class
Force
(
override
val
bot
:
Bot
,
val
title
:
String
,
val
message
:
String
)
:
BotOfflineEvent
(),
Packet
data class
Force
(
override
val
bot
:
Bot
,
val
title
:
String
,
val
message
:
String
)
:
BotOfflineEvent
(),
Packet
,
BotPassiveEvent
/**
* 被服务器断开或因网络问题而掉线
*/
data class
Dropped
(
override
val
bot
:
Bot
)
:
BotOfflineEvent
(),
Packet
,
BotPassiveEvent
}
}
/**
* [Bot] 主动重新登录.
*/
data class
BotReloginEvent
(
override
val
bot
:
Bot
,
val
cause
:
Throwable
?
)
:
BotEvent
,
BotActiveEvent
// endregion
// endregion
// region 消息
// region 消息
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
View file @
3eab26a5
...
@@ -23,8 +23,8 @@ import kotlin.reflect.KClass
...
@@ -23,8 +23,8 @@ import kotlin.reflect.KClass
val
EventLogger
:
MiraiLoggerWithSwitch
=
DefaultLogger
(
"Event"
).
withSwitch
(
false
)
val
EventLogger
:
MiraiLoggerWithSwitch
=
DefaultLogger
(
"Event"
).
withSwitch
(
false
)
@
PublishedApi
@
MiraiInternalAPI
internal
fun
<
L
:
Listener
<
E
>,
E
:
Event
>
KClass
<
out
E
>.
subscribeInternal
(
listener
:
L
):
L
{
fun
<
L
:
Listener
<
E
>,
E
:
Event
>
KClass
<
out
E
>.
subscribeInternal
(
listener
:
L
):
L
{
this
.
listeners
().
addLast
(
listener
)
this
.
listeners
().
addLast
(
listener
)
return
listener
return
listener
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt
View file @
3eab26a5
...
@@ -14,7 +14,7 @@ package net.mamoe.mirai.message.data
...
@@ -14,7 +14,7 @@ package net.mamoe.mirai.message.data
*
*
* @see At at 单个群成员
* @see At at 单个群成员
*/
*/
object
AtAll
:
Message
{
object
AtAll
:
Message
,
Message
.
Key
<
AtAll
>
{
override
fun
toString
():
String
=
"@全体成员"
override
fun
toString
():
String
=
"@全体成员"
// 自动为消息补充 " "
// 自动为消息补充 " "
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
View file @
3eab26a5
...
@@ -155,6 +155,7 @@ inline fun <reified M : Message> MessageChain.any(): Boolean = this.any { it is
...
@@ -155,6 +155,7 @@ inline fun <reified M : Message> MessageChain.any(): Boolean = this.any { it is
@Suppress
(
"UNCHECKED_CAST"
)
@Suppress
(
"UNCHECKED_CAST"
)
fun
<
M
:
Message
>
MessageChain
.
firstOrNull
(
key
:
Message
.
Key
<
M
>):
M
?
=
when
(
key
)
{
fun
<
M
:
Message
>
MessageChain
.
firstOrNull
(
key
:
Message
.
Key
<
M
>):
M
?
=
when
(
key
)
{
At
->
first
<
At
>()
At
->
first
<
At
>()
AtAll
->
first
<
AtAll
>()
PlainText
->
first
<
PlainText
>()
PlainText
->
first
<
PlainText
>()
Image
->
first
<
Image
>()
Image
->
first
<
Image
>()
Face
->
first
<
Face
>()
Face
->
first
<
Face
>()
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
View file @
3eab26a5
...
@@ -14,6 +14,8 @@ package net.mamoe.mirai.message.data
...
@@ -14,6 +14,8 @@ package net.mamoe.mirai.message.data
* 消息源只用于 [QuoteReply]
* 消息源只用于 [QuoteReply]
*
*
* `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg`
* `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg`
*
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
*/
*/
interface
MessageSource
:
Message
{
interface
MessageSource
:
Message
{
companion
object
:
Message
.
Key
<
MessageSource
>
companion
object
:
Message
.
Key
<
MessageSource
>
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
View file @
3eab26a5
...
@@ -33,4 +33,13 @@ fun MessageChain.quote(sender: Member): MessageChain {
...
@@ -33,4 +33,13 @@ fun MessageChain.quote(sender: Member): MessageChain {
return
QuoteReply
(
it
)
+
sender
.
at
()
+
" "
// required
return
QuoteReply
(
it
)
+
sender
.
at
()
+
" "
// required
}
}
error
(
"cannot find MessageSource"
)
error
(
"cannot find MessageSource"
)
}
/**
* 引用这条消息.
* 返回 `[QuoteReply] + [At] + [PlainText]`(必要的结构)
*/
fun
MessageSource
.
quote
(
sender
:
Member
):
MessageChain
{
@UseExperimental
(
MiraiInternalAPI
::
class
)
return
QuoteReply
(
this
)
+
sender
.
at
()
+
" "
// required
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
View file @
3eab26a5
...
@@ -55,12 +55,20 @@ abstract class BotNetworkHandler : CoroutineScope {
...
@@ -55,12 +55,20 @@ abstract class BotNetworkHandler : CoroutineScope {
/**
/**
* 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回.
* 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回.
* 本函数将挂起直到登录成功.
*
* - 会断开连接并重新登录.
* - 不会停止网络层的 [Job].
* - 重新登录时不会再次拉取联系人列表.
* - 挂起直到登录成功.
*
*
* 不要使用这个 API. 请使用 [Bot.login]
* 不要使用这个 API. 请使用 [Bot.login]
*
* @throws LoginFailedException 登录失败时
* @throws WrongPasswordException 密码错误时
*/
*/
@Suppress
(
"SpellCheckingInspection"
)
@MiraiInternalAPI
@MiraiInternalAPI
abstract
suspend
fun
login
()
abstract
suspend
fun
re
login
()
/**
/**
* 初始化获取好友列表等值.
* 初始化获取好友列表等值.
...
@@ -92,6 +100,7 @@ abstract class BotNetworkHandler : CoroutineScope {
...
@@ -92,6 +100,7 @@ abstract class BotNetworkHandler : CoroutineScope {
}
}
}
}
@UseExperimental
(
MiraiInternalAPI
::
class
)
suspend
fun
BotNetworkHandler
.
closeAndJoin
(
cause
:
Throwable
?
=
null
)
{
suspend
fun
BotNetworkHandler
.
closeAndJoin
(
cause
:
Throwable
?
=
null
)
{
this
.
close
(
cause
)
this
.
close
(
cause
)
this
.
supervisor
.
join
()
this
.
supervisor
.
join
()
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
0 → 100644
View file @
3eab26a5
package
net.mamoe.mirai.network
class
ForceOfflineException
(
override
val
message
:
String
?)
:
RuntimeException
()
\ No newline at end of file
mirai-core/src/
androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver
.kt
→
mirai-core/src/
commonMain/kotlin/net.mamoe.mirai/network/LoginFailedException
.kt
View file @
3eab26a5
...
@@ -7,24 +7,16 @@
...
@@ -7,24 +7,16 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
*/
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.network
import
kotlinx.io.core.IoBuffer
import
net.mamoe.mirai.Bot
/**
/**
*
在各平台实现的默认的验证码处理器.
*
正常登录失败时抛出
*/
*/
actual
var
defaultLoginSolver
:
LoginSolver
=
object
:
LoginSolver
()
{
sealed
class
LoginFailedException
:
RuntimeException
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
constructor
()
:
super
()
error
(
"should be implemented manually by you"
)
constructor
(
message
:
String
?)
:
super
(
message
)
}
constructor
(
message
:
String
?,
cause
:
Throwable
?)
:
super
(
message
,
cause
)
constructor
(
cause
:
Throwable
?)
:
super
(
cause
)
override
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
{
}
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
{
class
WrongPasswordException
(
message
:
String
?)
:
LoginFailedException
(
message
)
error
(
"should be implemented manually by you"
)
\ No newline at end of file
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Annotations.kt
View file @
3eab26a5
...
@@ -30,7 +30,7 @@ annotation class MiraiInternalAPI(
...
@@ -30,7 +30,7 @@ annotation class MiraiInternalAPI(
)
)
/**
/**
* 标记这个类, 类型, 函数, 属性, 字段, 或构造器为实验性的.
* 标记这个类, 类型, 函数, 属性, 字段, 或构造器为实验性的
API
.
*
*
* 这些 API 不具有稳定性, 且可能会在任意时刻更改.
* 这些 API 不具有稳定性, 且可能会在任意时刻更改.
* 不建议在发行版本中使用这些 API.
* 不建议在发行版本中使用这些 API.
...
@@ -56,7 +56,7 @@ annotation class MiraiDebugAPI(
...
@@ -56,7 +56,7 @@ annotation class MiraiDebugAPI(
)
)
/**
/**
* 标记
这个 API 是自 Mirai 某个版本起才受支持
.
* 标记
一个自 Mirai 某个版本起才支持的 API
.
*/
*/
@Target
(
CLASS
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
FUNCTION
,
PROPERTY_GETTER
,
PROPERTY_SETTER
,
TYPEALIAS
)
@Target
(
CLASS
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
FUNCTION
,
PROPERTY_GETTER
,
PROPERTY_SETTER
,
TYPEALIAS
)
@Retention
(
AnnotationRetention
.
BINARY
)
@Retention
(
AnnotationRetention
.
BINARY
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
View file @
3eab26a5
...
@@ -13,7 +13,6 @@ import kotlinx.io.core.IoBuffer
...
@@ -13,7 +13,6 @@ import kotlinx.io.core.IoBuffer
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
kotlin.jvm.JvmStatic
import
kotlin.jvm.JvmStatic
/**
/**
...
@@ -33,58 +32,74 @@ abstract class LoginSolver {
...
@@ -33,58 +32,74 @@ abstract class LoginSolver {
expect
var
defaultLoginSolver
:
LoginSolver
expect
var
defaultLoginSolver
:
LoginSolver
/**
/**
*
网络和连接
配置
*
[Bot]
配置
*/
*/
class
BotConfiguration
{
@Suppress
(
"PropertyName"
)
expect
open
class
BotConfiguration
()
{
/**
/**
* 日志记录器
* 日志记录器
*/
*/
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Bot(${it.uin})"
)
}
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
/**
/**
* 网络层日志构造器
* 网络层日志构造器
*/
*/
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Network(${it.bot.uin})"
)
}
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
/**
/**
* 设备信息覆盖
* 设备信息覆盖
. 默认使用随机的设备信息.
*/
*/
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
=
null
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
/**
/**
* 父 [CoroutineContext]
* 父 [CoroutineContext]
*/
*/
var
parentCoroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
var
parentCoroutineContext
:
CoroutineContext
/**
/**
* 心跳周期. 过长会导致被服务器断开连接.
* 心跳周期. 过长会导致被服务器断开连接.
*/
*/
var
heartbeatPeriodMillis
:
Long
=
30
.
secondsToMillis
var
heartbeatPeriodMillis
:
Long
/**
/**
* 每次心跳时等待结果的时间.
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/
*/
var
heartbeatTimeoutMillis
:
Long
=
2
.
secondsToMillis
var
heartbeatTimeoutMillis
:
Long
/**
/**
* 心跳失败后的第一次重连前的等待时间.
* 心跳失败后的第一次重连前的等待时间.
*/
*/
var
firstReconnectDelayMillis
:
Long
=
5
.
secondsToMillis
var
firstReconnectDelayMillis
:
Long
/**
/**
* 重连失败后, 继续尝试的每次等待时间
* 重连失败后, 继续尝试的每次等待时间
*/
*/
var
reconnectPeriodMillis
:
Long
=
60
.
secondsToMillis
var
reconnectPeriodMillis
:
Long
/**
/**
* 最多尝试多少次重连
* 最多尝试多少次重连
*/
*/
var
reconnectionRetryTimes
:
Int
=
3
var
reconnectionRetryTimes
:
Int
/**
/**
* 验证码处理器
* 验证码处理器
*/
*/
var
loginSolver
:
LoginSolver
=
defaultLoginSolver
var
loginSolver
:
LoginSolver
companion
object
{
companion
object
{
/**
/**
* 默认的配置实例
* 默认的配置实例
*/
*/
@JvmStatic
@JvmStatic
val
Default
=
BotConfiguration
()
val
Default
:
BotConfiguration
}
}
}
\ No newline at end of file
operator
fun
_NoNetworkLog
.
unaryPlus
()
/**
* 不记录网络层的 log.
* 网络层 log 包含包接收, 包发送, 和一些调试用的记录.
*/
@BotConfigurationDsl
val
NoNetworkLog
:
_NoNetworkLog
@Suppress
(
"ClassName"
)
object
_
NoNetworkLog
}
@DslMarker
annotation
class
BotConfigurationDsl
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
View file @
3eab26a5
...
@@ -11,16 +11,15 @@ package net.mamoe.mirai.utils
...
@@ -11,16 +11,15 @@ package net.mamoe.mirai.utils
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.protobuf.ProtoBuf
import
kotlinx.serialization.protobuf.ProtoBuf
import
net.mamoe.mirai.utils.cryptor.contentToString
/**
/**
* 设备信息. 可通过继承 [SystemDeviceInfo] 来在默认的基础上修改
* 设备信息. 可通过继承 [SystemDeviceInfo] 来在默认的基础上修改
*/
*/
abstract
class
DeviceInfo
internal
constructor
(
abstract
class
DeviceInfo
{
context
:
Context
@Transient
)
{
abstract
val
context
:
Context
val
context
:
Context
by
context
.
unsafeWeakRef
()
abstract
val
display
:
ByteArray
abstract
val
display
:
ByteArray
abstract
val
product
:
ByteArray
abstract
val
product
:
ByteArray
...
@@ -95,6 +94,45 @@ abstract class DeviceInfo internal constructor(
...
@@ -95,6 +94,45 @@ abstract class DeviceInfo internal constructor(
}
}
}
}
@Serializable
class
DeviceInfoData
(
override
val
display
:
ByteArray
,
override
val
product
:
ByteArray
,
override
val
device
:
ByteArray
,
override
val
board
:
ByteArray
,
override
val
brand
:
ByteArray
,
override
val
model
:
ByteArray
,
override
val
bootloader
:
ByteArray
,
override
val
fingerprint
:
ByteArray
,
override
val
bootId
:
ByteArray
,
override
val
procVersion
:
ByteArray
,
override
val
baseBand
:
ByteArray
,
override
val
version
:
VersionData
,
override
val
simInfo
:
ByteArray
,
override
val
osType
:
ByteArray
,
override
val
macAddress
:
ByteArray
,
override
val
wifiBSSID
:
ByteArray
?,
override
val
wifiSSID
:
ByteArray
?,
override
val
imsiMd5
:
ByteArray
,
override
val
imei
:
String
,
override
val
apn
:
ByteArray
)
:
DeviceInfo
()
{
@Transient
override
lateinit
var
context
:
Context
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
override
val
ipAddress
:
ByteArray
get
()
=
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
androidId
:
ByteArray
get
()
=
display
@Serializable
class
VersionData
(
override
val
incremental
:
ByteArray
=
SystemDeviceInfo
.
Version
.
incremental
,
override
val
release
:
ByteArray
=
SystemDeviceInfo
.
Version
.
release
,
override
val
codename
:
ByteArray
=
SystemDeviceInfo
.
Version
.
codename
,
override
val
sdk
:
Int
=
SystemDeviceInfo
.
Version
.
sdk
)
:
Version
}
/**
/**
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
*/
*/
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt
View file @
3eab26a5
This diff is collapsed.
Click to expand it.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/SystemDeviceInfo.kt
View file @
3eab26a5
...
@@ -9,13 +9,15 @@
...
@@ -9,13 +9,15 @@
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.utils.Context
import
net.mamoe.mirai.utils.DeviceInfo
/**
/**
* 通过本机信息来获取设备信息.
* 通过本机信息来获取设备信息.
*
*
* Android: 获取手机信息, 与 QQ 官方相同.
* Android: 获取手机信息, 与 QQ 官方相同.
* JVM: 部分为常量, 部分为随机
* JVM: 部分为常量, 部分为随机
*/
*/
open
expect
class
SystemDeviceInfo
(
context
:
Context
)
:
DeviceInfo
expect
open
class
SystemDeviceInfo
:
DeviceInfo
{
\ No newline at end of file
constructor
()
constructor
(
context
:
Context
)
object
Version
:
DeviceInfo
.
Version
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
View file @
3eab26a5
...
@@ -15,11 +15,13 @@ package net.mamoe.mirai.utils.io
...
@@ -15,11 +15,13 @@ package net.mamoe.mirai.utils.io
import
kotlinx.io.core.*
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.DefaultLogger
import
net.mamoe.mirai.utils.MiraiDebugAPI
import
net.mamoe.mirai.utils.MiraiLoggerWithSwitch
import
net.mamoe.mirai.utils.withSwitch
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.contract
import
kotlin.contracts.contract
import
kotlin.js.JsName
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmName
...
@@ -30,9 +32,6 @@ val DebugLogger : MiraiLoggerWithSwitch = DefaultLogger("Packet Debug").withSwit
...
@@ -30,9 +32,6 @@ val DebugLogger : MiraiLoggerWithSwitch = DefaultLogger("Packet Debug").withSwit
@MiraiDebugAPI
(
"Unstable"
)
@MiraiDebugAPI
(
"Unstable"
)
inline
fun
Throwable
.
logStacktrace
(
message
:
String
?
=
null
)
=
DebugLogger
.
error
(
message
,
this
)
inline
fun
Throwable
.
logStacktrace
(
message
:
String
?
=
null
)
=
DebugLogger
.
error
(
message
,
this
)
@MiraiDebugAPI
(
"Low efficiency."
)
inline
fun
debugPrintln
(
any
:
Any
?)
=
DebugLogger
.
debug
(
any
)
@MiraiDebugAPI
(
"Low efficiency."
)
@MiraiDebugAPI
(
"Low efficiency."
)
inline
fun
String
.
debugPrintThis
(
name
:
String
):
String
{
inline
fun
String
.
debugPrintThis
(
name
:
String
):
String
{
DebugLogger
.
debug
(
"$name=$this"
)
DebugLogger
.
debug
(
"$name=$this"
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
View file @
3eab26a5
...
@@ -81,7 +81,7 @@ inline fun TlvMap.getOrFail(tag: Int, lazyMessage: (tag: Int) -> String): ByteAr
...
@@ -81,7 +81,7 @@ inline fun TlvMap.getOrFail(tag: Int, lazyMessage: (tag: Int) -> String): ByteAr
return
this
[
tag
]
?:
error
(
lazyMessage
(
tag
))
return
this
[
tag
]
?:
error
(
lazyMessage
(
tag
))
}
}
@Mirai
Debug
API
@Mirai
Internal
API
inline
fun
Input
.
readTLVMap
(
tagSize
:
Int
=
2
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
=
readTLVMap
(
true
,
tagSize
,
suppressDuplication
)
inline
fun
Input
.
readTLVMap
(
tagSize
:
Int
=
2
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
=
readTLVMap
(
true
,
tagSize
,
suppressDuplication
)
@MiraiDebugAPI
@MiraiDebugAPI
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
View file @
3eab26a5
...
@@ -11,7 +11,6 @@ package net.mamoe.mirai.utils.io
...
@@ -11,7 +11,6 @@ package net.mamoe.mirai.utils.io
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
kotlinx.io.core.Closeable
import
kotlinx.io.errors.IOException
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
/**
...
@@ -37,4 +36,6 @@ expect class PlatformSocket() : Closeable {
...
@@ -37,4 +36,6 @@ expect class PlatformSocket() : Closeable {
suspend
fun
read
():
ByteReadPacket
suspend
fun
read
():
ByteReadPacket
val
isOpen
:
Boolean
val
isOpen
:
Boolean
override
fun
close
()
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/event/internal/EventInternalJvm.kt
0 → 100644
View file @
3eab26a5
/*
* 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.event.internal
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.Listener
import
net.mamoe.mirai.event.ListeningStatus
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
java.util.function.Consumer
import
java.util.function.Function
@MiraiInternalAPI
@Suppress
(
"FunctionName"
)
fun
<
E
:
Event
>
Class
<
E
>.
_subscribeEventForJaptOnly
(
scope
:
CoroutineScope
,
onEvent
:
Function
<
E
,
ListeningStatus
>):
Listener
<
E
>
{
return
this
.
kotlin
.
subscribeInternal
(
scope
.
Handler
{
onEvent
.
apply
(
it
)
})
}
@MiraiInternalAPI
@Suppress
(
"FunctionName"
)
fun
<
E
:
Event
>
Class
<
E
>.
_subscribeEventForJaptOnly
(
scope
:
CoroutineScope
,
onEvent
:
Consumer
<
E
>):
Listener
<
E
>
{
return
this
.
kotlin
.
subscribeInternal
(
scope
.
Handler
{
onEvent
.
accept
(
it
);
ListeningStatus
.
LISTENING
;
})
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
DefaultCaptchaSolver
Jvm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
BotConfiguration
Jvm.kt
View file @
3eab26a5
...
@@ -22,12 +22,14 @@ import kotlinx.coroutines.withContext
...
@@ -22,12 +22,14 @@ import kotlinx.coroutines.withContext
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.use
import
kotlinx.io.core.use
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
java.awt.Image
import
java.awt.Image
import
java.awt.image.BufferedImage
import
java.awt.image.BufferedImage
import
java.io.File
import
java.io.File
import
java.io.RandomAccessFile
import
java.io.RandomAccessFile
import
javax.imageio.ImageIO
import
javax.imageio.ImageIO
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
/**
/**
* 平台默认的验证码识别器.
* 平台默认的验证码识别器.
...
@@ -157,3 +159,98 @@ private fun BufferedImage.createCharImg(outputWidth: Int = 100, ignoreRate: Doub
...
@@ -157,3 +159,98 @@ private fun BufferedImage.createCharImg(outputWidth: Int = 100, ignoreRate: Doub
}
}
}
}
@Suppress
(
"ClassName"
,
"PropertyName"
)
actual
open
class
BotConfiguration
actual
constructor
()
{
/**
* 日志记录器
*/
actual
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Bot(${it.uin})"
)
}
/**
* 网络层日志构造器
*/
actual
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Network(${it.bot.uin})"
)
}
/**
* 设备信息覆盖. 默认使用随机的设备信息.
*/
actual
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
=
null
/**
* 父 [CoroutineContext]
*/
actual
var
parentCoroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
/**
* 心跳周期. 过长会导致被服务器断开连接.
*/
actual
var
heartbeatPeriodMillis
:
Long
=
60
.
secondsToMillis
/**
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/
actual
var
heartbeatTimeoutMillis
:
Long
=
2
.
secondsToMillis
/**
* 心跳失败后的第一次重连前的等待时间.
*/
actual
var
firstReconnectDelayMillis
:
Long
=
5
.
secondsToMillis
/**
* 重连失败后, 继续尝试的每次等待时间
*/
actual
var
reconnectPeriodMillis
:
Long
=
60
.
secondsToMillis
/**
* 最多尝试多少次重连
*/
actual
var
reconnectionRetryTimes
:
Int
=
3
/**
* 验证码处理器
*/
actual
var
loginSolver
:
LoginSolver
=
defaultLoginSolver
actual
companion
object
{
/**
* 默认的配置实例
*/
@JvmStatic
actual
val
Default
=
BotConfiguration
()
}
@Suppress
(
"NOTHING_TO_INLINE"
)
@BotConfigurationDsl
inline
operator
fun
FileBasedDeviceInfo
.
unaryPlus
()
{
deviceInfo
=
{
File
(
filepath
).
loadAsDeviceInfo
(
it
)
}
}
@Suppress
(
"NOTHING_TO_INLINE"
)
@BotConfigurationDsl
inline
operator
fun
FileBasedDeviceInfo
.
ByDeviceDotJson
.
unaryPlus
()
{
deviceInfo
=
{
File
(
"device.json"
).
loadAsDeviceInfo
(
it
)
}
}
actual
operator
fun
_NoNetworkLog
.
unaryPlus
()
{
networkLoggerSupplier
=
supplier
}
/**
* 不记录网络层的 log.
* 网络层 log 包含包接收, 包发送, 和一些调试用的记录.
*/
@BotConfigurationDsl
actual
val
NoNetworkLog
:
_NoNetworkLog
get
()
=
_NoNetworkLog
@BotConfigurationDsl
actual
object
_
NoNetworkLog
{
internal
val
supplier
=
{
_
:
BotNetworkHandler
->
SilentLogger
}
}
}
/**
* 使用文件系统存储设备信息.
*/
@BotConfigurationDsl
inline
class
FileBasedDeviceInfo
@BotConfigurationDsl
constructor
(
val
filepath
:
String
)
{
/**
* 使用 "device.json" 存储设备信息
*/
@BotConfigurationDsl
companion
object
ByDeviceDotJson
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
View file @
3eab26a5
...
@@ -18,37 +18,37 @@ import java.util.*
...
@@ -18,37 +18,37 @@ import java.util.*
actual
open
class
PlatformLogger
@JvmOverloads
internal
actual
constructor
(
actual
open
class
PlatformLogger
@JvmOverloads
internal
actual
constructor
(
override
val
identity
:
String
?
override
val
identity
:
String
?
)
:
MiraiLoggerPlatformBase
()
{
)
:
MiraiLoggerPlatformBase
()
{
override
fun
verbose0
(
any
:
Any
?)
=
println
(
any
,
LoggerTextFormat
.
RESET
)
override
fun
verbose0
(
message
:
String
?)
=
println
(
message
,
LoggerTextFormat
.
RESET
)
override
fun
verbose0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
verbose0
(
message
:
String
?,
e
:
Throwable
?)
{
if
(
message
!=
null
)
verbose
(
message
.
toString
())
if
(
message
!=
null
)
verbose
(
message
.
toString
())
e
?.
printStackTrace
()
e
?.
printStackTrace
()
}
}
override
fun
info0
(
any
:
Any
?)
=
println
(
any
,
LoggerTextFormat
.
LIGHT_GREEN
)
override
fun
info0
(
message
:
String
?)
=
println
(
message
,
LoggerTextFormat
.
LIGHT_GREEN
)
override
fun
info0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
info0
(
message
:
String
?,
e
:
Throwable
?)
{
if
(
message
!=
null
)
info
(
message
.
toString
())
if
(
message
!=
null
)
info
(
message
.
toString
())
e
?.
printStackTrace
()
e
?.
printStackTrace
()
}
}
override
fun
warning0
(
any
:
Any
?)
=
println
(
any
,
LoggerTextFormat
.
LIGHT_RED
)
override
fun
warning0
(
message
:
String
?)
=
println
(
message
,
LoggerTextFormat
.
LIGHT_RED
)
override
fun
warning0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
warning0
(
message
:
String
?,
e
:
Throwable
?)
{
if
(
message
!=
null
)
warning
(
message
.
toString
())
if
(
message
!=
null
)
warning
(
message
.
toString
())
e
?.
printStackTrace
()
e
?.
printStackTrace
()
}
}
override
fun
error0
(
any
:
Any
?)
=
println
(
any
,
LoggerTextFormat
.
RED
)
override
fun
error0
(
message
:
String
?)
=
println
(
message
,
LoggerTextFormat
.
RED
)
override
fun
error0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
error0
(
message
:
String
?,
e
:
Throwable
?)
{
if
(
message
!=
null
)
error
(
message
.
toString
())
if
(
message
!=
null
)
error
(
message
.
toString
())
e
?.
printStackTrace
()
e
?.
printStackTrace
()
}
}
override
fun
debug0
(
any
:
Any
?)
=
println
(
any
,
LoggerTextFormat
.
LIGHT_CYAN
)
override
fun
debug0
(
message
:
String
?)
=
println
(
message
,
LoggerTextFormat
.
LIGHT_CYAN
)
override
fun
debug0
(
message
:
String
?,
e
:
Throwable
?)
{
override
fun
debug0
(
message
:
String
?,
e
:
Throwable
?)
{
if
(
message
!=
null
)
debug
(
message
.
toString
())
if
(
message
!=
null
)
debug
(
message
.
toString
())
e
?.
printStackTrace
()
e
?.
printStackTrace
()
}
}
private
fun
println
(
value
:
Any
?,
color
:
LoggerTextFormat
)
{
private
fun
println
(
value
:
String
?,
color
:
LoggerTextFormat
)
{
val
time
=
SimpleDateFormat
(
"HH:mm:ss"
,
Locale
.
SIMPLIFIED_CHINESE
).
format
(
Date
())
val
time
=
SimpleDateFormat
(
"HH:mm:ss"
,
Locale
.
SIMPLIFIED_CHINESE
).
format
(
Date
())
if
(
identity
==
null
)
{
if
(
identity
==
null
)
{
...
@@ -62,6 +62,7 @@ actual open class PlatformLogger @JvmOverloads internal actual constructor(
...
@@ -62,6 +62,7 @@ actual open class PlatformLogger @JvmOverloads internal actual constructor(
/**
/**
* @author NaturalHG
* @author NaturalHG
*/
*/
@Suppress
(
"unused"
)
internal
enum
class
LoggerTextFormat
(
private
val
format
:
String
)
{
internal
enum
class
LoggerTextFormat
(
private
val
format
:
String
)
{
RESET
(
"\u001b[0m"
),
RESET
(
"\u001b[0m"
),
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
3eab26a5
...
@@ -10,38 +10,68 @@
...
@@ -10,38 +10,68 @@
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
kotlinx.io.core.toByteArray
import
kotlinx.io.core.toByteArray
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.UnstableDefault
import
kotlinx.serialization.json.Json
import
net.mamoe.mirai.utils.io.getRandomByteArray
import
net.mamoe.mirai.utils.io.getRandomByteArray
import
net.mamoe.mirai.utils.io.getRandomString
import
net.mamoe.mirai.utils.io.getRandomString
import
java.io.File
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
*/
@UseExperimental
(
UnstableDefault
::
class
)
fun
File
.
loadAsDeviceInfo
(
context
:
Context
=
ContextImpl
()):
DeviceInfo
{
if
(!
this
.
exists
()
||
this
.
length
()
==
0L
)
{
return
SystemDeviceInfo
(
context
).
also
{
this
.
writeText
(
Json
.
plain
.
stringify
(
SystemDeviceInfo
.
serializer
(),
it
))
}
}
return
Json
.
nonstrict
.
parse
(
DeviceInfoData
.
serializer
(),
this
.
readText
()).
also
{
it
.
context
=
context
}
}
@Serializable
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
actual
open
class
SystemDeviceInfo
actual
constructor
(
context
:
Context
)
:
DeviceInfo
(
context
)
{
actual
open
class
SystemDeviceInfo
actual
constructor
()
:
DeviceInfo
()
{
override
val
display
:
ByteArray
get
()
=
"MIRAI.200122.001"
.
toByteArray
()
actual
constructor
(
context
:
Context
)
:
this
()
{
override
val
product
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
this
.
context
=
context
override
val
device
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
}
override
val
board
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
override
val
brand
:
ByteArray
get
()
=
"mamoe"
.
toByteArray
()
@Transient
override
val
model
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
final
override
lateinit
var
context
:
Context
override
val
bootloader
:
ByteArray
get
()
=
"unknown"
.
toByteArray
()
override
val
fingerprint
:
ByteArray
get
()
=
"mamoe/mirai/mirai:10/MIRAI.200122.001/5891938:user/release-keys"
.
toByteArray
()
override
val
display
:
ByteArray
=
"MIRAI.200122.001"
.
toByteArray
()
override
val
product
:
ByteArray
=
"mirai"
.
toByteArray
()
override
val
device
:
ByteArray
=
"mirai"
.
toByteArray
()
override
val
board
:
ByteArray
=
"mirai"
.
toByteArray
()
override
val
brand
:
ByteArray
=
"mamoe"
.
toByteArray
()
override
val
model
:
ByteArray
=
"mirai"
.
toByteArray
()
override
val
bootloader
:
ByteArray
=
"unknown"
.
toByteArray
()
override
val
fingerprint
:
ByteArray
=
"mamoe/mirai/mirai:10/MIRAI.200122.001/${getRandomString(7, '0'..'9')}:user/release-keys"
.
toByteArray
()
override
val
bootId
:
ByteArray
=
ExternalImage
.
generateUUID
(
md5
(
getRandomByteArray
(
16
))).
toByteArray
()
override
val
bootId
:
ByteArray
=
ExternalImage
.
generateUUID
(
md5
(
getRandomByteArray
(
16
))).
toByteArray
()
override
val
procVersion
:
ByteArray
get
()
=
"Linux version 3.0.31-g6fb96c9
(android-build@xxx.xxx.xxx.xxx.com)"
.
toByteArray
()
override
val
procVersion
:
ByteArray
=
"Linux version 3.0.31-${getRandomString(8)}
(android-build@xxx.xxx.xxx.xxx.com)"
.
toByteArray
()
override
val
baseBand
:
ByteArray
get
()
=
byteArrayOf
()
override
val
baseBand
:
ByteArray
=
byteArrayOf
()
override
val
version
:
DeviceInfo
.
Version
get
()
=
Version
override
val
version
:
Version
=
Version
override
val
simInfo
:
ByteArray
get
()
=
"T-Mobile"
.
toByteArray
()
override
val
simInfo
:
ByteArray
=
"T-Mobile"
.
toByteArray
()
override
val
osType
:
ByteArray
get
()
=
"android"
.
toByteArray
()
override
val
osType
:
ByteArray
=
"android"
.
toByteArray
()
override
val
macAddress
:
ByteArray
get
()
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
macAddress
:
ByteArray
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiBSSID
:
ByteArray
?
get
()
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiBSSID
:
ByteArray
?
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiSSID
:
ByteArray
?
get
()
=
"<unknown ssid>"
.
toByteArray
()
override
val
wifiSSID
:
ByteArray
?
=
"<unknown ssid>"
.
toByteArray
()
override
val
imsiMd5
:
ByteArray
get
()
=
md5
(
getRandomByteArray
(
16
))
override
val
imsiMd5
:
ByteArray
=
md5
(
getRandomByteArray
(
16
))
override
val
imei
:
String
get
()
=
getRandomString
(
15
,
'0'
..
'9'
)
override
val
imei
:
String
=
getRandomString
(
15
,
'0'
..
'9'
)
override
val
ipAddress
:
ByteArray
get
()
=
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
ipAddress
:
ByteArray
get
()
=
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
androidId
:
ByteArray
get
()
=
display
override
val
androidId
:
ByteArray
get
()
=
display
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
override
val
apn
:
ByteArray
=
"wifi"
.
toByteArray
()
object
Version
:
DeviceInfo
.
Version
{
@Serializable
override
val
incremental
:
ByteArray
get
()
=
"5891938"
.
toByteArray
()
actual
object
Version
:
DeviceInfo
.
Version
{
override
val
release
:
ByteArray
get
()
=
"10"
.
toByteArray
()
override
val
incremental
:
ByteArray
=
"5891938"
.
toByteArray
()
override
val
codename
:
ByteArray
get
()
=
"REL"
.
toByteArray
()
override
val
release
:
ByteArray
=
"10"
.
toByteArray
()
override
val
sdk
:
Int
get
()
=
29
override
val
codename
:
ByteArray
=
"REL"
.
toByteArray
()
override
val
sdk
:
Int
=
29
}
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
View file @
3eab26a5
...
@@ -32,7 +32,7 @@ actual class PlatformSocket : Closeable {
...
@@ -32,7 +32,7 @@ actual class PlatformSocket : Closeable {
actual
val
isOpen
:
Boolean
actual
val
isOpen
:
Boolean
get
()
=
socket
.
isConnected
get
()
=
socket
.
isConnected
override
fun
close
()
{
actual
override
fun
close
()
{
if
(
::
socket
.
isInitialized
)
{
if
(
::
socket
.
isInitialized
)
{
socket
.
close
()
socket
.
close
()
}
}
...
...
mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
View file @
3eab26a5
...
@@ -27,6 +27,7 @@ import net.mamoe.mirai.message.data.firstOrNull
...
@@ -27,6 +27,7 @@ import net.mamoe.mirai.message.data.firstOrNull
import
net.mamoe.mirai.message.sendAsImageTo
import
net.mamoe.mirai.message.sendAsImageTo
import
net.mamoe.mirai.qqandroid.Bot
import
net.mamoe.mirai.qqandroid.Bot
import
net.mamoe.mirai.qqandroid.QQAndroid
import
net.mamoe.mirai.qqandroid.QQAndroid
import
net.mamoe.mirai.utils.FileBasedDeviceInfo
import
java.io.File
import
java.io.File
private
fun
readTestAccount
():
BotAccount
?
{
private
fun
readTestAccount
():
BotAccount
?
{
...
@@ -51,7 +52,7 @@ suspend fun main() {
...
@@ -51,7 +52,7 @@ suspend fun main() {
"123456"
"123456"
)
{
)
{
// 覆盖默认的配置
// 覆盖默认的配置
+
FileBasedDeviceInfo
// 使用 "device.json" 保存设备信息
// networkLoggerSupplier = { SilentLogger } // 禁用网络层输出
// networkLoggerSupplier = { SilentLogger } // 禁用网络层输出
}.
alsoLogin
()
}.
alsoLogin
()
...
...
mirai-japt/src/main/java/net/mamoe/mirai/japt/Events.java
0 → 100644
View file @
3eab26a5
/*
* 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.japt
;
import
kotlinx.coroutines.GlobalScope
;
import
net.mamoe.mirai.event.Event
;
import
net.mamoe.mirai.event.Listener
;
import
net.mamoe.mirai.event.ListeningStatus
;
import
net.mamoe.mirai.event.internal.EventInternalJvmKt
;
import
net.mamoe.mirai.japt.internal.EventsImplKt
;
import
org.jetbrains.annotations.NotNull
;
import
java.util.function.Consumer
;
import
java.util.function.Function
;
public
final
class
Events
{
@NotNull
public
static
<
E
extends
Event
>
Listener
<
E
>
subscribe
(
@NotNull
Class
<
E
>
eventClass
,
@NotNull
Function
<
E
,
ListeningStatus
>
onEvent
)
{
return
EventInternalJvmKt
.
_subscribeEventForJaptOnly
(
eventClass
,
GlobalScope
.
INSTANCE
,
onEvent
);
}
@NotNull
public
static
<
E
extends
Event
>
Listener
<
E
>
subscribeAlways
(
@NotNull
Class
<
E
>
eventClass
,
@NotNull
Consumer
<
E
>
onEvent
)
{
return
EventInternalJvmKt
.
_subscribeEventForJaptOnly
(
eventClass
,
GlobalScope
.
INSTANCE
,
onEvent
);
}
@NotNull
public
static
<
E
extends
Event
>
E
broadcast
(
@NotNull
E
event
)
{
return
EventsImplKt
.
broadcast
(
event
);
}
}
\ No newline at end of file
mirai-
core/src/jvmMain/kotlin/net/mamoe/mirai/event/SubscribersJvm
.kt
→
mirai-
japt/src/main/kotlin/net/mamoe/mirai/japt/internal/EventsImpl
.kt
View file @
3eab26a5
...
@@ -7,16 +7,10 @@
...
@@ -7,16 +7,10 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
*/
package
net.mamoe.mirai.
event
package
net.mamoe.mirai.
japt.internal
import
kotlinx.coroutines.runBlocking
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.broadcast
// TODO 添加更多
internal
fun
<
E
:
Event
>
broadcast
(
e
:
E
):
E
=
runBlocking
{
e
.
broadcast
()
}
/**
\ No newline at end of file
* Jvm 调用实现(阻塞)
*/
object
Events
{
/*
@JvmStatic
fun <E : Event> subscribe(type: Class<E>, handler: suspend (E) -> ListeningStatus) =
runBlocking { type.kotlin.subscribe(handler) }*/
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment