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
5b2ae6e9
Commit
5b2ae6e9
authored
Apr 23, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify Image structure, close #244
parent
eb123bb3
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
113 additions
and
289 deletions
+113
-289
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/FriendImpl.kt
...in/kotlin/net/mamoe/mirai/qqandroid/contact/FriendImpl.kt
+4
-21
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/GroupImpl.kt
...ain/kotlin/net/mamoe/mirai/qqandroid/contact/GroupImpl.kt
+5
-13
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/FlashImageImpl.kt
...otlin/net/mamoe/mirai/qqandroid/message/FlashImageImpl.kt
+4
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
...in/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
+10
-59
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+1
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x352.kt
...e/mirai/qqandroid/network/protocol/data/proto/Cmd0x352.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt
.../qqandroid/network/protocol/packet/chat/image/ImgStore.kt
+14
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
...c/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
+27
-89
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
+20
-72
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
...monTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
+3
-3
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
.../src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
+1
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
+19
-20
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
+3
-1
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/FriendImpl.kt
View file @
5b2ae6e9
...
@@ -91,24 +91,14 @@ internal class FriendImpl(
...
@@ -91,24 +91,14 @@ internal class FriendImpl(
fileId
=
0
,
fileId
=
0
,
fileMd5
=
image
.
md5
,
fileMd5
=
image
.
md5
,
fileSize
=
image
.
inputSize
.
toInt
(),
fileSize
=
image
.
inputSize
.
toInt
(),
fileName
=
image
.
md5
.
toUHexString
(
""
)
+
"."
+
image
.
format
,
fileName
=
image
.
md5
.
toUHexString
(
""
)
+
".gif"
,
imgOriginal
=
1
,
imgOriginal
=
1
imgWidth
=
image
.
width
,
imgHeight
=
image
.
height
,
imgType
=
image
.
imageType
)
)
).
sendAndExpect
<
LongConn
.
OffPicUp
.
Response
>()
).
sendAndExpect
<
LongConn
.
OffPicUp
.
Response
>()
@Suppress
(
"UNCHECKED_CAST"
)
// bug
@Suppress
(
"UNCHECKED_CAST"
)
// bug
return
when
(
response
)
{
return
when
(
response
)
{
is
LongConn
.
OffPicUp
.
Response
.
FileExists
->
OfflineFriendImage
(
is
LongConn
.
OffPicUp
.
Response
.
FileExists
->
OfflineFriendImage
(
response
.
resourceId
).
also
{
filepath
=
response
.
resourceId
,
md5
=
response
.
imageInfo
.
fileMd5
,
fileLength
=
response
.
imageInfo
.
fileSize
.
toInt
(),
height
=
response
.
imageInfo
.
fileHeight
,
width
=
response
.
imageInfo
.
fileWidth
,
resourceId
=
response
.
resourceId
).
also
{
ImageUploadEvent
.
Succeed
(
this
@FriendImpl
,
image
,
it
).
broadcast
()
ImageUploadEvent
.
Succeed
(
this
@FriendImpl
,
image
,
it
).
broadcast
()
}
}
is
LongConn
.
OffPicUp
.
Response
.
RequireUpload
->
{
is
LongConn
.
OffPicUp
.
Response
.
RequireUpload
->
{
...
@@ -132,14 +122,7 @@ internal class FriendImpl(
...
@@ -132,14 +122,7 @@ internal class FriendImpl(
//)
//)
// 为什么不能 ??
// 为什么不能 ??
return
OfflineFriendImage
(
return
OfflineFriendImage
(
response
.
resourceId
).
also
{
filepath
=
response
.
resourceId
,
md5
=
image
.
md5
,
fileLength
=
image
.
inputSize
.
toInt
(),
height
=
image
.
height
,
width
=
image
.
width
,
resourceId
=
response
.
resourceId
).
also
{
ImageUploadEvent
.
Succeed
(
this
@FriendImpl
,
image
,
it
).
broadcast
()
ImageUploadEvent
.
Succeed
(
this
@FriendImpl
,
image
,
it
).
broadcast
()
}
}
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/GroupImpl.kt
View file @
5b2ae6e9
...
@@ -400,11 +400,7 @@ internal class GroupImpl(
...
@@ -400,11 +400,7 @@ internal class GroupImpl(
uin
=
bot
.
id
,
uin
=
bot
.
id
,
groupCode
=
id
,
groupCode
=
id
,
md5
=
image
.
md5
,
md5
=
image
.
md5
,
size
=
image
.
inputSize
,
size
=
image
.
inputSize
picWidth
=
image
.
width
,
picHeight
=
image
.
height
,
picType
=
image
.
imageType
,
filename
=
image
.
filename
).
sendAndExpect
()
).
sendAndExpect
()
@Suppress
(
"UNCHECKED_CAST"
)
// bug
@Suppress
(
"UNCHECKED_CAST"
)
// bug
...
@@ -427,10 +423,8 @@ internal class GroupImpl(
...
@@ -427,10 +423,8 @@ internal class GroupImpl(
// fileId = response.fileId.toInt()
// fileId = response.fileId.toInt()
// )
// )
// println("NMSL")
// println("NMSL")
return
OfflineGroupImage
(
return
OfflineGroupImage
(
imageId
=
resourceId
)
md5
=
image
.
md5
,
.
also
{
ImageUploadEvent
.
Succeed
(
this
@GroupImpl
,
image
,
it
).
broadcast
()
}
filepath
=
resourceId
).
also
{
ImageUploadEvent
.
Succeed
(
this
@GroupImpl
,
image
,
it
).
broadcast
()
}
}
}
is
ImgStore
.
GroupPicUp
.
Response
.
RequireUpload
->
{
is
ImgStore
.
GroupPicUp
.
Response
.
RequireUpload
->
{
// 每 10KB 等 1 秒, 最少等待 5 秒
// 每 10KB 等 1 秒, 最少等待 5 秒
...
@@ -480,10 +474,8 @@ internal class GroupImpl(
...
@@ -480,10 +474,8 @@ internal class GroupImpl(
// imageType = image.imageType,
// imageType = image.imageType,
// fileId = response.fileId.toInt()
// fileId = response.fileId.toInt()
// )
// )
return
OfflineGroupImage
(
return
OfflineGroupImage
(
imageId
=
resourceId
)
md5
=
image
.
md5
,
.
also
{
ImageUploadEvent
.
Succeed
(
this
@GroupImpl
,
image
,
it
).
broadcast
()
}
filepath
=
resourceId
).
also
{
ImageUploadEvent
.
Succeed
(
this
@GroupImpl
,
image
,
it
).
broadcast
()
}
/*
/*
fileId = response.fileId.toInt(),
fileId = response.fileId.toInt(),
fileType = 0, // ?
fileType = 0, // ?
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/FlashImageImpl.kt
View file @
5b2ae6e9
...
@@ -2,6 +2,7 @@ package net.mamoe.mirai.qqandroid.message
...
@@ -2,6 +2,7 @@ package net.mamoe.mirai.qqandroid.message
import
net.mamoe.mirai.message.data.FriendFlashImage
import
net.mamoe.mirai.message.data.FriendFlashImage
import
net.mamoe.mirai.message.data.GroupFlashImage
import
net.mamoe.mirai.message.data.GroupFlashImage
import
net.mamoe.mirai.message.data.md5
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.HummerCommelem
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.ImMsgBody
import
net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
...
@@ -13,7 +14,7 @@ internal fun GroupFlashImage.toJceData() = ImMsgBody.Elem(
...
@@ -13,7 +14,7 @@ internal fun GroupFlashImage.toJceData() = ImMsgBody.Elem(
businessType
=
0
,
businessType
=
0
,
pbElem
=
HummerCommelem
.
MsgElemInfoServtype3
(
pbElem
=
HummerCommelem
.
MsgElemInfoServtype3
(
flashTroopPic
=
ImMsgBody
.
CustomFace
(
flashTroopPic
=
ImMsgBody
.
CustomFace
(
filePath
=
image
.
filepath
,
filePath
=
image
.
imageId
,
md5
=
image
.
md5
,
md5
=
image
.
md5
,
pbReserve
=
byteArrayOf
(
0
x78
,
0
x06
)
pbReserve
=
byteArrayOf
(
0
x78
,
0
x06
)
)
)
...
@@ -27,9 +28,8 @@ internal fun FriendFlashImage.toJceData() = ImMsgBody.Elem(
...
@@ -27,9 +28,8 @@ internal fun FriendFlashImage.toJceData() = ImMsgBody.Elem(
businessType
=
0
,
businessType
=
0
,
pbElem
=
HummerCommelem
.
MsgElemInfoServtype3
(
pbElem
=
HummerCommelem
.
MsgElemInfoServtype3
(
flashC2cPic
=
ImMsgBody
.
NotOnlineImage
(
flashC2cPic
=
ImMsgBody
.
NotOnlineImage
(
filePath
=
image
.
filepath
,
filePath
=
image
.
imageId
,
fileId
=
image
.
fileId
,
resId
=
image
.
imageId
,
resId
=
image
.
resourceId
,
picMd5
=
image
.
md5
,
picMd5
=
image
.
md5
,
oldPicMd5
=
false
,
oldPicMd5
=
false
,
pbReserve
=
byteArrayOf
(
0
x78
,
0
x06
)
pbReserve
=
byteArrayOf
(
0
x78
,
0
x06
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
View file @
5b2ae6e9
...
@@ -9,10 +9,7 @@
...
@@ -9,10 +9,7 @@
package
net.mamoe.mirai.qqandroid.message
package
net.mamoe.mirai.qqandroid.message
import
net.mamoe.mirai.message.data.OfflineFriendImage
import
net.mamoe.mirai.message.data.*
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.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.utils.hexToBytes
import
net.mamoe.mirai.qqandroid.utils.hexToBytes
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.ExternalImage
...
@@ -20,28 +17,12 @@ import net.mamoe.mirai.utils.ExternalImage
...
@@ -20,28 +17,12 @@ import net.mamoe.mirai.utils.ExternalImage
internal
class
OnlineGroupImageImpl
(
internal
class
OnlineGroupImageImpl
(
internal
val
delegate
:
ImMsgBody
.
CustomFace
internal
val
delegate
:
ImMsgBody
.
CustomFace
)
:
OnlineGroupImage
()
{
)
:
OnlineGroupImage
()
{
override
val
filepath
:
String
=
delegate
.
filePath
override
val
imageId
:
String
=
ExternalImage
.
generateImageId
(
delegate
.
md5
)
override
val
fileId
:
Int
get
()
=
delegate
.
fileId
override
val
serverIp
:
Int
get
()
=
delegate
.
serverIp
override
val
serverPort
:
Int
get
()
=
delegate
.
serverPort
override
val
fileType
:
Int
get
()
=
delegate
.
fileType
override
val
signature
:
ByteArray
get
()
=
delegate
.
signature
override
val
useful
:
Int
get
()
=
delegate
.
useful
override
val
md5
:
ByteArray
get
()
=
delegate
.
md5
override
val
bizType
:
Int
get
()
=
delegate
.
bizType
override
val
imageType
:
Int
get
()
=
delegate
.
imageType
override
val
width
:
Int
get
()
=
delegate
.
width
override
val
height
:
Int
get
()
=
delegate
.
height
override
val
source
:
Int
get
()
=
delegate
.
source
override
val
size
:
Int
get
()
=
delegate
.
size
override
val
original
:
Int
get
()
=
delegate
.
origin
override
val
pbReserve
:
ByteArray
get
()
=
delegate
.
pbReserve
override
val
imageId
:
String
=
ExternalImage
.
generateImageId
(
delegate
.
md5
,
imageType
)
override
val
originUrl
:
String
override
val
originUrl
:
String
get
()
=
"http://gchat.qpic.cn"
+
delegate
.
origUrl
get
()
=
"http://gchat.qpic.cn"
+
delegate
.
origUrl
override
fun
equals
(
other
:
Any
?):
Boolean
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
return
other
is
OnlineGroupImageImpl
&&
other
.
filepath
==
this
.
filepath
&&
other
.
md5
.
contentEquals
(
this
.
md5
)
return
other
is
OnlineGroupImageImpl
&&
other
.
imageId
==
this
.
imageId
}
}
override
fun
hashCode
():
Int
{
override
fun
hashCode
():
Int
{
...
@@ -52,23 +33,13 @@ internal class OnlineGroupImageImpl(
...
@@ -52,23 +33,13 @@ internal class OnlineGroupImageImpl(
internal
class
OnlineFriendImageImpl
(
internal
class
OnlineFriendImageImpl
(
internal
val
delegate
:
ImMsgBody
.
NotOnlineImage
internal
val
delegate
:
ImMsgBody
.
NotOnlineImage
)
:
OnlineFriendImage
()
{
)
:
OnlineFriendImage
()
{
override
val
resourceId
:
String
get
()
=
delegate
.
resId
override
val
imageId
:
String
get
()
=
delegate
.
resId
override
val
md5
:
ByteArray
get
()
=
delegate
.
picMd5
override
val
filepath
:
String
get
()
=
delegate
.
filePath
override
val
fileLength
:
Int
get
()
=
delegate
.
fileLen
override
val
height
:
Int
get
()
=
delegate
.
picHeight
override
val
width
:
Int
get
()
=
delegate
.
picWidth
override
val
bizType
:
Int
get
()
=
delegate
.
bizType
override
val
imageType
:
Int
get
()
=
delegate
.
imgType
override
val
downloadPath
:
String
get
()
=
delegate
.
downloadPath
override
val
fileId
:
Int
get
()
=
delegate
.
fileId
override
val
original
:
Int
get
()
=
delegate
.
original
override
val
original
:
Int
get
()
=
delegate
.
original
override
val
originUrl
:
String
override
val
originUrl
:
String
get
()
=
"http://c2cpicdw.qpic.cn"
+
this
.
delegate
.
origUrl
get
()
=
"http://c2cpicdw.qpic.cn"
+
this
.
delegate
.
origUrl
override
fun
equals
(
other
:
Any
?):
Boolean
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
return
other
is
OnlineFriendImageImpl
&&
other
.
resourceId
==
this
.
resourceId
&&
other
.
md5
return
other
is
OnlineFriendImageImpl
&&
other
.
imageId
==
this
.
imageId
.
contentEquals
(
this
.
md5
)
}
}
override
fun
hashCode
():
Int
{
override
fun
hashCode
():
Int
{
...
@@ -78,22 +49,8 @@ internal class OnlineFriendImageImpl(
...
@@ -78,22 +49,8 @@ internal class OnlineFriendImageImpl(
internal
fun
OfflineGroupImage
.
toJceData
():
ImMsgBody
.
CustomFace
{
internal
fun
OfflineGroupImage
.
toJceData
():
ImMsgBody
.
CustomFace
{
return
ImMsgBody
.
CustomFace
(
return
ImMsgBody
.
CustomFace
(
filePath
=
this
.
filepath
,
filePath
=
this
.
imageId
,
fileId
=
this
.
fileId
,
serverIp
=
this
.
serverIp
,
serverPort
=
this
.
serverPort
,
fileType
=
this
.
fileType
,
signature
=
this
.
signature
,
useful
=
this
.
useful
,
md5
=
this
.
md5
,
md5
=
this
.
md5
,
bizType
=
this
.
bizType
,
imageType
=
this
.
imageType
,
width
=
this
.
width
,
height
=
this
.
height
,
source
=
this
.
source
,
size
=
this
.
size
,
origin
=
this
.
original
,
pbReserve
=
this
.
pbReserve
,
flag
=
ByteArray
(
4
),
flag
=
ByteArray
(
4
),
//_400Height = 235,
//_400Height = 235,
//_400Url = "/gchatpic_new/1040400290/1041235568-2195821338-01E9451B70EDEAE3B37C101F1EEBF5B5/400?term=2",
//_400Url = "/gchatpic_new/1040400290/1041235568-2195821338-01E9451B70EDEAE3B37C101F1EEBF5B5/400?term=2",
...
@@ -108,18 +65,12 @@ private val oldData: ByteArray =
...
@@ -108,18 +65,12 @@ private val oldData: ByteArray =
internal
fun
OfflineFriendImage
.
toJceData
():
ImMsgBody
.
NotOnlineImage
{
internal
fun
OfflineFriendImage
.
toJceData
():
ImMsgBody
.
NotOnlineImage
{
return
ImMsgBody
.
NotOnlineImage
(
return
ImMsgBody
.
NotOnlineImage
(
filePath
=
this
.
filepath
,
filePath
=
this
.
imageId
,
resId
=
this
.
resourc
eId
,
resId
=
this
.
imag
eId
,
oldPicMd5
=
false
,
oldPicMd5
=
false
,
picMd5
=
this
.
md5
,
picMd5
=
this
.
md5
,
fileLen
=
this
.
fileLength
,
downloadPath
=
this
.
imageId
,
picHeight
=
this
.
height
,
original
=
1
,
picWidth
=
this
.
width
,
bizType
=
this
.
bizType
,
imgType
=
this
.
imageType
,
downloadPath
=
this
.
downloadPath
,
original
=
this
.
original
,
fileId
=
this
.
fileId
,
pbReserve
=
byteArrayOf
(
0
x78
,
0
x02
)
pbReserve
=
byteArrayOf
(
0
x78
,
0
x02
)
)
)
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
5b2ae6e9
...
@@ -28,7 +28,6 @@ import net.mamoe.mirai.qqandroid.utils.cryptor.ECDH
...
@@ -28,7 +28,6 @@ import net.mamoe.mirai.qqandroid.utils.cryptor.ECDH
import
net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import
net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
kotlin.random.Random
import
kotlin.random.Random
import
kotlin.random.nextInt
internal
val
DeviceInfo
.
guid
:
ByteArray
get
()
=
generateGuid
(
androidId
,
macAddress
)
internal
val
DeviceInfo
.
guid
:
ByteArray
get
()
=
generateGuid
(
androidId
,
macAddress
)
...
@@ -43,7 +42,7 @@ private fun generateGuid(androidId: ByteArray, macAddress: ByteArray): ByteArray
...
@@ -43,7 +42,7 @@ private fun generateGuid(androidId: ByteArray, macAddress: ByteArray): ByteArray
/**
/**
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
*/
*/
internal
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
internal
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
,
255
).
toByte
()
}
internal
object
DefaultServerList
:
Set
<
Pair
<
String
,
Int
>>
by
setOf
(
internal
object
DefaultServerList
:
Set
<
Pair
<
String
,
Int
>>
by
setOf
(
"42.81.169.46"
to
8080
,
"42.81.169.46"
to
8080
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x352.kt
View file @
5b2ae6e9
...
@@ -129,8 +129,8 @@ internal class Cmd0x352 : ProtoBuf {
...
@@ -129,8 +129,8 @@ internal class Cmd0x352 : ProtoBuf {
@ProtoId
(
11
)
@JvmField
val
retry
:
Int
=
0
,
//default
@ProtoId
(
11
)
@JvmField
val
retry
:
Int
=
0
,
//default
@ProtoId
(
12
)
@JvmField
val
buType
:
Int
=
1
,
//1或96 不确定
@ProtoId
(
12
)
@JvmField
val
buType
:
Int
=
1
,
//1或96 不确定
@ProtoId
(
13
)
@JvmField
val
imgOriginal
:
Int
,
//是否为原图
@ProtoId
(
13
)
@JvmField
val
imgOriginal
:
Int
,
//是否为原图
@ProtoId
(
14
)
@JvmField
val
imgWidth
:
Int
,
@ProtoId
(
14
)
@JvmField
val
imgWidth
:
Int
=
0
,
@ProtoId
(
15
)
@JvmField
val
imgHeight
:
Int
,
@ProtoId
(
15
)
@JvmField
val
imgHeight
:
Int
=
0
,
/**
/**
* ImgType:
* ImgType:
* JPG: 1000
* JPG: 1000
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt
View file @
5b2ae6e9
...
@@ -19,6 +19,19 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
...
@@ -19,6 +19,19 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import
net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
import
net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
import
kotlin.random.Random
import
kotlin.random.nextInt
internal
fun
getRandomString
(
length
:
Int
):
String
=
getRandomString
(
length
,
*
defaultRanges
)
private
val
defaultRanges
:
Array
<
CharRange
>
=
arrayOf
(
'a'
..
'z'
,
'A'
..
'Z'
,
'0'
..
'9'
)
internal
fun
getRandomString
(
length
:
Int
,
charRange
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRange
.
random
()
})
internal
fun
getRandomString
(
length
:
Int
,
vararg
charRanges
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRanges
[
Random
.
Default
.
nextInt
(
0
..
charRanges
.
lastIndex
)].
random
()
})
internal
class
ImgStore
{
internal
class
ImgStore
{
object
GroupPicUp
:
OutgoingPacketFactory
<
GroupPicUp
.
Response
>(
"ImgStore.GroupPicUp"
)
{
object
GroupPicUp
:
OutgoingPacketFactory
<
GroupPicUp
.
Response
>(
"ImgStore.GroupPicUp"
)
{
...
@@ -33,7 +46,7 @@ internal class ImgStore {
...
@@ -33,7 +46,7 @@ internal class ImgStore {
picHeight
:
Int
=
0
,
// not orthodox
picHeight
:
Int
=
0
,
// not orthodox
picType
:
Int
=
1000
,
picType
:
Int
=
1000
,
fileId
:
Long
=
0
,
fileId
:
Long
=
0
,
filename
:
String
,
filename
:
String
=
getRandomString
(
16
)
+
".gif"
,
// make server happier
srcTerm
:
Int
=
5
,
srcTerm
:
Int
=
5
,
platformType
:
Int
=
9
,
platformType
:
Int
=
9
,
buType
:
Int
=
1
,
buType
:
Int
=
1
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
View file @
5b2ae6e9
...
@@ -15,12 +15,12 @@
...
@@ -15,12 +15,12 @@
package
net.mamoe.mirai.message.data
package
net.mamoe.mirai.message.data
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.BotImpl
import
net.mamoe.mirai.BotImpl
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.SinceMirai
import
kotlin.js.JsName
import
kotlin.js.JsName
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmName
...
@@ -65,7 +65,18 @@ expect interface Image : Message, MessageContent {
...
@@ -65,7 +65,18 @@ expect interface Image : Message, MessageContent {
@Suppress
(
"FunctionName"
)
@Suppress
(
"FunctionName"
)
@JsName
(
"newImage"
)
@JsName
(
"newImage"
)
@JvmName
(
"newImage"
)
@JvmName
(
"newImage"
)
fun
Image
(
imageId
:
String
):
Image
=
when
{
fun
Image
(
imageId
:
String
):
OfflineImage
=
when
{
imageId
.
startsWith
(
'/'
)
->
OfflineFriendImage
(
imageId
)
// /f8f1ab55-bf8e-4236-b55e-955848d7069f
imageId
.
length
==
42
||
imageId
.
startsWith
(
'{'
)
&&
imageId
.
endsWith
(
'}'
)
->
OfflineGroupImage
(
imageId
)
// {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
else
->
throw
IllegalArgumentException
(
"illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE"
)
}
@JvmSynthetic
@Deprecated
(
"for binary compatibility"
,
level
=
DeprecationLevel
.
HIDDEN
)
@Suppress
(
"FunctionName"
)
@JsName
(
"newImage"
)
@JvmName
(
"newImage"
)
fun
Image2
(
imageId
:
String
):
Image
=
when
{
imageId
.
startsWith
(
'/'
)
->
OfflineFriendImage
(
imageId
)
// /f8f1ab55-bf8e-4236-b55e-955848d7069f
imageId
.
startsWith
(
'/'
)
->
OfflineFriendImage
(
imageId
)
// /f8f1ab55-bf8e-4236-b55e-955848d7069f
imageId
.
length
==
42
||
imageId
.
startsWith
(
'{'
)
&&
imageId
.
endsWith
(
'}'
)
->
OfflineGroupImage
(
imageId
)
// {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
imageId
.
length
==
42
||
imageId
.
startsWith
(
'{'
)
&&
imageId
.
endsWith
(
'}'
)
->
OfflineGroupImage
(
imageId
)
// {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
else
->
throw
IllegalArgumentException
(
"illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE"
)
else
->
throw
IllegalArgumentException
(
"illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE"
)
...
@@ -100,8 +111,7 @@ sealed class AbstractImage : Image {
...
@@ -100,8 +111,7 @@ sealed class AbstractImage : Image {
*/
*/
interface
OnlineImage
:
Image
{
interface
OnlineImage
:
Image
{
companion
object
Key
:
Message
.
Key
<
OnlineImage
>
{
companion
object
Key
:
Message
.
Key
<
OnlineImage
>
{
override
val
typeName
:
String
override
val
typeName
:
String
get
()
=
"OnlineImage"
get
()
=
"OnlineImage"
}
}
/**
/**
...
@@ -113,6 +123,7 @@ interface OnlineImage : Image {
...
@@ -113,6 +123,7 @@ interface OnlineImage : Image {
/**
/**
* 查询原图下载链接.
* 查询原图下载链接.
*/
*/
@JvmSynthetic
suspend
fun
Image
.
queryUrl
():
String
{
suspend
fun
Image
.
queryUrl
():
String
{
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
return
when
(
this
)
{
return
when
(
this
)
{
...
@@ -135,8 +146,7 @@ suspend fun Image.queryUrl(): String {
...
@@ -135,8 +146,7 @@ suspend fun Image.queryUrl(): String {
*/
*/
interface
OfflineImage
:
Image
{
interface
OfflineImage
:
Image
{
companion
object
Key
:
Message
.
Key
<
OfflineImage
>
{
companion
object
Key
:
Message
.
Key
<
OfflineImage
>
{
override
val
typeName
:
String
override
val
typeName
:
String
get
()
=
"OfflineImage"
get
()
=
"OfflineImage"
}
}
}
}
...
@@ -163,26 +173,8 @@ suspend fun OfflineImage.queryUrl(): String {
...
@@ -163,26 +173,8 @@ suspend fun OfflineImage.queryUrl(): String {
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
sealed
class
GroupImage
:
AbstractImage
()
{
sealed
class
GroupImage
:
AbstractImage
()
{
companion
object
Key
:
Message
.
Key
<
GroupImage
>
{
companion
object
Key
:
Message
.
Key
<
GroupImage
>
{
override
val
typeName
:
String
override
val
typeName
:
String
get
()
=
"GroupImage"
get
()
=
"GroupImage"
}
}
abstract
val
filepath
:
String
abstract
val
fileId
:
Int
abstract
val
serverIp
:
Int
abstract
val
serverPort
:
Int
abstract
val
fileType
:
Int
abstract
val
signature
:
ByteArray
abstract
val
useful
:
Int
abstract
val
md5
:
ByteArray
abstract
val
bizType
:
Int
abstract
val
imageType
:
Int
abstract
val
width
:
Int
abstract
val
height
:
Int
abstract
val
source
:
Int
abstract
val
size
:
Int
abstract
val
pbReserve
:
ByteArray
abstract
val
original
:
Int
}
}
/**
/**
...
@@ -190,35 +182,13 @@ sealed class GroupImage : AbstractImage() {
...
@@ -190,35 +182,13 @@ sealed class GroupImage : AbstractImage() {
*/
*/
@Serializable
@Serializable
data class
OfflineGroupImage
(
data class
OfflineGroupImage
(
override
val
filepath
:
String
,
// {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
override
val
imageId
:
String
override
val
md5
:
ByteArray
)
:
GroupImage
(),
OfflineImage
)
:
GroupImage
(),
OfflineImage
{
constructor
(
imageId
:
String
)
:
this
(
filepath
=
imageId
,
md5
=
calculateImageMd5ByImageId
(
imageId
))
override
val
fileId
:
Int
get
()
=
0
override
val
serverIp
:
Int
get
()
=
0
override
val
serverPort
:
Int
get
()
=
0
override
val
fileType
:
Int
get
()
=
0
// 0
override
val
signature
:
ByteArray
get
()
=
EMPTY_BYTE_ARRAY
override
val
useful
:
Int
get
()
=
1
override
val
bizType
:
Int
get
()
=
0
override
val
imageType
:
Int
get
()
=
0
override
val
width
:
Int
get
()
=
0
override
val
height
:
Int
get
()
=
0
override
val
source
:
Int
get
()
=
200
override
val
size
:
Int
get
()
=
0
override
val
original
:
Int
get
()
=
1
override
val
pbReserve
:
ByteArray
get
()
=
EMPTY_BYTE_ARRAY
override
val
imageId
:
String
get
()
=
filepath
override
fun
hashCode
():
Int
{
return
filepath
.
hashCode
()
+
31
*
md5
.
hashCode
()
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
@
get
:
JvmName
(
"calculateImageMd5"
)
return
other
is
OfflineGroupImage
&&
other
::
class
== this::class && other.md5.content
Equals
(
this
.
md5
)
&&
other
.
filepath
==
this
.
filepath
@SinceMirai
(
"0.39.0"
)
}
val
Image
.
md5
:
ByteArray
}
get
()
=
calculateImageMd5ByImageId
(
imageId
)
/**
/**
* 接收消息时获取到的 [GroupImage]. 它可以直接获取下载链接 [originUrl]
* 接收消息时获取到的 [GroupImage]. 它可以直接获取下载链接 [originUrl]
...
@@ -239,51 +209,19 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage
...
@@ -239,51 +209,19 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
sealed
class
FriendImage
:
AbstractImage
()
{
sealed
class
FriendImage
:
AbstractImage
()
{
companion
object
Key
:
Message
.
Key
<
FriendImage
>
{
companion
object
Key
:
Message
.
Key
<
FriendImage
>
{
override
val
typeName
:
String
override
val
typeName
:
String
get
()
=
"FriendImage"
get
()
=
"FriendImage"
}
}
abstract
val
resourceId
:
String
abstract
val
md5
:
ByteArray
abstract
val
filepath
:
String
abstract
val
fileLength
:
Int
abstract
val
height
:
Int
abstract
val
width
:
Int
open
val
bizType
:
Int
get
()
=
0
open
val
imageType
:
Int
get
()
=
1000
abstract
val
fileId
:
Int
open
val
downloadPath
:
String
get
()
=
resourceId
open
val
original
:
Int
get
()
=
1
open
val
original
:
Int
get
()
=
1
override
val
imageId
:
String
get
()
=
resourceId
}
}
/**
/**
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
*/
*/
@Serializable
data class
OfflineFriendImage
(
data class
OfflineFriendImage
(
override
val
resourceId
:
String
,
override
val
imageId
:
String
override
val
md5
:
ByteArray
,
)
:
FriendImage
(),
OfflineImage
@Transient
override
val
filepath
:
String
=
resourceId
,
@Transient
override
val
fileLength
:
Int
=
0
,
@Transient
override
val
height
:
Int
=
0
,
@Transient
override
val
width
:
Int
=
0
,
@Transient
override
val
bizType
:
Int
=
0
,
@Transient
override
val
imageType
:
Int
=
1000
,
@Transient
override
val
downloadPath
:
String
=
resourceId
,
@Transient
override
val
fileId
:
Int
=
0
)
:
FriendImage
(),
OfflineImage
{
constructor
(
imageId
:
String
)
:
this
(
resourceId
=
imageId
,
md5
=
calculateImageMd5ByImageId
(
imageId
))
override
fun
hashCode
():
Int
{
return
resourceId
.
hashCode
()
+
31
*
md5
.
hashCode
()
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
return
other
is
OfflineFriendImage
&&
other
::
class
== this::class &&
other.md5.content
Equals
(
this
.
md5
)
&&
other
.
resourceId
==
this
.
resourceId
}
}
/**
/**
* 接收消息时获取到的 [FriendImage]. 它可以直接获取下载链接 [originUrl]
* 接收消息时获取到的 [FriendImage]. 它可以直接获取下载链接 [originUrl]
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
View file @
5b2ae6e9
...
@@ -23,6 +23,7 @@ import net.mamoe.mirai.message.MessageReceipt
...
@@ -23,6 +23,7 @@ import net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.OfflineImage
import
net.mamoe.mirai.message.data.OfflineImage
import
net.mamoe.mirai.message.data.sendTo
import
net.mamoe.mirai.message.data.sendTo
import
net.mamoe.mirai.message.data.toLongUnsigned
import
kotlin.jvm.JvmSynthetic
import
kotlin.jvm.JvmSynthetic
/**
/**
...
@@ -34,52 +35,32 @@ import kotlin.jvm.JvmSynthetic
...
@@ -34,52 +35,32 @@ import kotlin.jvm.JvmSynthetic
* @See ExternalImage.upload 上传图片并得到 [Image] 消息
* @See ExternalImage.upload 上传图片并得到 [Image] 消息
*/
*/
class
ExternalImage
private
constructor
(
class
ExternalImage
private
constructor
(
val
width
:
Int
,
val
height
:
Int
,
val
md5
:
ByteArray
,
val
md5
:
ByteArray
,
imageFormat
:
String
,
val
input
:
Any
,
// Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
val
input
:
Any
,
// Input from kotlinx.io, InputStream from kotlinx.io MPP, ByteReadChannel from ktor
val
inputSize
:
Long
,
// dont be greater than Int.MAX
val
inputSize
:
Long
// dont be greater than Int.MAX
val
filename
:
String
)
{
)
{
constructor
(
constructor
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
md5
:
ByteArray
,
imageFormat
:
String
,
input
:
ByteReadChannel
,
input
:
ByteReadChannel
,
inputSize
:
Long
,
// dont be greater than Int.MAX
inputSize
:
Long
// dont be greater than Int.MAX
filename
:
String
)
:
this
(
md5
,
input
as
Any
,
inputSize
)
)
:
this
(
width
,
height
,
md5
,
imageFormat
,
input
as
Any
,
inputSize
,
filename
)
constructor
(
constructor
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
md5
:
ByteArray
,
imageFormat
:
String
,
input
:
Input
,
input
:
Input
,
inputSize
:
Long
,
// dont be greater than Int.MAX
inputSize
:
Long
// dont be greater than Int.MAX
filename
:
String
)
:
this
(
md5
,
input
as
Any
,
inputSize
)
)
:
this
(
width
,
height
,
md5
,
imageFormat
,
input
as
Any
,
inputSize
,
filename
)
constructor
(
constructor
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
md5
:
ByteArray
,
imageFormat
:
String
,
input
:
ByteReadPacket
input
:
ByteReadPacket
,
)
:
this
(
md5
,
input
as
Any
,
input
.
remaining
)
filename
:
String
)
:
this
(
width
,
height
,
md5
,
imageFormat
,
input
as
Any
,
input
.
remaining
,
filename
)
@OptIn
(
InternalSerializationApi
::
class
)
@OptIn
(
InternalSerializationApi
::
class
)
constructor
(
constructor
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
md5
:
ByteArray
,
imageFormat
:
String
,
input
:
InputStream
input
:
InputStream
,
)
:
this
(
md5
,
input
as
Any
,
input
.
available
().
toLongUnsigned
())
filename
:
String
)
:
this
(
width
,
height
,
md5
,
imageFormat
,
input
as
Any
,
input
.
available
().
toLong
(),
filename
)
init
{
init
{
require
(
inputSize
<
30L
*
1024
*
1024
)
{
"file is too big. Maximum is about 20MB"
}
require
(
inputSize
<
30L
*
1024
*
1024
)
{
"file is too big. Maximum is about 20MB"
}
...
@@ -87,63 +68,30 @@ class ExternalImage private constructor(
...
@@ -87,63 +68,30 @@ class ExternalImage private constructor(
companion
object
{
companion
object
{
fun
generateUUID
(
md5
:
ByteArray
):
String
{
fun
generateUUID
(
md5
:
ByteArray
):
String
{
return
"${md5[0
..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..
15]}"
return
"${md5[0
, 3]}-${md5[4, 5]}-${md5[6, 7]}-${md5[8, 9]}-${md5[10,
15]}"
}
}
fun
generateImageId
(
md5
:
ByteArray
,
imageType
:
Int
):
String
{
fun
generateImageId
(
md5
:
ByteArray
):
String
{
return
"""{${generateUUID(md5)}}.${determineFormat(imageType)}"""
return
"""{${generateUUID(md5)}}.gif"""
}
fun
determineImageType
(
format
:
String
):
Int
{
return
when
(
format
)
{
"jpg"
->
1000
"png"
->
1001
"webp"
->
1002
"bmp"
->
1005
"gig"
->
2000
"apng"
->
2001
"sharpp"
->
1004
else
->
1000
// unsupported, just make it jpg
}
}
fun
determineFormat
(
imageType
:
Int
):
String
{
return
when
(
imageType
)
{
1000
->
"jpg"
1001
->
"png"
1002
->
"webp"
1005
->
"bmp"
2000
->
"gig"
2001
->
"apng"
1004
->
"sharpp"
else
->
"jpg"
// unsupported, just make it jpg
}
}
}
}
}
val
format
:
String
=
/*
when
(
val
it
=
imageFormat
.
toLowerCase
())
{
"jpeg"
->
"jpg"
//必须转换
else
->
it
}
/**
* ImgType:
* ImgType:
* JPG: 1000
* JPG: 1000
* PNG: 1001
* PNG: 1001
* WEBP: 1002
* WEBP: 1002
* BMP: 1005
* BMP: 1005
* GIG: 2000 //
TODO
gig? gif?
* GIG: 2000 // gig? gif?
* APNG: 2001
* APNG: 2001
* SHARPP: 1004
* SHARPP: 1004
*/
*/
val
imageType
:
Int
get
()
=
determineImageType
(
format
)
override
fun
toString
():
String
=
"[ExternalImage(${width}x$height $format)]"
override
fun
toString
():
String
=
"[ExternalImage(${generateUUID(md5)})]"
fun
calculateImageResourceId
():
String
{
fun
calculateImageResourceId
():
String
{
return
"{${generateUUID(md5)}}.
$format
"
return
"{${generateUUID(md5)}}.
gif
"
}
}
}
}
...
@@ -176,8 +124,8 @@ suspend fun ExternalImage.upload(contact: Contact): OfflineImage = when (contact
...
@@ -176,8 +124,8 @@ suspend fun ExternalImage.upload(contact: Contact): OfflineImage = when (contact
@JvmSynthetic
@JvmSynthetic
suspend
inline
fun
<
C
:
Contact
>
C
.
sendImage
(
image
:
ExternalImage
):
MessageReceipt
<
C
>
=
image
.
sendTo
(
this
)
suspend
inline
fun
<
C
:
Contact
>
C
.
sendImage
(
image
:
ExternalImage
):
MessageReceipt
<
C
>
=
image
.
sendTo
(
this
)
internal
operator
fun
ByteArray
.
get
(
range
:
IntRange
):
String
=
buildString
{
internal
operator
fun
ByteArray
.
get
(
range
Start
:
Int
,
rangeEnd
:
Int
):
String
=
buildString
{
range
.
forEach
{
for
(
it
in
rangeStart
..
rangeEnd
)
{
append
(
this
@
get
[
it
].
fixToString
())
append
(
this
@
get
[
it
].
fixToString
())
}
}
}
}
...
...
mirai-core/src/commonTest/kotlin/net/mamoe/mirai/utils/ExternalImageTest.kt
View file @
5b2ae6e9
...
@@ -7,8 +7,8 @@ internal class ExternalImageTest {
...
@@ -7,8 +7,8 @@ internal class ExternalImageTest {
@Test
@Test
fun
testByteArrayGet
()
{
fun
testByteArrayGet
()
{
assertEquals
(
"0F"
,
byteArrayOf
(
0
x0f
)[
0
..
0
])
assertEquals
(
"0F"
,
byteArrayOf
(
0
x0f
)[
0
,
0
])
assertEquals
(
"10"
,
byteArrayOf
(
0
x10
)[
0
..
0
])
assertEquals
(
"10"
,
byteArrayOf
(
0
x10
)[
0
,
0
])
assertEquals
(
"0FFE"
,
byteArrayOf
(
0
x0F
,
0
xFE
.
toByte
())[
0
..
1
])
assertEquals
(
"0FFE"
,
byteArrayOf
(
0
x0F
,
0
xFE
.
toByte
())[
0
,
1
])
}
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
View file @
5b2ae6e9
...
@@ -43,8 +43,7 @@ import java.net.URL
...
@@ -43,8 +43,7 @@ import java.net.URL
*/
*/
actual
interface
Image
:
Message
,
MessageContent
{
actual
interface
Image
:
Message
,
MessageContent
{
actual
companion
object
Key
:
Message
.
Key
<
Image
>
{
actual
companion
object
Key
:
Message
.
Key
<
Image
>
{
actual
override
val
typeName
:
String
actual
override
val
typeName
:
String
get
()
=
"Image"
get
()
=
"Image"
}
}
/**
/**
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
View file @
5b2ae6e9
...
@@ -15,7 +15,6 @@ import kotlinx.coroutines.Dispatchers.IO
...
@@ -15,7 +15,6 @@ import kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.coroutines.io.ByteReadChannel
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.withContext
import
kotlinx.io.core.Input
import
kotlinx.io.core.Input
import
kotlinx.io.core.buildPacket
import
kotlinx.io.core.copyTo
import
kotlinx.io.core.copyTo
import
kotlinx.io.errors.IOException
import
kotlinx.io.errors.IOException
import
kotlinx.io.streams.asOutput
import
kotlinx.io.streams.asOutput
...
@@ -34,49 +33,49 @@ import javax.imageio.ImageIO
...
@@ -34,49 +33,49 @@ import javax.imageio.ImageIO
/**
/**
*
读取 [BufferedImage] 的属性
, 然后构造 [ExternalImage]
*
将 [BufferedImage] 保存稳临时文件
, 然后构造 [ExternalImage]
*/
*/
@JvmOverloads
@JvmOverloads
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
BufferedImage
.
toExternalImage
(
formatName
:
String
=
"gif"
):
ExternalImage
{
fun
BufferedImage
.
toExternalImage
(
formatName
:
String
=
"gif"
):
ExternalImage
{
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
val
digest
=
MessageDigest
.
getInstance
(
"md5"
)
digest
.
reset
()
digest
.
reset
()
val
buffer
=
buildPacket
{
file
.
outputStream
().
use
{
out
->
ImageIO
.
write
(
this
@
toExternalImage
,
formatName
,
object
:
OutputStream
()
{
ImageIO
.
write
(
this
@
toExternalImage
,
formatName
,
object
:
OutputStream
()
{
override
fun
write
(
b
:
Int
)
{
override
fun
write
(
b
:
Int
)
{
b
.
toByte
().
let
{
out
.
write
(
b
)
this
@
buildPacket
.
writeByte
(
it
)
digest
.
update
(
b
.
toByte
())
digest
.
update
(
it
)
}
}
override
fun
write
(
b
:
ByteArray
)
{
out
.
write
(
b
)
digest
.
update
(
b
)
}
override
fun
write
(
b
:
ByteArray
,
off
:
Int
,
len
:
Int
)
{
out
.
write
(
b
,
off
,
len
)
digest
.
update
(
b
,
off
,
len
)
}
}
})
})
}
}
return
ExternalImage
(
width
,
height
,
digest
.
digest
(),
formatName
,
buffer
,
getRandomString
(
16
)
+
"."
+
formatName
)
return
ExternalImage
(
digest
.
digest
(),
file
.
inputStream
()
)
}
}
suspend
inline
fun
BufferedImage
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
inline
fun
BufferedImage
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
/**
/**
*
读取文件头识别图片属性, 然后
构造 [ExternalImage]
*
直接使用文件 [inputStream]
构造 [ExternalImage]
*/
*/
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
File
.
toExternalImage
():
ExternalImage
{
fun
File
.
toExternalImage
():
ExternalImage
{
val
input
=
ImageIO
.
createImageInputStream
(
this
)
checkNotNull
(
input
)
{
"Unable to read file(path=${this.path}), no ImageInputStream found"
}
val
image
=
ImageIO
.
getImageReaders
(
input
).
asSequence
().
firstOrNull
()
?:
error
(
"Unable to read file(path=${this.path}), no ImageReader found (file type not supported)"
)
image
.
input
=
input
return
ExternalImage
(
return
ExternalImage
(
width
=
image
.
getWidth
(
0
),
height
=
image
.
getHeight
(
0
),
md5
=
this
.
inputStream
().
md5
(),
// dont change
md5
=
this
.
inputStream
().
md5
(),
// dont change
imageFormat
=
image
.
formatName
,
input
=
this
.
inputStream
()
input
=
this
.
inputStream
(),
filename
=
this
.
name
)
)
}
}
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/SystemDeviceInfo.kt
View file @
5b2ae6e9
...
@@ -87,7 +87,9 @@ internal fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Ra
...
@@ -87,7 +87,9 @@ internal fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Ra
* 随机生成长度为 [length] 的 [String].
* 随机生成长度为 [length] 的 [String].
*/
*/
internal
fun
getRandomString
(
length
:
Int
):
String
=
internal
fun
getRandomString
(
length
:
Int
):
String
=
getRandomString
(
length
,
'a'
..
'z'
,
'A'
..
'Z'
,
'0'
..
'9'
)
getRandomString
(
length
,
*
defaultRanges
)
private
val
defaultRanges
:
Array
<
CharRange
>
=
arrayOf
(
'a'
..
'z'
,
'A'
..
'Z'
,
'0'
..
'9'
)
/**
/**
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
...
...
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