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
f2608d69
Commit
f2608d69
authored
Mar 08, 2020
by
Him188
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
a8a0d583
454057f5
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
386 additions
and
194 deletions
+386
-194
CHANGELOG.md
CHANGELOG.md
+3
-0
gradle.properties
gradle.properties
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+2
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
+44
-11
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+2
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
...tlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
+2
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
.../net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
+10
-5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
.../mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
+4
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
.../mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
+1
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
...Main/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
+2
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
...roidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+5
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
...dMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
+3
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
...droidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
+66
-65
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/message/data/Json.kt
...rc/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt
+27
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt
...ommonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt
+24
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
...nMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
+7
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt
...onMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt
+26
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt
...src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt
+21
-16
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
...src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
+6
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt
...c/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt
+4
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt
+18
-19
mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt
...monTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt
+24
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
+3
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
...rc/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
+1
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+69
-50
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+3
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
...c/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
+4
-2
No files found.
CHANGELOG.md
View file @
f2608d69
...
...
@@ -2,6 +2,9 @@
开发版本. 频繁更新, 不保证高稳定性
## `0.27.0` 2020/3/8
-
支持
`XML`
,
`Json`
,
`LightApp`
等
`RichMessage`
## `0.26.2` 2020/3/8
-
新增
`MessageChain.repeat`
与
`MessageChain.times`
-
JVM 平台下
`PlatformLogger`
可重定向输出
...
...
gradle.properties
View file @
f2608d69
# style guide
kotlin.code.style
=
official
# config
miraiVersion
=
0.2
6.2
miraiVersion
=
0.2
7.0
kotlin.incremental.multiplatform
=
true
kotlin.parallel.tasks.in.project
=
true
# kotlin
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
View file @
f2608d69
...
...
@@ -78,6 +78,7 @@ internal class QQImpl(
return
MessageReceipt
(
source
,
this
,
null
)
}
@OptIn
(
MiraiInternalAPI
::
class
)
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
OfflineFriendImage
=
try
{
if
(
BeforeImageUploadEvent
(
this
,
image
).
broadcast
().
isCancelled
)
{
throw
EventCancelledException
(
"cancelled by BeforeImageUploadEvent.ToGroup"
)
...
...
@@ -111,7 +112,7 @@ internal class QQImpl(
ImageUploadEvent
.
Succeed
(
this
@QQImpl
,
image
,
it
).
broadcast
()
}
is
LongConn
.
OffPicUp
.
Response
.
RequireUpload
->
{
Http
.
postImage
(
MiraiPlatformUtils
.
Http
.
postImage
(
"0x6ff0070"
,
bot
.
uin
,
null
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
f2608d69
...
...
@@ -222,7 +222,7 @@ internal abstract class QQAndroidBotBase constructor(
}
override
suspend
fun
openChannel
(
image
:
Image
):
ByteReadChannel
{
return
Http
.
get
<
HttpResponse
>(
queryImageUrl
(
image
)).
content
.
toKotlinByteReadChannel
()
return
MiraiPlatformUtils
.
Http
.
get
<
HttpResponse
>(
queryImageUrl
(
image
)).
content
.
toKotlinByteReadChannel
()
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
View file @
f2608d69
...
...
@@ -9,18 +9,14 @@
package
net.mamoe.mirai.qqandroid.message
import
kotlinx.io.core.buildPacket
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.readUInt
import
kotlinx.io.core.*
import
net.mamoe.mirai.LowLevelAPI
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.MiraiDebugAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
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.utils.io.toByteArray
...
...
@@ -222,7 +218,7 @@ private val atAllData = ImMsgBody.Elem(
)
)
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
,
MiraiExperimentalAPI
::
class
)
internal
fun
MessageChain
.
toRichTextElems
(
forGroup
:
Boolean
):
MutableList
<
ImMsgBody
.
Elem
>
{
val
elements
=
mutableListOf
<
ImMsgBody
.
Elem
>()
...
...
@@ -243,6 +239,25 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
elements
.
add
(
ImMsgBody
.
Elem
(
text
=
it
.
toJceData
()))
elements
.
add
(
ImMsgBody
.
Elem
(
text
=
ImMsgBody
.
Text
(
str
=
" "
)))
}
is
LightApp
->
elements
.
add
(
ImMsgBody
.
Elem
(
lightApp
=
ImMsgBody
.
LightAppElem
(
data
=
byteArrayOf
(
1
)
+
MiraiPlatformUtils
.
zip
(
it
.
content
.
toByteArray
())
)
)
)
is
RichMessage
->
elements
.
add
(
ImMsgBody
.
Elem
(
richMsg
=
ImMsgBody
.
RichMsg
(
serviceId
=
when
(
it
)
{
is
XmlMessage
->
60
is
JsonMessage
->
1
else
->
error
(
"unsupported RichMessage"
)
},
template1
=
byteArrayOf
(
1
)
+
MiraiPlatformUtils
.
zip
(
it
.
content
.
toByteArray
())
)
)
)
is
OfflineGroupImage
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
toJceData
()))
is
OnlineGroupImageImpl
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
delegate
))
is
OnlineFriendImageImpl
->
elements
.
add
(
ImMsgBody
.
Elem
(
notOnlineImage
=
it
.
delegate
))
...
...
@@ -269,9 +284,10 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
}
this
.
forEach
(
::
transformOneMessage
)
// if(this.any<QuoteReply>()){
elements
.
add
(
ImMsgBody
.
Elem
(
generalFlags
=
ImMsgBody
.
GeneralFlags
(
pbReserve
=
"78 00 F8 01 00 C8 02 00"
.
hexToBytes
())))
// }
if
(
this
.
any
<
RichMessage
>())
{
// 08 09 78 00 A0 01 81 DC 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00
elements
.
add
(
ImMsgBody
.
Elem
(
generalFlags
=
ImMsgBody
.
GeneralFlags
(
pbReserve
=
"08 09 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00"
.
hexToBytes
())))
}
else
elements
.
add
(
ImMsgBody
.
Elem
(
generalFlags
=
ImMsgBody
.
GeneralFlags
(
pbReserve
=
"78 00 F8 01 00 C8 02 00"
.
hexToBytes
())))
return
elements
}
...
...
@@ -400,6 +416,23 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilde
}
}
}
it
.
lightApp
!=
null
->
{
val
content
=
MiraiPlatformUtils
.
unzip
(
it
.
lightApp
.
data
,
1
).
encodeToString
()
message
.
add
(
LightApp
(
content
))
}
it
.
richMsg
!=
null
->
{
val
content
=
MiraiPlatformUtils
.
unzip
(
it
.
richMsg
.
template1
,
1
).
encodeToString
()
when
(
it
.
richMsg
.
serviceId
)
{
1
->
message
.
add
(
JsonMessage
(
content
))
60
->
message
.
add
(
XmlMessage
(
content
))
else
->
{
@Suppress
(
"DEPRECATION"
)
MiraiLogger
.
debug
{
"unknown richMsg.serviceId: ${it.richMsg.serviceId}, content=${it.richMsg.template1.contentToString()}, \ntryUnzip=${content}"
}
}
}
}
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
f2608d69
...
...
@@ -191,8 +191,9 @@ internal open class QQAndroidClient(
lateinit
var
t104
:
ByteArray
}
@OptIn
(
MiraiInternalAPI
::
class
)
internal
fun
generateTgtgtKey
(
guid
:
ByteArray
):
ByteArray
=
md5
(
getRandomByteArray
(
16
)
+
guid
)
MiraiPlatformUtils
.
md5
(
getRandomByteArray
(
16
)
+
guid
)
internal
class
ReserveUinInfo
(
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/highway.kt
View file @
f2608d69
...
...
@@ -26,6 +26,7 @@ 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
@OptIn
(
MiraiInternalAPI
::
class
,
InternalSerializationApi
::
class
)
internal
fun
createImageDataPacketSequence
(
// RequestDataTrans
...
...
@@ -77,7 +78,7 @@ internal fun createImageDataPacketSequence( // RequestDataTrans
dataoffset
=
offset
,
filesize
=
dataSize
.
toLong
(),
serviceticket
=
uKey
,
md5
=
net
.
mamoe
.
mirai
.
u
tils
.
md5
(
chunkedInput
.
buffer
,
0
,
chunkedInput
.
bufferSize
),
md5
=
MiraiPlatformU
tils
.
md5
(
chunkedInput
.
buffer
,
0
,
chunkedInput
.
bufferSize
),
fileMd5
=
fileMd5
,
flag
=
0
,
rtcode
=
0
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
f2608d69
...
...
@@ -342,7 +342,7 @@ internal object KnownPacketFactories {
1
->
{
input
.
discardExact
(
4
)
input
.
useBytes
{
data
,
length
->
data
.
unzip
(
length
=
length
).
let
{
MiraiPlatformUtils
.
unzip
(
data
,
0
,
length
).
let
{
val
size
=
it
.
toInt
()
if
(
size
==
it
.
size
||
size
==
it
.
size
+
4
)
{
it
.
toReadPacket
(
offset
=
4
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
View file @
f2608d69
...
...
@@ -15,9 +15,10 @@ import kotlinx.io.core.toByteArray
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.qqandroid.network.protocol.LoginType
import
net.mamoe.mirai.qqandroid.utils.NetworkType
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
net.mamoe.mirai.utils.md5
import
kotlin.random.Random
/**
...
...
@@ -76,6 +77,7 @@ fun BytePacketBuilder.t18(
}
shouldEqualsTo
22
}
@OptIn
(
MiraiInternalAPI
::
class
)
fun
BytePacketBuilder
.
t106
(
appId
:
Long
=
16L
,
subAppId
:
Long
=
537062845L
,
...
...
@@ -96,7 +98,7 @@ fun BytePacketBuilder.t106(
guid
?.
requireSize
(
16
)
writeShortLVPacket
{
encryptAndWrite
(
md5
(
passwordMd5
+
ByteArray
(
4
)
+
(
salt
.
takeIf
{
it
!=
0L
}
?:
uin
).
toInt
().
toByteArray
()))
{
encryptAndWrite
(
MiraiPlatformUtils
.
md5
(
passwordMd5
+
ByteArray
(
4
)
+
(
salt
.
takeIf
{
it
!=
0L
}
?:
uin
).
toInt
().
toByteArray
()))
{
writeShort
(
4
)
//TGTGTVer
writeInt
(
Random
.
nextInt
())
writeInt
(
5
)
//ssoVer
...
...
@@ -321,12 +323,13 @@ fun BytePacketBuilder.t144(
}
}
@OptIn
(
MiraiInternalAPI
::
class
)
fun
BytePacketBuilder
.
t109
(
androidId
:
ByteArray
)
{
writeShort
(
0
x109
)
writeShortLVPacket
{
writeFully
(
md5
(
androidId
))
writeFully
(
MiraiPlatformUtils
.
md5
(
androidId
))
}
shouldEqualsTo
16
}
...
...
@@ -556,21 +559,23 @@ fun BytePacketBuilder.t400(
}
}
@OptIn
(
MiraiInternalAPI
::
class
)
fun
BytePacketBuilder
.
t187
(
macAddress
:
ByteArray
)
{
writeShort
(
0
x187
)
writeShortLVPacket
{
writeFully
(
md5
(
macAddress
))
// may be md5
writeFully
(
MiraiPlatformUtils
.
md5
(
macAddress
))
// may be md5
}
}
@OptIn
(
MiraiInternalAPI
::
class
)
fun
BytePacketBuilder
.
t188
(
androidId
:
ByteArray
)
{
writeShort
(
0
x188
)
writeShortLVPacket
{
writeFully
(
md5
(
androidId
))
writeFully
(
MiraiPlatformUtils
.
md5
(
androidId
))
}
shouldEqualsTo
16
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/StatSvc.kt
View file @
f2608d69
...
...
@@ -23,9 +23,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import
net.mamoe.mirai.qqandroid.utils.NetworkType
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
import
net.mamoe.mirai.utils.localIpAddress
@Suppress
(
"EnumEntryName"
)
internal
enum
class
RegPushReason
{
...
...
@@ -89,6 +90,7 @@ internal class StatSvc {
private
const
val
subAppId
=
537062845L
@OptIn
(
MiraiInternalAPI
::
class
)
operator
fun
invoke
(
client
:
QQAndroidClient
,
regPushReason
:
RegPushReason
=
RegPushReason
.
appRegister
...
...
@@ -138,7 +140,7 @@ internal class StatSvc {
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
(),
uOldSSOIp
=
0
,
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
uNewSSOIp
=
MiraiPlatformUtils
.
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
},
strVendorName
=
"MIUI"
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt
View file @
f2608d69
...
...
@@ -84,7 +84,7 @@ internal class WtLogin {
t8
(
2052
)
t104
(
client
.
t104
)
t116
(
150470524
,
66560
)
t401
(
md5
(
client
.
device
.
guid
+
"stMNokHgxZUGhsYp"
.
toByteArray
()
+
t402
))
t401
(
MiraiPlatformUtils
.
md5
(
client
.
device
.
guid
+
"stMNokHgxZUGhsYp"
.
toByteArray
()
+
t402
))
}
}
}
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
View file @
f2608d69
...
...
@@ -44,6 +44,7 @@ fun Bitmap.toExternalImage(formatName: String = "gif"): ExternalImage {
/**
* 读取文件头识别图片属性, 然后构造 [ExternalImage]
*/
@OptIn
(
MiraiInternalAPI
::
class
)
@Throws
(
IOException
::
class
)
fun
File
.
toExternalImage
():
ExternalImage
{
val
input
=
BitmapFactory
.
decodeFile
(
this
.
absolutePath
)
...
...
@@ -52,7 +53,7 @@ fun File.toExternalImage(): ExternalImage {
return
ExternalImage
(
width
=
input
.
width
,
height
=
input
.
height
,
md5
=
this
.
inputStream
().
use
{
it
.
md5
(
)
},
md5
=
this
.
inputStream
().
use
{
MiraiPlatformUtils
.
md5
(
it
)
},
imageFormat
=
this
.
nameWithoutExtension
,
input
=
this
.
inputStream
().
asInput
(
IoBuffer
.
Pool
),
inputSize
=
this
.
length
(),
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
f2608d69
...
...
@@ -21,6 +21,8 @@ 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
java.io.File
/**
...
...
@@ -102,6 +104,7 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
(
context
.
applicationContext
.
getSystemService
(
Context
.
WIFI_SERVICE
)
as
WifiManager
).
connectionInfo
.
ssid
.
toByteArray
()
}.
getOrElse
{
byteArrayOf
()
}
@OptIn
(
MiraiInternalAPI
::
class
)
override
val
imsiMd5
:
ByteArray
@SuppressLint
(
"HardwareIds"
)
get
()
=
md5
(
kotlin
.
runCatching
{
...
...
@@ -117,6 +120,8 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
(
context
.
applicationContext
.
getSystemService
(
Context
.
TELEPHONY_SERVICE
)
as
TelephonyManager
).
deviceId
}
}.
getOrElse
{
""
}
@OptIn
(
MiraiInternalAPI
::
class
)
override
val
ipAddress
:
ByteArray
get
()
=
localIpAddress
().
split
(
"."
).
map
{
it
.
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
androidId
:
ByteArray
get
()
=
Build
.
ID
.
toByteArray
()
override
val
apn
:
ByteArray
get
()
=
"wifi"
.
toByteArray
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
View file @
f2608d69
...
...
@@ -10,7 +10,8 @@
package
net.mamoe.mirai.utils.cryptor
import
android.annotation.SuppressLint
import
net.mamoe.mirai.utils.md5
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import
java.security.*
import
java.security.spec.ECGenParameterSpec
import
java.security.spec.X509EncodedKeySpec
...
...
@@ -71,6 +72,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
.
genKeyPair
())
}
@OptIn
(
MiraiInternalAPI
::
class
)
actual
fun
calculateShareKey
(
privateKey
:
ECDHPrivateKey
,
publicKey
:
ECDHPublicKey
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/platformAndroid.kt
View file @
f2608d69
...
...
@@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"NOTHING_TO_INLINE"
)
package
net.mamoe.mirai.utils
import
io.ktor.client.HttpClient
...
...
@@ -15,88 +17,87 @@ import io.ktor.util.KtorExperimentalAPI
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.io.ByteArrayPool
import
java.io.ByteArrayOutputStream
import
java.io.DataInput
import
java.io.EOFException
import
java.io.InputStream
import
java.net.InetAddress
import
java.security.MessageDigest
import
java.util.zip.Deflater
import
java.util.zip.Inflater
/**
*
Ktor HttpClient. 不同平台使用不同引擎.
*
时间戳
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
get
()
=
HttpClient
(
CIO
)
actual
val
currentTimeMillis
:
Long
get
()
=
System
.
currentTimeMillis
()
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
InetAddress
.
getLocalHost
().
hostAddress
}.
getOrElse
{
"192.168.1.123"
}
@MiraiInternalAPI
actual
object
MiraiPlatformUtils
{
actual
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
/**
* MD5 算法
*
* @return 16 bytes
*/
actual
fun
md5
(
byteArray
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
byteArray
,
offset
,
length
)
}.
digest
()
fun
InputStream
.
md5
():
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
this
.
readInSequence
{
digest
.
update
(
it
.
toByte
())
}
return
digest
.
digest
()
}
fun
DataInput
.
md5
():
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
val
buffer
=
byteArrayOf
(
1
)
while
(
true
)
{
try
{
this
.
readFully
(
buffer
)
}
catch
(
e
:
EOFException
)
{
break
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
()
}
digest
.
update
(
buffer
[
0
])
}
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
zip
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
{
data
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
@OptIn
(
MiraiInternalAPI
::
class
)
actual
fun
ByteArray
.
unzip
(
offset
:
Int
,
length
:
Int
):
ByteArray
{
this
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
val
deflater
=
Deflater
()
deflater
.
setInput
(
data
,
offset
,
length
)
deflater
.
finish
()
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
this
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
}
return
it
.
take
(
deflater
.
deflate
(
it
)).
toByteArray
().
also
{
deflater
.
end
()
}
}
}
inflater
.
end
()
return
output
.
toByteArray
()
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
val
currentTimeMillis
:
Long
get
()
=
System
.
currentTimeMillis
()
\ No newline at end of file
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
get
()
=
HttpClient
(
CIO
)
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
InetAddress
.
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
)
}
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotAccount.kt
View file @
f2608d69
...
...
@@ -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.
md5
import
net.mamoe.mirai.utils.
MiraiPlatformUtils
import
kotlin.annotation.AnnotationTarget.*
@MiraiInternalAPI
...
...
@@ -28,7 +28,7 @@ data class BotAccount(
@MiraiInternalAPI
val
passwordMd5
:
ByteArray
// md5
)
{
constructor
(
id
:
Long
,
passwordPlainText
:
String
)
:
this
(
id
,
md5
(
passwordPlainText
.
toByteArray
()))
constructor
(
id
:
Long
,
passwordPlainText
:
String
)
:
this
(
id
,
MiraiPlatformUtils
.
md5
(
passwordPlainText
.
toByteArray
()))
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Json.kt
0 → 100644
View file @
f2608d69
/*
* 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.message.data
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.SinceMirai
/**
* Json 消息.
*
* @see LightApp 一些消息实际上是 [LightApp]
*/
@SinceMirai
(
"0.27.0"
)
@OptIn
(
MiraiExperimentalAPI
::
class
)
class
JsonMessage
(
override
val
content
:
String
)
:
RichMessage
{
companion
object
Key
:
Message
.
Key
<
JsonMessage
>
// serviceId = 1
override
fun
toString
():
String
=
content
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/LightApp.kt
0 → 100644
View file @
f2608d69
/*
* 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.message.data
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.SinceMirai
/**
* 小程序分享, 如音乐分享
*/
@OptIn
(
MiraiExperimentalAPI
::
class
)
@SinceMirai
(
"0.27.0"
)
class
LightApp
constructor
(
override
val
content
:
String
)
:
RichMessage
{
companion
object
Key
:
Message
.
Key
<
LightApp
>
override
fun
toString
():
String
=
content
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
View file @
f2608d69
...
...
@@ -61,7 +61,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
fun
<
M
:
Message
>
getOrNull
(
key
:
Message
.
Key
<
M
>):
M
?
=
firstOrNull
(
key
)
/**
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [X
ML
Message], [QuoteReply].
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [X
ml
Message], [QuoteReply].
* 仅供 `Java` 使用
*/
@Suppress
(
"FunctionName"
,
"INAPPLICABLE_JVM_NAME"
)
...
...
@@ -73,7 +73,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
}
/**
* 遍历每一个消息, 即 [MessageSource] [At], [AtAll], [PlainText], [Image], [Face], [X
ML
Message], [QuoteReply].
* 遍历每一个消息, 即 [MessageSource] [At], [AtAll], [PlainText], [Image], [Face], [X
ml
Message], [QuoteReply].
* 仅供 `Java` 使用
*/
@Suppress
(
"FunctionName"
,
"INAPPLICABLE_JVM_NAME"
)
...
...
@@ -88,7 +88,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
// region accessors
/**
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [X
ML
Message], [QuoteReply]
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [X
ml
Message], [QuoteReply]
*/
@JvmSynthetic
inline
fun
MessageChain
.
foreachContent
(
block
:
(
Message
)
->
Unit
)
{
...
...
@@ -130,6 +130,10 @@ fun <M : Message> MessageChain.firstOrNull(key: Message.Key<M>): M? = when (key)
Face
->
first
<
Face
>()
QuoteReply
->
first
<
QuoteReply
>()
MessageSource
->
first
<
MessageSource
>()
XmlMessage
->
first
<
XmlMessage
>()
JsonMessage
->
first
<
JsonMessage
>()
RichMessage
->
first
<
RichMessage
>()
LightApp
->
first
<
LightApp
>()
else
->
null
}
as
M
?
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/
data/ImageLink
.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/
message/data/RichMessage
.kt
View file @
f2608d69
...
...
@@ -7,20 +7,20 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.data
package
net.mamoe.mirai.
message.
data
import
io.ktor.client.request.get
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.utils.Http
import
net.mamoe.mirai.utils.SinceMirai
interface
ImageLink
{
/**
* 原图
*/
val
original
:
String
suspend
fun
downloadAsByteArray
():
ByteArray
=
download
().
readBytes
()
/**
* XML 消息等富文本消息
*
* @see XmlMessage
* @see JsonMessage
* @see LightApp
*/
@SinceMirai
(
"0.27.0"
)
interface
RichMessage
:
MessageContent
{
companion
object
Key
:
Message
.
Key
<
RichMessage
>
suspend
fun
download
():
ByteReadPacket
=
Http
.
get
(
original
)
val
content
:
String
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/XML.kt
View file @
f2608d69
...
...
@@ -15,6 +15,7 @@
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.SinceMirai
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
...
...
@@ -23,20 +24,25 @@ import kotlin.jvm.JvmName
*
* @see buildXMLMessage
*/
@MiraiExperimentalAPI
inline
class
XMLMessage
(
val
stringValue
:
String
)
:
Message
,
MessageContent
{
override
fun
followedBy
(
tail
:
Message
):
Nothing
=
error
(
"XMLMessage Message cannot be followed"
)
override
fun
toString
():
String
=
stringValue
@SinceMirai
(
"0.27.0"
)
@OptIn
(
MiraiExperimentalAPI
::
class
)
class
XmlMessage
constructor
(
override
val
content
:
String
)
:
RichMessage
{
companion
object
Key
:
Message
.
Key
<
XmlMessage
>
// override val serviceId: Int get() = 60
override
fun
toString
():
String
=
content
}
/**
* 构造一条 XML 消息
*/
@MiraiExperimentalAPI
(
"还未支持"
)
inline
fun
buildXMLMessage
(
block
:
@XMLDsl
XMLMessageBuilder
.()
->
Unit
):
XMLMessage
=
XMLMessage
(
XMLMessageBuilder
().
apply
(
block
).
text
)
@SinceMirai
(
"0.27.0"
)
@MiraiExperimentalAPI
inline
fun
buildXMLMessage
(
block
:
@XMLDsl
XMLMessageBuilder
.()
->
Unit
):
XmlMessage
=
XmlMessage
(
XMLMessageBuilder
().
apply
(
block
).
text
)
@S
uppress
(
"NOTHING_TO_INLINE
"
)
@S
inceMirai
(
"0.27.0
"
)
@XMLDsl
class
ItemBuilder
(
var
bg
:
Int
=
0
,
...
...
@@ -46,21 +52,20 @@ class ItemBuilder(
internal
val
builder
:
StringBuilder
=
StringBuilder
()
val
text
:
String
get
()
=
"<item bg='$bg' layout='$layout'>$builder</item>"
inline
fun
summary
(
text
:
String
,
color
:
String
=
"#FFFFFF
"
)
{
fun
summary
(
text
:
String
,
color
:
String
=
"#000000
"
)
{
this
.
builder
.
append
(
"<summary color='$color'>$text</summary>"
)
}
inline
fun
title
(
text
:
String
,
size
:
Int
=
18
,
color
:
String
=
"#FFFFFF
"
)
{
fun
title
(
text
:
String
,
size
:
Int
=
25
,
color
:
String
=
"#000000
"
)
{
this
.
builder
.
append
(
"<title size='$size' color='$color'>$text</title>"
)
}
inline
fun
picture
(
coverUrl
:
String
)
{
fun
picture
(
coverUrl
:
String
)
{
this
.
builder
.
append
(
"<picture cover='$coverUrl'/>"
)
}
}
@XMLDsl
@Suppress
(
"NOTHING_TO_INLINE"
)
class
XMLMessageBuilder
(
var
templateId
:
Int
=
1
,
var
serviceId
:
Int
=
1
,
...
...
@@ -70,7 +75,7 @@ class XMLMessageBuilder(
*/
var
actionData
:
String
=
""
,
/**
* 摘要
* 摘要
, 在官方客户端内消息列表中显示
*/
var
brief
:
String
=
""
,
var
flag
:
Int
=
3
,
...
...
@@ -89,11 +94,11 @@ class XMLMessageBuilder(
"</msg>"
@XMLDsl
inline
fun
item
(
block
:
@XMLDsl
ItemBuilder
.()
->
Unit
)
{
fun
item
(
block
:
@XMLDsl
ItemBuilder
.()
->
Unit
)
{
builder
.
append
(
ItemBuilder
().
apply
(
block
).
text
)
}
inline
fun
source
(
name
:
String
,
iconURL
:
String
=
""
)
{
fun
source
(
name
:
String
,
iconURL
:
String
=
""
)
{
sourceName
=
name
sourceIconURL
=
iconURL
}
...
...
@@ -101,4 +106,4 @@ class XMLMessageBuilder(
@Target
(
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
TYPE
)
@DslMarker
internal
annotation
class
XMLDsl
\ No newline at end of file
annotation
class
XMLDsl
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DeviceInfo.kt
View file @
f2608d69
...
...
@@ -94,6 +94,7 @@ abstract class DeviceInfo {
}
}
@OptIn
(
MiraiInternalAPI
::
class
)
@Serializable
class
DeviceInfoData
(
override
val
display
:
ByteArray
,
...
...
@@ -122,7 +123,8 @@ class DeviceInfoData(
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
override
val
ipAddress
:
ByteArray
get
()
=
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
get
()
=
MiraiPlatformUtils
.
localIpAddress
().
split
(
"."
).
map
{
it
.
toUByte
().
toByte
()
}.
takeIf
{
it
.
size
==
4
}
?.
toByteArray
()
?:
byteArrayOf
()
override
val
androidId
:
ByteArray
get
()
=
display
...
...
@@ -138,7 +140,9 @@ class DeviceInfoData(
/**
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
*/
fun
generateGuid
(
androidId
:
ByteArray
,
macAddress
:
ByteArray
):
ByteArray
=
md5
(
androidId
+
macAddress
)
@OptIn
(
MiraiInternalAPI
::
class
)
fun
generateGuid
(
androidId
:
ByteArray
,
macAddress
:
ByteArray
):
ByteArray
=
MiraiPlatformUtils
.
md5
(
androidId
+
macAddress
)
/*
fun DeviceInfo.toOidb0x769DeviceInfo() : Oidb0x769.DeviceInfo = Oidb0x769.DeviceInfo(
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/annotataions.kt
View file @
f2608d69
...
...
@@ -17,7 +17,7 @@ import kotlin.annotation.AnnotationTarget.*
* 这些 API 可能会在任意时刻更改, 且不会发布任何预警.
* 非常不建议在发行版本中使用这些 API.
*/
@Retention
(
AnnotationRetention
.
BINARY
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@RequiresOptIn
(
level
=
RequiresOptIn
.
Level
.
ERROR
)
@Target
(
CLASS
,
TYPEALIAS
,
FUNCTION
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
...
...
@@ -35,7 +35,7 @@ annotation class MiraiInternalAPI(
* 这些 API 不具有稳定性, 且可能会在任意时刻更改.
* 不建议在发行版本中使用这些 API.
*/
@Retention
(
AnnotationRetention
.
BINARY
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@RequiresOptIn
(
level
=
RequiresOptIn
.
Level
.
WARNING
)
@Target
(
CLASS
,
TYPEALIAS
,
FUNCTION
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
)
annotation
class
MiraiExperimentalAPI
(
...
...
@@ -48,7 +48,7 @@ annotation class MiraiExperimentalAPI(
* 这些 API 不具有稳定性, 可能会在任意时刻更改, 并且效率非常低下.
* 非常不建议在发行版本中使用这些 API.
*/
@Retention
(
AnnotationRetention
.
BINARY
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@RequiresOptIn
(
level
=
RequiresOptIn
.
Level
.
WARNING
)
@Target
(
CLASS
,
TYPEALIAS
,
FUNCTION
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
)
annotation
class
MiraiDebugAPI
(
...
...
@@ -59,6 +59,6 @@ annotation class MiraiDebugAPI(
* 标记一个自 Mirai 某个版本起才支持的 API.
*/
@Target
(
CLASS
,
PROPERTY
,
FIELD
,
CONSTRUCTOR
,
FUNCTION
,
PROPERTY_GETTER
,
PROPERTY_SETTER
,
TYPEALIAS
)
@Retention
(
AnnotationRetention
.
BINARY
)
@Retention
(
AnnotationRetention
.
SOURCE
)
@MustBeDocumented
annotation
class
SinceMirai
(
val
version
:
String
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/platform.kt
View file @
f2608d69
...
...
@@ -12,7 +12,6 @@
package
net.mamoe.mirai.utils
import
io.ktor.client.HttpClient
import
kotlinx.io.core.toByteArray
/**
* 时间戳
...
...
@@ -21,30 +20,30 @@ expect val currentTimeMillis: Long
inline
val
currentTimeSeconds
:
Long
get
()
=
currentTimeMillis
/
1000
/**
* 解 zip 压缩
* 仅供内部使用的工具类.
* 不写为扩展是为了避免污染命名空间.
*/
expect
fun
ByteArray
.
unzip
(
offset
:
Int
=
0
,
length
:
Int
=
this
.
size
-
offset
):
ByteArray
@MiraiInternalAPI
expect
object
MiraiPlatformUtils
{
fun
unzip
(
data
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
data
.
size
-
offset
):
ByteArray
/**
* MD5 算法
*
* @return 16 bytes
*/
expect
fun
md5
(
byteArray
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
byteArray
.
size
-
offset
):
ByteArray
fun
zip
(
data
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
data
.
size
-
offset
):
ByteArray
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
())
/**
* Localhost 解析
*/
expect
fun
localIpAddress
():
String
fun
md5
(
data
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
data
.
size
-
offset
):
ByteArray
inline
fun
md5
(
str
:
String
):
ByteArray
fun
localIpAddress
():
String
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@MiraiInternalAPI
val
Http
:
HttpClient
}
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
expect
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
)
{
...
...
mirai-core/src/commonTest/kotlin/net.mamoe.mirai.utils/PlatformUtilsTest.kt
0 → 100644
View file @
f2608d69
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.utils
import
kotlinx.io.core.toByteArray
import
net.mamoe.mirai.utils.io.encodeToString
import
kotlin.test.Test
import
kotlin.test.assertEquals
internal
class
PlatformUtilsTest
{
@OptIn
(
MiraiInternalAPI
::
class
)
@Test
fun
testZip
()
{
assertEquals
(
"test"
,
MiraiPlatformUtils
.
unzip
(
MiraiPlatformUtils
.
zip
(
"test"
.
toByteArray
())).
encodeToString
())
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
View file @
f2608d69
...
...
@@ -11,8 +11,8 @@
package
net.mamoe.mirai.utils
import
kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.coroutines.withContext
import
kotlinx.io.core.Input
import
kotlinx.io.core.buildPacket
...
...
@@ -60,6 +60,7 @@ suspend inline fun BufferedImage.suspendToExternalImage(): ExternalImage = withC
/**
* 读取文件头识别图片属性, 然后构造 [ExternalImage]
*/
@OptIn
(
MiraiInternalAPI
::
class
)
@Throws
(
IOException
::
class
)
fun
File
.
toExternalImage
():
ExternalImage
{
val
input
=
ImageIO
.
createImageInputStream
(
this
)
...
...
@@ -71,7 +72,7 @@ fun File.toExternalImage(): ExternalImage {
return
ExternalImage
(
width
=
image
.
getWidth
(
0
),
height
=
image
.
getHeight
(
0
),
md5
=
this
.
inputStream
().
md5
(
),
// dont change
md5
=
MiraiPlatformUtils
.
md5
(
this
.
inputStream
()
),
// dont change
imageFormat
=
image
.
formatName
,
input
=
this
.
inputStream
(),
filename
=
this
.
name
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLoggerJvm.kt
View file @
f2608d69
...
...
@@ -15,7 +15,7 @@ import java.util.*
/**
* JVM 控制台日志实现
*/
actual
open
class
PlatformLogger
@JvmOverloads
constructor
(
actual
open
class
PlatformLogger
constructor
(
override
val
identity
:
String
?
=
"Mirai"
,
open
val
output
:
(
String
)
->
Unit
)
:
MiraiLoggerPlatformBase
()
{
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
View file @
f2608d69
...
...
@@ -7,78 +7,97 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"NOTHING_TO_INLINE"
)
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.*
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.io.OutputStream
import
java.net.InetAddress
import
java.security.MessageDigest
import
java.util.zip.Deflater
import
java.util.zip.Inflater
actual
fun
md5
(
byteArray
:
ByteArray
,
offset
:
Int
,
length
:
Int
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
apply
{
update
(
byteArray
,
offset
,
length
)
}.
digest
()
/**
* 时间戳
*/
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
)
fun
InputStream
.
md5
():
ByteArray
=
this
.
use
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
this
.
use
{
input
->
object
:
OutputStream
()
{
override
fun
write
(
b
:
Int
)
{
digest
.
update
(
b
.
toByte
())
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
))
}
}
}.
use
{
output
->
input
.
copyTo
(
output
)
inflater
.
end
()
return
output
.
toByteArray
()
}
}
return
digest
.
digest
()
}
fun
DataInput
.
md5
():
ByteArray
{
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
val
buffer
=
byteArrayOf
(
1
)
while
(
true
)
{
try
{
this
.
readFully
(
buffer
)
}
catch
(
e
:
EOFException
)
{
break
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
()
}
}
digest
.
update
(
buffer
[
0
])
}
return
digest
.
digest
()
}
actual
fun
localIpAddress
():
String
=
InetAddress
.
getLocalHost
().
hostAddress
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
val
Http
:
HttpClient
get
()
=
HttpClient
(
CIO
)
actual
inline
fun
md5
(
str
:
String
):
ByteArray
=
md5
(
str
.
toByteArray
()
)
@OptIn
(
MiraiInternalAPI
::
class
)
actual
fun
ByteArray
.
unzip
(
offset
:
Int
,
length
:
Int
):
ByteArray
{
this
.
checkOffsetAndLength
(
offset
,
length
)
if
(
length
==
0
)
return
ByteArray
(
0
)
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn
(
KtorExperimentalAPI
::
class
)
actual
val
Http
:
HttpClient
get
()
=
HttpClient
(
CIO
)
val
inflater
=
Inflater
()
inflater
.
reset
()
ByteArrayOutputStream
().
use
{
output
->
inflater
.
setInput
(
this
,
offset
,
length
)
ByteArrayPool
.
useInstance
{
while
(!
inflater
.
finished
())
{
output
.
write
(
it
,
0
,
inflater
.
inflate
(
it
))
/**
* Localhost 解析
*/
actual
fun
localIpAddress
():
String
=
runCatching
{
InetAddress
.
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
)
}
}
inflater
.
end
()
return
output
.
toByteArray
()
return
digest
.
digest
()
}
}
/**
* 时间戳
*/
actual
val
currentTimeMillis
:
Long
get
()
=
System
.
currentTimeMillis
()
\ No newline at end of file
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
f2608d69
...
...
@@ -15,6 +15,8 @@ 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
java.io.File
...
...
@@ -37,7 +39,7 @@ fun File.loadAsDeviceInfo(context: Context = ContextImpl()): DeviceInfo {
private
val
JSON
=
Json
(
JsonConfiguration
.
Stable
)
@Serializable
@OptIn
(
ExperimentalUnsignedTypes
::
class
)
@OptIn
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
actual
open
class
SystemDeviceInfo
actual
constructor
()
:
DeviceInfo
()
{
actual
constructor
(
context
:
Context
)
:
this
()
{
this
.
context
=
context
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
View file @
f2608d69
...
...
@@ -9,7 +9,8 @@
package
net.mamoe.mirai.utils.cryptor
import
net.mamoe.mirai.utils.md5
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
...
...
@@ -58,6 +59,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
.
genKeyPair
())
}
@OptIn
(
MiraiInternalAPI
::
class
)
actual
fun
calculateShareKey
(
privateKey
:
ECDHPrivateKey
,
publicKey
:
ECDHPublicKey
...
...
@@ -65,7 +67,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
val
instance
=
KeyAgreement
.
getInstance
(
"ECDH"
,
"BC"
)
instance
.
init
(
privateKey
)
instance
.
doPhase
(
publicKey
,
true
)
return
md5
(
instance
.
generateSecret
())
return
MiraiPlatformUtils
.
md5
(
instance
.
generateSecret
())
}
actual
fun
constructPublicKey
(
key
:
ByteArray
):
ECDHPublicKey
{
...
...
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