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
b7fa7adf
Commit
b7fa7adf
authored
Mar 01, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Java-friendly APIs for Contacts
parent
422d84d1
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
2158 additions
and
149 deletions
+2158
-149
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+53
-27
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
...src/androidMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
+2
-2
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Contact.kt
...src/androidMain/kotlin/net/mamoe/mirai/contact/Contact.kt
+96
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
...ain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
+340
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Group.kt
...e/src/androidMain/kotlin/net/mamoe/mirai/contact/Group.kt
+208
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Member.kt
.../src/androidMain/kotlin/net/mamoe/mirai/contact/Member.kt
+126
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/QQ.kt
...core/src/androidMain/kotlin/net/mamoe/mirai/contact/QQ.kt
+87
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt
...n/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt
+196
-0
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
...Main/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
+39
-13
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
.../kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
+6
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
.../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
+19
-14
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+32
-57
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
+28
-11
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
+21
-16
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/jvmHappy.kt
...src/commonMain/kotlin/net.mamoe.mirai/contact/jvmHappy.kt
+27
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/javaHappy.kt
...i-core/src/commonMain/kotlin/net.mamoe.mirai/javaHappy.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/OverFileSizeMaxException.kt
.../kotlin/net.mamoe.mirai/utils/OverFileSizeMaxException.kt
+2
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
...ore/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
+1
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Contact.kt
...ore/src/jvmMain/kotlin/net/mamoe/mirai/contact/Contact.kt
+100
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
...ain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
+340
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt
...-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt
+209
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Member.kt
...core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Member.kt
+126
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/QQ.kt
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/QQ.kt
+88
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt
...mMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt
+5
-5
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
.../kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
+6
-0
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
View file @
b7fa7adf
...
@@ -35,22 +35,6 @@ import net.mamoe.mirai.utils.io.toUHexString
...
@@ -35,22 +35,6 @@ import net.mamoe.mirai.utils.io.toUHexString
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.FriendInfo
as
JceFriendInfo
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.FriendInfo
as
JceFriendInfo
internal
abstract
class
ContactImpl
:
Contact
{
override
fun
hashCode
():
Int
{
var
result
=
bot
.
hashCode
()
result
=
31
*
result
+
id
.
hashCode
()
return
result
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
@Suppress
(
"DuplicatedCode"
)
if
(
this
===
other
)
return
true
if
(
other
!
is
Contact
)
return
false
if
(
this
::
class
!= other::class) return false
return this.id == other.id && this.bot == other.bot
}
}
internal
inline
class
FriendInfoImpl
(
internal
inline
class
FriendInfoImpl
(
private
val
jceFriendInfo
:
JceFriendInfo
private
val
jceFriendInfo
:
JceFriendInfo
)
:
FriendInfo
{
)
:
FriendInfo
{
...
@@ -63,7 +47,7 @@ internal class QQImpl(
...
@@ -63,7 +47,7 @@ internal class QQImpl(
override
val
coroutineContext
:
CoroutineContext
,
override
val
coroutineContext
:
CoroutineContext
,
override
val
id
:
Long
,
override
val
id
:
Long
,
private
val
friendInfo
:
FriendInfo
private
val
friendInfo
:
FriendInfo
)
:
ContactImpl
(),
QQ
{
)
:
QQ
()
{
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
override
val
nick
:
String
override
val
nick
:
String
get
()
=
friendInfo
.
nick
get
()
=
friendInfo
.
nick
...
@@ -159,7 +143,21 @@ internal class QQImpl(
...
@@ -159,7 +143,21 @@ internal class QQImpl(
}
}
}
finally
{
}
finally
{
(
image
.
input
as
?
Closeable
)
?.
close
()
(
image
.
input
as
?
Closeable
)
?.
close
()
(
image
.
input
as
?
io
.
ktor
.
utils
.
io
.
core
.
Closeable
)
?.
close
()
(
image
.
input
as
?
Closeable
)
?.
close
()
}
override
fun
hashCode
():
Int
{
var
result
=
bot
.
hashCode
()
result
=
31
*
result
+
id
.
hashCode
()
return
result
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
@Suppress
(
"DuplicatedCode"
)
if
(
this
===
other
)
return
true
if
(
other
!
is
Contact
)
return
false
if
(
this
::
class
!= other::class) return false
return this.id == other.id && this.bot == other.bot
}
}
@
MiraiExperimentalAPI
@
MiraiExperimentalAPI
...
@@ -187,10 +185,26 @@ internal class MemberImpl(
...
@@ -187,10 +185,26 @@ internal class MemberImpl(
group
:
GroupImpl
,
group
:
GroupImpl
,
override
val
coroutineContext
:
CoroutineContext
,
override
val
coroutineContext
:
CoroutineContext
,
memberInfo
:
MemberInfo
memberInfo
:
MemberInfo
)
:
ContactImpl
(),
Member
,
QQ
by
qq
{
)
:
Member
()
{
override
val
group
:
GroupImpl
by
group
.
unsafeWeakRef
()
override
val
group
:
GroupImpl
by
group
.
unsafeWeakRef
()
val
qq
:
QQImpl
by
qq
.
unsafeWeakRef
()
val
qq
:
QQImpl
by
qq
.
unsafeWeakRef
()
// region QQ delegate
override
val
id
:
Long
=
qq
.
id
override
val
nick
:
String
=
qq
.
nick
@MiraiExperimentalAPI
override
suspend
fun
queryProfile
():
Profile
=
qq
.
queryProfile
()
@MiraiExperimentalAPI
override
suspend
fun
queryPreviousNameList
():
PreviousNameList
=
qq
.
queryPreviousNameList
()
@MiraiExperimentalAPI
override
suspend
fun
queryRemark
():
FriendNameRemark
=
qq
.
queryRemark
()
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
QQ
>
=
qq
.
sendMessage
(
message
)
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
=
qq
.
uploadImage
(
image
)
// endregion
override
var
permission
:
MemberPermission
=
memberInfo
.
permission
override
var
permission
:
MemberPermission
=
memberInfo
.
permission
@Suppress
(
"PropertyName"
)
@Suppress
(
"PropertyName"
)
internal
var
_nameCard
:
String
=
memberInfo
.
nameCard
internal
var
_nameCard
:
String
=
memberInfo
.
nameCard
...
@@ -307,10 +321,9 @@ internal class MemberImpl(
...
@@ -307,10 +321,9 @@ internal class MemberImpl(
return
result
return
result
}
}
@Suppress
(
"DuplicatedCode"
)
override
fun
equals
(
other
:
Any
?):
Boolean
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
// 不要删除. trust me
if
(
this
===
other
)
return
true
if
(
this
===
other
)
return
true
if
(
other
!
is
Member
)
return
false
if
(
other
!
is
Contact
)
return
false
if
(
this
::
class
!= other::class) return false
if
(
this
::
class
!= other::class) return false
return this.id == other.id && this.bot == other.bot
return this.id == other.id && this.bot == other.bot
}
}
...
@@ -347,7 +360,7 @@ internal class GroupImpl(
...
@@ -347,7 +360,7 @@ internal class GroupImpl(
override
val
id
:
Long
,
override
val
id
:
Long
,
groupInfo
:
GroupInfo
,
groupInfo
:
GroupInfo
,
members
:
Sequence
<
MemberInfo
>
members
:
Sequence
<
MemberInfo
>
)
:
ContactImpl
(),
Group
{
)
:
Group
()
{
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
val
uin
:
Long
=
groupInfo
.
uin
val
uin
:
Long
=
groupInfo
.
uin
...
@@ -398,11 +411,11 @@ internal class GroupImpl(
...
@@ -398,11 +411,11 @@ internal class GroupImpl(
}.
toLockFreeLinkedList
())
}.
toLockFreeLinkedList
())
internal
var
_name
:
String
=
groupInfo
.
name
internal
var
_name
:
String
=
groupInfo
.
name
internal
var
_announcement
:
String
=
groupInfo
.
memo
private
var
_announcement
:
String
=
groupInfo
.
memo
internal
var
_allowMemberInvite
:
Boolean
=
groupInfo
.
allowMemberInvite
private
var
_allowMemberInvite
:
Boolean
=
groupInfo
.
allowMemberInvite
internal
var
_confessTalk
:
Boolean
=
groupInfo
.
confessTalk
internal
var
_confessTalk
:
Boolean
=
groupInfo
.
confessTalk
internal
var
_muteAll
:
Boolean
=
groupInfo
.
muteAll
internal
var
_muteAll
:
Boolean
=
groupInfo
.
muteAll
internal
var
_autoApprove
:
Boolean
=
groupInfo
.
autoApprove
private
var
_autoApprove
:
Boolean
=
groupInfo
.
autoApprove
internal
var
_anonymousChat
:
Boolean
=
groupInfo
.
allowAnonymousChat
internal
var
_anonymousChat
:
Boolean
=
groupInfo
.
allowAnonymousChat
override
var
name
:
String
override
var
name
:
String
...
@@ -666,10 +679,23 @@ internal class GroupImpl(
...
@@ -666,10 +679,23 @@ internal class GroupImpl(
}
}
}
finally
{
}
finally
{
(
image
.
input
as
?
Closeable
)
?.
close
()
(
image
.
input
as
?
Closeable
)
?.
close
()
(
image
.
input
as
?
io
.
ktor
.
utils
.
io
.
core
.
Closeable
)
?.
close
()
}
}
override
fun
toString
():
String
{
override
fun
toString
():
String
{
return
"Group($id)"
return
"Group($id)"
}
}
override
fun
hashCode
():
Int
{
var
result
=
bot
.
hashCode
()
result
=
31
*
result
+
id
.
hashCode
()
return
result
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
@Suppress
(
"DuplicatedCode"
,
"DuplicatedCode"
)
if
(
this
===
other
)
return
true
if
(
other
!
is
Contact
)
return
false
if
(
this
::
class
!= other::class) return false
return this.id == other.id && this.bot == other.bot
}
}
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
View file @
b7fa7adf
...
@@ -169,9 +169,9 @@ actual abstract class BotJavaHappyAPI actual constructor() {
...
@@ -169,9 +169,9 @@ actual abstract class BotJavaHappyAPI actual constructor() {
}
}
}
}
// !!
!
不要 crossinline, 会编译失败
// !! 不要 crossinline, 会编译失败
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
private
fun
<
R
>
Bot
.
future
(
block
:
suspend
Bot
.()
->
R
):
Future
<
R
>
{
internal
fun
<
R
,
C
:
CoroutineScope
>
C
.
future
(
block
:
suspend
C
.()
->
R
):
Future
<
R
>
{
val
future
=
object
:
Future
<
R
>
{
val
future
=
object
:
Future
<
R
>
{
val
value
:
CompletableDeferred
<
R
>
=
CompletableDeferred
()
val
value
:
CompletableDeferred
<
R
>
=
CompletableDeferred
()
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Contact.kt
0 → 100644
View file @
b7fa7adf
/*
* 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.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.BeforeImageUploadEvent
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.ImageUploadEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.id
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.OverFileSizeMaxException
import
net.mamoe.mirai.utils.WeakRefProperty
/**
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
*
* @author Him188moe
*/
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
actual
abstract
class
Contact
:
CoroutineScope
,
ContactJavaHappyAPI
()
{
/**
* 这个联系人所属 [Bot].
*/
@WeakRefProperty
actual
abstract
val
bot
:
Bot
/**
* 可以是 QQ 号码或者群号码.
*
* 对于 [QQ], `uin` 与 `id` 是相同的意思.
* 对于 [Group], `groupCode` 与 `id` 是相同的意思.
*
* @see QQ.id
* @see Group.id
*/
actual
abstract
val
id
:
Long
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
*/
actual
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
out
Contact
>
/**
* 上传一个图片以备发送.
*
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
* @see ImageUploadEvent 图片发送完成事件
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
*/
actual
abstract
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
/**
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
*
* 注:
* [id] 相同的 [Member] 和 [QQ], 他们并不 [equals].
* 因为, [Member] 含义为群员, 必属于一个群.
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
*/
actual
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
actual
abstract
override
fun
hashCode
():
Int
/**
* @return "QQ($id)" or "Group($id)" or "Member($id)"
*/
actual
abstract
override
fun
toString
():
String
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
0 → 100644
View file @
b7fa7adf
This diff is collapsed.
Click to expand it.
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Group.kt
0 → 100644
View file @
b7fa7adf
/*
* 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.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
/**
* 群. 在 QQ Android 中叫做 "Troop"
*/
actual
abstract
class
Group
:
Contact
(),
CoroutineScope
{
/**
* 群名称.
*
* 在修改时将会异步上传至服务器.
* 频繁修改可能会被服务器拒绝.
*
* @see MemberPermissionChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
name
:
String
/**
* 入群公告, 没有时为空字符串.
*
* 在修改时将会异步上传至服务器.
*
* @see GroupEntranceAnnouncementChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
entranceAnnouncement
:
String
/**
* 全体禁言状态. `true` 为开启.
*
* 当前仅能修改状态.
*
* @see GroupMuteAllEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isMuteAll
:
Boolean
/**
* 坦白说状态. `true` 为允许.
*
* 在修改时将会异步上传至服务器.
*
* @see GroupAllowConfessTalkEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isConfessTalkEnabled
:
Boolean
/**
* 允许群员邀请好友入群的状态. `true` 为允许
*
* 在修改时将会异步上传至服务器.
*
* @see GroupAllowMemberInviteEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isAllowMemberInvite
:
Boolean
/**
* 自动加群审批
*/
actual
abstract
val
isAutoApproveEnabled
:
Boolean
/**
* 匿名聊天
*/
actual
abstract
val
isAnonymousChatEnabled
:
Boolean
/**
* 同为 groupCode, 用户看到的群号码.
*/
actual
abstract
override
val
id
:
Long
/**
* 群主.
*
* @return 若机器人是群主, 返回 [botAsMember]. 否则返回相应的成员
*/
actual
abstract
val
owner
:
Member
/**
* [Bot] 在群内的 [Member] 实例
*/
@MiraiExperimentalAPI
actual
abstract
val
botAsMember
:
Member
/**
* 机器人被禁言还剩余多少秒
*
* @see BotMuteEvent 机器人被禁言事件
* @see isBotMuted 判断机器人是否正在被禁言
*/
actual
abstract
val
botMuteRemaining
:
Int
/**
* 机器人在这个群里的权限
*
* @see Group.checkBotPermission 检查 [Bot] 在这个群里的权限
* @see Group.checkBotPermissionOperator 要求 [Bot] 在这个群里的权限为 [管理员或群主][MemberPermission.isOperator]
*
* @see BotGroupPermissionChangeEvent 机器人群员修改
*/
actual
abstract
val
botPermission
:
MemberPermission
/**
* 群头像下载链接.
*/
actual
val
avatarUrl
:
String
get
()
=
"https://p.qlogo.cn/gh/$id/${id}_1/640"
/**
* 群成员列表, 不含机器人自己, 含群主.
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
*/
actual
abstract
val
members
:
ContactList
<
Member
>
/**
* 获取群成员实例. 不存在时抛出 [kotlin.NoSuchElementException]
*/
actual
abstract
operator
fun
get
(
id
:
Long
):
Member
/**
* 获取群成员实例, 不存在则 null
*/
actual
abstract
fun
getOrNull
(
id
:
Long
):
Member
?
/**
* 检查此 id 的群成员是否存在
*/
actual
abstract
operator
fun
contains
(
id
:
Long
):
Boolean
/**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
quit
():
Boolean
/**
* 构造一个 [Member].
* 非特殊情况请不要使用这个函数. 优先使用 [get].
*/
@JvmName
(
"newMember"
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
,
"FunctionName"
)
@MiraiExperimentalAPI
(
"dangerous"
)
actual
abstract
fun
Member
(
memberInfo
:
MemberInfo
):
Member
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
actual
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
Group
>
actual
companion
object
{
/**
* by @kar98k
*/
actual
fun
calculateGroupUinByGroupCode
(
groupCode
:
Long
):
Long
{
var
left
:
Long
=
groupCode
/
1000000L
when
(
left
)
{
in
0
..
10
->
left
+=
202
in
11
..
19
->
left
+=
480
-
11
in
20
..
66
->
left
+=
2100
-
20
in
67
..
156
->
left
+=
2010
-
67
in
157
..
209
->
left
+=
2147
-
157
in
210
..
309
->
left
+=
4100
-
210
in
310
..
499
->
left
+=
3800
-
310
}
return
left
*
1000000L
+
groupCode
%
1000000L
}
actual
fun
calculateGroupCodeByGroupUin
(
groupUin
:
Long
):
Long
{
var
left
:
Long
=
groupUin
/
1000000L
when
(
left
)
{
in
0
+
202
..
10
+
202
->
left
-=
202
in
11
+
480
-
11
..
19
+
480
-
11
->
left
-=
480
-
11
in
20
+
2100
-
20
..
66
+
2100
-
20
->
left
-=
2100
-
20
in
67
+
2010
-
67
..
156
+
2010
-
67
->
left
-=
2010
-
67
in
157
+
2147
-
157
..
209
+
2147
-
157
->
left
-=
2147
-
157
in
210
+
4100
-
210
..
309
+
4100
-
210
->
left
-=
4100
-
210
in
310
+
3800
-
310
..
499
+
3800
-
310
->
left
-=
3800
-
310
}
return
left
*
1000000L
+
groupUin
%
1000000L
}
}
@MiraiExperimentalAPI
actual
fun
toFullString
():
String
{
return
"Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
}
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/Member.kt
0 → 100644
View file @
b7fa7adf
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.WeakRefProperty
/**
* 群成员.
*/
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
actual
abstract
class
Member
:
MemberJavaHappyAPI
()
{
/**
* 所在的群.
*/
@WeakRefProperty
actual
abstract
val
group
:
Group
/**
* 成员的权限, 动态更新.
*
* @see MemberPermissionChangeEvent 权限变更事件. 由群主或机器人的操作触发.
*/
actual
abstract
val
permission
:
MemberPermission
/**
* 群名片. 可能为空.
*
* 管理员和群主都可修改任何人(包括群主)的群名片.
*
* 在修改时将会异步上传至服务器.
*
* @see [nameCardOrNick] 获取非空群名片或昵称
*
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
*/
actual
abstract
var
nameCard
:
String
/**
* 群头衔.
*
* 仅群主可以修改群头衔.
*
* 在修改时将会异步上传至服务器.
*
* @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
*/
actual
abstract
var
specialTitle
:
String
/**
* 被禁言剩余时长. 单位为秒.
*
* @see isMuted 判断改成员是否处于禁言状态
* @see mute 设置禁言
* @see unmute 取消禁言
*/
actual
abstract
val
muteTimeRemaining
:
Int
/**
* 禁言.
*
* QQ 中最小操作和显示的时间都是一分钟.
* 机器人可以实现精确到秒, 会被客户端显示为 1 分钟但不影响实际禁言时间.
*
* 管理员可禁言成员, 群主可禁言管理员和群员.
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 机器人无权限时返回 `false`
*
* @see Int.minutesToSeconds
* @see Int.hoursToSeconds
* @see Int.daysToSeconds
*
* @see MemberMuteEvent 成员被禁言事件
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"muteSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
mute
(
durationSeconds
:
Int
)
/**
* 解除禁言.
*
* 管理员可解除成员的禁言, 群主可解除管理员和群员的禁言.
*
* @see MemberUnmuteEvent 成员被取消禁言事件.
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"unmuteSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
unmute
()
/**
* 踢出该成员.
*
* 管理员可踢出成员, 群主可踢出管理员和群员.
*
* @see MemberLeaveEvent.Kick 成员被踢出事件.
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"kickSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
kick
(
message
:
String
)
/**
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
*/
actual
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
actual
abstract
override
fun
hashCode
():
Int
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/contact/QQ.kt
0 → 100644
View file @
b7fa7adf
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.data.FriendNameRemark
import
net.mamoe.mirai.data.PreviousNameList
import
net.mamoe.mirai.data.Profile
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
/**
* QQ 对象.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
*
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
*
* A QQ instance helps you to receive event from or sendPacket event to.
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
*
* @author Him188moe
*/
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
actual
abstract
class
QQ
:
Contact
(),
CoroutineScope
{
/**
* 请求头像下载链接
*/
// @MiraiExperimentalAPI
//suspend fun queryAvatar(): AvatarLink
/**
* QQ 号码
*/
actual
abstract
override
val
id
:
Long
/**
* 昵称
*/
actual
abstract
val
nick
:
String
/**
* 查询用户资料
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryProfile
():
Profile
/**
* 头像下载链接
*/
actual
val
avatarUrl
:
String
get
()
=
"http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
/**
* 查询曾用名.
*
* 曾用名可能是:
* - 昵称
* - 共同群内的群名片
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryPreviousNameList
():
PreviousNameList
/**
* 查询机器人账号给这个人设置的备注
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryRemark
():
FriendNameRemark
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmName
(
"sendMessageSuspend"
)
@JvmSynthetic
actual
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
QQ
>
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt
0 → 100644
View file @
b7fa7adf
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.message
import
android.graphics.Bitmap
import
io.ktor.utils.io.core.Input
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.utils.OverFileSizeMaxException
import
net.mamoe.mirai.utils.sendTo
import
net.mamoe.mirai.utils.toExternalImage
import
net.mamoe.mirai.utils.upload
import
java.io.File
import
java.io.InputStream
import
java.net.URL
/*
* 发送图片的一些扩展函数.
*/
// region IMAGE.sendAsImageTo(Contact)
/**
* 在 [Dispatchers.IO] 中将图片发送到指定联系人. 不会创建临时文件
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
Bitmap
.
sendTo
(
contact
:
Contact
)
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
sendTo
(
contact
)
/**
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
URL
.
sendAsImageTo
(
contact
:
Contact
)
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
sendTo
(
contact
)
/**
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
Input
.
sendAsImageTo
(
contact
:
Contact
)
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
sendTo
(
contact
)
/**
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
InputStream
.
sendAsImageTo
(
contact
:
Contact
)
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
sendTo
(
contact
)
/**
* 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
File
.
sendAsImageTo
(
contact
:
Contact
)
{
require
(
this
.
exists
()
&&
this
.
canRead
())
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
sendTo
(
contact
)
}
// endregion
// region IMAGE.Upload(Contact): Image
/**
* 在 [Dispatchers.IO] 中将图片上传后构造 [Image]. 不会创建临时文件
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
Bitmap
.
upload
(
contact
:
Contact
):
Image
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
upload
(
contact
)
/**
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片上传后构造 [Image]
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
URL
.
uploadAsImage
(
contact
:
Contact
):
Image
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
upload
(
contact
)
/**
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传后构造 [Image]
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
Input
.
uploadAsImage
(
contact
:
Contact
):
Image
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
upload
(
contact
)
/**
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传后构造 [Image]
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
InputStream
.
uploadAsImage
(
contact
:
Contact
):
Image
=
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
upload
(
contact
)
/**
* 在 [Dispatchers.IO] 中将文件作为图片上传后构造 [Image]
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
fun
File
.
uploadAsImage
(
contact
:
Contact
):
Image
{
require
(
this
.
exists
()
&&
this
.
canRead
())
return
withContext
(
Dispatchers
.
IO
)
{
toExternalImage
()
}.
upload
(
contact
)
}
// endregion
// region Contact.sendImage(IMAGE)
/**
* 在 [Dispatchers.IO] 中将图片发送到指定联系人. 不会保存临时文件
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
sendImage
(
bufferedImage
:
Bitmap
)
=
bufferedImage
.
sendTo
(
this
)
/**
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
sendImage
(
imageUrl
:
URL
)
=
imageUrl
.
sendAsImageTo
(
this
)
/**
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
sendImage
(
imageInput
:
Input
)
=
imageInput
.
sendAsImageTo
(
this
)
/**
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
sendImage
(
imageStream
:
InputStream
)
=
imageStream
.
sendAsImageTo
(
this
)
/**
* 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
sendImage
(
file
:
File
)
=
file
.
sendAsImageTo
(
this
)
// endregion
// region Contact.uploadImage(IMAGE)
/**
* 在 [Dispatchers.IO] 中将图片上传, 但不发送. 不会保存临时文件
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
bufferedImage
:
Bitmap
):
Image
=
bufferedImage
.
upload
(
this
)
/**
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片上传, 但不发送
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageUrl
:
URL
):
Image
=
imageUrl
.
uploadAsImage
(
this
)
/**
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传, 但不发送
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageInput
:
Input
):
Image
=
imageInput
.
uploadAsImage
(
this
)
/**
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传, 但不发送
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageStream
:
InputStream
):
Image
=
imageStream
.
uploadAsImage
(
this
)
/**
* 在 [Dispatchers.IO] 中将文件作为图片上传, 但不发送
* @throws OverFileSizeMaxException
*/
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
file
:
File
):
Image
=
file
.
uploadAsImage
(
this
)
// endregion
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/ExternalImageAndroid.kt
View file @
b7fa7adf
...
@@ -7,15 +7,16 @@
...
@@ -7,15 +7,16 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
android.graphics.BitmapFactory
import
io.ktor.utils.io.ByteReadChannel
import
io.ktor.utils.io.core.Input
import
io.ktor.utils.io.core.Input
import
io.ktor.utils.io.core.copyTo
import
io.ktor.utils.io.core.copyTo
import
io.ktor.utils.io.errors.IOException
import
io.ktor.utils.io.errors.IOException
import
io.ktor.utils.io.streams.asInput
import
io.ktor.utils.io.streams.asOutput
import
io.ktor.utils.io.streams.asOutput
import
kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.withContext
...
@@ -27,6 +28,17 @@ import java.net.URL
...
@@ -27,6 +28,17 @@ import java.net.URL
* 将各类型图片容器转为 [ExternalImage]
* 将各类型图片容器转为 [ExternalImage]
*/
*/
/**
* 读取 [BufferedImage] 的属性, 然后构造 [ExternalImage]
*/
@Throws
(
IOException
::
class
)
fun
Bitmap
.
toExternalImage
(
formatName
:
String
=
"gif"
):
Nothing
{
TODO
()
}
// suspend inline fun BufferedImage.suspendToExternalImage(): ExternalImage = withContext(IO) { toExternalImage() }
/**
/**
* 读取文件头识别图片属性, 然后构造 [ExternalImage]
* 读取文件头识别图片属性, 然后构造 [ExternalImage]
*/
*/
...
@@ -48,8 +60,7 @@ fun File.toExternalImage(): ExternalImage {
...
@@ -48,8 +60,7 @@ fun File.toExternalImage(): ExternalImage {
/**
/**
* 在 [IO] 中进行 [File.toExternalImage]
* 在 [IO] 中进行 [File.toExternalImage]
*/
*/
@Suppress
(
"unused"
)
suspend
inline
fun
File
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
fun
File
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
/**
/**
* 下载文件到临时目录然后调用 [File.toExternalImage]
* 下载文件到临时目录然后调用 [File.toExternalImage]
...
@@ -61,6 +72,7 @@ fun URL.toExternalImage(): ExternalImage {
...
@@ -61,6 +72,7 @@ fun URL.toExternalImage(): ExternalImage {
openStream
().
use
{
input
->
openStream
().
use
{
input
->
input
.
copyTo
(
output
)
input
.
copyTo
(
output
)
}
}
output
.
flush
()
}
}
return
file
.
toExternalImage
()
return
file
.
toExternalImage
()
}
}
...
@@ -68,8 +80,7 @@ fun URL.toExternalImage(): ExternalImage {
...
@@ -68,8 +80,7 @@ fun URL.toExternalImage(): ExternalImage {
/**
/**
* 在 [IO] 中进行 [URL.toExternalImage]
* 在 [IO] 中进行 [URL.toExternalImage]
*/
*/
@Suppress
(
"unused"
)
suspend
inline
fun
URL
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
fun
URL
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
/**
/**
* 保存为临时文件然后调用 [File.toExternalImage]
* 保存为临时文件然后调用 [File.toExternalImage]
...
@@ -77,8 +88,9 @@ suspend fun URL.suspendToExternalImage(): ExternalImage = withContext(IO) { toEx
...
@@ -77,8 +88,9 @@ suspend fun URL.suspendToExternalImage(): ExternalImage = withContext(IO) { toEx
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
InputStream
.
toExternalImage
():
ExternalImage
{
fun
InputStream
.
toExternalImage
():
ExternalImage
{
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
file
.
outputStream
().
asOutput
().
use
{
file
.
outputStream
().
use
{
this
.
asInput
().
copyTo
(
it
)
this
.
copyTo
(
it
)
it
.
flush
()
}
}
this
.
close
()
this
.
close
()
return
file
.
toExternalImage
()
return
file
.
toExternalImage
()
...
@@ -87,17 +99,19 @@ fun InputStream.toExternalImage(): ExternalImage {
...
@@ -87,17 +99,19 @@ fun InputStream.toExternalImage(): ExternalImage {
/**
/**
* 在 [IO] 中进行 [InputStream.toExternalImage]
* 在 [IO] 中进行 [InputStream.toExternalImage]
*/
*/
@Suppress
(
"unused"
)
suspend
inline
fun
InputStream
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
fun
InputStream
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
/**
/**
* 保存为临时文件然后调用 [File.toExternalImage]
* 保存为临时文件然后调用 [File.toExternalImage].
*
* 需要函数调用者 close [this]
*/
*/
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
Input
.
toExternalImage
():
ExternalImage
{
fun
Input
.
toExternalImage
():
ExternalImage
{
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
file
.
outputStream
().
asOutput
().
use
{
file
.
outputStream
().
asOutput
().
use
{
this
.
copyTo
(
it
)
this
.
copyTo
(
it
)
it
.
flush
()
}
}
return
file
.
toExternalImage
()
return
file
.
toExternalImage
()
}
}
...
@@ -105,5 +119,17 @@ fun Input.toExternalImage(): ExternalImage {
...
@@ -105,5 +119,17 @@ fun Input.toExternalImage(): ExternalImage {
/**
/**
* 在 [IO] 中进行 [Input.toExternalImage]
* 在 [IO] 中进行 [Input.toExternalImage]
*/
*/
@Suppress
(
"unused"
)
suspend
inline
fun
Input
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
fun
Input
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
/**
* 保存为临时文件然后调用 [File.toExternalImage].
*/
suspend
fun
ByteReadChannel
.
toExternalImage
():
ExternalImage
{
val
file
=
createTempFile
().
apply
{
deleteOnExit
()
}
file
.
outputStream
().
use
{
withContext
(
IO
)
{
copyTo
(
it
)
}
it
.
flush
()
}
return
file
.
suspendToExternalImage
()
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
0 → 100644
View file @
b7fa7adf
package
net.mamoe.mirai.utils
/**
* 图片文件过大
*/
actual
class
OverFileSizeMaxException
:
IllegalStateException
()
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
View file @
b7fa7adf
...
@@ -14,6 +14,7 @@ package net.mamoe.mirai.contact
...
@@ -14,6 +14,7 @@ package net.mamoe.mirai.contact
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.BeforeImageUploadEvent
import
net.mamoe.mirai.event.events.BeforeImageUploadEvent
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.ImageUploadEvent
import
net.mamoe.mirai.event.events.ImageUploadEvent
...
@@ -23,25 +24,26 @@ import net.mamoe.mirai.message.MessageReceipt
...
@@ -23,25 +24,26 @@ import net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.recall
import
net.mamoe.mirai.recall
import
net.mamoe.mirai.recallIn
import
net.mamoe.mirai.recallIn
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.OverFileSizeMaxException
import
net.mamoe.mirai.utils.WeakRefProperty
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
/**
/**
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
*
*
* @author Him188moe
* @author Him188moe
*/
*/
// 不要删除多平台结构 !!! kotlin bug
interface
Contact
:
CoroutineScope
{
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
expect
abstract
class
Contact
()
:
CoroutineScope
,
ContactJavaHappyAPI
{
/**
/**
* 这个联系人所属 [Bot].
* 这个联系人所属 [Bot].
*/
*/
@WeakRefProperty
@WeakRefProperty
val
bot
:
Bot
abstract
val
bot
:
Bot
/**
/**
* 可以是 QQ 号码或者群号码.
* 可以是 QQ 号码或者群号码.
...
@@ -52,7 +54,7 @@ interface Contact : CoroutineScope {
...
@@ -52,7 +54,7 @@ interface Contact : CoroutineScope {
* @see QQ.id
* @see QQ.id
* @see Group.id
* @see Group.id
*/
*/
val
id
:
Long
abstract
val
id
:
Long
/**
/**
* 向这个对象发送消息.
* 向这个对象发送消息.
...
@@ -65,11 +67,12 @@ interface Contact : CoroutineScope {
...
@@ -65,11 +67,12 @@ interface Contact : CoroutineScope {
*
*
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
*/
*/
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
out
Contact
>
@JvmName
(
"sendMessageSuspend"
)
@JvmSynthetic
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
out
Contact
>
/**
/**
* 上传一个图片以备发送.
* 上传一个图片以备发送.
* TODO 群图片与好友图片在服务器上是通用的, 在 mirai 目前不通用.
*
*
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
* @see ImageUploadEvent 图片发送完成事件
* @see ImageUploadEvent 图片发送完成事件
...
@@ -77,7 +80,9 @@ interface Contact : CoroutineScope {
...
@@ -77,7 +80,9 @@ interface Contact : CoroutineScope {
* @throws EventCancelledException 当发送消息事件被取消
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
*/
*/
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
@JvmName
(
"uploadImageSuspend"
)
@JvmSynthetic
abstract
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
/**
/**
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
...
@@ -87,17 +92,17 @@ interface Contact : CoroutineScope {
...
@@ -87,17 +92,17 @@ interface Contact : CoroutineScope {
* 因为, [Member] 含义为群员, 必属于一个群.
* 因为, [Member] 含义为群员, 必属于一个群.
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
*/
*/
override
fun
equals
(
other
:
Any
?):
Boolean
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
*/
override
fun
hashCode
():
Int
abstract
override
fun
hashCode
():
Int
/**
/**
* @return "QQ($id)" or "Group($id)" or "Member($id)"
* @return "QQ($id)" or "Group($id)" or "Member($id)"
*/
*/
override
fun
toString
():
String
abstract
override
fun
toString
():
String
}
}
/**
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
View file @
b7fa7adf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
...
@@ -21,11 +21,13 @@ import net.mamoe.mirai.message.MessageReceipt
...
@@ -21,11 +21,13 @@ import net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
/**
/**
* 群. 在 QQ Android 中叫做 "Troop"
* 群. 在 QQ Android 中叫做 "Troop"
*/
*/
interface
Group
:
Contact
,
CoroutineScope
{
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
expect
abstract
class
Group
()
:
Contact
,
CoroutineScope
{
/**
/**
* 群名称.
* 群名称.
*
*
...
@@ -35,7 +37,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -35,7 +37,7 @@ interface Group : Contact, CoroutineScope {
* @see MemberPermissionChangeEvent
* @see MemberPermissionChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
*/
var
name
:
String
abstract
var
name
:
String
/**
/**
* 入群公告, 没有时为空字符串.
* 入群公告, 没有时为空字符串.
*
*
...
@@ -44,7 +46,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -44,7 +46,7 @@ interface Group : Contact, CoroutineScope {
* @see GroupEntranceAnnouncementChangeEvent
* @see GroupEntranceAnnouncementChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
*/
var
entranceAnnouncement
:
String
abstract
var
entranceAnnouncement
:
String
/**
/**
* 全体禁言状态. `true` 为开启.
* 全体禁言状态. `true` 为开启.
*
*
...
@@ -53,7 +55,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -53,7 +55,7 @@ interface Group : Contact, CoroutineScope {
* @see GroupMuteAllEvent
* @see GroupMuteAllEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
*/
var
isMuteAll
:
Boolean
abstract
var
isMuteAll
:
Boolean
/**
/**
* 坦白说状态. `true` 为允许.
* 坦白说状态. `true` 为允许.
*
*
...
@@ -62,7 +64,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -62,7 +64,7 @@ interface Group : Contact, CoroutineScope {
* @see GroupAllowConfessTalkEvent
* @see GroupAllowConfessTalkEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
*/
var
isConfessTalkEnabled
:
Boolean
abstract
var
isConfessTalkEnabled
:
Boolean
/**
/**
* 允许群员邀请好友入群的状态. `true` 为允许
* 允许群员邀请好友入群的状态. `true` 为允许
*
*
...
@@ -71,33 +73,33 @@ interface Group : Contact, CoroutineScope {
...
@@ -71,33 +73,33 @@ interface Group : Contact, CoroutineScope {
* @see GroupAllowMemberInviteEvent
* @see GroupAllowMemberInviteEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
*/
var
isAllowMemberInvite
:
Boolean
abstract
var
isAllowMemberInvite
:
Boolean
/**
/**
* 自动加群审批
* 自动加群审批
*/
*/
val
isAutoApproveEnabled
:
Boolean
abstract
val
isAutoApproveEnabled
:
Boolean
/**
/**
* 匿名聊天
* 匿名聊天
*/
*/
val
isAnonymousChatEnabled
:
Boolean
abstract
val
isAnonymousChatEnabled
:
Boolean
/**
/**
* 同为 groupCode, 用户看到的群号码.
* 同为 groupCode, 用户看到的群号码.
*/
*/
override
val
id
:
Long
abstract
override
val
id
:
Long
/**
/**
* 群主.
* 群主.
*
*
* @return 若机器人是群主, 返回 [botAsMember]. 否则返回相应的成员
* @return 若机器人是群主, 返回 [botAsMember]. 否则返回相应的成员
*/
*/
val
owner
:
Member
abstract
val
owner
:
Member
/**
/**
* [Bot] 在群内的 [Member] 实例
* [Bot] 在群内的 [Member] 实例
*/
*/
@MiraiExperimentalAPI
@MiraiExperimentalAPI
val
botAsMember
:
Member
abstract
val
botAsMember
:
Member
/**
/**
* 机器人被禁言还剩余多少秒
* 机器人被禁言还剩余多少秒
...
@@ -105,7 +107,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -105,7 +107,7 @@ interface Group : Contact, CoroutineScope {
* @see BotMuteEvent 机器人被禁言事件
* @see BotMuteEvent 机器人被禁言事件
* @see isBotMuted 判断机器人是否正在被禁言
* @see isBotMuted 判断机器人是否正在被禁言
*/
*/
val
botMuteRemaining
:
Int
abstract
val
botMuteRemaining
:
Int
/**
/**
* 机器人在这个群里的权限
* 机器人在这个群里的权限
...
@@ -115,39 +117,41 @@ interface Group : Contact, CoroutineScope {
...
@@ -115,39 +117,41 @@ interface Group : Contact, CoroutineScope {
*
*
* @see BotGroupPermissionChangeEvent 机器人群员修改
* @see BotGroupPermissionChangeEvent 机器人群员修改
*/
*/
val
botPermission
:
MemberPermission
abstract
val
botPermission
:
MemberPermission
/**
/**
* 群头像下载链接.
* 群头像下载链接.
*/
*/
val
avatarUrl
:
String
get
()
=
"https://p.qlogo.cn/gh/$id/${id}_1/640"
val
avatarUrl
:
String
/**
/**
* 群成员列表, 不含机器人自己, 含群主.
* 群成员列表, 不含机器人自己, 含群主.
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
*/
*/
val
members
:
ContactList
<
Member
>
abstract
val
members
:
ContactList
<
Member
>
/**
/**
* 获取群成员实例. 不存在时抛出 [kotlin.NoSuchElementException]
* 获取群成员实例. 不存在时抛出 [kotlin.NoSuchElementException]
*/
*/
operator
fun
get
(
id
:
Long
):
Member
abstract
operator
fun
get
(
id
:
Long
):
Member
/**
/**
* 获取群成员实例, 不存在则 null
* 获取群成员实例, 不存在则 null
*/
*/
fun
getOrNull
(
id
:
Long
):
Member
?
abstract
fun
getOrNull
(
id
:
Long
):
Member
?
/**
/**
* 检查此 id 的群成员是否存在
* 检查此 id 的群成员是否存在
*/
*/
operator
fun
contains
(
id
:
Long
):
Boolean
abstract
operator
fun
contains
(
id
:
Long
):
Boolean
/**
/**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/
*/
@JvmName
(
"quitSuspend"
)
@JvmSynthetic
@MiraiExperimentalAPI
(
"还未支持"
)
@MiraiExperimentalAPI
(
"还未支持"
)
suspend
fun
quit
():
Boolean
abstract
suspend
fun
quit
():
Boolean
/**
/**
* 构造一个 [Member].
* 构造一个 [Member].
...
@@ -156,7 +160,7 @@ interface Group : Contact, CoroutineScope {
...
@@ -156,7 +160,7 @@ interface Group : Contact, CoroutineScope {
@MiraiExperimentalAPI
(
"dangerous"
)
@MiraiExperimentalAPI
(
"dangerous"
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
,
"FunctionName"
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
,
"FunctionName"
)
@JvmName
(
"newMember"
)
@JvmName
(
"newMember"
)
fun
Member
(
memberInfo
:
MemberInfo
):
Member
abstract
fun
Member
(
memberInfo
:
MemberInfo
):
Member
/**
/**
* 向这个对象发送消息.
* 向这个对象发送消息.
...
@@ -169,48 +173,19 @@ interface Group : Contact, CoroutineScope {
...
@@ -169,48 +173,19 @@ interface Group : Contact, CoroutineScope {
*
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
*/
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
Group
>
@JvmName
(
"sendMessageSuspend"
)
@JvmSynthetic
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
Group
>
companion
object
{
companion
object
{
// don't @JvmStatic: JDK 1.8 required
fun
calculateGroupUinByGroupCode
(
groupCode
:
Long
):
Long
/**
fun
calculateGroupCodeByGroupUin
(
groupUin
:
Long
):
Long
* by @kar98k
*/
// don't @JvmStatic: JDK 1.8 required
fun
calculateGroupUinByGroupCode
(
groupCode
:
Long
):
Long
{
var
left
:
Long
=
groupCode
/
1000000L
when
(
left
)
{
in
0
..
10
->
left
+=
202
in
11
..
19
->
left
+=
480
-
11
in
20
..
66
->
left
+=
2100
-
20
in
67
..
156
->
left
+=
2010
-
67
in
157
..
209
->
left
+=
2147
-
157
in
210
..
309
->
left
+=
4100
-
210
in
310
..
499
->
left
+=
3800
-
310
}
return
left
*
1000000L
+
groupCode
%
1000000L
}
fun
calculateGroupCodeByGroupUin
(
groupUin
:
Long
):
Long
{
var
left
:
Long
=
groupUin
/
1000000L
when
(
left
)
{
in
0
+
202
..
10
+
202
->
left
-=
202
in
11
+
480
-
11
..
19
+
480
-
11
->
left
-=
480
-
11
in
20
+
2100
-
20
..
66
+
2100
-
20
->
left
-=
2100
-
20
in
67
+
2010
-
67
..
156
+
2010
-
67
->
left
-=
2010
-
67
in
157
+
2147
-
157
..
209
+
2147
-
157
->
left
-=
2147
-
157
in
210
+
4100
-
210
..
309
+
4100
-
210
->
left
-=
4100
-
210
in
310
+
3800
-
310
..
499
+
3800
-
310
->
left
-=
3800
-
310
}
return
left
*
1000000L
+
groupUin
%
1000000L
}
}
}
@MiraiExperimentalAPI
@MiraiExperimentalAPI
fun
toFullString
():
String
=
"Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
fun
toFullString
():
String
}
}
/**
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
View file @
b7fa7adf
...
@@ -12,27 +12,33 @@
...
@@ -12,27 +12,33 @@
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.WeakRefProperty
import
net.mamoe.mirai.utils.WeakRefProperty
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
import
kotlin.time.Duration
import
kotlin.time.Duration
import
kotlin.time.ExperimentalTime
import
kotlin.time.ExperimentalTime
/**
/**
* 群成员.
* 群成员.
*/
*/
// 不要删除多平台结构, kotlin bug
interface
Member
:
QQ
,
Contact
{
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
expect
abstract
class
Member
()
:
MemberJavaHappyAPI
{
/**
/**
* 所在的群.
* 所在的群.
*/
*/
@WeakRefProperty
@WeakRefProperty
val
group
:
Group
abstract
val
group
:
Group
/**
/**
* 成员的权限, 动态更新.
* 成员的权限, 动态更新.
*
*
* @see MemberPermissionChangeEvent 权限变更事件. 由群主或机器人的操作触发.
* @see MemberPermissionChangeEvent 权限变更事件. 由群主或机器人的操作触发.
*/
*/
val
permission
:
MemberPermission
abstract
val
permission
:
MemberPermission
/**
/**
* 群名片. 可能为空.
* 群名片. 可能为空.
...
@@ -46,7 +52,7 @@ interface Member : QQ, Contact {
...
@@ -46,7 +52,7 @@ interface Member : QQ, Contact {
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
* @throws PermissionDeniedException 无权限修改时
*/
*/
var
nameCard
:
String
abstract
var
nameCard
:
String
/**
/**
* 群头衔.
* 群头衔.
...
@@ -58,7 +64,7 @@ interface Member : QQ, Contact {
...
@@ -58,7 +64,7 @@ interface Member : QQ, Contact {
* @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
* @throws PermissionDeniedException 无权限修改时
*/
*/
var
specialTitle
:
String
abstract
var
specialTitle
:
String
/**
/**
* 被禁言剩余时长. 单位为秒.
* 被禁言剩余时长. 单位为秒.
...
@@ -67,7 +73,7 @@ interface Member : QQ, Contact {
...
@@ -67,7 +73,7 @@ interface Member : QQ, Contact {
* @see mute 设置禁言
* @see mute 设置禁言
* @see unmute 取消禁言
* @see unmute 取消禁言
*/
*/
val
muteTimeRemaining
:
Int
abstract
val
muteTimeRemaining
:
Int
/**
/**
* 禁言.
* 禁言.
...
@@ -87,7 +93,9 @@ interface Member : QQ, Contact {
...
@@ -87,7 +93,9 @@ interface Member : QQ, Contact {
* @see MemberMuteEvent 成员被禁言事件
* @see MemberMuteEvent 成员被禁言事件
* @throws PermissionDeniedException 无权限修改时
* @throws PermissionDeniedException 无权限修改时
*/
*/
suspend
fun
mute
(
durationSeconds
:
Int
)
@JvmName
(
"muteSuspend"
)
@JvmSynthetic
abstract
suspend
fun
mute
(
durationSeconds
:
Int
)
/**
/**
* 解除禁言.
* 解除禁言.
...
@@ -97,7 +105,9 @@ interface Member : QQ, Contact {
...
@@ -97,7 +105,9 @@ interface Member : QQ, Contact {
* @see MemberUnmuteEvent 成员被取消禁言事件.
* @see MemberUnmuteEvent 成员被取消禁言事件.
* @throws PermissionDeniedException 无权限修改时
* @throws PermissionDeniedException 无权限修改时
*/
*/
suspend
fun
unmute
()
@JvmName
(
"unmuteSuspend"
)
@JvmSynthetic
abstract
suspend
fun
unmute
()
/**
/**
* 踢出该成员.
* 踢出该成员.
...
@@ -107,12 +117,19 @@ interface Member : QQ, Contact {
...
@@ -107,12 +117,19 @@ interface Member : QQ, Contact {
* @see MemberLeaveEvent.Kick 成员被踢出事件.
* @see MemberLeaveEvent.Kick 成员被踢出事件.
* @throws PermissionDeniedException 无权限修改时
* @throws PermissionDeniedException 无权限修改时
*/
*/
suspend
fun
kick
(
message
:
String
=
""
)
@JvmName
(
"kickSuspend"
)
@JvmSynthetic
abstract
suspend
fun
kick
(
message
:
String
=
""
)
/**
/**
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
*/
*/
override
fun
equals
(
other
:
Any
?):
Boolean
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
abstract
override
fun
hashCode
():
Int
}
}
/**
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
View file @
b7fa7adf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
...
@@ -22,6 +22,8 @@ import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
...
@@ -22,6 +22,8 @@ import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
/**
/**
* QQ 对象.
* QQ 对象.
...
@@ -35,33 +37,32 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI
...
@@ -35,33 +37,32 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI
*
*
* @author Him188moe
* @author Him188moe
*/
*/
interface
QQ
:
Contact
,
CoroutineScope
{
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
expect
abstract
class
QQ
()
:
Contact
,
CoroutineScope
{
/**
/**
*
QQ 号码
*
请求头像下载链接
*/
*/
override
val
id
:
Long
// @MiraiExperimentalAPI
//suspend fun queryAvatar(): AvatarLink
/**
/**
*
昵称
*
QQ 号码
*/
*/
val
nick
:
String
abstract
override
val
id
:
Long
/**
/**
*
请求头像下载链接
*
昵称
*/
*/
// @MiraiExperimentalAPI
abstract
val
nick
:
String
//suspend fun queryAvatar(): AvatarLink
/**
/**
* 查询用户资料
* 查询用户资料
*/
*/
@MiraiExperimentalAPI
(
"还未支持"
)
@MiraiExperimentalAPI
(
"还未支持"
)
suspend
fun
queryProfile
():
Profile
abstract
suspend
fun
queryProfile
():
Profile
/**
/**
* 头像下载链接
* 头像下载链接
*/
*/
val
avatarUrl
:
String
get
()
=
"http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
val
avatarUrl
:
String
/**
/**
* 查询曾用名.
* 查询曾用名.
...
@@ -71,13 +72,13 @@ interface QQ : Contact, CoroutineScope {
...
@@ -71,13 +72,13 @@ interface QQ : Contact, CoroutineScope {
* - 共同群内的群名片
* - 共同群内的群名片
*/
*/
@MiraiExperimentalAPI
(
"还未支持"
)
@MiraiExperimentalAPI
(
"还未支持"
)
suspend
fun
queryPreviousNameList
():
PreviousNameList
abstract
suspend
fun
queryPreviousNameList
():
PreviousNameList
/**
/**
* 查询机器人账号给这个人设置的备注
* 查询机器人账号给这个人设置的备注
*/
*/
@MiraiExperimentalAPI
(
"还未支持"
)
@MiraiExperimentalAPI
(
"还未支持"
)
suspend
fun
queryRemark
():
FriendNameRemark
abstract
suspend
fun
queryRemark
():
FriendNameRemark
/**
/**
* 向这个对象发送消息.
* 向这个对象发送消息.
...
@@ -90,5 +91,9 @@ interface QQ : Contact, CoroutineScope {
...
@@ -90,5 +91,9 @@ interface QQ : Contact, CoroutineScope {
*
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
*/
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
QQ
>
@JvmSynthetic
@JvmName
(
"sendMessageSuspend"
)
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
QQ
>
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/jvmHappy.kt
0 → 100644
View file @
b7fa7adf
/*
* 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.contact
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* [Contact] 中为了让 `Java` 更容易调用的 API
*/
@MiraiInternalAPI
@JavaHappyAPI
expect
abstract
class
ContactJavaHappyAPI
/**
* [Member] 中为了让 `Java` 更容易调用的 API
*/
@MiraiInternalAPI
@JavaHappyAPI
expect
abstract
class
MemberJavaHappyAPI
:
QQ
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/javaHappy.kt
View file @
b7fa7adf
...
@@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
...
@@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
*/
*/
@MiraiInternalAPI
@MiraiInternalAPI
@Experimental
(
level
=
Experimental
.
Level
.
ERROR
)
@Experimental
(
level
=
Experimental
.
Level
.
ERROR
)
@Target
(
AnnotationTarget
.
PROPERTY
,
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
TYPE
)
@Target
(
AnnotationTarget
.
PROPERTY
,
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
TYPE
,
AnnotationTarget
.
CLASS
)
annotation
class
JavaHappyAPI
annotation
class
JavaHappyAPI
/**
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/OverFileSizeMaxException.kt
View file @
b7fa7adf
...
@@ -17,5 +17,5 @@ import kotlin.jvm.JvmName
...
@@ -17,5 +17,5 @@ import kotlin.jvm.JvmName
/**
/**
* 图片文件过大
* 图片文件过大
*/
*/
// 不要删除多平台结构, 这是 kotlin 的 bug
class
OverFileSizeMaxException
:
IllegalStateException
()
expect
class
OverFileSizeMaxException
()
:
IllegalStateException
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaHappyAPI.kt
View file @
b7fa7adf
...
@@ -170,7 +170,7 @@ actual abstract class BotJavaHappyAPI actual constructor() {
...
@@ -170,7 +170,7 @@ actual abstract class BotJavaHappyAPI actual constructor() {
}
}
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
private
fun
<
R
>
Bot
.
future
(
block
:
suspend
Bot
.()
->
R
):
Future
<
R
>
{
internal
fun
<
R
,
C
:
CoroutineScope
>
C
.
future
(
block
:
suspend
C
.()
->
R
):
Future
<
R
>
{
val
future
=
object
:
Future
<
R
>
{
val
future
=
object
:
Future
<
R
>
{
val
value
:
CompletableDeferred
<
R
>
=
CompletableDeferred
()
val
value
:
CompletableDeferred
<
R
>
=
CompletableDeferred
()
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Contact.kt
0 → 100644
View file @
b7fa7adf
/*
* 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.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.BeforeImageUploadEvent
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.ImageUploadEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.id
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.OverFileSizeMaxException
import
net.mamoe.mirai.utils.WeakRefProperty
/**
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
*
* @author Him188moe
*/
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
actual
abstract
class
Contact
:
CoroutineScope
,
ContactJavaHappyAPI
()
{
/**
* 这个联系人所属 [Bot].
*/
@WeakRefProperty
actual
abstract
val
bot
:
Bot
/**
* 可以是 QQ 号码或者群号码.
*
* 对于 [QQ], `uin` 与 `id` 是相同的意思.
* 对于 [Group], `groupCode` 与 `id` 是相同的意思.
*
* @see QQ.id
* @see Group.id
*/
actual
abstract
val
id
:
Long
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
*/
@JvmName
(
"sendMessageSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
out
Contact
>
/**
* 上传一个图片以备发送.
*
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
* @see ImageUploadEvent 图片发送完成事件
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB)
*/
@JvmName
(
"uploadImageSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
/**
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
*
* 注:
* [id] 相同的 [Member] 和 [QQ], 他们并不 [equals].
* 因为, [Member] 含义为群员, 必属于一个群.
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
*/
actual
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
actual
abstract
override
fun
hashCode
():
Int
/**
* @return "QQ($id)" or "Group($id)" or "Member($id)"
*/
actual
abstract
override
fun
toString
():
String
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJavaHappyAPI.kt
0 → 100644
View file @
b7fa7adf
This diff is collapsed.
Click to expand it.
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt
0 → 100644
View file @
b7fa7adf
/*
* 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.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
/**
* 群. 在 QQ Android 中叫做 "Troop"
*/
actual
abstract
class
Group
:
Contact
(),
CoroutineScope
{
/**
* 群名称.
*
* 在修改时将会异步上传至服务器.
* 频繁修改可能会被服务器拒绝.
*
* @see MemberPermissionChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
name
:
String
/**
* 入群公告, 没有时为空字符串.
*
* 在修改时将会异步上传至服务器.
*
* @see GroupEntranceAnnouncementChangeEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
entranceAnnouncement
:
String
/**
* 全体禁言状态. `true` 为开启.
*
* 当前仅能修改状态.
*
* @see GroupMuteAllEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isMuteAll
:
Boolean
/**
* 坦白说状态. `true` 为允许.
*
* 在修改时将会异步上传至服务器.
*
* @see GroupAllowConfessTalkEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isConfessTalkEnabled
:
Boolean
/**
* 允许群员邀请好友入群的状态. `true` 为允许
*
* 在修改时将会异步上传至服务器.
*
* @see GroupAllowMemberInviteEvent
* @throws PermissionDeniedException 无权限修改时将会抛出异常
*/
actual
abstract
var
isAllowMemberInvite
:
Boolean
/**
* 自动加群审批
*/
actual
abstract
val
isAutoApproveEnabled
:
Boolean
/**
* 匿名聊天
*/
actual
abstract
val
isAnonymousChatEnabled
:
Boolean
/**
* 同为 groupCode, 用户看到的群号码.
*/
actual
abstract
override
val
id
:
Long
/**
* 群主.
*
* @return 若机器人是群主, 返回 [botAsMember]. 否则返回相应的成员
*/
actual
abstract
val
owner
:
Member
/**
* [Bot] 在群内的 [Member] 实例
*/
@MiraiExperimentalAPI
actual
abstract
val
botAsMember
:
Member
/**
* 机器人被禁言还剩余多少秒
*
* @see BotMuteEvent 机器人被禁言事件
* @see isBotMuted 判断机器人是否正在被禁言
*/
actual
abstract
val
botMuteRemaining
:
Int
/**
* 机器人在这个群里的权限
*
* @see Group.checkBotPermission 检查 [Bot] 在这个群里的权限
* @see Group.checkBotPermissionOperator 要求 [Bot] 在这个群里的权限为 [管理员或群主][MemberPermission.isOperator]
*
* @see BotGroupPermissionChangeEvent 机器人群员修改
*/
actual
abstract
val
botPermission
:
MemberPermission
/**
* 群头像下载链接.
*/
actual
val
avatarUrl
:
String
get
()
=
"https://p.qlogo.cn/gh/$id/${id}_1/640"
/**
* 群成员列表, 不含机器人自己, 含群主.
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
*/
actual
abstract
val
members
:
ContactList
<
Member
>
/**
* 获取群成员实例. 不存在时抛出 [kotlin.NoSuchElementException]
*/
actual
abstract
operator
fun
get
(
id
:
Long
):
Member
/**
* 获取群成员实例, 不存在则 null
*/
actual
abstract
fun
getOrNull
(
id
:
Long
):
Member
?
/**
* 检查此 id 的群成员是否存在
*/
actual
abstract
operator
fun
contains
(
id
:
Long
):
Boolean
/**
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
quit
():
Boolean
/**
* 构造一个 [Member].
* 非特殊情况请不要使用这个函数. 优先使用 [get].
*/
@JvmName
(
"newMember"
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
,
"FunctionName"
)
@MiraiExperimentalAPI
(
"dangerous"
)
actual
abstract
fun
Member
(
memberInfo
:
MemberInfo
):
Member
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmSynthetic
actual
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
Group
>
actual
companion
object
{
/**
* by @kar98k
*/
actual
fun
calculateGroupUinByGroupCode
(
groupCode
:
Long
):
Long
{
var
left
:
Long
=
groupCode
/
1000000L
when
(
left
)
{
in
0
..
10
->
left
+=
202
in
11
..
19
->
left
+=
480
-
11
in
20
..
66
->
left
+=
2100
-
20
in
67
..
156
->
left
+=
2010
-
67
in
157
..
209
->
left
+=
2147
-
157
in
210
..
309
->
left
+=
4100
-
210
in
310
..
499
->
left
+=
3800
-
310
}
return
left
*
1000000L
+
groupCode
%
1000000L
}
actual
fun
calculateGroupCodeByGroupUin
(
groupUin
:
Long
):
Long
{
var
left
:
Long
=
groupUin
/
1000000L
when
(
left
)
{
in
0
+
202
..
10
+
202
->
left
-=
202
in
11
+
480
-
11
..
19
+
480
-
11
->
left
-=
480
-
11
in
20
+
2100
-
20
..
66
+
2100
-
20
->
left
-=
2100
-
20
in
67
+
2010
-
67
..
156
+
2010
-
67
->
left
-=
2010
-
67
in
157
+
2147
-
157
..
209
+
2147
-
157
->
left
-=
2147
-
157
in
210
+
4100
-
210
..
309
+
4100
-
210
->
left
-=
4100
-
210
in
310
+
3800
-
310
..
499
+
3800
-
310
->
left
-=
3800
-
310
}
return
left
*
1000000L
+
groupUin
%
1000000L
}
}
@MiraiExperimentalAPI
actual
fun
toFullString
():
String
{
return
"Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Member.kt
0 → 100644
View file @
b7fa7adf
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.JavaHappyAPI
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.WeakRefProperty
/**
* 群成员.
*/
@UseExperimental
(
MiraiInternalAPI
::
class
,
JavaHappyAPI
::
class
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
actual
abstract
class
Member
:
MemberJavaHappyAPI
()
{
/**
* 所在的群.
*/
@WeakRefProperty
actual
abstract
val
group
:
Group
/**
* 成员的权限, 动态更新.
*
* @see MemberPermissionChangeEvent 权限变更事件. 由群主或机器人的操作触发.
*/
actual
abstract
val
permission
:
MemberPermission
/**
* 群名片. 可能为空.
*
* 管理员和群主都可修改任何人(包括群主)的群名片.
*
* 在修改时将会异步上传至服务器.
*
* @see [nameCardOrNick] 获取非空群名片或昵称
*
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
*/
actual
abstract
var
nameCard
:
String
/**
* 群头衔.
*
* 仅群主可以修改群头衔.
*
* 在修改时将会异步上传至服务器.
*
* @see MemberSpecialTitleChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件. 修改时也会触发此事件.
* @throws PermissionDeniedException 无权限修改时
*/
actual
abstract
var
specialTitle
:
String
/**
* 被禁言剩余时长. 单位为秒.
*
* @see isMuted 判断改成员是否处于禁言状态
* @see mute 设置禁言
* @see unmute 取消禁言
*/
actual
abstract
val
muteTimeRemaining
:
Int
/**
* 禁言.
*
* QQ 中最小操作和显示的时间都是一分钟.
* 机器人可以实现精确到秒, 会被客户端显示为 1 分钟但不影响实际禁言时间.
*
* 管理员可禁言成员, 群主可禁言管理员和群员.
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 机器人无权限时返回 `false`
*
* @see Int.minutesToSeconds
* @see Int.hoursToSeconds
* @see Int.daysToSeconds
*
* @see MemberMuteEvent 成员被禁言事件
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"muteSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
mute
(
durationSeconds
:
Int
)
/**
* 解除禁言.
*
* 管理员可解除成员的禁言, 群主可解除管理员和群员的禁言.
*
* @see MemberUnmuteEvent 成员被取消禁言事件.
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"muteSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
unmute
()
/**
* 踢出该成员.
*
* 管理员可踢出成员, 群主可踢出管理员和群员.
*
* @see MemberLeaveEvent.Kick 成员被踢出事件.
* @throws PermissionDeniedException 无权限修改时
*/
@JvmName
(
"muteSuspend"
)
@JvmSynthetic
actual
abstract
suspend
fun
kick
(
message
:
String
)
/**
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
*/
actual
abstract
override
fun
equals
(
other
:
Any
?):
Boolean
/**
* @return `bot.hashCode() * 31 + id.hashCode()`
*/
actual
abstract
override
fun
hashCode
():
Int
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/QQ.kt
0 → 100644
View file @
b7fa7adf
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.contact
import
kotlinx.coroutines.CoroutineScope
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.data.FriendNameRemark
import
net.mamoe.mirai.data.PreviousNameList
import
net.mamoe.mirai.data.Profile
import
net.mamoe.mirai.event.events.EventCancelledException
import
net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
/**
* QQ 对象.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
*
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
*
* A QQ instance helps you to receive event from or sendPacket event to.
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
*
* @author Him188moe
*/
@Suppress
(
"INAPPLICABLE_JVM_NAME"
)
actual
abstract
class
QQ
:
Contact
(),
CoroutineScope
{
/**
* 请求头像下载链接
*/
// @MiraiExperimentalAPI
//suspend fun queryAvatar(): AvatarLink
/**
* QQ 号码
*/
actual
abstract
override
val
id
:
Long
/**
* 昵称
*/
actual
abstract
val
nick
:
String
/**
* 查询用户资料
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryProfile
():
Profile
/**
* 头像下载链接
*/
actual
val
avatarUrl
:
String
get
()
=
"http://q1.qlogo.cn/g?b=qq&nk=$id&s=640"
/**
* 查询曾用名.
*
* 曾用名可能是:
* - 昵称
* - 共同群内的群名片
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryPreviousNameList
():
PreviousNameList
/**
* 查询机器人账号给这个人设置的备注
*/
@MiraiExperimentalAPI
(
"还未支持"
)
actual
abstract
suspend
fun
queryRemark
():
FriendNameRemark
/**
* 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*
* @throws EventCancelledException 当发送消息事件被取消
* @throws IllegalStateException 发送群消息时若 [Bot] 被禁言抛出
*
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
*/
@JvmName
(
"sendMessageSuspend"
)
@JvmSynthetic
actual
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
):
MessageReceipt
<
QQ
>
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt
View file @
b7fa7adf
...
@@ -155,35 +155,35 @@ suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this)
...
@@ -155,35 +155,35 @@ suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this)
// region Contact.uploadImage(IMAGE)
// region Contact.uploadImage(IMAGE)
/**
/**
* 在 [Dispatchers.IO] 中将图片
发送到指定联系人
. 不会保存临时文件
* 在 [Dispatchers.IO] 中将图片
上传, 但不发送
. 不会保存临时文件
* @throws OverFileSizeMaxException
* @throws OverFileSizeMaxException
*/
*/
@Throws
(
OverFileSizeMaxException
::
class
)
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
bufferedImage
:
BufferedImage
):
Image
=
bufferedImage
.
upload
(
this
)
suspend
inline
fun
Contact
.
uploadImage
(
bufferedImage
:
BufferedImage
):
Image
=
bufferedImage
.
upload
(
this
)
/**
/**
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片
发送到指定联系人
* 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片
上传, 但不发送
* @throws OverFileSizeMaxException
* @throws OverFileSizeMaxException
*/
*/
@Throws
(
OverFileSizeMaxException
::
class
)
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageUrl
:
URL
):
Image
=
imageUrl
.
uploadAsImage
(
this
)
suspend
inline
fun
Contact
.
uploadImage
(
imageUrl
:
URL
):
Image
=
imageUrl
.
uploadAsImage
(
this
)
/**
/**
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片
发送到指定联系人
* 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片
上传, 但不发送
* @throws OverFileSizeMaxException
* @throws OverFileSizeMaxException
*/
*/
@Throws
(
OverFileSizeMaxException
::
class
)
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageInput
:
Input
):
Image
=
imageInput
.
uploadAsImage
(
this
)
suspend
inline
fun
Contact
.
uploadImage
(
imageInput
:
Input
):
Image
=
imageInput
.
uploadAsImage
(
this
)
/**
/**
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片
发送到指定联系人
* 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片
上传, 但不发送
* @throws OverFileSizeMaxException
* @throws OverFileSizeMaxException
*/
*/
@Throws
(
OverFileSizeMaxException
::
class
)
@Throws
(
OverFileSizeMaxException
::
class
)
suspend
inline
fun
Contact
.
uploadImage
(
imageStream
:
InputStream
):
Image
=
imageStream
.
uploadAsImage
(
this
)
suspend
inline
fun
Contact
.
uploadImage
(
imageStream
:
InputStream
):
Image
=
imageStream
.
uploadAsImage
(
this
)
/**
/**
* 在 [Dispatchers.IO] 中将文件作为图片
发送到指定联系人
* 在 [Dispatchers.IO] 中将文件作为图片
上传, 但不发送
* @throws OverFileSizeMaxException
* @throws OverFileSizeMaxException
*/
*/
@Throws
(
OverFileSizeMaxException
::
class
)
@Throws
(
OverFileSizeMaxException
::
class
)
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/OverFileSizeMaxException.kt
0 → 100644
View file @
b7fa7adf
package
net.mamoe.mirai.utils
/**
* 图片文件过大
*/
actual
class
OverFileSizeMaxException
:
IllegalStateException
()
\ 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