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
35e9138c
Commit
35e9138c
authored
Feb 14, 2020
by
ryoii
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin'
parents
2b60130b
8ea7027f
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
529 additions
and
195 deletions
+529
-195
CHANGELOG.md
CHANGELOG.md
+23
-0
gradle.properties
gradle.properties
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+7
-8
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
+2
-1
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/defaultLoginSolver.kt
...idMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt
+0
-30
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/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/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-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
...i-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
+2
-1
No files found.
CHANGELOG.md
View file @
35e9138c
...
...
@@ -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
### mirai-core
-
**支持 at 全体成员: `AtAll`**
### mirai-core-qqandroid
-
**支持 `AtAll` 的发送和解析**
-
**修复某些情况下禁言处理异常**
...
...
gradle.properties
View file @
35e9138c
# style guide
kotlin.code.style
=
official
# config
mirai_version
=
0.1
4
.0
mirai_version
=
0.1
5
.0
kotlin.incremental.multiplatform
=
true
kotlin.parallel.tasks.in.project
=
true
# kotlin
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
35e9138c
...
...
@@ -67,11 +67,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
private
val
packetReceiveLock
:
Mutex
=
Mutex
()
private
fun
startPacketReceiverJobOrGet
():
Job
{
val
job
=
_packetReceiverJob
if
(
job
!=
null
&&
job
.
isActive
&&
channel
.
isOpen
)
{
return
job
}
private
fun
startPacketReceiverJobOrKill
(
cancelCause
:
CancellationException
?
=
null
):
Job
{
_packetReceiverJob
?.
cancel
(
cancelCause
)
return
this
.
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
while
(
channel
.
isOpen
)
{
...
...
@@ -103,8 +100,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
channel
=
PlatformSocket
()
// TODO: 2020/2/14 连接多个服务器
channel
.
connect
(
"113.96.13.208"
,
8080
)
startPacketReceiverJobOrGet
()
withTimeoutOrNull
(
3000
)
{
channel
.
connect
(
"113.96.13.208"
,
8080
)
}
?:
error
(
"timeout connecting server"
)
startPacketReceiverJobOrKill
(
CancellationException
(
"reconnect"
))
// logger.info("Trying login")
var
response
:
WtLogin
.
Login
.
LoginPacketResponse
=
WtLogin
.
Login
.
SubCommand9
(
bot
.
client
).
sendAndExpect
()
...
...
@@ -532,5 +531,5 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
super
.
close
(
cause
)
}
override
suspend
fun
awaitDisconnection
()
=
_packetReceiverJob
?.
join
()
?:
Unit
override
suspend
fun
awaitDisconnection
()
=
supervisor
.
join
()
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
View file @
35e9138c
...
...
@@ -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.buildResponseUniPacket
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.read
import
net.mamoe.mirai.utils.io.readString
...
...
@@ -250,7 +251,7 @@ internal class OnlinePush {
)
}
else
->
{
bot
.
network
.
logger
.
debug
{
"Unknown server messages $message"
}
bot
.
network
.
logger
.
debug
{
"Unknown server messages $message"
}
return
NoPacket
}
}
...
...
mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
View file @
35e9138c
...
...
@@ -124,7 +124,7 @@ fun ByteReadPacket.decodeMultiClientToServerPackets() {
}
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
)
{
1
->
it
.
key
.
toUByte
().
contentToString
()
2
->
it
.
key
.
toUShort
().
contentToString
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/BotConfigurationAndroid.kt
0 → 100644
View file @
35e9138c
/*
* 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 @
35e9138c
...
...
@@ -16,40 +16,40 @@ import android.util.Log
* 不应该直接构造这个类的实例. 需使用 [DefaultLogger]
*/
actual
open
class
PlatformLogger
actual
constructor
(
override
val
identity
:
String
?)
:
MiraiLoggerPlatformBase
()
{
override
fun
verbose0
(
any
:
Any
?)
{
Log
.
v
(
identity
,
any
?.
toString
()
?:
""
)
override
fun
verbose0
(
message
:
String
?)
{
Log
.
v
(
identity
,
message
?:
""
)
}
override
fun
verbose0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
v
(
identity
,
message
?:
""
,
e
)
}
override
fun
debug0
(
any
:
Any
?)
{
Log
.
d
(
identity
,
any
?.
toString
()
?:
""
)
override
fun
debug0
(
message
:
String
?)
{
Log
.
d
(
identity
,
message
?:
""
)
}
override
fun
debug0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
d
(
identity
,
message
?:
""
,
e
)
}
override
fun
info0
(
any
:
Any
?)
{
Log
.
i
(
identity
,
any
?.
toString
()
?:
""
)
override
fun
info0
(
message
:
String
?)
{
Log
.
i
(
identity
,
message
?:
""
)
}
override
fun
info0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
i
(
identity
,
message
?:
""
,
e
)
}
override
fun
warning0
(
any
:
Any
?)
{
Log
.
w
(
identity
,
any
?.
toString
()
?:
""
)
override
fun
warning0
(
message
:
String
?)
{
Log
.
w
(
identity
,
message
?:
""
)
}
override
fun
warning0
(
message
:
String
?,
e
:
Throwable
?)
{
Log
.
w
(
identity
,
message
?:
""
,
e
)
}
override
fun
error0
(
any
:
Any
?)
{
Log
.
e
(
identity
,
any
?.
toString
()
?:
""
)
override
fun
error0
(
message
:
String
?)
{
Log
.
e
(
identity
,
message
?:
""
)
}
override
fun
error0
(
message
:
String
?,
e
:
Throwable
?)
{
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
35e9138c
...
...
@@ -14,13 +14,40 @@ import android.net.wifi.WifiManager
import
android.os.Build
import
android.telephony.TelephonyManager
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
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
*/
@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].
* 部分需要权限, 若无权限则会使用默认值.
*/
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
product
:
ByteArray
get
()
=
Build
.
PRODUCT
.
toByteArray
()
override
val
device
:
ByteArray
get
()
=
Build
.
DEVICE
.
toByteArray
()
...
...
@@ -88,7 +115,8 @@ actual open class SystemDeviceInfo actual constructor(context: Context) : Device
override
val
androidId
:
ByteArray
get
()
=
Build
.
ID
.
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
release
:
ByteArray
get
()
=
Build
.
VERSION
.
RELEASE
.
toByteArray
()
override
val
codename
:
ByteArray
get
()
=
Build
.
VERSION
.
CODENAME
.
toByteArray
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt
deleted
100644 → 0
View file @
2b60130b
/*
* 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
/**
* 在各平台实现的默认的验证码处理器.
*/
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"
)
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
View file @
35e9138c
...
...
@@ -14,6 +14,8 @@ package net.mamoe.mirai.message.data
* 消息源只用于 [QuoteReply]
*
* `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg`
*
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
*/
interface
MessageSource
:
Message
{
companion
object
:
Message
.
Key
<
MessageSource
>
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
View file @
35e9138c
...
...
@@ -33,4 +33,13 @@ fun MessageChain.quote(sender: Member): MessageChain {
return
QuoteReply
(
it
)
+
sender
.
at
()
+
" "
// required
}
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/utils/BotConfiguration.kt
View file @
35e9138c
...
...
@@ -13,7 +13,6 @@ import kotlinx.io.core.IoBuffer
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
kotlin.jvm.JvmStatic
/**
...
...
@@ -33,58 +32,74 @@ abstract class 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]
*/
var
parentCoroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
var
parentCoroutineContext
:
CoroutineContext
/**
* 心跳周期. 过长会导致被服务器断开连接.
*/
var
heartbeatPeriodMillis
:
Long
=
60
.
secondsToMillis
var
heartbeatPeriodMillis
:
Long
/**
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 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
{
/**
* 默认的配置实例
*/
@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 @
35e9138c
...
...
@@ -11,16 +11,15 @@ package net.mamoe.mirai.utils
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.protobuf.ProtoBuf
import
net.mamoe.mirai.utils.cryptor.contentToString
/**
* 设备信息. 可通过继承 [SystemDeviceInfo] 来在默认的基础上修改
*/
abstract
class
DeviceInfo
internal
constructor
(
context
:
Context
)
{
val
context
:
Context
by
context
.
unsafeWeakRef
()
abstract
class
DeviceInfo
{
@Transient
abstract
val
context
:
Context
abstract
val
display
:
ByteArray
abstract
val
product
:
ByteArray
...
...
@@ -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()
*/
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/MiraiLogger.kt
View file @
35e9138c
This diff is collapsed.
Click to expand it.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/SystemDeviceInfo.kt
View file @
35e9138c
...
...
@@ -9,13 +9,15 @@
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.utils.Context
import
net.mamoe.mirai.utils.DeviceInfo
/**
* 通过本机信息来获取设备信息.
*
* Android: 获取手机信息, 与 QQ 官方相同.
* JVM: 部分为常量, 部分为随机
*/
open
expect
class
SystemDeviceInfo
(
context
:
Context
)
:
DeviceInfo
\ No newline at end of file
expect
open
class
SystemDeviceInfo
:
DeviceInfo
{
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 @
35e9138c
...
...
@@ -15,11 +15,13 @@ package net.mamoe.mirai.utils.io
import
kotlinx.io.core.*
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.InvocationKind
import
kotlin.contracts.contract
import
kotlin.js.JsName
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
...
...
@@ -30,9 +32,6 @@ val DebugLogger : MiraiLoggerWithSwitch = DefaultLogger("Packet Debug").withSwit
@MiraiDebugAPI
(
"Unstable"
)
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."
)
inline
fun
String
.
debugPrintThis
(
name
:
String
):
String
{
DebugLogger
.
debug
(
"$name=$this"
)
...
...
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 @
35e9138c
...
...
@@ -22,12 +22,14 @@ import kotlinx.coroutines.withContext
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.use
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
java.awt.Image
import
java.awt.image.BufferedImage
import
java.io.File
import
java.io.RandomAccessFile
import
javax.imageio.ImageIO
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
/**
* 平台默认的验证码识别器.
...
...
@@ -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 @
35e9138c
...
...
@@ -18,37 +18,37 @@ import java.util.*
actual
open
class
PlatformLogger
@JvmOverloads
internal
actual
constructor
(
override
val
identity
:
String
?
)
:
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
?)
{
if
(
message
!=
null
)
verbose
(
message
.
toString
())
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
?)
{
if
(
message
!=
null
)
info
(
message
.
toString
())
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
?)
{
if
(
message
!=
null
)
warning
(
message
.
toString
())
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
?)
{
if
(
message
!=
null
)
error
(
message
.
toString
())
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
?)
{
if
(
message
!=
null
)
debug
(
message
.
toString
())
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
())
if
(
identity
==
null
)
{
...
...
@@ -62,6 +62,7 @@ actual open class PlatformLogger @JvmOverloads internal actual constructor(
/**
* @author NaturalHG
*/
@Suppress
(
"unused"
)
internal
enum
class
LoggerTextFormat
(
private
val
format
:
String
)
{
RESET
(
"\u001b[0m"
),
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
35e9138c
...
...
@@ -10,38 +10,68 @@
package
net.mamoe.mirai.utils
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.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
)
actual
open
class
SystemDeviceInfo
actual
constructor
(
context
:
Context
)
:
DeviceInfo
(
context
)
{
override
val
display
:
ByteArray
get
()
=
"MIRAI.200122.001"
.
toByteArray
()
override
val
product
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
override
val
device
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
override
val
board
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
override
val
brand
:
ByteArray
get
()
=
"mamoe"
.
toByteArray
()
override
val
model
:
ByteArray
get
()
=
"mirai"
.
toByteArray
()
override
val
bootloader
:
ByteArray
get
()
=
"unknown"
.
toByteArray
()
override
val
fingerprint
:
ByteArray
get
()
=
"mamoe/mirai/mirai:10/MIRAI.200122.001/5891938:user/release-keys"
.
toByteArray
()
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
=
"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
procVersion
:
ByteArray
get
()
=
"Linux version 3.0.31-g6fb96c9
(android-build@xxx.xxx.xxx.xxx.com)"
.
toByteArray
()
override
val
baseBand
:
ByteArray
get
()
=
byteArrayOf
()
override
val
version
:
DeviceInfo
.
Version
get
()
=
Version
override
val
simInfo
:
ByteArray
get
()
=
"T-Mobile"
.
toByteArray
()
override
val
osType
:
ByteArray
get
()
=
"android"
.
toByteArray
()
override
val
macAddress
:
ByteArray
get
()
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiBSSID
:
ByteArray
?
get
()
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiSSID
:
ByteArray
?
get
()
=
"<unknown ssid>"
.
toByteArray
()
override
val
imsiMd5
:
ByteArray
get
()
=
md5
(
getRandomByteArray
(
16
))
override
val
imei
:
String
get
()
=
getRandomString
(
15
,
'0'
..
'9'
)
override
val
procVersion
:
ByteArray
=
"Linux version 3.0.31-${getRandomString(8)}
(android-build@xxx.xxx.xxx.xxx.com)"
.
toByteArray
()
override
val
baseBand
:
ByteArray
=
byteArrayOf
()
override
val
version
:
Version
=
Version
override
val
simInfo
:
ByteArray
=
"T-Mobile"
.
toByteArray
()
override
val
osType
:
ByteArray
=
"android"
.
toByteArray
()
override
val
macAddress
:
ByteArray
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiBSSID
:
ByteArray
?
=
"02:00:00:00:00:00"
.
toByteArray
()
override
val
wifiSSID
:
ByteArray
?
=
"<unknown ssid>"
.
toByteArray
()
override
val
imsiMd5
:
ByteArray
=
md5
(
getRandomByteArray
(
16
))
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
androidId
:
ByteArray
get
()
=
display
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
override
val
apn
:
ByteArray
=
"wifi"
.
toByteArray
()
object
Version
:
DeviceInfo
.
Version
{
override
val
incremental
:
ByteArray
get
()
=
"5891938"
.
toByteArray
()
override
val
release
:
ByteArray
get
()
=
"10"
.
toByteArray
()
override
val
codename
:
ByteArray
get
()
=
"REL"
.
toByteArray
()
override
val
sdk
:
Int
get
()
=
29
@Serializable
actual
object
Version
:
DeviceInfo
.
Version
{
override
val
incremental
:
ByteArray
=
"5891938"
.
toByteArray
()
override
val
release
:
ByteArray
=
"10"
.
toByteArray
()
override
val
codename
:
ByteArray
=
"REL"
.
toByteArray
()
override
val
sdk
:
Int
=
29
}
}
\ No newline at end of file
mirai-demos/mirai-demo-1/src/main/java/demo/subscribe/SubscribeSamples.kt
View file @
35e9138c
...
...
@@ -27,6 +27,7 @@ import net.mamoe.mirai.message.data.firstOrNull
import
net.mamoe.mirai.message.sendAsImageTo
import
net.mamoe.mirai.qqandroid.Bot
import
net.mamoe.mirai.qqandroid.QQAndroid
import
net.mamoe.mirai.utils.FileBasedDeviceInfo
import
java.io.File
private
fun
readTestAccount
():
BotAccount
?
{
...
...
@@ -51,7 +52,7 @@ suspend fun main() {
"123456"
)
{
// 覆盖默认的配置
+
FileBasedDeviceInfo
// 使用 "device.json" 保存设备信息
// networkLoggerSupplier = { SilentLogger } // 禁用网络层输出
}.
alsoLogin
()
...
...
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