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
07788546
Commit
07788546
authored
Apr 24, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add docs, rearrange implementations
parent
92a1b0d4
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
164 additions
and
73 deletions
+164
-73
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
...in/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
.../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
+5
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
...c/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
+81
-17
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
...commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
+15
-28
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
...nMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
+5
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt
...rc/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt
+30
-10
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
.../src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
+27
-8
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/imagesImpl.kt
View file @
07788546
...
@@ -34,9 +34,9 @@ internal class OnlineFriendImageImpl(
...
@@ -34,9 +34,9 @@ internal class OnlineFriendImageImpl(
internal
val
delegate
:
ImMsgBody
.
NotOnlineImage
internal
val
delegate
:
ImMsgBody
.
NotOnlineImage
)
:
OnlineFriendImage
()
{
)
:
OnlineFriendImage
()
{
override
val
imageId
:
String
get
()
=
delegate
.
resId
override
val
imageId
:
String
get
()
=
delegate
.
resId
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
// TODO: 2020/4/24 动态获取图片下载链接的 host
override
fun
equals
(
other
:
Any
?):
Boolean
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
return
other
is
OnlineFriendImageImpl
&&
other
.
imageId
==
this
.
imageId
return
other
is
OnlineFriendImageImpl
&&
other
.
imageId
==
this
.
imageId
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
View file @
07788546
...
@@ -72,13 +72,13 @@ abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot
...
@@ -72,13 +72,13 @@ abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot
/**
/**
* 上传一个图片以备发送.
* 上传一个图片以备发送.
*
*
* @see Image 查看更多信息
* @see Image 查看
有关图片的
更多信息
*
*
* @see BeforeImageUploadEvent 图片发送前事件,
cancellable
* @see BeforeImageUploadEvent 图片发送前事件,
可拦截.
* @see ImageUploadEvent 图片发送完成事件
* @see ImageUploadEvent 图片发送完成事件
, 不可拦截.
*
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws EventCancelledException 当发送消息事件被取消
时抛出
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时
. (最大大小约为 2
0 MB)
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时
抛出. (最大大小约为 20 MB, 但 mirai 限制的大小为 3
0 MB)
*/
*/
@JvmSynthetic
@JvmSynthetic
abstract
suspend
fun
uploadImage
(
image
:
ExternalImage
):
OfflineImage
abstract
suspend
fun
uploadImage
(
image
:
ExternalImage
):
OfflineImage
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
View file @
07788546
...
@@ -19,6 +19,7 @@ import net.mamoe.mirai.Bot
...
@@ -19,6 +19,7 @@ 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.ExternalImage
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.PlannedRemoval
import
net.mamoe.mirai.utils.PlannedRemoval
import
net.mamoe.mirai.utils.SinceMirai
import
net.mamoe.mirai.utils.SinceMirai
...
@@ -28,9 +29,23 @@ import kotlin.jvm.JvmName
...
@@ -28,9 +29,23 @@ import kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
import
kotlin.jvm.JvmSynthetic
/**
/**
* 自定义表情 (收藏的表情)
, 图片
* 自定义表情 (收藏的表情)
和普通图片.
*
*
* 查看平台 actual 定义以获取更多说明.
*
* 最推荐的存储方式是存储图片原文件, 每次发送图片时都使用文件上传.
* 在上传时服务器会根据其缓存情况回复已有的图片 ID 或要求客户端上传. 详见 [Contact.uploadImage]
*
*
* ### [toString] 和 [contentToString]
* - [toString] 固定返回 `[mirai:image:<ID>]` 格式字符串, 其中 `<ID>` 代表 [imageId].
* - [contentToString] 固定返回 `"[图片]"`
*
* ### 上传和发送图片
* @see Contact.uploadImage 上传 [图片文件][ExternalImage] 并得到 [Image] 消息
* @see Contact.sendImage 上传 [图片文件][ExternalImage] 并发送返回的 [Image] 作为一条消息
* @see Image.sendTo 上传图片并得到 [Image] 消息
*
* 查看平台 `actual` 定义以获取上传方式扩展.
*
*
* @see FlashImage 闪照
* @see FlashImage 闪照
* @see Image.flash 转换普通图片为闪照
* @see Image.flash 转换普通图片为闪照
...
@@ -42,15 +57,33 @@ expect interface Image : Message, MessageContent {
...
@@ -42,15 +57,33 @@ expect interface Image : Message, MessageContent {
/**
/**
* 图片的 id.
* 图片的 id.
* 图片 id 不一定会长时间保存, 因此不建议使用 id 发送图片.
*
*
* 示例:
* 图片 id 不一定会长时间保存, 也可能在将来改变格式, 因此不建议使用 id 发送图片.
* 好友图片的 id: `/f8f1ab55-bf8e-4236-b55e-955848d7069f` 或 `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
*
* 群图片的 id: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png`
* ### 格式
* 群图片:
* - [GROUP_IMAGE_ID_REGEX], 示例: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai` (后缀一定为 ".mirai")
*
* 好友图片:
* - [FRIEND_IMAGE_ID_REGEX_1], 示例: `/f8f1ab55-bf8e-4236-b55e-955848d7069f`
* - [FRIEND_IMAGE_ID_REGEX_2], 示例: `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
*
*
* @see Image 使用 id 构造图片
* @see Image 使用 id 构造图片
*/
*/
val
imageId
:
String
val
imageId
:
String
/* 实现:
final override fun toString(): String = _stringValue!!
final override fun contentToString(): String = "[图片]"
*/
@Deprecated
(
"""
不要自行实现 OnlineGroupImage, 它必须由协议模块实现, 否则会无法发送也无法解析.
"""
,
level
=
DeprecationLevel
.
HIDDEN
)
@Suppress
(
"PropertyName"
,
"DeprecatedCallableAddReplaceWith"
)
@
get
:
JvmSynthetic
val
DoNotImplementThisClass
:
Nothing
?
}
}
/**
/**
...
@@ -120,15 +153,29 @@ fun Image(imageId: String): OfflineImage = when {
...
@@ -120,15 +153,29 @@ fun Image(imageId: String): OfflineImage = when {
@JvmName
(
"newImage"
)
@JvmName
(
"newImage"
)
fun
Image2
(
imageId
:
String
):
Image
=
Image
(
imageId
)
fun
Image2
(
imageId
:
String
):
Image
=
Image
(
imageId
)
@MiraiInternalAPI
(
"使用 Image"
)
/**
* 所有 [Image] 实现的基类.
*/
@Deprecated
(
"This is internal API. Use Image instead"
,
level
=
DeprecationLevel
.
HIDDEN
,
// so that others can't see this class
replaceWith
=
ReplaceWith
(
"Image"
)
)
@MiraiInternalAPI
(
"Use Image instead"
)
sealed
class
AbstractImage
:
Image
{
sealed
class
AbstractImage
:
Image
{
@Deprecated
(
"""
不要自行实现 OnlineGroupImage, 它必须由协议模块实现, 否则会无法发送也无法解析.
"""
,
level
=
DeprecationLevel
.
HIDDEN
)
@Suppress
(
"PropertyName"
,
"DeprecatedCallableAddReplaceWith"
)
@
get
:
JvmSynthetic
final
override
val
DoNotImplementThisClass
:
Nothing
?
get
()
=
error
(
"stub"
)
private
var
_stringValue
:
String
?
=
null
private
var
_stringValue
:
String
?
=
null
get
()
{
get
()
=
field
?:
kotlin
.
run
{
return
field
?:
kotlin
.
run
{
field
=
"[mirai:image:$imageId]"
field
=
"[mirai:image:$imageId]"
field
field
}
}
}
override
val
length
:
Int
get
()
=
_stringValue
!!
.
length
override
val
length
:
Int
get
()
=
_stringValue
!!
.
length
override
fun
get
(
index
:
Int
):
Char
=
_stringValue
!!
[
index
]
override
fun
get
(
index
:
Int
):
Char
=
_stringValue
!!
[
index
]
...
@@ -205,8 +252,9 @@ suspend fun OfflineImage.queryUrl(): String {
...
@@ -205,8 +252,9 @@ suspend fun OfflineImage.queryUrl(): String {
/**
/**
* 群图片.
* 群图片.
*
*
* [imageId] 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.
png` (42
长度)
* [imageId] 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.
mirai` (45
长度)
*/
*/
@Suppress
(
"DEPRECATION_ERROR"
)
// CustomFace
// CustomFace
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
sealed
class
GroupImage
:
AbstractImage
()
{
sealed
class
GroupImage
:
AbstractImage
()
{
...
@@ -217,11 +265,20 @@ sealed class GroupImage : AbstractImage() {
...
@@ -217,11 +265,20 @@ sealed class GroupImage : AbstractImage() {
/**
/**
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
*
* @param imageId 参考 [Image.imageId]
*/
*/
@Serializable
@Serializable
data class
OfflineGroupImage
(
data class
OfflineGroupImage
(
override
val
imageId
:
String
override
val
imageId
:
String
)
:
GroupImage
(),
OfflineImage
)
:
GroupImage
(),
OfflineImage
{
init
{
@Suppress
(
"DEPRECATION"
)
require
(
imageId
matches
GROUP_IMAGE_ID_REGEX
||
imageId
matches
GROUP_IMAGE_ID_REGEX_OLD
)
{
"Illegal imageId. It must matches GROUP_IMAGE_ID_REGEX"
}
}
}
@
get
:
JvmName
(
"calculateImageMd5"
)
@
get
:
JvmName
(
"calculateImageMd5"
)
@SinceMirai
(
"0.39.0"
)
@SinceMirai
(
"0.39.0"
)
...
@@ -244,22 +301,29 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage
...
@@ -244,22 +301,29 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage
*
*
* [imageId] 形如 `/f8f1ab55-bf8e-4236-b55e-955848d7069f` (37 长度) 或 `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206` (54 长度)
* [imageId] 形如 `/f8f1ab55-bf8e-4236-b55e-955848d7069f` (37 长度) 或 `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206` (54 长度)
*/
// NotOnlineImage
*/
// NotOnlineImage
@Suppress
(
"DEPRECATION_ERROR"
)
@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
get
()
=
"FriendImage"
override
val
typeName
:
String
get
()
=
"FriendImage"
}
}
open
val
original
:
Int
get
()
=
1
}
}
/**
/**
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [Bot.queryImageUrl]
*
* @param imageId 参考 [Image.imageId]
*/
*/
@Serializable
@Serializable
data class
OfflineFriendImage
(
data class
OfflineFriendImage
(
override
val
imageId
:
String
override
val
imageId
:
String
)
:
FriendImage
(),
OfflineImage
)
:
FriendImage
(),
OfflineImage
{
init
{
require
(
imageId
matches
FRIEND_IMAGE_ID_REGEX_1
||
imageId
matches
FRIEND_IMAGE_ID_REGEX_2
)
{
"Illegal imageId. It must matches either FRIEND_IMAGE_ID_REGEX_1 or FRIEND_IMAGE_ID_REGEX_2"
}
}
}
/**
/**
* 接收消息时获取到的 [FriendImage]. 它可以直接获取下载链接 [originUrl]
* 接收消息时获取到的 [FriendImage]. 它可以直接获取下载链接 [originUrl]
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
View file @
07788546
...
@@ -13,6 +13,7 @@ package net.mamoe.mirai.message.data
...
@@ -13,6 +13,7 @@ package net.mamoe.mirai.message.data
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Message.Key
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.PlannedRemoval
import
net.mamoe.mirai.utils.PlannedRemoval
import
net.mamoe.mirai.utils.SinceMirai
import
net.mamoe.mirai.utils.SinceMirai
...
@@ -50,6 +51,9 @@ import kotlin.jvm.JvmSynthetic
...
@@ -50,6 +51,9 @@ import kotlin.jvm.JvmSynthetic
*
*
* 但注意: 不能 `String + Message`. 只能 `Message + String`
* 但注意: 不能 `String + Message`. 只能 `Message + String`
*
*
* #### 实现规范
* 除 [MessageChain] 外, 所有 [Message] 的实现类都有伴生对象实现 [Key] 接口.
*
* @see PlainText 纯文本
* @see PlainText 纯文本
* @see Image 图片
* @see Image 图片
* @see Face 原生表情
* @see Face 原生表情
...
@@ -68,10 +72,14 @@ import kotlin.jvm.JvmSynthetic
...
@@ -68,10 +72,14 @@ import kotlin.jvm.JvmSynthetic
@OptIn
(
MiraiInternalAPI
::
class
)
@OptIn
(
MiraiInternalAPI
::
class
)
interface
Message
{
interface
Message
{
/**
/**
* 类型 Key.
* 类型 Key. 由伴生对象实现, 表示一个 [Message] 对象的类型.
*
* 除 [MessageChain] 外, 每个 [Message] 类型都拥有一个`伴生对象`(companion object) 来持有一个 Key
* 除 [MessageChain] 外, 每个 [Message] 类型都拥有一个`伴生对象`(companion object) 来持有一个 Key
* 在 [MessageChain.get] 时将会使用到这个 Key 进行判断类型.
* 在 [MessageChain.get] 时将会使用到这个 Key 进行判断类型.
*
*
* #### 用例
* [MessageChain.get]: 允许使用数组访问操作符获取指定类型的消息元素 ```val image: Image = chain[Image]```
*
* @param M 指代持有这个 Key 的消息类型
* @param M 指代持有这个 Key 的消息类型
*/
*/
interface
Key
<
out
M
:
Message
>
{
interface
Key
<
out
M
:
Message
>
{
...
@@ -83,21 +91,23 @@ interface Message {
...
@@ -83,21 +91,23 @@ interface Message {
}
}
/**
/**
*
把 `this` 连接到 [tail] 的头部. 类似于字符串相加
.
*
将 `this` 和 [tail] 连接
.
*
*
* 连接后可以保证 [ConstrainSingle] 的元素单独存在.
* 连接后可以保证 [ConstrainSingle] 的元素单独存在.
*
*
* 例:
* 例:
* ```
kotlin
* ```
* val a = PlainText("Hello ")
* val a = PlainText("Hello ")
* val b = PlainText("world!")
* val b = PlainText("world!")
* val c:
CombinedMessage
= a + b
* val c:
MessageChain
= a + b
* println(c) // "Hello world!"
* println(c) // "Hello world!"
*
*
* val d = PlainText("world!")
* val d = PlainText("world!")
* val e = c + d; // PlainText + CombinedMessage
* val e = c + d; // PlainText + CombinedMessage
* println(c) // "Hello world!"
* println(c) // "Hello world!"
* ```
* ```
*
* @see plus `+` 操作符重载
*/
*/
@SinceMirai
(
"0.34.0"
)
@SinceMirai
(
"0.34.0"
)
@JvmSynthetic
// in java they should use `plus` instead
@JvmSynthetic
// in java they should use `plus` instead
...
@@ -144,30 +154,7 @@ interface Message {
...
@@ -144,30 +154,7 @@ interface Message {
* @sample net.mamoe.mirai.message.data.ContentEqualsTest
* @sample net.mamoe.mirai.message.data.ContentEqualsTest
*/
*/
@SinceMirai
(
"0.38.0"
)
@SinceMirai
(
"0.38.0"
)
fun
contentEquals
(
another
:
Message
,
ignoreCase
:
Boolean
=
false
):
Boolean
{
fun
contentEquals
(
another
:
Message
,
ignoreCase
:
Boolean
=
false
):
Boolean
=
contentEqualsImpl
(
another
,
ignoreCase
)
if
(!
this
.
contentToString
().
equals
(
another
.
contentToString
(),
ignoreCase
=
ignoreCase
))
return
false
return
when
{
this
is
SingleMessage
&&
another
is
SingleMessage
->
true
this
is
SingleMessage
&&
another
is
MessageChain
->
another
.
all
{
it
is
MessageMetadata
||
it
is
PlainText
}
this
is
MessageChain
&&
another
is
SingleMessage
->
this
.
all
{
it
is
MessageMetadata
||
it
is
PlainText
}
this
is
MessageChain
&&
another
is
MessageChain
->
{
val
anotherIterator
=
another
.
iterator
()
/**
* 逐个判断非 [PlainText] 的 [Message] 是否 [equals]
*/
this
.
forEachContent
{
thisElement
->
if
(
thisElement
.
isPlain
())
return
@
forEachContent
for
(
it
in
anotherIterator
)
{
if
(
it
.
isPlain
()
||
it
!
is
MessageContent
)
continue
if
(
thisElement
!=
it
)
return
false
}
}
return
true
}
else
->
error
(
"shouldn't be reached"
)
}
}
/**
/**
* 判断内容是否与 [another] 相等.
* 判断内容是否与 [another] 相等.
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
View file @
07788546
...
@@ -117,12 +117,13 @@ interface MessageChain : Message, Iterable<SingleMessage> {
...
@@ -117,12 +117,13 @@ interface MessageChain : Message, Iterable<SingleMessage> {
/**
/**
* 遍历每一个 [消息内容][MessageContent]
* 遍历每一个 [消息内容][MessageContent]
*/
*/
@SinceMirai
(
"0.39.0"
)
@JvmSynthetic
@JvmSynthetic
inline
fun
MessageChain
.
forEachContent
(
block
:
(
MessageContent
)
->
Unit
)
{
inline
fun
MessageChain
.
forEachContent
(
block
:
(
MessageContent
)
->
Unit
)
{
this
.
forEach
{
for
(
element
in
this
)
{
if
(
i
t
!
is
MessageMetadata
)
{
if
(
elemen
t
!
is
MessageMetadata
)
{
check
(
i
t
is
MessageContent
)
{
"internal error: Message must be either MessageMetaData or MessageContent"
}
check
(
elemen
t
is
MessageContent
)
{
"internal error: Message must be either MessageMetaData or MessageContent"
}
block
(
i
t
)
block
(
elemen
t
)
}
}
}
}
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt
View file @
07788546
...
@@ -18,6 +18,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
...
@@ -18,6 +18,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
import
kotlin.jvm.JvmSynthetic
import
kotlin.native.concurrent.SharedImmutable
/////////////////////////
/////////////////////////
//// IMPLEMENTATIONS ////
//// IMPLEMENTATIONS ////
...
@@ -43,6 +44,32 @@ internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): Co
...
@@ -43,6 +44,32 @@ internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): Co
return
CombinedMessage
(
EmptyMessageChain
,
this
.
followedBy
(
tail
))
return
CombinedMessage
(
EmptyMessageChain
,
this
.
followedBy
(
tail
))
}
}
@JvmSynthetic
internal
fun
Message
.
contentEqualsImpl
(
another
:
Message
,
ignoreCase
:
Boolean
):
Boolean
{
if
(!
this
.
contentToString
().
equals
(
another
.
contentToString
(),
ignoreCase
=
ignoreCase
))
return
false
return
when
{
this
is
SingleMessage
&&
another
is
SingleMessage
->
true
this
is
SingleMessage
&&
another
is
MessageChain
->
another
.
all
{
it
is
MessageMetadata
||
it
is
PlainText
}
this
is
MessageChain
&&
another
is
SingleMessage
->
this
.
all
{
it
is
MessageMetadata
||
it
is
PlainText
}
this
is
MessageChain
&&
another
is
MessageChain
->
{
val
anotherIterator
=
another
.
iterator
()
/**
* 逐个判断非 [PlainText] 的 [Message] 是否 [equals]
*/
this
.
forEachContent
{
thisElement
->
if
(
thisElement
.
isPlain
())
return
@
forEachContent
for
(
it
in
anotherIterator
)
{
if
(
it
.
isPlain
()
||
it
!
is
MessageContent
)
continue
if
(
thisElement
!=
it
)
return
false
}
}
return
true
}
else
->
error
(
"shouldn't be reached"
)
}
}
@JvmSynthetic
@JvmSynthetic
internal
fun
Message
.
followedByImpl
(
tail
:
Message
):
MessageChain
{
internal
fun
Message
.
followedByImpl
(
tail
:
Message
):
MessageChain
{
when
{
when
{
...
@@ -283,18 +310,10 @@ internal class SingleMessageChainImpl constructor(
...
@@ -283,18 +310,10 @@ internal class SingleMessageChainImpl constructor(
//////////////////////
//////////////////////
@SharedImmutable
internal
val
EMPTY_BYTE_ARRAY
=
ByteArray
(
0
)
internal
val
EMPTY_BYTE_ARRAY
=
ByteArray
(
0
)
// /000000000-3814297509-BFB7027B9354B8F899A062061D74E206
private
val
FRIEND_IMAGE_ID_REGEX_1
=
Regex
(
"""/[0-9]*-[0-9]*-[0-9a-zA-Z]{32}"""
)
// /f8f1ab55-bf8e-4236-b55e-955848d7069f
private
val
FRIEND_IMAGE_ID_REGEX_2
=
Regex
(
"""/.{8}-(.{4}-){3}.{12}"""
)
// {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
private
val
GROUP_IMAGE_ID_REGEX
=
Regex
(
"""\{.{8}-(.{4}-){3}.{12}}\..*"""
)
@Suppress
(
"NOTHING_TO_INLINE"
)
// no stack waste
@Suppress
(
"NOTHING_TO_INLINE"
)
// no stack waste
internal
inline
fun
Char
.
hexDigitToByte
():
Int
{
internal
inline
fun
Char
.
hexDigitToByte
():
Int
{
return
when
(
this
)
{
return
when
(
this
)
{
...
@@ -335,11 +354,12 @@ internal fun String.imageIdToMd5(offset: Int): ByteArray {
...
@@ -335,11 +354,12 @@ internal fun String.imageIdToMd5(offset: Int): ByteArray {
@OptIn
(
ExperimentalStdlibApi
::
class
)
@OptIn
(
ExperimentalStdlibApi
::
class
)
internal
fun
calculateImageMd5ByImageId
(
imageId
:
String
):
ByteArray
{
internal
fun
calculateImageMd5ByImageId
(
imageId
:
String
):
ByteArray
{
@Suppress
(
"DEPRECATION"
)
return
when
{
return
when
{
imageId
.
matches
(
FRIEND_IMAGE_ID_REGEX_1
)
->
imageId
.
imageIdToMd5
(
imageId
.
skipToSecondHyphen
()
+
1
)
imageId
.
matches
(
FRIEND_IMAGE_ID_REGEX_1
)
->
imageId
.
imageIdToMd5
(
imageId
.
skipToSecondHyphen
()
+
1
)
imageId
.
matches
(
FRIEND_IMAGE_ID_REGEX_2
)
->
imageId
.
matches
(
FRIEND_IMAGE_ID_REGEX_2
)
->
imageId
.
imageIdToMd5
(
1
)
imageId
.
imageIdToMd5
(
1
)
imageId
.
matches
(
GROUP_IMAGE_ID_REGEX
)
->
{
imageId
.
matches
(
GROUP_IMAGE_ID_REGEX
)
||
imageId
.
matches
(
GROUP_IMAGE_ID_REGEX_OLD
)
->
{
imageId
.
imageIdToMd5
(
1
)
imageId
.
imageIdToMd5
(
1
)
}
}
else
->
error
(
else
->
error
(
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/data/Image.kt
View file @
07788546
...
@@ -14,6 +14,7 @@ package net.mamoe.mirai.message.data
...
@@ -14,6 +14,7 @@ package net.mamoe.mirai.message.data
import
kotlinx.io.core.Input
import
kotlinx.io.core.Input
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.utils.ExternalImage
import
java.io.File
import
java.io.File
import
java.io.InputStream
import
java.io.InputStream
import
java.net.URL
import
java.net.URL
...
@@ -21,10 +22,15 @@ import java.net.URL
...
@@ -21,10 +22,15 @@ import java.net.URL
/**
/**
* 自定义表情 (收藏的表情) 和普通图片.
* 自定义表情 (收藏的表情) 和普通图片.
*
*
*
* 最推荐的存储方式是存储图片原文件, 每次发送图片时都使用文件上传.
* 在上传时服务器会根据其缓存情况回复已有的图片 ID 或要求客户端上传. 详见 [Contact.uploadImage]
*
*
* ### 上传和发送图片
* ### 上传和发送图片
* @see Contact.uploadImage 上传
图片
并得到 [Image] 消息
* @see Contact.uploadImage 上传
[图片文件][ExternalImage]
并得到 [Image] 消息
* @see Contact.sendImage 上传
并发送单个图片
作为一条消息
* @see Contact.sendImage 上传
[图片文件][ExternalImage] 并发送返回的 [Image]
作为一条消息
* @see Image.sendTo 上传
图片
并得到 [Image] 消息
* @see Image.sendTo 上传
[图片文件][ExternalImage]
并得到 [Image] 消息
*
*
* @see File.uploadAsImage
* @see File.uploadAsImage
* @see InputStream.uploadAsImage
* @see InputStream.uploadAsImage
...
@@ -46,16 +52,29 @@ actual interface Image : Message, MessageContent {
...
@@ -46,16 +52,29 @@ actual interface Image : Message, MessageContent {
actual
override
val
typeName
:
String
get
()
=
"Image"
actual
override
val
typeName
:
String
get
()
=
"Image"
}
}
/**
/**
* 图片的 id.
* 图片的 id.
* 图片 id 不一定会长时间保存, 因此不建议使用 id 发送图片.
* 图片 id 主要根据图片文件 md5 计算得到.
*
*
* 示例:
* 图片 id 不一定会长时间保存, 也可能在将来改变格式, 因此不建议使用 id 发送图片.
* 好友图片的 id: `/f8f1ab55-bf8e-4236-b55e-955848d7069f` 或 `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
*
* 群图片的 id: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png`
* ### 格式
* 群图片:
* - [GROUP_IMAGE_ID_REGEX], 示例: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai` (后缀一定为 ".mirai")
*
* 好友图片:
* - [FRIEND_IMAGE_ID_REGEX_1], 示例: `/f8f1ab55-bf8e-4236-b55e-955848d7069f`
* - [FRIEND_IMAGE_ID_REGEX_2], 示例: `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
*
*
* @see Image 使用 id 构造图片
* @see Image 使用 id 构造图片
*/
*/
actual
val
imageId
:
String
actual
val
imageId
:
String
@Deprecated
(
"""
不要自行实现 OnlineGroupImage, 它必须由协议模块实现, 否则会无法发送也无法解析.
"""
,
level
=
DeprecationLevel
.
HIDDEN
)
@Suppress
(
"PropertyName"
,
"DeprecatedCallableAddReplaceWith"
)
@
get
:
JvmSynthetic
actual
val
DoNotImplementThisClass
:
Nothing
?
}
}
\ 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