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
97522bdf
Commit
97522bdf
authored
Apr 02, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rearrange internal APIs
parent
97b66273
Changes
95
Show whitespace changes
Inline
Side-by-side
Showing
95 changed files
with
1083 additions
and
862 deletions
+1083
-862
mirai-core-qqandroid/README.md
mirai-core-qqandroid/README.md
+3
-1
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...roidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+2
-2
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
...lin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
+102
-0
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformDatagramChannel.android.kt
.../mirai/qqandroid/utils/PlatformDatagramChannel.android.kt
+4
-3
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
.../kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
+2
-4
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
...lin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
+27
-0
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHAndroid.kt
...in/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHAndroid.kt
+1
-1
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/setVisible.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/utils/setVisible.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+3
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/QQImpl.kt
...onMain/kotlin/net/mamoe/mirai/qqandroid/contact/QQImpl.kt
+2
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/IOFormat.kt
...in/net/mamoe/mirai/qqandroid/io/serialization/IOFormat.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/JceOld.kt
...tlin/net/mamoe/mirai/qqandroid/io/serialization/JceOld.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceNew.kt
.../net/mamoe/mirai/qqandroid/io/serialization/jce/JceNew.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt
...otlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt
+3
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/convension.kt
...in/kotlin/net/mamoe/mirai/qqandroid/message/convension.kt
+4
-3
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/faceImpl.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/message/faceImpl.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
...in/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
+1
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+5
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+53
-11
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt
...et/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
...tlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
+3
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+11
-17
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
.../net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
.../mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
+2
-5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt
...qqandroid/network/protocol/packet/chat/TroopManagement.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
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt
.../qqandroid/network/protocol/packet/login/ConfigPushSvc.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
.../mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
+5
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
.../mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
+6
-9
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/ByteArrayPool.kt
...n/kotlin/net/mamoe/mirai/qqandroid/utils/ByteArrayPool.kt
+25
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.common.kt
.../mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.common.kt
+3
-26
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformDatagramChannel.kt
...et/mamoe/mirai/qqandroid/utils/PlatformDatagramChannel.kt
+4
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
.../kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
+2
-3
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/byteArrays.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/utils/byteArrays.kt
+8
-8
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/contentToString.kt
...kotlin/net/mamoe/mirai/qqandroid/utils/contentToString.kt
+3
-8
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/conversion.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/utils/conversion.kt
+24
-45
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDH.kt
...in/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDH.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/TEA.kt
...ain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/TEA.kt
+3
-3
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/io/chunked.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/utils/io/chunked.kt
+11
-5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/io/input.kt
...onMain/kotlin/net/mamoe/mirai/qqandroid/utils/io/input.kt
+17
-28
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/tryNTimes.kt
...nMain/kotlin/net/mamoe/mirai/qqandroid/utils/tryNTimes.kt
+10
-20
mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid/io/serialization/JceInputTest.kt
...et.mamoe.mirai.qqandroid/io/serialization/JceInputTest.kt
+0
-0
mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid/utils/PlatformUtilsTest.kt
...tlin/net.mamoe.mirai.qqandroid/utils/PlatformUtilsTest.kt
+2
-2
mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid/utils/TypeConversionTest.kt
...lin/net.mamoe.mirai.qqandroid/utils/TypeConversionTest.kt
+1
-5
mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt
mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt
+9
-5
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
.../jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+1
-1
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
...lin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
+101
-0
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
.../kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt
+2
-3
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocketJvm.kt
...tlin/net/mamoe/mirai/qqandroid/utils/PlatformSocketJvm.kt
+2
-2
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
...lin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
+5
-0
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHJvm.kt
...kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHJvm.kt
+1
-1
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/setVisible.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/utils/setVisible.kt
+1
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/Context.android.kt
...droidMain/kotlin/net/mamoe/mirai/utils/Context.android.kt
+0
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImage.android.kt
...ain/kotlin/net/mamoe/mirai/utils/ExternalImage.android.kt
+2
-3
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/LoginSolver.android.kt
...dMain/kotlin/net/mamoe/mirai/utils/LoginSolver.android.kt
+48
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformLogger.android.kt
...in/kotlin/net/mamoe/mirai/utils/PlatformLogger.android.kt
+0
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.android.kt
.../kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.android.kt
+7
-11
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/internal/addSuppressed.android.kt
...n/net/mamoe/mirai/utils/internal/addSuppressed.android.kt
+3
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/internal/md5.android.kt
...Main/kotlin/net/mamoe/mirai/utils/internal/md5.android.kt
+22
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
...droidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
+2
-102
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
+1
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/javaFriendly.kt
...commonMain/kotlin/net.mamoe.mirai/contact/javaFriendly.kt
+0
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
...mmonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
+6
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
.../net.mamoe.mirai/event/internal/InternalEventListeners.kt
+4
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/linear.kt
...ore/src/commonMain/kotlin/net.mamoe.mirai/event/linear.kt
+5
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt
...in/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt
+3
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
...nMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
+0
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
...n/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
+8
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/LoginFailedException.kt
...in/kotlin/net.mamoe.mirai/network/LoginFailedException.kt
+19
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
...mmonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
+53
-60
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Context.common.kt
...commonMain/kotlin/net.mamoe.mirai/utils/Context.common.kt
+0
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
...src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
+1
-15
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
+14
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/LoginSolver.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/LoginSolver.kt
+81
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/SuspendLazy.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/SuspendLazy.kt
+0
-53
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt
+14
-7
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotations.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/annotations.kt
+6
-11
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt
+37
-78
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt
...nMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt
+29
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/tryNTimes.kt
...onMain/kotlin/net.mamoe.mirai/utils/internal/tryNTimes.kt
+34
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/maps.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/utils/maps.kt
+0
-26
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/utils.kt
...core/src/commonMain/kotlin/net.mamoe.mirai/utils/utils.kt
+79
-0
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ImageTest.kt
...mmonTest/kotlin/net/mamoe/mirai/message.data/ImageTest.kt
+7
-1
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
...monTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
+14
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt
...c/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt
+2
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Context.kt
...-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Context.kt
+3
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
+2
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/LoginSolver.jvm.kt
...c/jvmMain/kotlin/net/mamoe/mirai/utils/LoginSolver.jvm.kt
+28
-111
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformLogger.jvm.kt
...vmMain/kotlin/net/mamoe/mirai/utils/PlatformLogger.jvm.kt
+0
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+2
-86
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+33
-12
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.jvm.kt
...e/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.jvm.kt
+0
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/addSuppressed.jvm.kt
...otlin/net/mamoe/mirai/utils/internal/addSuppressed.jvm.kt
+1
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt
+22
-0
No files found.
mirai-core-qqandroid/README.md
View file @
97522bdf
# mirai-core-qqandroid
Protocol support for QQ for Android for Mirai.
QQ for Android 8.2.7 协议实现.
相较于
`mirai-core`
, 此模块仅提供协议和功能的实现, 不提供额外的公开的 API.
\ No newline at end of file
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
97522bdf
...
...
@@ -17,11 +17,11 @@ import kotlinx.coroutines.io.*
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.utils.BotConfiguration
import
net.mamoe.mirai.utils.Context
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.toReadPacket
import
java.nio.ByteBuffer
@OptIn
(
MiraiInternalAPI
::
class
)
...
...
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"unused"
,
"unused"
)
package
net.mamoe.mirai.qqandroid.utils
import
io.ktor.client.HttpClient
import
io.ktor.client.engine.cio.CIO
import
io.ktor.util.KtorExperimentalAPI
import
kotlinx.io.pool.useInstance
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.net.Inet4Address
import
java.security.MessageDigest
import
java.util.zip.Deflater
import
java.util.zip.GZIPInputStream
import
java.util.zip.GZIPOutputStream
import
java.util.zip.Inflater
internal
actual
object
MiraiPlatformUtils
{
actual
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
data
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
}
}
inflater
.
end
()
return
output
.
toByteArray
()
}
}
actual
fun
zip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
deflater
=
Deflater
()
deflater
.
setInput
(
data
,
offset
,
length
)
deflater
.
finish
()
ByteArrayPool
.
useInstance
{
return
it
.
take
(
deflater
.
deflate
(
it
)).
toByteArray
().
also
{
deflater
.
end
()
}
}
}
actual
fun
md5
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
data
,
offset
,
length
)
}.
digest
()
}
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
=
HttpClient
(
CIO
)
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
Inet4Address
.
getLocalHost
().
hostAddress
}.
getOrElse
{
"192.168.1.123"
}
fun
md5
(
stream
:
InputStream
):
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
stream
.
readInSequence
{
digest
.
update
(
it
.
toByte
())
}
return
digest
.
digest
()
}
private
inline
fun
InputStream
.
readInSequence
(
block
:
(
Int
)
->
Unit
)
{
var
read
:
Int
while
(
this
.
read
().
also
{
read
=
it
}
!=
-
1
)
{
block
(
read
)
}
}
actual
fun
gzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
ByteArrayOutputStream
().
use
{
buf
->
GZIPOutputStream
(
buf
).
use
{
gzip
->
data
.
inputStream
(
offset
,
length
).
use
{
t
->
t
.
copyTo
(
gzip
)
}
}
buf
.
flush
()
return
buf
.
toByteArray
()
}
}
actual
fun
ungzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
return
GZIPInputStream
(
data
.
inputStream
(
offset
,
length
)).
use
{
it
.
readBytes
()
}
}
}
\ No newline at end of file
mirai-core
/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformDatagramChannelA
ndroid.kt
→
mirai-core
-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformDatagramChannel.a
ndroid.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
...
...
@@ -23,12 +23,13 @@ import java.nio.channels.WritableByteChannel
/**
* 多平台适配的 DatagramChannel.
*/
actual
class
PlatformDatagramChannel
actual
constructor
(
internal
actual
class
PlatformDatagramChannel
actual
constructor
(
serverHost
:
String
,
serverPort
:
Short
)
:
Closeable
{
@PublishedApi
internal
val
channel
:
DatagramChannel
=
DatagramChannel
.
open
().
connect
(
InetSocketAddress
(
serverHost
,
serverPort
.
toInt
()))
internal
val
channel
:
DatagramChannel
=
DatagramChannel
.
open
().
connect
(
InetSocketAddress
(
serverHost
,
serverPort
.
toInt
()))
actual
val
isOpen
:
Boolean
get
()
=
channel
.
isOpen
override
fun
close
()
=
channel
.
close
()
...
...
mirai-core
/src/jvmMain/kotlin/net/mamoe/mirai/utils/io
/PlatformSocket.kt
→
mirai-core
-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils
/PlatformSocket.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
...
...
@@ -16,7 +16,6 @@ import kotlinx.io.core.Closeable
import
kotlinx.io.core.ExperimentalIoApi
import
kotlinx.io.streams.readPacketAtMost
import
kotlinx.io.streams.writePacket
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
java.io.BufferedInputStream
import
java.io.BufferedOutputStream
import
java.io.IOException
...
...
@@ -25,8 +24,7 @@ import java.net.Socket
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
actual
class
PlatformSocket
:
Closeable
{
internal
actual
class
PlatformSocket
:
Closeable
{
private
lateinit
var
socket
:
Socket
actual
val
isOpen
:
Boolean
...
...
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"DuplicatedCode"
)
package
net.mamoe.mirai.qqandroid.utils
import
android.os.Build
private
var
isAddSuppressedSupported
:
Boolean
=
true
@PublishedApi
internal
actual
fun
Throwable
.
addSuppressedMirai
(
e
:
Throwable
)
{
if
(
this
==
e
)
{
return
}
if
(!
isAddSuppressedSupported
)
{
return
}
try
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
KITKAT
)
{
this
.
addSuppressed
(
e
)
}
else
{
isAddSuppressedSupported
=
false
}
}
catch
(
e
:
Exception
)
{
isAddSuppressedSupported
=
false
}
}
\ No newline at end of file
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHAndroid.kt
View file @
97522bdf
...
...
@@ -10,9 +10,9 @@
package
net.mamoe.mirai.qqandroid.utils.cryptor
import
android.annotation.SuppressLint
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils.md5
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import
java.security.*
import
java.security.spec.ECGenParameterSpec
import
java.security.spec.X509EncodedKeySpec
...
...
mirai-core
/src/androidMain/kotlin/net/mamoe/mirai
/utils/setVisible.kt
→
mirai-core
-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid
/utils/setVisible.kt
View file @
97522bdf
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.
qqandroid.
utils
import
kotlin.reflect.KProperty1
import
kotlin.reflect.jvm.javaField
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
97522bdf
...
...
@@ -45,10 +45,11 @@ import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.LongMsg
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.*
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.encodeToString
import
net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.utils.io.toReadPacket
import
kotlin.collections.asSequence
import
kotlin.coroutines.CoroutineContext
import
kotlin.math.absoluteValue
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/QQImpl.kt
View file @
97522bdf
...
...
@@ -37,8 +37,9 @@ import net.mamoe.mirai.qqandroid.network.highway.postImage
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.toUHexString
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.contract
import
kotlin.coroutines.CoroutineContext
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/IOFormat.kt
View file @
97522bdf
...
...
@@ -6,7 +6,7 @@ import kotlinx.serialization.DeserializationStrategy
import
kotlinx.serialization.SerialFormat
import
kotlinx.serialization.SerializationStrategy
interface
IOFormat
:
SerialFormat
{
inter
nal
inter
face
IOFormat
:
SerialFormat
{
fun
<
T
>
dumpTo
(
serializer
:
SerializationStrategy
<
T
>,
ojb
:
T
,
output
:
Output
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/JceOld.kt
View file @
97522bdf
...
...
@@ -38,7 +38,7 @@ import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.ZERO_TYPE
import
net.mamoe.mirai.qqandroid.io.serialization.jce.JceHead
import
net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import
net.mamoe.mirai.qqandroid.utils.io.readString
import
net.mamoe.mirai.
utils.io
.toReadPacket
import
net.mamoe.mirai.
qqandroid.utils
.toReadPacket
@PublishedApi
internal
val
CharsetGBK
=
Charset
.
forName
(
"GBK"
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceNew.kt
View file @
97522bdf
...
...
@@ -19,7 +19,7 @@ import kotlinx.serialization.modules.SerialModule
import
net.mamoe.mirai.qqandroid.io.serialization.IOFormat
import
net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import
net.mamoe.mirai.qqandroid.io.serialization.JceOld
import
net.mamoe.mirai.
utils.io
.toReadPacket
import
net.mamoe.mirai.
qqandroid.utils
.toReadPacket
/**
* Jce 数据结构序列化和反序列化器.
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/utils.kt
View file @
97522bdf
...
...
@@ -23,11 +23,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion2
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion3
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.firstValue
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.qqandroid.utils.read
import
net.mamoe.mirai.qqandroid.utils.io.readPacketExact
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.io.toUHexString
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
...
...
@@ -76,6 +74,7 @@ internal fun <T : ProtoBuf> ByteReadPacket.decodeUniPacket(deserializer: Deseria
}
}
}
private
fun
<
K
,
V
>
Map
<
K
,
V
>.
firstValue
():
V
=
this
.
entries
.
first
().
value
internal
fun
<
R
>
ByteReadPacket
.
decodeUniRequestPacketAndDeserialize
(
name
:
String
?
=
null
,
block
:
(
ByteArray
)
->
R
):
R
{
val
request
=
this
.
readJceStruct
(
RequestPacket
.
serializer
())
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/convension.kt
View file @
97522bdf
...
...
@@ -22,10 +22,11 @@ import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.HummerCommelem
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.encodeToString
import
net.mamoe.mirai.qqandroid.utils.hexToBytes
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.utils.io.hexToBytes
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.qqandroid.utils.read
private
val
UNSUPPORTED_MERGED_MESSAGE_PLAIN
=
PlainText
(
"你的QQ暂不支持查看[转发多条消息],请期待后续版本。"
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/faceImpl.kt
View file @
97522bdf
...
...
@@ -2,8 +2,8 @@ package net.mamoe.mirai.qqandroid.message
import
net.mamoe.mirai.message.data.Face
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.
utils.io
.hexToBytes
import
net.mamoe.mirai.
utils.io
.toByteArray
import
net.mamoe.mirai.
qqandroid.utils
.hexToBytes
import
net.mamoe.mirai.
qqandroid.utils
.toByteArray
internal
val
FACE_BUF
=
"00 01 00 04 52 CC F5 D0"
.
hexToBytes
()
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
View file @
97522bdf
...
...
@@ -14,9 +14,8 @@ import net.mamoe.mirai.message.data.OfflineGroupImage
import
net.mamoe.mirai.message.data.OnlineFriendImage
import
net.mamoe.mirai.message.data.OnlineGroupImage
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.utils.hexToBytes
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.io.hexToBytes
internal
class
OnlineGroupImageImpl
(
internal
val
delegate
:
ImMsgBody
.
CustomFace
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
97522bdf
...
...
@@ -36,11 +36,12 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
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.WtLogin
import
net.mamoe.mirai.qqandroid.utils.PlatformSocket
import
net.mamoe.mirai.qqandroid.utils.io.readPacketExact
import
net.mamoe.mirai.qqandroid.utils.io.useBytes
import
net.mamoe.mirai.qqandroid.utils.tryNTimes
import
net.mamoe.mirai.qqandroid.utils.tryNTimesOrException
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.PlatformSocket
import
kotlin.coroutines.CoroutineContext
import
kotlin.jvm.Volatile
import
kotlin.time.ExperimentalTime
...
...
@@ -570,10 +571,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
/**
* 发送一个包, 并挂起直到接收到指定的返回包或超时(3000ms)
*
* @param retry 当不为 0 时将使用 [ByteArrayPool] 缓存. 因此若非必要, 请不要允许 retry
*/
suspend
fun
<
E
:
Packet
>
OutgoingPacket
.
sendAndExpect
(
timeoutMillis
:
Long
=
3000
,
retry
:
Int
=
0
):
E
{
suspend
fun
<
E
:
Packet
>
OutgoingPacket
.
sendAndExpect
(
timeoutMillis
:
Long
=
3000
,
retry
:
Int
=
1
):
E
{
require
(
timeoutMillis
>
100
)
{
"timeoutMillis must > 100"
}
require
(
retry
>=
0
)
{
"retry must >= 0"
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
97522bdf
...
...
@@ -21,11 +21,30 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
import
net.mamoe.mirai.qqandroid.network.protocol.packet.Tlv
import
net.mamoe.mirai.qqandroid.utils.*
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.qqandroid.utils.cryptor.ECDH
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.qqandroid.utils.read
import
net.mamoe.mirai.qqandroid.utils.toUHexString
import
net.mamoe.mirai.utils.*
import
kotlin.random.Random
import
kotlin.random.nextInt
internal
val
DeviceInfo
.
guid
:
ByteArray
get
()
=
generateGuid
(
androidId
,
macAddress
)
/**
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
*/
@OptIn
(
MiraiInternalAPI
::
class
)
private
fun
generateGuid
(
androidId
:
ByteArray
,
macAddress
:
ByteArray
):
ByteArray
=
MiraiPlatformUtils
.
md5
(
androidId
+
macAddress
)
/**
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
*/
internal
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
/*
APP ID:
...
...
@@ -150,10 +169,12 @@ internal open class QQAndroidClient(
var
t150
:
Tlv
?
=
null
var
rollbackSig
:
ByteArray
?
=
null
var
ipFromT149
:
ByteArray
?
=
null
/**
* 客户端与服务器时间差
*/
var
timeDifference
:
Long
=
0
/**
* 真实 QQ 号. 使用邮箱等登录时则需获取这个 uin 进行后续一些操作.
*
...
...
@@ -177,6 +198,7 @@ internal open class QQAndroidClient(
* t186
*/
var
pwdFlag
:
Boolean
=
false
/**
* t537
*/
...
...
@@ -301,20 +323,33 @@ internal class WLoginSigInfo(
}
internal
class
UserStSig
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
LSKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserStWebSig
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserA8
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
LSKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserStWebSig
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserA8
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserA5
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
SKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
SKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
UserSig64
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
OpenKey
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
VKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
VKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
AccessToken
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
D2
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
Sid
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
Sid
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
AqSig
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
internal
class
Pt4Token
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
Pt4Token
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
typealias
PSKeyMap
=
MutableMap
<
String
,
PSKey
>
internal
typealias
Pt4TokenMap
=
MutableMap
<
String
,
Pt4Token
>
...
...
@@ -323,7 +358,13 @@ internal inline fun Input.readUShortLVString(): String = kotlinx.io.core.String(
internal
inline
fun
Input
.
readUShortLVByteArray
():
ByteArray
=
this
.
readBytes
(
this
.
readUShort
().
toInt
())
internal
fun
parsePSKeyMapAndPt4TokenMap
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
,
outPSKeyMap
:
PSKeyMap
,
outPt4TokenMap
:
Pt4TokenMap
)
=
internal
fun
parsePSKeyMapAndPt4TokenMap
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
,
outPSKeyMap
:
PSKeyMap
,
outPt4TokenMap
:
Pt4TokenMap
)
=
data
.
read
{
repeat
(
readShort
().
toInt
())
{
val
domain
=
readUShortLVString
()
...
...
@@ -337,7 +378,8 @@ internal fun parsePSKeyMapAndPt4TokenMap(data: ByteArray, creationTime: Long, ex
}
}
internal
class
PSKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
PSKey
(
data
:
ByteArray
,
creationTime
:
Long
,
expireTime
:
Long
)
:
KeyWithExpiry
(
data
,
creationTime
,
expireTime
)
internal
class
WtSessionTicket
(
data
:
ByteArray
,
creationTime
:
Long
)
:
KeyWithCreationTime
(
data
,
creationTime
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/HighwayHelper.kt
View file @
97522bdf
...
...
@@ -31,10 +31,10 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.copyAndClose
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.PlatformSocket
import
net.mamoe.mirai.qqandroid.utils.io.withUse
import
kotlinx.serialization.InternalSerializationApi
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.PlatformSocket
@OptIn
(
MiraiInternalAPI
::
class
,
InternalSerializationApi
::
class
)
@Suppress
(
"SpellCheckingInspection"
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
View file @
97522bdf
...
...
@@ -24,9 +24,10 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.*
import
kotlinx.serialization.InternalSerializationApi
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.io.chunkedFlow
@OptIn
(
MiraiInternalAPI
::
class
,
InternalSerializationApi
::
class
)
internal
fun
createImageDataPacketSequence
(
// RequestDataTrans
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
97522bdf
...
...
@@ -27,20 +27,20 @@ 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.WtLogin
import
net.mamoe.mirai.qqandroid.network.readUShortLVByteArray
import
net.mamoe.mirai.qqandroid.utils.*
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import
net.mamoe.mirai.qqandroid.utils.cryptor.adjustToPublicKey
import
net.mamoe.mirai.qqandroid.utils.io.readPacketExact
import
net.mamoe.mirai.qqandroid.utils.io.readString
import
net.mamoe.mirai.qqandroid.utils.io.useBytes
import
net.mamoe.mirai.qqandroid.utils.io.withUse
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.qqandroid.utils.toUHexString
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.toInt
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.jvm.JvmName
internal
sealed
class
PacketFactory
<
TPacket
:
Packet
?>
{
/**
* 筛选从服务器接收到的包时的 commandName
...
...
@@ -127,9 +127,6 @@ internal typealias PacketConsumer<T> = suspend (packetFactory: PacketFactory<T>,
@PublishedApi
internal
val
PacketLogger
:
MiraiLoggerWithSwitch
=
DefaultLogger
(
"Packet"
).
withSwitch
(
false
)
/**
* 已知的数据包工厂列表.
*/
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
internal
object
KnownPacketFactories
{
object
OutgoingFactories
:
List
<
OutgoingPacketFactory
<
*
>>
by
mutableListOf
(
...
...
@@ -292,9 +289,6 @@ internal object KnownPacketFactories {
lateinit
var
consumer
:
PacketConsumer
<
T
>
}
/**
* 解析 SSO 层包装
*/
@OptIn
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
private
fun
parseSsoFrame
(
bot
:
QQAndroidBot
,
input
:
ByteReadPacket
):
IncomingPacket
<
*
>
{
val
commandName
:
String
...
...
@@ -363,14 +357,14 @@ internal object KnownPacketFactories {
)
{
@Suppress
(
"DuplicatedCode"
)
check
(
readByte
().
toInt
()
==
2
)
this
.
discardExact
(
2
)
// 27 + 2 + body.size
this
.
discardExact
(
2
)
// const, =8001
this
.
readUShort
()
// commandId
this
.
readShort
()
// const, =0x0001
this
.
readUInt
().
toLong
()
// qq
this
.
discardExact
(
2
)
this
.
discardExact
(
2
)
this
.
readUShort
()
this
.
readShort
()
this
.
readUInt
().
toLong
()
val
encryptionMethod
=
this
.
readUShort
().
toInt
()
this
.
discardExact
(
1
)
// const = 0
this
.
discardExact
(
1
)
val
packet
=
when
(
encryptionMethod
)
{
4
->
{
var
data
=
TEA
.
decrypt
(
this
,
bot
.
client
.
ecdh
.
keyPair
.
initialShareKey
,
(
this
.
remaining
-
1
).
toInt
())
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
View file @
97522bdf
...
...
@@ -16,12 +16,12 @@ import kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.toByteArray
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.qqandroid.network.protocol.LoginType
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.qqandroid.utils.io.*
import
net.mamoe.mirai.qqandroid.utils.toByteArray
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils.currentTimeMillis
import
net.mamoe.mirai.utils.io.*
import
kotlin.random.Random
/**
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
View file @
97522bdf
...
...
@@ -12,14 +12,11 @@
package
net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.io.serialization.writeProtoBuf
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup
import
net.mamoe.mirai.qqandroid.message.toRichTextElems
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
...
...
@@ -31,9 +28,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils._miraiContentToString
import
net.mamoe.mirai.qqandroid.utils._miraiContentToString
internal
class
MessageValidationData
@OptIn
(
MiraiInternalAPI
::
class
)
constructor
(
val
data
:
ByteArray
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/TroopManagement.kt
View file @
97522bdf
...
...
@@ -27,8 +27,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.*
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import
net.mamoe.mirai.qqandroid.utils.encodeToString
import
net.mamoe.mirai.utils.daysToSeconds
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.data.GroupInfo
as
MiraiGroupInfo
@OptIn
(
LowLevelAPI
::
class
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
View file @
97522bdf
...
...
@@ -44,8 +44,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.buildResponseUniPacket
import
net.mamoe.mirai.qqandroid.utils.io.readString
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.debug
import
net.mamoe.mirai.
utils.io
.read
import
net.mamoe.mirai.
utils.io
.toUHexString
import
net.mamoe.mirai.
qqandroid.utils
.read
import
net.mamoe.mirai.
qqandroid.utils
.toUHexString
internal
class
OnlinePush
{
/**
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/ConfigPushSvc.kt
View file @
97522bdf
...
...
@@ -21,7 +21,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
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.io
.toUHexString
import
net.mamoe.mirai.
qqandroid.utils
.toUHexString
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.PushReq
as
PushReqJceStruct
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
View file @
97522bdf
...
...
@@ -10,11 +10,12 @@
package
net.mamoe.mirai.qqandroid.network.protocol.packet.login
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.*
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.guid
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestMSFForceOffline
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RspMSFForceOffline
...
...
@@ -22,11 +23,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.jce.SvcReqRegister
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.Oidb0x769
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.StatSvcGetOnline
import
net.mamoe.mirai.qqandroid.network.protocol.packet.*
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.qqandroid.utils.encodeToString
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.utils.io.toReadPacket
@Suppress
(
"EnumEntryName"
)
internal
enum
class
RegPushReason
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
View file @
97522bdf
...
...
@@ -12,18 +12,18 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import
io.ktor.util.InternalAPI
import
kotlinx.io.core.*
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.*
import
net.mamoe.mirai.qqandroid.network.protocol.LoginType
import
net.mamoe.mirai.qqandroid.network.protocol.packet.*
import
net.mamoe.mirai.qqandroid.utils.
GuidSource
import
net.mamoe.mirai.qqandroid.utils.
MacOrAndroidIdChangeFlag
import
net.mamoe.mirai.qqandroid.utils.
*
import
net.mamoe.mirai.qqandroid.utils.
cryptor.TEA
import
net.mamoe.mirai.qqandroid.utils.guidFlag
import
net.mamoe.mirai.qqandroid.utils.io.*
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.currentTimeSeconds
import
net.mamoe.mirai.utils.error
internal
class
WtLogin
{
/**
...
...
@@ -310,7 +310,6 @@ internal class WtLogin {
}
@InternalAPI
@OptIn
(
MiraiDebugAPI
::
class
)
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
LoginPacketResponse
{
discardExact
(
2
)
// subCommand
...
...
@@ -369,7 +368,6 @@ internal class WtLogin {
}
@InternalAPI
@OptIn
(
MiraiDebugAPI
::
class
)
private
fun
onSolveLoginCaptcha
(
tlvMap
:
TlvMap
,
bot
:
QQAndroidBot
):
LoginPacketResponse
.
Captcha
{
/*
java.lang.IllegalStateException: UNKNOWN CAPTCHA QUESTION:
...
...
@@ -405,7 +403,6 @@ internal class WtLogin {
error
(
"UNKNOWN CAPTCHA, tlvMap="
+
tlvMap
.
_miraiContentToString
())
}
@OptIn
(
MiraiDebugAPI
::
class
)
private
fun
onLoginSuccess
(
tlvMap
:
TlvMap
,
bot
:
QQAndroidBot
):
LoginPacketResponse
.
Success
{
val
client
=
bot
.
client
//println("TLV KEYS: " + tlvMap.keys.joinToString { it.contentToString() })
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/io
/ByteArrayPool.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
/ByteArrayPool.kt
View file @
97522bdf
/*
* 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
*/
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
)
package
net.mamoe.mirai.utils.io
package
net.mamoe.mirai.qqandroid.utils
import
kotlinx.io.pool.DefaultPool
import
kotlinx.io.pool.ObjectPool
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 缓存 [ByteArray] 实例的 [ObjectPool]
*
* **注意**: 这是 Mirai 内部 API. 它可能在任何时刻被改动. 不要将它用于生产环境
*/
@MiraiInternalAPI
object
ByteArrayPool
:
DefaultPool
<
ByteArray
>(
256
)
{
internal
object
ByteArrayPool
:
DefaultPool
<
ByteArray
>(
256
)
{
/**
* 每一个 [ByteArray] 的大小
*/
...
...
@@ -39,4 +23,3 @@ object ByteArrayPool : DefaultPool<ByteArray>(256) {
require
(
size
<=
BUFFER_SIZE
)
{
"sizePerPacket is too large. Maximum buffer size=$BUFFER_SIZE"
}
}
}
\ No newline at end of file
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/platform
.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.common
.kt
View file @
97522bdf
/*
* 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
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.qqandroid.utils
import
io.ktor.client.HttpClient
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 时间戳.
*/
expect
val
currentTimeMillis
:
Long
inline
val
currentTimeSeconds
:
Long
get
()
=
currentTimeMillis
/
1000
/**
* 仅供内部使用的工具类.
* 不写为扩展是为了避免污染命名空间.
*/
@MiraiInternalAPI
expect
object
MiraiPlatformUtils
{
internal
expect
object
MiraiPlatformUtils
{
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
data
.
size
-
offset
):
ByteArray
fun
zip
(
data
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
data
.
size
-
offset
):
ByteArray
...
...
@@ -48,7 +26,6 @@ expect object MiraiPlatformUtils {
val
Http
:
HttpClient
}
@Suppress
(
"DuplicatedCode"
)
// false positive. `this` is not the same for `List<Byte>` and `ByteArray`
internal
fun
ByteArray
.
checkOffsetAndLength
(
offset
:
Int
,
length
:
Int
)
{
require
(
offset
>=
0
)
{
"offset shouldn't be negative: $offset"
}
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/io
/PlatformDatagramChannel.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
/PlatformDatagramChannel.kt
View file @
97522bdf
...
...
@@ -7,17 +7,15 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 多平台适配的 DatagramChannel.
*/
@MiraiInternalAPI
expect
class
PlatformDatagramChannel
(
serverHost
:
String
,
serverPort
:
Short
)
:
Closeable
{
internal
expect
class
PlatformDatagramChannel
(
serverHost
:
String
,
serverPort
:
Short
)
:
Closeable
{
/**
* @throws SendPacketInternalException
*/
...
...
@@ -34,9 +32,9 @@ expect class PlatformDatagramChannel(serverHost: String, serverPort: Short) : Cl
/**
* 在 [PlatformDatagramChannel.send] 或 [PlatformDatagramChannel.read] 时出现的错误.
*/
class
SendPacketInternalException
(
cause
:
Throwable
?)
:
Exception
(
cause
)
internal
class
SendPacketInternalException
(
cause
:
Throwable
?)
:
Exception
(
cause
)
/**
* 在 [PlatformDatagramChannel.send] 或 [PlatformDatagramChannel.read] 时出现的错误.
*/
class
ReadPacketInternalException
(
cause
:
Throwable
?)
:
Exception
(
cause
)
\ No newline at end of file
internal
class
ReadPacketInternalException
(
cause
:
Throwable
?)
:
Exception
(
cause
)
\ No newline at end of file
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/io
/PlatformSocket.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
/PlatformSocket.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
...
...
@@ -16,8 +16,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
expect
class
PlatformSocket
()
:
Closeable
{
internal
expect
class
PlatformSocket
()
:
Closeable
{
suspend
fun
connect
(
serverHost
:
String
,
serverPort
:
Int
)
/**
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/io
/byteArrays.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
/byteArrays.kt
View file @
97522bdf
...
...
@@ -11,14 +11,13 @@
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"Utils"
)
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.io.charsets.Charset
import
kotlinx.io.charsets.Charsets
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.String
import
kotlinx.io.core.use
import
net.mamoe.mirai.utils.checkOffsetAndLength
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.contract
...
...
@@ -31,7 +30,7 @@ import kotlin.jvm.JvmSynthetic
@JvmOverloads
@Suppress
(
"DuplicatedCode"
)
// false positive. foreach is not common to UByteArray and ByteArray
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
fun
List
<
Byte
>.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
internal
fun
List
<
Byte
>.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
require
(
offset
>=
0
)
{
"offset shouldn't be negative: $offset"
}
require
(
length
>=
0
)
{
"length shouldn't be negative: $length"
}
require
(
offset
+
length
<=
this
.
size
)
{
"offset ($offset) + length ($length) > array.size (${this.size})"
}
...
...
@@ -55,7 +54,7 @@ fun List<Byte>.toUHexString(separator: String = " ", offset: Int = 0, length: In
@JvmOverloads
@Suppress
(
"DuplicatedCode"
)
// false positive. foreach is not common to UByteArray and ByteArray
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
internal
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
this
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
{
return
""
...
...
@@ -76,7 +75,7 @@ fun ByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: Int
@JvmSynthetic
@Suppress
(
"DuplicatedCode"
)
// false positive. foreach is not common to UByteArray and ByteArray
@ExperimentalUnsignedTypes
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
internal
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
,
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
String
{
if
(
length
==
0
)
{
return
""
}
...
...
@@ -94,13 +93,14 @@ fun UByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: In
}
@Suppress
(
"NOTHING_TO_INLINE"
)
inline
fun
ByteArray
.
encodeToString
(
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
,
charset
=
charset
)
in
ternal
in
line
fun
ByteArray
.
encodeToString
(
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
,
charset
=
charset
)
inline
fun
ByteArray
.
toReadPacket
(
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
)
=
@PublishedApi
internal
inline
fun
ByteArray
.
toReadPacket
(
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
)
=
ByteReadPacket
(
this
,
offset
=
offset
,
length
=
length
)
@OptIn
(
ExperimentalContracts
::
class
)
inline
fun
<
R
>
ByteArray
.
read
(
t
:
ByteReadPacket
.()
->
R
):
R
{
in
ternal
in
line
fun
<
R
>
ByteArray
.
read
(
t
:
ByteReadPacket
.()
->
R
):
R
{
contract
{
callsInPlace
(
t
,
InvocationKind
.
EXACTLY_ONCE
)
}
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai
/utils/contentToString.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid
/utils/contentToString.kt
View file @
97522bdf
...
...
@@ -9,9 +9,8 @@
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
,
"NO_REFLECTION_IN_CLASS_PATH"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.
qqandroid.
utils
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.reflect.KClass
import
kotlin.reflect.KProperty
import
kotlin.reflect.KProperty1
...
...
@@ -22,8 +21,7 @@ private val indent: String = " ".repeat(4)
/**
* 将所有元素加入转换为多行的字符串表示.
*/
@MiraiDebugAPI
internal
fun
<
T
>
Sequence
<
T
>.
joinToStringPrefixed
(
prefix
:
String
,
transform
:
(
T
)
->
CharSequence
):
String
{
private
fun
<
T
>
Sequence
<
T
>.
joinToStringPrefixed
(
prefix
:
String
,
transform
:
(
T
)
->
CharSequence
):
String
{
return
this
.
joinToString
(
prefix
=
"$prefix$indent"
,
separator
=
"\n$prefix$indent"
,
transform
=
transform
)
}
...
...
@@ -38,9 +36,7 @@ internal fun <T> Sequence<T>.joinToStringPrefixed(prefix: String, transform: (T)
* 其他类型: 反射获取它和它的所有来自 Mirai 的 super 类型的所有自有属性并递归调用 [_miraiContentToString]. 嵌套结构将会以缩进表示
*/
@Suppress
(
"FunctionName"
)
// 这样就不容易被 IDE 提示
@MiraiDebugAPI
(
"Extremely slow"
)
//@Suppress("Unsupported") // false positive
fun
Any
?.
_miraiContentToString
(
prefix
:
String
=
""
):
String
=
when
(
this
)
{
internal
fun
Any
?.
_miraiContentToString
(
prefix
:
String
=
""
):
String
=
when
(
this
)
{
is
Unit
->
"Unit"
is
UInt
->
"0x"
+
this
.
toUHexString
(
""
)
+
"($this)"
is
UByte
->
"0x"
+
this
.
toUHexString
()
+
"($this)"
...
...
@@ -135,7 +131,6 @@ private val KProperty1<*, *>.isConst: Boolean get() = false // on JVM, it will b
@Suppress
(
"EXTENSION_SHADOWED_BY_MEMBER"
)
private
val
KClass
<*>.
isData
:
Boolean
get
()
=
false
// on JVM, it will be resolved to member function
@MiraiDebugAPI
private
fun
Any
.
contentToStringReflectively
(
prefix
:
String
,
filter
:
((
name
:
String
,
value
:
Any
?)
->
Boolean
)?
=
null
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/io
/conversion.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
/conversion.kt
View file @
97522bdf
...
...
@@ -9,7 +9,7 @@
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlin.random.Random
import
kotlin.random.nextInt
...
...
@@ -22,7 +22,7 @@ import kotlin.random.nextInt
/**
* 255 -> 00 FF
*/
fun
Short
.
toByteArray
():
ByteArray
=
with
(
toInt
())
{
internal
fun
Short
.
toByteArray
():
ByteArray
=
with
(
toInt
())
{
byteArrayOf
(
(
shr
(
8
)
and
0
xFF
).
toByte
(),
(
shr
(
0
)
and
0
xFF
).
toByte
()
...
...
@@ -32,7 +32,7 @@ fun Short.toByteArray(): ByteArray = with(toInt()) {
/**
* 255 -> 00 00 00 FF
*/
fun
Int
.
toByteArray
():
ByteArray
=
byteArrayOf
(
internal
fun
Int
.
toByteArray
():
ByteArray
=
byteArrayOf
(
ushr
(
24
).
toByte
(),
ushr
(
16
).
toByte
(),
ushr
(
8
).
toByte
(),
...
...
@@ -42,7 +42,7 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
/**
* 255 -> 00 00 00 FF
*/
fun
Long
.
toByteArray
():
ByteArray
=
byteArrayOf
(
internal
fun
Long
.
toByteArray
():
ByteArray
=
byteArrayOf
(
(
ushr
(
56
)
and
0
xFF
).
toByte
(),
(
ushr
(
48
)
and
0
xFF
).
toByte
(),
(
ushr
(
40
)
and
0
xFF
).
toByte
(),
...
...
@@ -53,40 +53,40 @@ fun Long.toByteArray(): ByteArray = byteArrayOf(
(
ushr
(
0
)
and
0
xFF
).
toByte
()
)
fun
Int
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUHexString
(
separator
)
internal
fun
Int
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUHexString
(
separator
)
/**
* 255 -> 00 FF
*/
fun
UShort
.
toByteArray
():
ByteArray
=
with
(
toUInt
())
{
internal
fun
UShort
.
toByteArray
():
ByteArray
=
with
(
toUInt
())
{
byteArrayOf
(
(
shr
(
8
)
and
255
u
).
toByte
(),
(
shr
(
0
)
and
255
u
).
toByte
()
)
}
fun
Short
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUShort
().
toUHexString
(
separator
)
internal
fun
Short
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUShort
().
toUHexString
(
separator
)
fun
UShort
.
toUHexString
(
separator
:
String
=
" "
):
String
=
internal
fun
UShort
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toInt
().
shr
(
8
).
toUShort
().
toUByte
().
toUHexString
()
+
separator
+
this
.
toUByte
().
toUHexString
()
fun
ULong
.
toUHexString
(
separator
:
String
=
" "
):
String
=
internal
fun
ULong
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toLong
().
toUHexString
(
separator
)
fun
Long
.
toUHexString
(
separator
:
String
=
" "
):
String
=
internal
fun
Long
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
ushr
(
32
).
toUInt
().
toUHexString
(
separator
)
+
separator
+
this
.
toUInt
().
toUHexString
(
separator
)
/**
* 255 -> 00 FF
*/
fun
UByte
.
toByteArray
():
ByteArray
=
byteArrayOf
((
this
and
255
u
).
toByte
())
internal
fun
UByte
.
toByteArray
():
ByteArray
=
byteArrayOf
((
this
and
255
u
).
toByte
())
fun
UByte
.
toUHexString
():
String
=
this
.
toByte
().
toUHexString
()
internal
fun
UByte
.
toUHexString
():
String
=
this
.
toByte
().
toUHexString
()
/**
* 255u -> 00 00 00 FF
*/
fun
UInt
.
toByteArray
():
ByteArray
=
byteArrayOf
(
internal
fun
UInt
.
toByteArray
():
ByteArray
=
byteArrayOf
(
(
shr
(
24
)
and
255
u
).
toByte
(),
(
shr
(
16
)
and
255
u
).
toByte
(),
(
shr
(
8
)
and
255
u
).
toByte
(),
...
...
@@ -96,23 +96,23 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf(
/**
* 转 [ByteArray] 后再转 hex
*/
fun
UInt
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUHexString
(
separator
)
internal
fun
UInt
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUHexString
(
separator
)
/**
* 转无符号十六进制表示, 并补充首位 `0`.
* 转换结果示例: `FF`, `0E`
*/
fun
Byte
.
toUHexString
():
String
=
this
.
toUByte
().
fixToUHex
()
internal
fun
Byte
.
toUHexString
():
String
=
this
.
toUByte
().
fixToUHex
()
/**
* 转无符号十六进制表示, 并补充首位 `0`.
*/
fun
Byte
.
fixToUHex
():
String
=
this
.
toUByte
().
fixToUHex
()
internal
fun
Byte
.
fixToUHex
():
String
=
this
.
toUByte
().
fixToUHex
()
/**
* 转无符号十六进制表示, 并补充首位 `0`.
*/
fun
UByte
.
fixToUHex
():
String
=
internal
fun
UByte
.
fixToUHex
():
String
=
if
(
this
.
toInt
()
in
0
..
15
)
"0${this.toString(16).toUpperCase()}"
else
this
.
toString
(
16
).
toUpperCase
()
/**
...
...
@@ -120,7 +120,7 @@ fun UByte.fixToUHex(): String =
*
* 这个方法很累, 不建议经常使用.
*/
fun
String
.
hexToBytes
():
ByteArray
=
internal
fun
String
.
hexToBytes
():
ByteArray
=
this
.
split
(
" "
)
.
asSequence
()
.
filterNot
{
it
.
isEmpty
()
}
...
...
@@ -133,7 +133,7 @@ fun String.hexToBytes(): ByteArray =
*
* 这个方法很累, 不建议经常使用.
*/
fun
String
.
chunkedHexToBytes
():
ByteArray
=
internal
fun
String
.
chunkedHexToBytes
():
ByteArray
=
this
.
asSequence
().
chunked
(
2
).
map
{
(
it
[
0
].
toString
()
+
it
[
1
]).
toUByte
(
16
).
toByte
()
}.
toList
().
toByteArray
()
/**
...
...
@@ -141,7 +141,7 @@ fun String.chunkedHexToBytes(): ByteArray =
*
* 这个方法很累, 不建议经常使用.
*/
fun
String
.
autoHexToBytes
():
ByteArray
=
internal
fun
String
.
autoHexToBytes
():
ByteArray
=
this
.
replace
(
"\n"
,
""
).
replace
(
" "
,
""
).
asSequence
().
chunked
(
2
).
map
{
(
it
[
0
].
toString
()
+
it
[
1
]).
toUByte
(
16
).
toByte
()
}.
toList
().
toByteArray
()
...
...
@@ -151,7 +151,7 @@ fun String.autoHexToBytes(): ByteArray =
*
* 这个方法很累, 不建议经常使用.
*/
fun
String
.
hexToUBytes
():
UByteArray
=
internal
fun
String
.
hexToUBytes
():
UByteArray
=
this
.
split
(
" "
)
.
asSequence
()
.
filterNot
{
it
.
isEmpty
()
}
...
...
@@ -159,27 +159,6 @@ fun String.hexToUBytes(): UByteArray =
.
toList
()
.
toUByteArray
()
/**
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
*/
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
/**
* 随机生成长度为 [length] 的 [String].
*/
fun
getRandomString
(
length
:
Int
):
String
=
getRandomString
(
length
,
'a'
..
'z'
,
'A'
..
'Z'
,
'0'
..
'9'
)
/**
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
*/
fun
getRandomString
(
length
:
Int
,
charRange
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRange
.
random
()
})
/**
* 根据所给 [charRanges] 随机生成长度为 [length] 的 [String].
*/
fun
getRandomString
(
length
:
Int
,
vararg
charRanges
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRanges
[
Random
.
Default
.
nextInt
(
0
..
charRanges
.
lastIndex
)].
random
()
})
/**
* 将 [this] 前 4 个 [Byte] 的 bits 合并为一个 [Int]
*
...
...
@@ -188,15 +167,15 @@ fun getRandomString(length: Int, vararg charRanges: CharRange): String =
* 一个 [Int] 有 32 bits
* 本函数将 4 个 [Byte] 的 bits 连接得到 [Int]
*/
fun
ByteArray
.
toUInt
():
UInt
=
internal
fun
ByteArray
.
toUInt
():
UInt
=
(
this
[
0
].
toUInt
().
and
(
255
u
)
shl
24
)
+
(
this
[
1
].
toUInt
().
and
(
255
u
)
shl
16
)
+
(
this
[
2
].
toUInt
().
and
(
255
u
)
shl
8
)
+
(
this
[
3
].
toUInt
().
and
(
255
u
)
shl
0
)
fun
ByteArray
.
toUShort
():
UShort
=
internal
fun
ByteArray
.
toUShort
():
UShort
=
((
this
[
0
].
toUInt
().
and
(
255
u
)
shl
8
)
+
(
this
[
1
].
toUInt
().
and
(
255
u
)
shl
0
)).
toUShort
()
fun
ByteArray
.
toInt
():
Int
=
internal
fun
ByteArray
.
toInt
():
Int
=
(
this
[
0
].
toInt
().
and
(
255
)
shl
24
)
+
(
this
[
1
].
toInt
().
and
(
255
)
shl
16
)
+
(
this
[
2
].
toInt
().
and
(
255
)
shl
8
)
+
(
this
[
3
].
toInt
().
and
(
255
)
shl
0
)
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDH.kt
View file @
97522bdf
...
...
@@ -9,7 +9,7 @@
package
net.mamoe.mirai.qqandroid.utils.cryptor
import
net.mamoe.mirai.
utils.io
.chunkedHexToBytes
import
net.mamoe.mirai.
qqandroid.utils
.chunkedHexToBytes
expect
interface
ECDHPrivateKey
{
fun
getEncoded
():
ByteArray
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/TEA.kt
View file @
97522bdf
...
...
@@ -11,10 +11,10 @@ package net.mamoe.mirai.qqandroid.utils.cryptor
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.toByteArray
import
net.mamoe.mirai.qqandroid.utils.toUHexString
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.toByteArray
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.experimental.and
import
kotlin.experimental.xor
import
kotlin.jvm.JvmStatic
...
...
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai
/utils/io/chunked.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid
/utils/io/chunked.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.utils.io
package
net.mamoe.mirai.
qqandroid.
utils.io
import
kotlinx.coroutines.ExperimentalCoroutinesApi
import
kotlinx.coroutines.flow.Flow
...
...
@@ -20,12 +20,13 @@ import kotlinx.io.core.Input
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlinx.serialization.InternalSerializationApi
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
/**
* 由 [chunkedFlow] 分割得到的区块
*/
class
ChunkedInput
(
internal
class
ChunkedInput
(
/**
* 区块的数据.
* 由 [ByteArrayPool] 缓存并管理, 只可在 [Flow.collect] 中访问.
...
...
@@ -51,11 +52,16 @@ class ChunkedInput(
* 若 [ByteReadPacket.remaining] 小于 [sizePerPacket], 将会返回唯一元素 [this] 的 [Sequence]
*/
@OptIn
(
MiraiInternalAPI
::
class
)
fun
ByteReadPacket
.
chunkedFlow
(
sizePerPacket
:
Int
):
Flow
<
ChunkedInput
>
{
internal
fun
ByteReadPacket
.
chunkedFlow
(
sizePerPacket
:
Int
):
Flow
<
ChunkedInput
>
{
ByteArrayPool
.
checkBufferSize
(
sizePerPacket
)
if
(
this
.
remaining
<=
sizePerPacket
.
toLong
())
{
ByteArrayPool
.
useInstance
{
buffer
->
return
flowOf
(
ChunkedInput
(
buffer
,
this
.
readAvailable
(
buffer
,
0
,
sizePerPacket
)))
return
flowOf
(
ChunkedInput
(
buffer
,
this
.
readAvailable
(
buffer
,
0
,
sizePerPacket
)
)
)
}
}
return
flow
{
...
...
@@ -76,7 +82,7 @@ fun ByteReadPacket.chunkedFlow(sizePerPacket: Int): Flow<ChunkedInput> {
* 其长度分别为: 300, 300, 300, 100.
*/
@OptIn
(
MiraiInternalAPI
::
class
)
fun
ByteReadChannel
.
chunkedFlow
(
sizePerPacket
:
Int
):
Flow
<
ChunkedInput
>
{
internal
fun
ByteReadChannel
.
chunkedFlow
(
sizePerPacket
:
Int
):
Flow
<
ChunkedInput
>
{
ByteArrayPool
.
checkBufferSize
(
sizePerPacket
)
if
(
this
.
isClosedForRead
)
{
return
flowOf
()
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/io/input.kt
View file @
97522bdf
...
...
@@ -18,7 +18,6 @@ import kotlinx.io.charsets.Charset
import
kotlinx.io.charsets.Charsets
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.MiraiDebugAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
...
...
@@ -27,21 +26,12 @@ import kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
import
kotlinx.serialization.InternalSerializationApi
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.io.toUHexString
@OptIn
(
MiraiInternalAPI
::
class
,
InternalSerializationApi
::
class
)
fun
ByteReadPacket
.
copyTo
(
outputStream
:
OutputStream
)
{
ByteArrayPool
.
useInstance
{
while
(
this
.
isNotEmpty
)
{
outputStream
.
write
(
it
,
0
,
this
.
readAvailable
(
it
))
}
}
}
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.qqandroid.utils.toUHexString
@MiraiInternalAPI
inline
fun
<
R
>
ByteReadPacket
.
useBytes
(
in
ternal
in
line
fun
<
R
>
ByteReadPacket
.
useBytes
(
n
:
Int
=
remaining
.
toInt
(),
//not that safe but adequate
block
:
(
data
:
ByteArray
,
length
:
Int
)
->
R
):
R
=
ByteArrayPool
.
useInstance
{
...
...
@@ -50,12 +40,12 @@ inline fun <R> ByteReadPacket.useBytes(
}
@MiraiInternalAPI
inline
fun
ByteReadPacket
.
readPacketExact
(
in
ternal
in
line
fun
ByteReadPacket
.
readPacketExact
(
n
:
Int
=
remaining
.
toInt
()
//not that safe but adequate
):
ByteReadPacket
=
this
.
readBytes
(
n
).
toReadPacket
()
@OptIn
(
ExperimentalContracts
::
class
)
inline
fun
<
C
:
Closeable
,
R
>
C
.
withUse
(
block
:
C
.()
->
R
):
R
{
in
ternal
in
line
fun
<
C
:
Closeable
,
R
>
C
.
withUse
(
block
:
C
.()
->
R
):
R
{
contract
{
callsInPlace
(
block
,
InvocationKind
.
EXACTLY_ONCE
)
}
...
...
@@ -64,24 +54,23 @@ inline fun <C : Closeable, R> C.withUse(block: C.() -> R): R {
private
inline
fun
<
R
>
inline
(
block
:
()
->
R
):
R
=
block
()
typealias
TlvMap
=
MutableMap
<
Int
,
ByteArray
>
internal
typealias
TlvMap
=
MutableMap
<
Int
,
ByteArray
>
inline
fun
TlvMap
.
getOrFail
(
tag
:
Int
):
ByteArray
{
return
this
[
tag
]
?:
error
(
"cannot find tlv 0x${tag.toUHexString("")}($tag)"
)
in
ternal
in
line
fun
TlvMap
.
getOrFail
(
tag
:
Int
):
ByteArray
{
return
this
[
tag
]
?:
error
(
"cannot find tlv 0x${tag.
toUHexString("")}($tag)"
)
}
inline
fun
TlvMap
.
getOrFail
(
tag
:
Int
,
lazyMessage
:
(
tag
:
Int
)
->
String
):
ByteArray
{
in
ternal
in
line
fun
TlvMap
.
getOrFail
(
tag
:
Int
,
lazyMessage
:
(
tag
:
Int
)
->
String
):
ByteArray
{
return
this
[
tag
]
?:
error
(
lazyMessage
(
tag
))
}
@Suppress
(
"FunctionName"
)
@MiraiInternalAPI
inline
fun
Input
.
_readTLVMap
(
tagSize
:
Int
=
2
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
=
in
ternal
in
line
fun
Input
.
_readTLVMap
(
tagSize
:
Int
=
2
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
=
_readTLVMap
(
true
,
tagSize
,
suppressDuplication
)
@MiraiDebugAPI
@Suppress
(
"DuplicatedCode"
,
"FunctionName"
)
fun
Input
.
_readTLVMap
(
expectingEOF
:
Boolean
=
true
,
tagSize
:
Int
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
{
internal
fun
Input
.
_readTLVMap
(
expectingEOF
:
Boolean
=
true
,
tagSize
:
Int
,
suppressDuplication
:
Boolean
=
true
):
TlvMap
{
val
map
=
mutableMapOf
<
Int
,
ByteArray
>()
var
key
=
0
...
...
@@ -138,18 +127,18 @@ fun Input._readTLVMap(expectingEOF: Boolean = true, tagSize: Int, suppressDuplic
return
map
}
inline
fun
Input
.
readString
(
length
:
Int
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
in
ternal
in
line
fun
Input
.
readString
(
length
:
Int
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
),
charset
=
charset
)
inline
fun
Input
.
readString
(
length
:
Long
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
in
ternal
in
line
fun
Input
.
readString
(
length
:
Long
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
inline
fun
Input
.
readString
(
length
:
Short
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
in
ternal
in
line
fun
Input
.
readString
(
length
:
Short
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
@JvmSynthetic
inline
fun
Input
.
readString
(
length
:
UShort
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
in
ternal
in
line
fun
Input
.
readString
(
length
:
UShort
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
inline
fun
Input
.
readString
(
length
:
Byte
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
in
ternal
in
line
fun
Input
.
readString
(
length
:
Byte
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
\ No newline at end of file
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai
/utils/tryNTimes.kt
→
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid
/utils/tryNTimes.kt
View file @
97522bdf
...
...
@@ -6,15 +6,23 @@
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"DuplicatedCode"
)
package
net.mamoe.mirai.utils
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"Utils"
)
package
net.mamoe.mirai.qqandroid.utils
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
@PublishedApi
internal
expect
fun
Throwable
.
addSuppressedMirai
(
e
:
Throwable
)
@MiraiInternalAPI
@Suppress
(
"DuplicatedCode"
)
inline
fun
<
R
>
tryNTimes
(
repeat
:
Int
,
block
:
(
Int
)
->
R
):
R
{
in
ternal
in
line
fun
<
R
>
tryNTimes
(
repeat
:
Int
,
block
:
(
Int
)
->
R
):
R
{
var
lastException
:
Throwable
?
=
null
repeat
(
repeat
)
{
...
...
@@ -30,24 +38,6 @@ inline fun <R> tryNTimes(repeat: Int, block: (Int) -> R): R {
throw
lastException
!!
}
@MiraiInternalAPI
@Suppress
(
"DuplicatedCode"
)
inline
fun
<
R
>
tryNTimesOrNull
(
repeat
:
Int
,
block
:
(
Int
)
->
R
):
R
?
{
var
lastException
:
Throwable
?
=
null
repeat
(
repeat
)
{
try
{
return
block
(
it
)
}
catch
(
e
:
Throwable
)
{
if
(
lastException
==
null
)
{
lastException
=
e
}
else
lastException
!!
.
addSuppressedMirai
(
e
)
}
}
return
null
}
@MiraiInternalAPI
@Suppress
(
"DuplicatedCode"
)
inline
fun
<
R
>
tryNTimesOrException
(
repeat
:
Int
,
block
:
(
Int
)
->
R
):
Throwable
?
{
...
...
mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid
.io.
serialization/JceInputTest.kt
→
mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid
/io/
serialization/JceInputTest.kt
View file @
97522bdf
File moved
mirai-core
/src/commonTest/kotlin/net/mamoe/mirai
/utils/PlatformUtilsTest.kt
→
mirai-core
-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid
/utils/PlatformUtilsTest.kt
View file @
97522bdf
...
...
@@ -7,10 +7,10 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.
qqandroid.
utils
import
kotlinx.io.core.toByteArray
import
net.mamoe.mirai.utils.
io.encodeToString
import
net.mamoe.mirai.utils.
MiraiInternalAPI
import
kotlin.test.Test
import
kotlin.test.assertEquals
...
...
mirai-core
/src/commonTest/kotlin/net/mamoe/mirai
/utils/TypeConversionTest.kt
→
mirai-core
-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid
/utils/TypeConversionTest.kt
View file @
97522bdf
...
...
@@ -7,16 +7,12 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.
qqandroid.
utils
import
net.mamoe.mirai.utils.io.hexToBytes
import
net.mamoe.mirai.utils.io.toByteArray
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.test.Test
import
kotlin.test.assertEquals
import
kotlin.test.assertTrue
class
TypeConversionTest
{
@ExperimentalUnsignedTypes
...
...
mirai-core-qqandroid/src/commonTest/kotlin/test/printing.kt
View file @
97522bdf
...
...
@@ -16,12 +16,12 @@ import kotlinx.io.core.Input
import
kotlinx.io.core.readAvailable
import
kotlinx.io.core.use
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.qqandroid.utils.ByteArrayPool
import
net.mamoe.mirai.qqandroid.utils.toReadPacket
import
net.mamoe.mirai.qqandroid.utils.toUHexString
import
net.mamoe.mirai.utils.DefaultLogger
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiLoggerWithSwitch
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.io.toUHexString
import
net.mamoe.mirai.utils.withSwitch
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
...
...
@@ -30,13 +30,17 @@ import kotlin.contracts.contract
val
DebugLogger
:
MiraiLoggerWithSwitch
=
DefaultLogger
(
"Packet Debug"
).
withSwitch
(
true
)
inline
fun
ByteArray
.
debugPrintThis
(
name
:
String
):
ByteArray
{
in
ternal
in
line
fun
ByteArray
.
debugPrintThis
(
name
:
String
):
ByteArray
{
DebugLogger
.
debug
(
name
+
"="
+
this
.
toUHexString
())
return
this
}
@OptIn
(
ExperimentalContracts
::
class
,
MiraiInternalAPI
::
class
)
inline
fun
<
R
>
Input
.
debugIfFail
(
name
:
String
=
""
,
onFail
:
(
ByteArray
)
->
ByteReadPacket
=
{
it
.
toReadPacket
()
},
block
:
ByteReadPacket
.()
->
R
):
R
{
internal
inline
fun
<
R
>
Input
.
debugIfFail
(
name
:
String
=
""
,
onFail
:
(
ByteArray
)
->
ByteReadPacket
=
{
it
.
toReadPacket
()
},
block
:
ByteReadPacket
.()
->
R
):
R
{
contract
{
callsInPlace
(
block
,
InvocationKind
.
EXACTLY_ONCE
)
...
...
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
97522bdf
...
...
@@ -22,7 +22,7 @@ import net.mamoe.mirai.utils.Context
import
net.mamoe.mirai.utils.ContextImpl
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
net.mamoe.mirai.
utils.io
.toReadPacket
import
net.mamoe.mirai.
qqandroid.utils
.toReadPacket
import
java.nio.ByteBuffer
@OptIn
(
MiraiInternalAPI
::
class
)
...
...
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/MiraiPlatformUtils.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.qqandroid.utils
import
io.ktor.client.HttpClient
import
io.ktor.client.engine.cio.CIO
import
io.ktor.util.KtorExperimentalAPI
import
kotlinx.io.pool.useInstance
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.io.OutputStream
import
java.net.Inet4Address
import
java.security.MessageDigest
import
java.util.zip.Deflater
import
java.util.zip.GZIPInputStream
import
java.util.zip.GZIPOutputStream
import
java.util.zip.Inflater
internal
actual
object
MiraiPlatformUtils
{
actual
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
data
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
}
}
inflater
.
end
()
return
output
.
toByteArray
()
}
}
actual
fun
zip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
deflater
=
Deflater
()
deflater
.
setInput
(
data
,
offset
,
length
)
deflater
.
finish
()
ByteArrayPool
.
useInstance
{
return
it
.
take
(
deflater
.
deflate
(
it
)).
toByteArray
().
also
{
deflater
.
end
()
}
}
}
actual
fun
gzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
ByteArrayOutputStream
().
use
{
buf
->
GZIPOutputStream
(
buf
).
use
{
gzip
->
data
.
inputStream
(
offset
,
length
).
use
{
t
->
t
.
copyTo
(
gzip
)
}
}
buf
.
flush
()
return
buf
.
toByteArray
()
}
}
actual
fun
ungzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
return
GZIPInputStream
(
data
.
inputStream
(
offset
,
length
)).
use
{
it
.
readBytes
()
}
}
actual
fun
md5
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
data
,
offset
,
length
)
}.
digest
()
}
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
=
HttpClient
(
CIO
)
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
Inet4Address
.
getLocalHost
().
hostAddress
}.
getOrElse
{
"192.168.1.123"
}
fun
md5
(
stream
:
InputStream
):
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
stream
.
use
{
input
->
object
:
OutputStream
()
{
override
fun
write
(
b
:
Int
)
{
digest
.
update
(
b
.
toByte
())
}
}.
use
{
output
->
input
.
copyTo
(
output
)
}
}
return
digest
.
digest
()
}
}
\ No newline at end of file
mirai-core
/src/androidMain/kotlin/net/mamoe/mirai/utils/io
/PlatformSocket.kt
→
mirai-core
-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils
/PlatformSocket.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
...
...
@@ -25,8 +25,7 @@ import java.net.Socket
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
actual
class
PlatformSocket
:
Closeable
{
internal
actual
class
PlatformSocket
:
Closeable
{
private
lateinit
var
socket
:
Socket
actual
val
isOpen
:
Boolean
...
...
mirai-core
/src/jvmMain/kotlin/net/mamoe/mirai/utils/io
/PlatformSocketJvm.kt
→
mirai-core
-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils
/PlatformSocketJvm.kt
View file @
97522bdf
...
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.
utils.io
package
net.mamoe.mirai.
qqandroid.utils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
...
...
@@ -24,7 +24,7 @@ import java.nio.channels.WritableByteChannel
/**
* 多平台适配的 DatagramChannel.
*/
actual
class
PlatformDatagramChannel
actual
constructor
(
internal
actual
class
PlatformDatagramChannel
actual
constructor
(
serverHost
:
String
,
serverPort
:
Short
)
:
Closeable
{
...
...
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/addSuppressedMirai.kt
0 → 100644
View file @
97522bdf
package
net.mamoe.mirai.qqandroid.utils
@PublishedApi
internal
actual
fun
Throwable
.
addSuppressedMirai
(
e
:
Throwable
)
{
}
\ No newline at end of file
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/ECDHJvm.kt
View file @
97522bdf
...
...
@@ -9,8 +9,8 @@
package
net.mamoe.mirai.qqandroid.utils.cryptor
import
net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
org.bouncycastle.jce.provider.BouncyCastleProvider
import
java.security.*
import
java.security.spec.ECGenParameterSpec
...
...
mirai-core
/src/jvmMain/kotlin/net/mamoe/mirai
/utils/setVisible.kt
→
mirai-core
-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid
/utils/setVisible.kt
View file @
97522bdf
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.
qqandroid.
utils
import
kotlin.reflect.KProperty1
import
kotlin.reflect.jvm.javaField
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/Context.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/Context.
android.
kt
View file @
97522bdf
File moved
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImage
A
ndroid.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImage
.a
ndroid.kt
View file @
97522bdf
...
...
@@ -10,7 +10,6 @@
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.utils
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
kotlinx.coroutines.Dispatchers.IO
...
...
@@ -21,6 +20,7 @@ import kotlinx.io.core.copyTo
import
kotlinx.io.errors.IOException
import
kotlinx.io.streams.asInput
import
kotlinx.io.streams.asOutput
import
net.mamoe.mirai.utils.internal.md5
import
java.io.File
import
java.io.InputStream
import
java.net.URL
...
...
@@ -29,7 +29,6 @@ import java.net.URL
* 将各类型图片容器转为 [ExternalImage]
*/
/**
* 读取 [Bitmap] 的属性, 然后构造 [ExternalImage]
*/
...
...
@@ -53,7 +52,7 @@ fun File.toExternalImage(): ExternalImage {
return
ExternalImage
(
width
=
input
.
width
,
height
=
input
.
height
,
md5
=
this
.
inputStream
().
use
{
MiraiPlatformUtils
.
md5
(
it
)
},
md5
=
this
.
inputStream
().
use
{
it
.
md5
(
)
},
imageFormat
=
this
.
nameWithoutExtension
,
input
=
this
.
inputStream
().
asInput
(
IoBuffer
.
Pool
),
inputSize
=
this
.
length
(),
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/
BotConfigurationA
ndroid.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/
LoginSolver.a
ndroid.kt
View file @
97522bdf
...
...
@@ -10,94 +10,9 @@
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
java.io.File
@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
=
5
.
secondsToMillis
/**
* 最多尝试多少次重连
*/
actual
var
reconnectionRetryTimes
:
Int
=
Int
.
MAX_VALUE
/**
* 验证码处理器
*/
actual
var
loginSolver
:
LoginSolver
=
LoginSolver
.
Default
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
}
actual
typealias
Throws
=
kotlin
.
jvm
.
Throws
/**
* 验证码, 设备锁解决器
...
...
@@ -125,3 +40,9 @@ actual abstract class LoginSolver {
}
}
internal
actual
fun
getFileBasedDeviceInfoSupplier
(
filename
:
String
):
((
Context
)
->
DeviceInfo
)?
{
return
{
File
(
filename
).
loadAsDeviceInfo
(
it
)
}
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformLogger
A
ndroid.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformLogger
.a
ndroid.kt
View file @
97522bdf
File moved
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.
android.
kt
View file @
97522bdf
...
...
@@ -20,9 +20,7 @@ import kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
kotlinx.serialization.UnstableDefault
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.json.JsonConfiguration
import
net.mamoe.mirai.utils.MiraiPlatformUtils.localIpAddress
import
net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import
net.mamoe.mirai.utils.internal.md5
import
java.io.File
/**
...
...
@@ -41,7 +39,10 @@ fun File.loadAsDeviceInfo(context: Context): DeviceInfo {
}
@OptIn
(
UnstableDefault
::
class
)
private
val
JSON
=
Json
(
JsonConfiguration
.
Default
)
private
val
JSON
=
Json
{
isLenient
=
true
ignoreUnknownKeys
=
true
}
/**
* 部分引用指向 [Build].
...
...
@@ -109,9 +110,9 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
@OptIn
(
MiraiInternalAPI
::
class
)
override
val
imsiMd5
:
ByteArray
@SuppressLint
(
"HardwareIds"
)
get
()
=
md5
(
kotlin
.
runCatching
{
get
()
=
kotlin
.
runCatching
{
(
context
.
applicationContext
.
getSystemService
(
Context
.
TELEPHONY_SERVICE
)
as
TelephonyManager
).
subscriberId
.
toByteArray
()
}.
getOrEmpty
())
}.
getOrEmpty
()
.
md5
(
)
override
val
imei
:
String
@SuppressLint
(
"HardwareIds"
)
...
...
@@ -124,11 +125,6 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
}
}.
getOrElse
{
""
}
@OptIn
(
MiraiInternalAPI
::
class
)
override
val
ipAddress
:
ByteArray
get
()
=
kotlin
.
runCatching
{
localIpAddress
().
split
(
"."
).
map
{
it
.
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
ByteArray
(
4
)
}.
getOrElse
{
ByteArray
(
4
)
}
override
val
androidId
:
ByteArray
get
()
=
Build
.
ID
.
toByteArray
()
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/
addSuppresse
d.kt
→
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/
internal/addSuppressed.androi
d.kt
View file @
97522bdf
package
net.mamoe.mirai.utils
@
file
:
Suppress
(
"DuplicatedCode"
)
package
net.mamoe.mirai.utils.internal
import
android.os.Build
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/internal/md5.android.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.utils.internal
import
java.io.InputStream
import
java.security.MessageDigest
internal
actual
fun
ByteArray
.
md5
(
offset
:
Int
,
length
:
Int
):
ByteArray
{
this
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
this
@
md5
,
offset
,
length
)
}.
digest
()
}
internal
actual
fun
InputStream
.
md5
():
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
this
.
readInSequence
{
digest
.
update
(
it
.
toByte
())
}
return
digest
.
digest
()
}
internal
actual
typealias
InputStream
=
InputStream
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
View file @
97522bdf
...
...
@@ -8,112 +8,12 @@
*/
@
file
:
Suppress
(
"NOTHING_TO_INLINE"
)
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"Utils"
)
package
net.mamoe.mirai.utils
import
io.ktor.client.HttpClient
import
io.ktor.client.engine.cio.CIO
import
io.ktor.util.KtorExperimentalAPI
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.net.Inet4Address
import
java.security.MessageDigest
import
java.util.zip.Deflater
import
java.util.zip.GZIPInputStream
import
java.util.zip.GZIPOutputStream
import
java.util.zip.Inflater
/**
* 时间戳
*/
actual
val
currentTimeMillis
:
Long
get
()
=
System
.
currentTimeMillis
()
@MiraiInternalAPI
actual
object
MiraiPlatformUtils
{
actual
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
data
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
}
}
inflater
.
end
()
return
output
.
toByteArray
()
}
}
actual
fun
zip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
deflater
=
Deflater
()
deflater
.
setInput
(
data
,
offset
,
length
)
deflater
.
finish
()
ByteArrayPool
.
useInstance
{
return
it
.
take
(
deflater
.
deflate
(
it
)).
toByteArray
().
also
{
deflater
.
end
()
}
}
}
actual
fun
md5
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
data
,
offset
,
length
)
}.
digest
()
}
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
=
HttpClient
(
CIO
)
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
Inet4Address
.
getLocalHost
().
hostAddress
}.
getOrElse
{
"192.168.1.123"
}
fun
md5
(
stream
:
InputStream
):
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
stream
.
readInSequence
{
digest
.
update
(
it
.
toByte
())
}
return
digest
.
digest
()
}
private
inline
fun
InputStream
.
readInSequence
(
block
:
(
Int
)
->
Unit
)
{
var
read
:
Int
while
(
this
.
read
().
also
{
read
=
it
}
!=
-
1
)
{
block
(
read
)
}
}
actual
fun
gzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
ByteArrayOutputStream
().
use
{
buf
->
GZIPOutputStream
(
buf
).
use
{
gzip
->
data
.
inputStream
(
offset
,
length
).
use
{
t
->
t
.
copyTo
(
gzip
)
}
}
buf
.
flush
()
return
buf
.
toByteArray
()
}
}
actual
fun
ungzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
return
GZIPInputStream
(
data
.
inputStream
(
offset
,
length
)).
use
{
it
.
readBytes
()
}
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt
View file @
97522bdf
...
...
@@ -14,7 +14,7 @@ package net.mamoe.mirai
import
kotlinx.io.core.toByteArray
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.
MiraiPlatformUtils
import
net.mamoe.mirai.utils.
internal.md5
import
kotlin.annotation.AnnotationTarget.*
@MiraiInternalAPI
...
...
@@ -28,7 +28,7 @@ data class BotAccount(
@MiraiInternalAPI
val
passwordMd5
:
ByteArray
// md5
)
{
constructor
(
id
:
Long
,
passwordPlainText
:
String
)
:
this
(
id
,
MiraiPlatformUtils
.
md5
(
passwordPlainText
.
toByteArray
()
))
constructor
(
id
:
Long
,
passwordPlainText
:
String
)
:
this
(
id
,
passwordPlainText
.
toByteArray
().
md5
(
))
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
View file @
97522bdf
...
...
@@ -22,6 +22,7 @@ import net.mamoe.mirai.network.ForceOfflineException
import
net.mamoe.mirai.network.LoginFailedException
import
net.mamoe.mirai.network.closeAndJoin
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.internal.tryNTimesOrException
import
kotlin.coroutines.CoroutineContext
/*
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/j
vmHapp
y.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/j
avaFriendl
y.kt
View file @
97522bdf
File moved
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
View file @
97522bdf
...
...
@@ -18,8 +18,10 @@ import net.mamoe.mirai.event.BroadcastControllable
import
net.mamoe.mirai.event.CancellableEvent
import
net.mamoe.mirai.event.events.ImageUploadEvent.Failed
import
net.mamoe.mirai.event.events.ImageUploadEvent.Succeed
import
net.mamoe.mirai.message.data.ExperimentalMessageSource
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
...
...
@@ -96,6 +98,7 @@ sealed class MessageSendEvent : BotEvent, BotActiveEvent, AbstractCancellableEve
/**
* 消息撤回事件. 可是任意消息被任意人撤回.
*/
@OptIn
(
ExperimentalMessageSource
::
class
)
sealed
class
MessageRecallEvent
:
BotEvent
{
/**
* 消息原发送人
...
...
@@ -106,6 +109,7 @@ sealed class MessageRecallEvent : BotEvent {
* 消息 id.
* @see MessageSource.id
*/
@ExperimentalMessageSource
abstract
val
messageId
:
Long
/**
...
...
@@ -118,6 +122,7 @@ sealed class MessageRecallEvent : BotEvent {
*/
data class
FriendRecall
(
override
val
bot
:
Bot
,
@ExperimentalMessageSource
override
val
messageId
:
Long
,
override
val
messageTime
:
Int
,
/**
...
...
@@ -132,6 +137,7 @@ sealed class MessageRecallEvent : BotEvent {
data class
GroupRecall
(
override
val
bot
:
Bot
,
override
val
authorId
:
Long
,
@ExperimentalMessageSource
override
val
messageId
:
Long
,
override
val
messageTime
:
Int
,
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
View file @
97522bdf
...
...
@@ -16,14 +16,15 @@ import net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.EventDisabled
import
net.mamoe.mirai.event.Listener
import
net.mamoe.mirai.event.ListeningStatus
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.isRemoved
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.coroutineContext
import
kotlin.jvm.JvmField
import
kotlin.reflect.KClass
val
EventLogger
:
MiraiLoggerWithSwitch
=
DefaultLogger
(
"Event"
).
withSwitch
(
false
)
@MiraiInternalAPI
fun
<
L
:
Listener
<
E
>,
E
:
Event
>
KClass
<
out
E
>.
subscribeInternal
(
listener
:
L
):
L
{
with
(
this
.
listeners
())
{
...
...
@@ -67,7 +68,6 @@ internal class Handler<in E : Event>
}
@Suppress
(
"unused"
)
@OptIn
(
MiraiDebugAPI
::
class
)
override
suspend
fun
onEvent
(
event
:
E
):
ListeningStatus
{
if
(
isCompleted
||
isCancelled
)
return
ListeningStatus
.
STOPPED
if
(!
isActive
)
return
ListeningStatus
.
LISTENING
...
...
@@ -144,8 +144,6 @@ internal object EventListenerManager {
internal
suspend
inline
fun
Event
.
broadcastInternal
()
=
coroutineScope
{
if
(
EventDisabled
)
return
@
coroutineScope
EventLogger
.
info
{
"Event broadcast: $this"
}
val
listeners
=
this
@
broadcastInternal
::
class
.
listeners
()
callAndRemoveIfRequired
(
this
@
broadcastInternal
,
listeners
)
listeners
.
supertypes
.
forEach
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/linear.kt
View file @
97522bdf
...
...
@@ -84,6 +84,11 @@ inline fun <reified E : Event, R : Any> CoroutineScope.subscribingGetAsync(
}
//////////////
//// internal
//////////////
@PublishedApi
internal
suspend
inline
fun
<
reified
E
:
Event
,
R
>
subscribingGetOrNullImpl
(
coroutineScope
:
CoroutineScope
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt
View file @
97522bdf
...
...
@@ -18,6 +18,9 @@ import kotlin.jvm.JvmName
/**
* 链接的两个消息.
*
* 不要直接构造 [CombinedMessage], 使用 [Message.plus]
* 要连接多个 [Message], 使用 [buildMessageChain]
*
* @see Message.plus
*
* Left-biased list
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
View file @
97522bdf
...
...
@@ -18,7 +18,6 @@ import kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.io.PlatformDatagramChannel
/**
* Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务.
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/ForceOfflineException.kt
View file @
97522bdf
package
net.mamoe.mirai.network
class
ForceOfflineException
(
override
val
message
:
String
?)
:
RuntimeException
()
\ No newline at end of file
import
kotlinx.coroutines.CancellationException
import
kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
/**
* 当 [Bot] 被迫下线时抛出, 作为 [Job.cancel] 的 `cause`
*/
class
ForceOfflineException
(
override
val
message
:
String
?)
:
CancellationException
(
message
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/LoginFailedException.kt
View file @
97522bdf
...
...
@@ -7,10 +7,14 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.network
import
net.mamoe.mirai.Bot
/**
*
正常登录失败时抛出
*
在 [登录][Bot.login] 失败时抛出, 可正常地中断登录过程.
*/
sealed
class
LoginFailedException
:
RuntimeException
{
constructor
()
:
super
()
...
...
@@ -19,4 +23,17 @@ sealed class LoginFailedException : RuntimeException {
constructor
(
cause
:
Throwable
?)
:
super
(
cause
)
}
/**
* 密码输入错误
*/
class
WrongPasswordException
(
message
:
String
?)
:
LoginFailedException
(
message
)
/**
* 非 mirai 实现的异常
*/
abstract
class
CustomLoginFailedException
:
LoginFailedException
{
constructor
()
:
super
()
constructor
(
message
:
String
?)
:
super
(
message
)
constructor
(
message
:
String
?,
cause
:
Throwable
?)
:
super
(
message
,
cause
)
constructor
(
cause
:
Throwable
?)
:
super
(
cause
)
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
View file @
97522bdf
...
...
@@ -6,129 +6,122 @@
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
,
"DEPRECATION_ERROR"
)
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.LoginFailedException
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
kotlin.jvm.JvmOverloads
import
kotlin.jvm.JvmStatic
/**
* 验证码, 设备锁解决器
*/
expect
abstract
class
LoginSolver
{
/**
* 处理图片验证码.
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止
*
* @throws LoginFailedException
*/
abstract
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
ByteArray
):
String
?
/**
* 处理滑动验证码.
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止
*
* @throws LoginFailedException
* @return 验证码解决成功后获得的 ticket.
*/
abstract
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
/**
* 处理不安全设备验证.
* 在处理完成后返回任意内容 (包含 `null`) 均视为处理成功.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止.
*
* @return 任意内容. 返回值保留以供未来更新.
* @throws LoginFailedException
*/
abstract
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
companion
object
{
val
Default
:
LoginSolver
}
}
/**
* [Bot] 配置
*/
@Suppress
(
"PropertyName"
)
expect
open
class
BotConfiguration
()
{
open
class
BotConfiguration
{
/**
* 日志记录器
*/
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
var
botLoggerSupplier
:
((
Bot
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Bot(${it.uin})"
)
}
/**
* 网络层日志构造器
*/
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
var
networkLoggerSupplier
:
((
BotNetworkHandler
)
->
MiraiLogger
)
=
{
DefaultLogger
(
"Network(${it.bot.uin})"
)
}
/**
* 设备信息覆盖. 默认使用随机的设备信息.
*/
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
var
deviceInfo
:
((
Context
)
->
DeviceInfo
)?
=
null
/**
* 父 [CoroutineContext]
*/
var
parentCoroutineContext
:
CoroutineContext
var
parentCoroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
/**
* 心跳周期. 过长会导致被服务器断开连接.
*/
var
heartbeatPeriodMillis
:
Long
var
heartbeatPeriodMillis
:
Long
=
60
.
secondsToMillis
/**
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 5s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/
var
heartbeatTimeoutMillis
:
Long
var
heartbeatTimeoutMillis
:
Long
=
2
.
secondsToMillis
/**
* 心跳失败后的第一次重连前的等待时间.
*/
var
firstReconnectDelayMillis
:
Long
var
firstReconnectDelayMillis
:
Long
=
5
.
secondsToMillis
/**
* 重连失败后, 继续尝试的每次等待时间
*/
var
reconnectPeriodMillis
:
Long
var
reconnectPeriodMillis
:
Long
=
5
.
secondsToMillis
/**
* 最多尝试多少次重连
*/
var
reconnectionRetryTimes
:
Int
var
reconnectionRetryTimes
:
Int
=
Int
.
MAX_VALUE
/**
* 验证码处理器
*/
var
loginSolver
:
LoginSolver
var
loginSolver
:
LoginSolver
=
LoginSolver
.
Default
companion
object
{
/**
* 默认的配置实例
*/
@JvmStatic
val
Default
:
BotConfiguration
val
Default
=
BotConfiguration
()
}
operator
fun
_NoNetworkLog
.
unaryPlus
()
/**
* 不显示网络日志
*/
fun
noNetworkLog
()
{
networkLoggerSupplier
=
{
_
:
BotNetworkHandler
->
SilentLogger
}
}
/**
* 不记录网络层的 log.
* 网络层 log 包含包接收, 包发送, 和一些调试用的记录.
* 使用文件存储设备信息
*
* 此函数只在 JVM 有效. 在其他平台将会导致一直使用默认的随机的设备信息.
*/
@BotConfigurationDsl
val
NoNetworkLog
:
_NoNetworkLog
@JvmOverloads
fun
fileBasedDeviceInfo
(
filename
:
String
=
"device.json"
)
{
deviceInfo
=
getFileBasedDeviceInfoSupplier
(
filename
)
}
@Suppress
(
"ClassName"
)
object
_
NoNetworkLog
@PlannedRemoval
(
"0.34.0"
)
@Deprecated
(
"use fileBasedDeviceInfo(filepath"
,
level
=
DeprecationLevel
.
ERROR
,
replaceWith
=
ReplaceWith
(
"fileBasedDeviceInfo"
)
)
operator
fun
FileBasedDeviceInfo
.
unaryPlus
()
{
fileBasedDeviceInfo
(
this
.
filepath
)
}
}
/**
* 使用文件系统存储设备信息.
*/
@PlannedRemoval
(
"0.34.0"
)
@Deprecated
(
"use fileBasedDeviceInfo(filepath"
,
level
=
DeprecationLevel
.
ERROR
)
inline
class
FileBasedDeviceInfo
(
val
filepath
:
String
)
{
/**
* 使用 "device.json" 存储设备信息
*/
companion
object
ByDeviceDotJson
}
@DslMarker
annotation
class
BotConfigurationDsl
\ No newline at end of file
@OptIn
(
ExperimentalMultiplatform
::
class
)
internal
expect
fun
getFileBasedDeviceInfoSupplier
(
filename
:
String
):
((
Context
)
->
DeviceInfo
)?
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Context.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/Context.
common.
kt
View file @
97522bdf
File moved
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
View file @
97522bdf
...
...
@@ -49,14 +49,12 @@ abstract class DeviceInfo {
abstract
val
imsiMd5
:
ByteArray
abstract
val
imei
:
String
abstract
val
ipAddress
:
ByteArray
val
ipAddress
:
ByteArray
get
()
=
byteArrayOf
(
192
.
toByte
(),
168
.
toByte
(),
1
,
123
)
abstract
val
androidId
:
ByteArray
abstract
val
apn
:
ByteArray
val
guid
:
ByteArray
by
lazy
{
generateGuid
(
androidId
,
macAddress
)
}
fun
generateDeviceInfoData
():
ByteArray
{
@Serializable
class
DevInfo
(
...
...
@@ -121,11 +119,6 @@ class DeviceInfoData(
@Transient
override
lateinit
var
context
:
Context
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
override
val
ipAddress
:
ByteArray
get
()
=
MiraiPlatformUtils
.
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
androidId
:
ByteArray
get
()
=
display
@Serializable
...
...
@@ -137,13 +130,6 @@ class DeviceInfoData(
)
:
Version
}
/**
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
*/
@OptIn
(
MiraiInternalAPI
::
class
)
fun
generateGuid
(
androidId
:
ByteArray
,
macAddress
:
ByteArray
):
ByteArray
=
MiraiPlatformUtils
.
md5
(
androidId
+
macAddress
)
/*
fun DeviceInfo.toOidb0x769DeviceInfo() : Oidb0x769.DeviceInfo = Oidb0x769.DeviceInfo(
brand = brand.encodeToString(),
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
View file @
97522bdf
...
...
@@ -15,6 +15,7 @@ import kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.io.InputStream
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Input
import
kotlinx.serialization.InternalSerializationApi
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
...
...
@@ -22,8 +23,7 @@ import net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.OfflineImage
import
net.mamoe.mirai.message.data.sendTo
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlinx.serialization.InternalSerializationApi
import
kotlin.jvm.JvmSynthetic
/**
* 外部图片. 图片数据还没有读取到内存.
...
...
@@ -150,6 +150,7 @@ class ExternalImage private constructor(
/**
* 将图片发送给指定联系人
*/
@JvmSynthetic
suspend
fun
<
C
:
Contact
>
ExternalImage
.
sendTo
(
contact
:
C
):
MessageReceipt
<
C
>
=
when
(
contact
)
{
is
Group
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
is
QQ
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
...
...
@@ -162,6 +163,7 @@ suspend fun <C : Contact> ExternalImage.sendTo(contact: C): MessageReceipt<C> =
*
* @see contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人
*/
@JvmSynthetic
suspend
fun
ExternalImage
.
upload
(
contact
:
Contact
):
OfflineImage
=
when
(
contact
)
{
is
Group
->
contact
.
uploadImage
(
this
)
is
QQ
->
contact
.
uploadImage
(
this
)
...
...
@@ -171,10 +173,18 @@ suspend fun ExternalImage.upload(contact: Contact): OfflineImage = when (contact
/**
* 将图片发送给 [this]
*/
@JvmSynthetic
suspend
inline
fun
<
C
:
Contact
>
C
.
sendImage
(
image
:
ExternalImage
):
MessageReceipt
<
C
>
=
image
.
sendTo
(
this
)
private
operator
fun
ByteArray
.
get
(
range
:
IntRange
):
String
=
buildString
{
internal
operator
fun
ByteArray
.
get
(
range
:
IntRange
):
String
=
buildString
{
range
.
forEach
{
append
(
this
@
get
[
it
].
toUHexString
())
append
(
this
@
get
[
it
].
fixToString
())
}
}
private
fun
Byte
.
fixToString
():
String
{
return
when
(
this
.
toInt
())
{
in
0
..
15
->
"0${this.toString(16)}"
else
->
this
.
toString
(
16
)
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/LoginSolver.kt
0 → 100644
View file @
97522bdf
/*
* 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
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.LoginFailedException
import
kotlin.reflect.KClass
/**
* This annotation indicates what exceptions should be declared by a function when compiled to a JVM method.
*
* Example:
*
* ```
* @Throws(IOException::class)
* fun readFile(name: String): String {...}
* ```
*
* will be translated to
*
* ```
* String readFile(String name) throws IOException {...}
* ```
*
* @property exceptionClasses the list of checked exception classes that may be thrown by the function.
*/
@Target
(
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
PROPERTY_GETTER
,
AnnotationTarget
.
PROPERTY_SETTER
,
AnnotationTarget
.
CONSTRUCTOR
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@OptIn
(
ExperimentalMultiplatform
::
class
)
@OptionalExpectation
expect
annotation
class
Throws
(
vararg
val
exceptionClasses
:
KClass
<
out
Throwable
>)
/**
* 验证码, 设备锁解决器
*/
expect
abstract
class
LoginSolver
{
/**
* 处理图片验证码.
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止
*
* @throws LoginFailedException
*/
abstract
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
ByteArray
):
String
?
/**
* 处理滑动验证码.
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止
*
* @throws LoginFailedException
* @return 验证码解决成功后获得的 ticket.
*/
abstract
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
/**
* 处理不安全设备验证.
* 在处理完成后返回任意内容 (包含 `null`) 均视为处理成功.
* 抛出一个 [LoginFailedException] 以正常地终止登录, 抛出任意其他 [Exception] 将视为异常终止.
*
* @return 任意内容. 返回值保留以供未来更新.
* @throws LoginFailedException
*/
abstract
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
companion
object
{
val
Default
:
LoginSolver
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/SuspendLazy.kt
deleted
100644 → 0
View file @
97b66273
/*
* 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
*/
@
file
:
Suppress
(
"unused"
,
"FunctionName"
,
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.utils
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.async
import
net.mamoe.mirai.contact.QQ
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
/**
* 创建一个在当前 [CoroutineScope] 下执行初始化的 [suspendLazy]
*
* ```kotlin
* val image: Deferred<Image> by suspendLazy{ /* intializer */
}
*
```
*/
inline
fun
<
R
>
CoroutineScope
.
suspendLazy
(
context
:
CoroutineContext
=
EmptyCoroutineContext
,
noinline
initializer
:
suspend
()
->
R
):
Lazy
<
Deferred
<
R
>>
=
SuspendLazy
(
this
,
context
,
initializer
)
/**
* 挂起初始化的 [lazy], 是属性不能 `suspend` 的替代品.
*
* 本对象代表值初始化时将会通过 [CoroutineScope.async] 运行 [valueUpdater]
*
* [SuspendLazy] 是:
* - 线程安全
* - 只会被初始化一次.
* - `SuspendLazy<R>.value` 返回 `Deferred<R>`
* - 可以用作属性代表 (`val profile: by SuspendLazy(GlobalScope) { calculateValue() }`)
*
* @sample QQ.profile
*/
@PublishedApi
internal
class
SuspendLazy
<
R
>(
scope
:
CoroutineScope
,
coroutineContext
:
CoroutineContext
=
EmptyCoroutineContext
,
initializer
:
suspend
()
->
R
)
:
Lazy
<
Deferred
<
R
>>
{
private
val
valueUpdater
:
Deferred
<
R
>
by
lazy
{
scope
.
async
(
context
=
coroutineContext
)
{
initializer
()
}
}
override
val
value
:
Deferred
<
R
>
get
()
=
valueUpdater
override
fun
isInitialized
():
Boolean
=
valueUpdater
.
isCompleted
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt
View file @
97522bdf
...
...
@@ -7,10 +7,11 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
)
@
file
:
Suppress
(
"unused"
,
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.utils
import
kotlin.jvm.JvmSynthetic
import
kotlin.reflect.KProperty
// TODO: 2020/2/10 添加中文 doc
...
...
@@ -18,7 +19,7 @@ import kotlin.reflect.KProperty
/**
* WeakRef that `getValue` for delegation throws an [IllegalStateException] if the referent is released by GC. Therefore it returns notnull value only
*/
inline
class
UnsafeWeakRef
<
T
>(
private
val
weakRef
:
WeakRef
<
T
>)
{
class
UnsafeWeakRef
<
T
>(
private
val
weakRef
:
WeakRef
<
T
>)
{
fun
get
():
T
=
weakRef
.
get
()
?:
error
(
"WeakRef is released"
)
fun
clear
()
=
weakRef
.
clear
()
}
...
...
@@ -30,7 +31,8 @@ inline class UnsafeWeakRef<T>(private val weakRef: WeakRef<T>) {
* val bot: Bot by param.unsafeWeakRef()
* ```
*/
operator
fun
<
T
>
UnsafeWeakRef
<
T
>.
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
=
get
()
@JvmSynthetic
inline
operator
fun
<
T
>
UnsafeWeakRef
<
T
>.
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
=
get
()
/**
* Weak Reference.
...
...
@@ -62,12 +64,14 @@ annotation class WeakRefProperty
* Provides a weak reference to [this]
* The `getValue` for delegation returns [this] when [this] is not released by GC
*/
fun
<
T
>
T
.
weakRef
():
WeakRef
<
T
>
=
WeakRef
(
this
)
@JvmSynthetic
inline
fun
<
T
>
T
.
weakRef
():
WeakRef
<
T
>
=
WeakRef
(
this
)
/**
* Constructs an unsafe inline delegate for [this]
*/
fun
<
T
>
WeakRef
<
T
>.
unsafe
():
UnsafeWeakRef
<
T
>
=
UnsafeWeakRef
(
this
)
@JvmSynthetic
inline
fun
<
T
>
WeakRef
<
T
>.
unsafe
():
UnsafeWeakRef
<
T
>
=
UnsafeWeakRef
(
this
)
/**
* Provides a weak reference to [this].
...
...
@@ -75,7 +79,8 @@ fun <T> WeakRef<T>.unsafe(): UnsafeWeakRef<T> = UnsafeWeakRef(this)
*
* **UNSTABLE API**: It is strongly suggested not to use this api
*/
fun
<
T
>
T
.
unsafeWeakRef
():
UnsafeWeakRef
<
T
>
=
UnsafeWeakRef
(
this
.
weakRef
())
@JvmSynthetic
inline
fun
<
T
>
T
.
unsafeWeakRef
():
UnsafeWeakRef
<
T
>
=
UnsafeWeakRef
(
this
.
weakRef
())
/**
* Provides delegate value.
...
...
@@ -84,9 +89,11 @@ fun <T> T.unsafeWeakRef(): UnsafeWeakRef<T> = UnsafeWeakRef(this.weakRef())
* val bot: Bot? by param.weakRef()
* ```
*/
operator
fun
<
T
>
WeakRef
<
T
>.
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
?
=
this
.
get
()
@JvmSynthetic
inline
operator
fun
<
T
>
WeakRef
<
T
>.
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
?
=
this
.
get
()
/**
* Call the block if the referent is absent
*/
@JvmSynthetic
inline
fun
<
T
,
R
>
WeakRef
<
T
>.
ifAbsent
(
block
:
(
T
)
->
R
):
R
?
=
this
.
get
()
?.
let
(
block
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotat
a
ions.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotations.kt
View file @
97522bdf
...
...
@@ -43,22 +43,17 @@ annotation class MiraiExperimentalAPI(
)
/**
* 标记这个类, 类型, 函数, 属性, 字段, 或构造器为仅供调试阶段使用的.
*
* 这些 API 不具有稳定性, 可能会在任意时刻更改, 并且效率非常低下.
* 非常不建议在发行版本中使用这些 API.
* 标记一个自 Mirai 某个版本起才支持或在这个版本修改过的 API.
*/
@Target
(
CLASS
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
FUNCTION
,
PROPERTY_GETTER
,
PROPERTY_SETTER
,
TYPEALIAS
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@RequiresOptIn
(
level
=
RequiresOptIn
.
Level
.
WARNING
)
@Target
(
CLASS
,
TYPEALIAS
,
FUNCTION
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
)
annotation
class
MiraiDebugAPI
(
val
message
:
String
=
""
)
@MustBeDocumented
annotation
class
SinceMirai
(
val
version
:
String
)
/**
* 标记一个
自 Mirai 某个版本起才支持或在这个版本修改过
的 API.
* 标记一个
正计划在 [version] 版本时删除
的 API.
*/
@Target
(
CLASS
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
FUNCTION
,
PROPERTY_GETTER
,
PROPERTY_SETTER
,
TYPEALIAS
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@MustBeDocumented
annotation
class
SinceMirai
(
val
version
:
String
)
\ No newline at end of file
internal
annotation
class
PlannedRemoval
(
val
version
:
String
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/channels.kt
View file @
97522bdf
...
...
@@ -18,10 +18,8 @@ import kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.coroutines.io.ByteWriteChannel
import
kotlinx.coroutines.io.readAvailable
import
kotlinx.io.OutputStream
import
kotlinx.serialization.InternalSerializationApi
import
kotlinx.io.core.Output
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
kotlinx.serialization.InternalSerializationApi
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
...
...
@@ -31,56 +29,38 @@ import kotlin.jvm.JvmName
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
*/
@OptIn
(
InternalSerializationApi
::
class
)
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyTo
(
dst
:
OutputStream
)
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
write
(
buffer
,
0
,
size
)
}
}
}
/**
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
*/
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyTo
(
dst
:
Output
)
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
/**
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
*/
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyTo
(
dst
:
ByteWriteChannel
)
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
/* // 垃圾 kotlin, Unresolved reference: ByteWriteChannel
/**
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
*/
suspend fun ByteReadChannel.copyTo(dst: kotlinx.coroutines.io.ByteWriteChannel) {
ByteArrayPool.useInstance {
do {
val size = this.readAvailable(it)
dst.writeFully(it, 0, size)
} while (size != 0)
}
}
*/
// copyAndClose
...
...
@@ -88,16 +68,15 @@ suspend fun ByteReadChannel.copyTo(dst: kotlinx.coroutines.io.ByteWriteChannel)
/**
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
*/
@MiraiExperimentalAPI
@OptIn
(
InternalSerializationApi
::
class
)
suspend
fun
ByteReadChannel
.
copyAndClose
(
dst
:
OutputStream
)
{
// 在 JVM 这个 API 不是 internal 的
try
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
write
(
buffer
,
0
,
size
)
}
}
}
finally
{
dst
.
close
()
}
...
...
@@ -106,15 +85,14 @@ suspend fun ByteReadChannel.copyAndClose(dst: OutputStream) { // 在 JVM 这个
/**
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
*/
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyAndClose
(
dst
:
Output
)
{
try
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
finally
{
dst
.
close
()
}
...
...
@@ -123,16 +101,15 @@ suspend fun ByteReadChannel.copyAndClose(dst: Output) {
/**
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
*/
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyAndClose
(
dst
:
ByteWriteChannel
)
{
@Suppress
(
"DuplicatedCode"
)
try
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
finally
{
@Suppress
(
"DuplicatedCode"
)
dst
.
close
(
null
)
...
...
@@ -142,35 +119,17 @@ suspend fun ByteReadChannel.copyAndClose(dst: ByteWriteChannel) {
/**
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
*/
@MiraiExperimentalAPI
suspend
fun
ByteReadChannel
.
copyAndClose
(
dst
:
io
.
ktor
.
utils
.
io
.
ByteWriteChannel
)
{
@Suppress
(
"DuplicatedCode"
)
try
{
@OptIn
(
MiraiInternalAPI
::
class
)
ByteArrayPool
.
useInstance
{
buffer
->
val
buffer
=
ByteArray
(
2048
)
var
size
:
Int
while
(
this
.
readAvailable
(
buffer
).
also
{
size
=
it
}
>
0
)
{
dst
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
finally
{
@Suppress
(
"DuplicatedCode"
)
dst
.
close
(
null
)
}
}
\ No newline at end of file
/*// 垃圾 kotlin, Unresolved reference: ByteWriteChannel
/**
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
*/
suspend fun ByteReadChannel.copyAndClose(dst: kotlinx.coroutines.io.ByteWriteChannel) {
dst.close(kotlin.runCatching {
ByteArrayPool.useInstance {
do {
val size = this.readAvailable(it)
dst.writeFully(it, 0, size)
} while (size != 0)
}
}.exceptionOrNull())
}
*/
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/md5.common.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.utils.internal
expect
abstract
class
InputStream
{
open
fun
available
():
Int
open
fun
close
()
abstract
fun
read
():
Int
open
fun
read
(
b
:
ByteArray
):
Int
open
fun
read
(
b
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
Int
open
fun
skip
(
n
:
Long
):
Long
}
internal
expect
fun
InputStream
.
md5
():
ByteArray
internal
expect
fun
ByteArray
.
md5
(
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
ByteArray
@Suppress
(
"DuplicatedCode"
)
// false positive. `this` is not the same for `List<Byte>` and `ByteArray`
internal
fun
ByteArray
.
checkOffsetAndLength
(
offset
:
Int
,
length
:
Int
)
{
require
(
offset
>=
0
)
{
"offset shouldn't be negative: $offset"
}
require
(
length
>=
0
)
{
"length shouldn't be negative: $length"
}
require
(
offset
+
length
<=
this
.
size
)
{
"offset ($offset) + length ($length) > array.size (${this.size})"
}
}
internal
inline
fun
InputStream
.
readInSequence
(
block
:
(
Int
)
->
Unit
)
{
var
read
:
Int
while
(
this
.
read
().
also
{
read
=
it
}
!=
-
1
)
{
block
(
read
)
}
}
mirai-core
-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/inline
.kt
→
mirai-core
/src/commonMain/kotlin/net.mamoe.mirai/utils/internal/tryNTimes
.kt
View file @
97522bdf
...
...
@@ -7,25 +7,28 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
JvmName
(
"Utils"
)
@
file
:
JvmMultifileClass
package
net.mamoe.mirai.utils.internal
package
net.mamoe.mirai.qqandroid.utils
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.contract
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
/**
* Inline the block
*/
@OptIn
(
ExperimentalContracts
::
class
)
@PublishedApi
internal
inline
fun
<
R
>
inline
(
block
:
()
->
R
):
R
{
contract
{
callsInPlace
(
block
,
InvocationKind
.
EXACTLY_ONCE
)
internal
expect
fun
Throwable
.
addSuppressedMirai
(
e
:
Throwable
)
@MiraiInternalAPI
@Suppress
(
"DuplicatedCode"
)
internal
inline
fun
<
R
>
tryNTimesOrException
(
repeat
:
Int
,
block
:
(
Int
)
->
R
):
Throwable
?
{
var
lastException
:
Throwable
?
=
null
repeat
(
repeat
)
{
try
{
block
(
it
)
return
null
}
catch
(
e
:
Throwable
)
{
if
(
lastException
==
null
)
{
lastException
=
e
}
else
lastException
!!
.
addSuppressedMirai
(
e
)
}
}
return
block
()
return
lastException
!!
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/maps.kt
deleted
100644 → 0
View file @
97b66273
/*
* 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
*/
@
file
:
Suppress
(
"NOTHING_TO_INLINE"
)
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"Utils"
)
package
net.mamoe.mirai.utils
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
inline
fun
<
K
,
V
>
Map
<
K
,
V
>.
firstValue
():
V
=
this
.
entries
.
first
().
value
inline
fun
<
K
,
V
>
Map
<
K
,
V
>.
firstValueOrNull
():
V
?
=
this
.
entries
.
firstOrNull
()
?.
value
inline
fun
<
K
,
V
>
Map
<
K
,
V
>.
firstKey
():
K
=
this
.
entries
.
first
().
key
inline
fun
<
K
,
V
>
Map
<
K
,
V
>.
firstKeyOrNull
():
K
?
=
this
.
entries
.
firstOrNull
()
?.
key
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/
time
.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/
utils
.kt
View file @
97522bdf
...
...
@@ -14,33 +14,66 @@ package net.mamoe.mirai.utils
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
// 临时使用, 待 Kotlin Duration 稳定后使用 Duration.
// 内联属性, 则将来删除这些 API 将不会导致二进制不兼容.
/**
* 时间戳
*/
expect
val
currentTimeMillis
:
Long
@
get
:
JvmSynthetic
inline
val
currentTimeSeconds
:
Long
get
()
=
currentTimeMillis
/
1000
inline
val
Int
.
secondsToMillis
:
Long
get
()
=
this
*
1000L
inline
val
Int
.
minutesToMillis
:
Long
get
()
=
this
*
60
.
secondsToMillis
// 临时使用, 待 Kotlin Duration 稳定后使用 Duration.
// 内联属性, 则将来删除这些 API 将不会导致二进制不兼容.
@
get
:
JvmSynthetic
inline
val
Int
.
secondsToMillis
:
Long
get
()
=
this
*
1000L
inline
val
Int
.
hoursToMillis
:
Long
get
()
=
this
*
60
.
minutesToMillis
@
get
:
JvmSynthetic
inline
val
Int
.
minutesToMillis
:
Long
get
()
=
this
*
60
.
secondsToMillis
inline
val
Int
.
daysToMillis
:
Long
get
()
=
this
*
24
.
hoursToMillis
@
get
:
JvmSynthetic
inline
val
Int
.
hoursToMillis
:
Long
get
()
=
this
*
60
.
minutesToMillis
inline
val
Int
.
weeksToMillis
:
Long
get
()
=
this
*
7
.
daysToMillis
@
get
:
JvmSynthetic
inline
val
Int
.
daysToMillis
:
Long
get
()
=
this
*
24
.
hoursToMillis
inline
val
Int
.
monthsToMillis
:
Long
get
()
=
this
*
30
.
daysToMillis
@
get
:
JvmSynthetic
inline
val
Int
.
weeksToMillis
:
Long
get
()
=
this
*
7
.
daysToMillis
@
get
:
JvmSynthetic
inline
val
Int
.
monthsToMillis
:
Long
get
()
=
this
*
30
.
daysToMillis
inline
val
Int
.
millisToSeconds
:
Long
get
()
=
(
this
/
1000
).
toLong
()
@
get
:
JvmSynthetic
inline
val
Int
.
millisToSeconds
:
Long
get
()
=
(
this
/
1000
).
toLong
()
inline
val
Int
.
minutesToSeconds
:
Long
get
()
=
(
this
*
60
).
toLong
()
@
get
:
JvmSynthetic
inline
val
Int
.
minutesToSeconds
:
Long
get
()
=
(
this
*
60
).
toLong
()
inline
val
Int
.
hoursToSeconds
:
Long
get
()
=
this
*
60
.
minutesToSeconds
@
get
:
JvmSynthetic
inline
val
Int
.
hoursToSeconds
:
Long
get
()
=
this
*
60
.
minutesToSeconds
inline
val
Int
.
daysToSeconds
:
Long
get
()
=
this
*
24
.
hoursToSeconds
@
get
:
JvmSynthetic
inline
val
Int
.
daysToSeconds
:
Long
get
()
=
this
*
24
.
hoursToSeconds
inline
val
Int
.
weeksToSeconds
:
Long
get
()
=
this
*
7
.
daysToSeconds
@
get
:
JvmSynthetic
inline
val
Int
.
weeksToSeconds
:
Long
get
()
=
this
*
7
.
daysToSeconds
inline
val
Int
.
monthsToSeconds
:
Long
get
()
=
this
*
30
.
daysToSeconds
\ No newline at end of file
@
get
:
JvmSynthetic
inline
val
Int
.
monthsToSeconds
:
Long
get
()
=
this
*
30
.
daysToSeconds
\ No newline at end of file
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ImageTest.kt
View file @
97522bdf
...
...
@@ -7,13 +7,19 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.utils.io.autoHexToBytes
import
kotlin.test.Test
import
kotlin.test.assertEquals
import
kotlin.test.assertFailsWith
internal
fun
String
.
autoHexToBytes
():
ByteArray
=
this
.
replace
(
"\n"
,
""
).
replace
(
" "
,
""
).
asSequence
().
chunked
(
2
).
map
{
(
it
[
0
].
toString
()
+
it
[
1
]).
toUByte
(
16
).
toByte
()
}.
toList
().
toByteArray
()
internal
class
ImageTest
{
@Test
...
...
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
0 → 100644
View file @
97522bdf
package
net.mamoe.mirai.utils
import
kotlin.test.Test
import
kotlin.test.assertEquals
internal
class
ExternalImageTest
{
@Test
fun
testByteArrayGet
()
{
assertEquals
(
"0F"
,
byteArrayOf
(
0
x0f
)[
0
..
0
])
assertEquals
(
"10"
,
byteArrayOf
(
0
x10
)[
0
..
0
])
assertEquals
(
"0FFE"
,
byteArrayOf
(
0
x0F
,
0
xFE
.
toByte
())[
0
..
0
])
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessagePacket.kt
View file @
97522bdf
...
...
@@ -18,6 +18,7 @@ import kotlinx.io.core.use
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.copyAndClose
import
net.mamoe.mirai.utils.copyTo
...
...
@@ -31,7 +32,7 @@ import java.net.URL
* 一条从服务器接收到的消息事件.
* JVM 平台相关扩展
*/
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
,
MiraiExperimentalAPI
::
class
)
actual
abstract
class
MessagePacket
<
TSender
:
QQ
,
TSubject
:
Contact
>
actual
constructor
()
:
MessagePacketBase
<
TSender
,
TSubject
>()
{
// region 上传图片
suspend
inline
fun
uploadImage
(
image
:
BufferedImage
):
Image
=
subject
.
uploadImage
(
image
)
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Context.kt
View file @
97522bdf
...
...
@@ -9,6 +9,8 @@
package
net.mamoe.mirai.utils
import
kotlinx.io.pool.DefaultPool
actual
abstract
class
Context
open
class
ContextImpl
:
Context
()
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
View file @
97522bdf
...
...
@@ -19,7 +19,7 @@ import kotlinx.io.core.buildPacket
import
kotlinx.io.core.copyTo
import
kotlinx.io.errors.IOException
import
kotlinx.io.streams.asOutput
import
net.mamoe.mirai.utils.i
o.getRandomString
import
net.mamoe.mirai.utils.i
nternal.md5
import
java.awt.image.BufferedImage
import
java.io.File
import
java.io.InputStream
...
...
@@ -72,7 +72,7 @@ fun File.toExternalImage(): ExternalImage {
return
ExternalImage
(
width
=
image
.
getWidth
(
0
),
height
=
image
.
getHeight
(
0
),
md5
=
MiraiPlatformUtils
.
md5
(
this
.
inputStream
()
),
// dont change
md5
=
this
.
inputStream
().
md5
(
),
// dont change
imageFormat
=
image
.
formatName
,
input
=
this
.
inputStream
(),
filename
=
this
.
name
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
BotConfigurationJ
vm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
LoginSolver.j
vm.kt
View file @
97522bdf
...
...
@@ -31,6 +31,9 @@ import javax.imageio.ImageIO
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
actual
typealias
Throws
=
kotlin
.
jvm
.
Throws
@MiraiExperimentalAPI
class
DefaultLoginSolver
(
private
val
input
:
suspend
()
->
String
,
private
val
overrideLogger
:
MiraiLogger
?
=
null
...
...
@@ -92,6 +95,31 @@ class DefaultLoginSolver(
}
}
/**
* 验证码, 设备锁解决器
*/
actual
abstract
class
LoginSolver
{
actual
abstract
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
ByteArray
):
String
?
actual
abstract
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
actual
abstract
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
actual
companion
object
{
actual
val
Default
:
LoginSolver
@OptIn
(
MiraiExperimentalAPI
::
class
)
get
()
=
DefaultLoginSolver
(
input
=
{
withContext
(
Dispatchers
.
IO
)
{
readLine
()
}
?:
error
(
"No standard input"
)
})
}
}
///////////////////////////////
//////////////// internal
///////////////////////////////
internal
actual
fun
getFileBasedDeviceInfoSupplier
(
filename
:
String
):
((
Context
)
->
DeviceInfo
)?
{
return
{
File
(
filename
).
loadAsDeviceInfo
(
it
)
}
}
// Copied from Ktor CIO
private
fun
File
.
writeChannel
(
coroutineContext
:
CoroutineContext
=
Dispatchers
.
IO
...
...
@@ -103,7 +131,6 @@ private fun File.writeChannel(
}
}.
channel
private
val
loginSolverLock
=
Mutex
()
/**
...
...
@@ -159,113 +186,3 @@ 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
=
5
.
secondsToMillis
/**
* 最多尝试多少次重连
*/
actual
var
reconnectionRetryTimes
:
Int
=
Int
.
MAX_VALUE
/**
* 验证码处理器
*/
actual
var
loginSolver
:
LoginSolver
=
LoginSolver
.
Default
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
}
/**
* 验证码, 设备锁解决器
*/
actual
abstract
class
LoginSolver
{
actual
abstract
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
ByteArray
):
String
?
actual
abstract
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
url
:
String
):
String
?
actual
abstract
suspend
fun
onSolveUnsafeDeviceLoginVerify
(
bot
:
Bot
,
url
:
String
):
String
?
actual
companion
object
{
actual
val
Default
:
LoginSolver
get
()
=
DefaultLoginSolver
(
input
=
{
withContext
(
Dispatchers
.
IO
)
{
readLine
()
}
?:
error
(
"No standard input"
)
})
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
MiraiLoggerJ
vm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
PlatformLogger.j
vm.kt
View file @
97522bdf
File moved
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
View file @
97522bdf
...
...
@@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"Utils"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.utils
...
...
@@ -15,7 +17,6 @@ import io.ktor.client.HttpClient
import
io.ktor.client.engine.cio.CIO
import
io.ktor.util.KtorExperimentalAPI
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.io.OutputStream
...
...
@@ -31,88 +32,3 @@ import java.util.zip.Inflater
*/
actual
val
currentTimeMillis
:
Long
get
()
=
System
.
currentTimeMillis
()
@MiraiInternalAPI
actual
object
MiraiPlatformUtils
{
actual
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
data
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
}
}
inflater
.
end
()
return
output
.
toByteArray
()
}
}
actual
fun
zip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
deflater
=
Deflater
()
deflater
.
setInput
(
data
,
offset
,
length
)
deflater
.
finish
()
ByteArrayPool
.
useInstance
{
return
it
.
take
(
deflater
.
deflate
(
it
)).
toByteArray
().
also
{
deflater
.
end
()
}
}
}
actual
fun
gzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
ByteArrayOutputStream
().
use
{
buf
->
GZIPOutputStream
(
buf
).
use
{
gzip
->
data
.
inputStream
(
offset
,
length
).
use
{
t
->
t
.
copyTo
(
gzip
)
}
}
buf
.
flush
()
return
buf
.
toByteArray
()
}
}
actual
fun
ungzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
return
GZIPInputStream
(
data
.
inputStream
(
offset
,
length
)).
use
{
it
.
readBytes
()
}
}
actual
fun
md5
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
data
,
offset
,
length
)
}.
digest
()
}
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
=
HttpClient
(
CIO
)
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
Inet4Address
.
getLocalHost
().
hostAddress
}.
getOrElse
{
"192.168.1.123"
}
fun
md5
(
stream
:
InputStream
):
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
stream
.
use
{
input
->
object
:
OutputStream
()
{
override
fun
write
(
b
:
Int
)
{
digest
.
update
(
b
.
toByte
())
}
}.
use
{
output
->
input
.
copyTo
(
output
)
}
}
return
digest
.
digest
()
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
97522bdf
...
...
@@ -12,19 +12,16 @@ 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
kotlinx.serialization.json.JsonConfiguration
import
net.mamoe.mirai.utils.MiraiPlatformUtils.localIpAddress
import
net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import
net.mamoe.mirai.utils.io.getRandomByteArray
import
net.mamoe.mirai.utils.io.getRandomString
import
net.mamoe.mirai.utils.internal.md5
import
java.io.File
import
kotlin.random.Random
import
kotlin.random.nextInt
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
*/
@OptIn
(
UnstableDefault
::
class
)
fun
File
.
loadAsDeviceInfo
(
context
:
Context
=
ContextImpl
()):
DeviceInfo
{
if
(!
this
.
exists
()
||
this
.
length
()
==
0L
)
{
return
SystemDeviceInfo
(
context
).
also
{
...
...
@@ -55,9 +52,11 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
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
=
"Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)"
.
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
(
getRandomByteArray
(
16
).
md5
()).
toByteArray
()
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
()
...
...
@@ -65,9 +64,8 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
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
imsiMd5
:
ByteArray
=
getRandomByteArray
(
16
).
md5
(
)
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
=
"wifi"
.
toByteArray
()
...
...
@@ -79,3 +77,26 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
override
val
sdk
:
Int
=
29
}
}
/**
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
*/
internal
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
/**
* 随机生成长度为 [length] 的 [String].
*/
internal
fun
getRandomString
(
length
:
Int
):
String
=
getRandomString
(
length
,
'a'
..
'z'
,
'A'
..
'Z'
,
'0'
..
'9'
)
/**
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
*/
internal
fun
getRandomString
(
length
:
Int
,
charRange
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRange
.
random
()
})
/**
* 根据所给 [charRanges] 随机生成长度为 [length] 的 [String].
*/
internal
fun
getRandomString
(
length
:
Int
,
vararg
charRanges
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRanges
[
Random
.
Default
.
nextInt
(
0
..
charRanges
.
lastIndex
)].
random
()
})
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef
J
vm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef
.j
vm.kt
View file @
97522bdf
File moved
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
addSuppressed
.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
internal/addSuppressed.jvm
.kt
View file @
97522bdf
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
.internal
private
var
isAddSuppressedSupported
:
Boolean
=
true
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/internal/md5.jvm.kt
0 → 100644
View file @
97522bdf
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.utils.internal
import
java.io.InputStream
import
java.security.MessageDigest
internal
actual
fun
ByteArray
.
md5
(
offset
:
Int
,
length
:
Int
):
ByteArray
{
this
.
checkOffsetAndLength
(
offset
,
length
)
return
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
this
@
md5
,
offset
,
length
)
}.
digest
()
}
internal
actual
fun
InputStream
.
md5
():
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
this
.
readInSequence
{
digest
.
update
(
it
.
toByte
())
}
return
digest
.
digest
()
}
internal
actual
typealias
InputStream
=
java
.
io
.
InputStream
\ No newline at end of file
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