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
b797ef3c
Commit
b797ef3c
authored
Nov 24, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Redesign Contacts: Use interfaces and hide internal implementations
parent
1a56235c
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
327 additions
and
210 deletions
+327
-210
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
+19
-14
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
...i-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
+2
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
.../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
+16
-186
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+57
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
+31
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
+33
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/data/Profile.kt
...commonMain/kotlin/net.mamoe.mirai/contact/data/Profile.kt
+52
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
...in/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
+87
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
.../src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
+0
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/Profile.kt
...mamoe.mirai/network/protocol/tim/packet/action/Profile.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt
...i/network/protocol/tim/packet/event/EventPacketFactory.kt
+0
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt
...irai/network/protocol/tim/packet/event/MemberKickEvent.kt
+25
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/PasswordSubmission.kt
...i/network/protocol/tim/packet/login/PasswordSubmission.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
+2
-0
No files found.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
View file @
b797ef3c
...
@@ -7,6 +7,8 @@ import kotlinx.coroutines.sync.Mutex
...
@@ -7,6 +7,8 @@ import kotlinx.coroutines.sync.Mutex
import
kotlinx.coroutines.sync.withLock
import
kotlinx.coroutines.sync.withLock
import
net.mamoe.mirai.Bot.ContactSystem
import
net.mamoe.mirai.Bot.ContactSystem
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.contact.internal.GroupImpl
import
net.mamoe.mirai.contact.internal.QQImpl
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
...
@@ -95,27 +97,31 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
...
@@ -95,27 +97,31 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
* @see Bot.contacts
* @see Bot.contacts
*/
*/
inner
class
ContactSystem
internal
constructor
()
{
inner
class
ContactSystem
internal
constructor
()
{
inline
val
bot
:
Bot
get
()
=
this
@Bot
val
bot
:
Bot
get
()
=
this
@Bot
private
val
_groups
=
ContactList
<
Group
>(
)
@Suppress
(
"PropertyName"
)
private
lateinit
var
groupsUpdater
:
Job
internal
val
_groups
=
MutableContactList
<
Group
>()
val
groups
=
ContactList
<
Group
>()
internal
lateinit
var
groupsUpdater
:
Job
private
val
groupsLock
=
Mutex
()
private
val
groupsLock
=
Mutex
()
private
val
_qqs
=
ContactList
<
QQ
>()
//todo 实现群列表和好友列表获取
val
groups
:
ContactList
<
Group
>
=
ContactList
(
_groups
)
private
lateinit
var
qqUpdaterJob
:
Job
val
qqs
:
ContactList
<
QQ
>
=
_qqs
@Suppress
(
"PropertyName"
)
internal
val
_qqs
=
MutableContactList
<
QQ
>()
//todo 实现群列表和好友列表获取
internal
lateinit
var
qqUpdaterJob
:
Job
private
val
qqsLock
=
Mutex
()
private
val
qqsLock
=
Mutex
()
val
qqs
:
ContactList
<
QQ
>
=
ContactList
(
_qqs
)
/**
/**
* 获取缓存的 QQ 对象. 若没有对应的缓存, 则会创建一个.
* 获取缓存的 QQ 对象. 若没有对应的缓存, 则会创建一个.
*
*
* 注: 这个方法是线程安全的
* 注: 这个方法是线程安全的
*/
*/
suspend
fun
getQQ
(
id
:
UInt
):
QQ
=
suspend
fun
getQQ
(
id
:
UInt
):
QQ
=
if
(
qqs
.
containsKey
(
id
))
qqs
[
id
]
!!
if
(
_qqs
.
containsKey
(
id
))
_
qqs
[
id
]
!!
else
qqsLock
.
withLock
{
else
qqsLock
.
withLock
{
qqs
.
getOrPut
(
id
)
{
QQ
(
bot
,
id
)
}
_qqs
.
getOrPut
(
id
)
{
QQImpl
(
bot
,
id
)
}
}
}
/**
/**
...
@@ -131,12 +137,11 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
...
@@ -131,12 +137,11 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
* 注: 这个方法是线程安全的
* 注: 这个方法是线程安全的
*/
*/
suspend
fun
getGroup
(
id
:
GroupId
):
Group
=
id
.
value
.
let
{
suspend
fun
getGroup
(
id
:
GroupId
):
Group
=
id
.
value
.
let
{
if
(
groups
.
containsKey
(
it
))
groups
[
it
]
!!
if
(
_groups
.
containsKey
(
it
))
_
groups
[
it
]
!!
else
groupsLock
.
withLock
{
else
groupsLock
.
withLock
{
groups
.
getOrPut
(
it
)
{
Group
(
bot
,
id
)
}
_groups
.
getOrPut
(
it
)
{
GroupImpl
(
bot
,
id
)
}
}
}
}
}
}
}
suspend
inline
fun
Int
.
qq
():
QQ
=
getQQ
(
this
.
coerceAtLeastOrFail
(
0
).
toUInt
())
suspend
inline
fun
Int
.
qq
():
QQ
=
getQQ
(
this
.
coerceAtLeastOrFail
(
0
).
toUInt
())
...
@@ -152,8 +157,8 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
...
@@ -152,8 +157,8 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
suspend
fun
close
()
{
suspend
fun
close
()
{
network
.
close
()
network
.
close
()
this
.
coroutineContext
.
cancelChildren
()
this
.
coroutineContext
.
cancelChildren
()
contacts
.
groups
.
clear
()
contacts
.
_
groups
.
clear
()
contacts
.
qqs
.
clear
()
contacts
.
_
qqs
.
clear
()
}
}
companion
object
{
companion
object
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
View file @
b797ef3c
...
@@ -38,14 +38,12 @@ suspend inline fun Bot.getGroup(internalId: GroupInternalId): Group = this.conta
...
@@ -38,14 +38,12 @@ suspend inline fun Bot.getGroup(internalId: GroupInternalId): Group = this.conta
/**
/**
* 取得机器人的群成员列表
* 取得机器人的群成员列表
*/
*/
inline
val
Bot
.
groups
:
ContactList
<
Group
>
inline
val
Bot
.
groups
:
ContactList
<
Group
>
get
()
=
this
.
contacts
.
groups
get
()
=
this
.
contacts
.
groups
/**
/**
* 取得机器人的好友列表
* 取得机器人的好友列表
*/
*/
inline
val
Bot
.
qqs
:
ContactList
<
QQ
>
inline
val
Bot
.
qqs
:
ContactList
<
QQ
>
get
()
=
this
.
contacts
.
qqs
get
()
=
this
.
contacts
.
qqs
/**
/**
* 以 [BotSession] 作为接收器 (receiver) 并调用 [block], 返回 [block] 的返回值.
* 以 [BotSession] 作为接收器 (receiver) 并调用 [block], 返回 [block] 的返回值.
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
,
"MemberVisibilityCanBePrivate"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
com.soywiz.klock.Date
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.Deferred
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.MessageChain
import
net.mamoe.mirai.message.MessageChain
import
net.mamoe.mirai.message.singleChain
import
net.mamoe.mirai.message.singleChain
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.protocol.tim.packet.action.RequestProfileDetailsPacket
import
net.mamoe.mirai.network.protocol.tim.packet.action.RequestProfileDetailsResponse
import
net.mamoe.mirai.network.protocol.tim.packet.action.SendFriendMessagePacket
import
net.mamoe.mirai.network.protocol.tim.packet.action.SendGroupMessagePacket
import
net.mamoe.mirai.network.sessionKey
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.sendPacket
import
net.mamoe.mirai.utils.SuspendLazy
import
net.mamoe.mirai.utils.internal.PositiveNumbers
import
net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import
net.mamoe.mirai.withSession
import
net.mamoe.mirai.withSession
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.InvocationKind
import
kotlin.contracts.contract
import
kotlin.contracts.contract
class
ContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
by
mutableMapOf
()
/**
/**
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
* 联系人. 虽然叫做联系人, 但他的子类有 [QQ] 和 [群][Group].
*
*
* @param bot 这个联系人所属 [Bot]
* @param id 可以是 QQ 号码或者群号码 [GroupId].
*
* @author Him188moe
* @author Him188moe
*/
*/
sealed
class
Contact
(
val
bot
:
Bot
,
val
id
:
UInt
)
{
interface
Contact
{
/**
* 这个联系人所属 [Bot]
*/
val
bot
:
Bot
/**
* 可以是 QQ 号码或者群号码 [GroupId].
*/
val
id
:
UInt
/**
/**
* 向这个对象发送消息.
* 向这个对象发送消息.
*
*
* 速度太快会被服务器屏蔽(无响应). 在测试中不延迟地发送 6 条消息就会被屏蔽之后的数据包 1 秒左右.
* 速度太快会被服务器屏蔽(无响应). 在测试中不延迟地发送 6 条消息就会被屏蔽之后的数据包 1 秒左右.
*/
*/
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
)
suspend
fun
sendMessage
(
message
:
MessageChain
)
//这两个方法应写为扩展函数, 但为方便 import 还是写在这里
//这两个方法应写为扩展函数, 但为方便 import 还是写在这里
...
@@ -51,62 +43,6 @@ sealed class Contact(val bot: Bot, val id: UInt) {
...
@@ -51,62 +43,6 @@ sealed class Contact(val bot: Bot, val id: UInt) {
suspend
fun
sendMessage
(
message
:
Message
)
=
sendMessage
(
message
.
singleChain
())
suspend
fun
sendMessage
(
message
:
Message
)
=
sendMessage
(
message
.
singleChain
())
}
}
/**
* 一般的用户可见的 ID.
* 在 TIM/QQ 客户端中所看到的的号码均是这个 ID.
*
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
*
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
*/
inline
class
GroupId
(
inline
val
value
:
UInt
)
/**
* 将 [this] 转为 [GroupId].
*/
fun
UInt
.
groupId
():
GroupId
=
GroupId
(
this
)
/**
* 将无符号整数格式的 [Long] 转为 [GroupId].
*
* 注: 在 Java 中常用 [Long] 来表示 [UInt]
*/
fun
@
receiver
:
PositiveNumbers
Long
.
groupId
():
GroupId
=
GroupId
(
this
.
coerceAtLeastOrFail
(
0
).
toUInt
())
/**
* 一些群 API 使用的 ID. 在使用时会特别注明
*
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
*
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
*/
inline
class
GroupInternalId
(
inline
val
value
:
UInt
)
/**
* 群.
*
* Group ID 与 Group Number 并不是同一个值.
* - Group Number([Group.id]) 是通常使用的群号码.(在 QQ 客户端中可见)
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
* @author Him188moe
*/
@Suppress
(
"MemberVisibilityCanBePrivate"
,
"CanBeParameter"
)
class
Group
internal
constructor
(
bot
:
Bot
,
val
groupId
:
GroupId
)
:
Contact
(
bot
,
groupId
.
value
)
{
val
internalId
=
GroupId
(
id
).
toInternalId
()
val
members
:
ContactList
<
Member
>
get
()
=
TODO
(
"Implementing group members is less important"
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
sendPacket
(
SendGroupMessagePacket
(
bot
.
qqAccount
,
internalId
,
bot
.
sessionKey
,
message
))
}
override
fun
toString
():
String
=
"Group(${this.id})"
companion
object
}
/**
/**
* 以 [BotSession] 作为接收器 (receiver) 并调用 [block], 返回 [block] 的返回值.
* 以 [BotSession] 作为接收器 (receiver) 并调用 [block], 返回 [block] 的返回值.
* 这个方法将能帮助使用在 [BotSession] 中定义的一些扩展方法, 如 [BotSession.sendAndExpectAsync]
* 这个方法将能帮助使用在 [BotSession] 中定义的一些扩展方法, 如 [BotSession.sendAndExpectAsync]
...
@@ -120,117 +56,11 @@ inline fun <R> Contact.withSession(block: BotSession.() -> R): R {
...
@@ -120,117 +56,11 @@ inline fun <R> Contact.withSession(block: BotSession.() -> R): R {
}
}
/**
/**
* QQ 对象.
* 只读联系人列表
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
* 它不能被直接构造. 任何时候都应从 [Bot.qq], [Bot.ContactSystem.getQQ], [BotSession.qq] 或事件中获取.
*
* 对于同一个 [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
*/
*/
open
class
QQ
internal
constructor
(
bot
:
Bot
,
id
:
UInt
)
:
Contact
(
bot
,
id
)
{
class
ContactList
<
C
:
Contact
>
internal
constructor
(
private
val
delegate
:
MutableContactList
<
C
>)
:
Map
<
UInt
,
C
>
by
delegate
private
var
_profile
:
Profile
?
=
null
private
val
_initialProfile
by
bot
.
network
.
SuspendLazy
{
updateProfile
()
}
/**
* 用户资料.
*/
val
profile
:
Deferred
<
Profile
>
get
()
=
if
(
_profile
==
null
)
_initialProfile
else
CompletableDeferred
(
_profile
!!
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
=
bot
.
sendPacket
(
SendFriendMessagePacket
(
bot
.
qqAccount
,
id
,
bot
.
sessionKey
,
message
))
/**
* 更新个人资料.
* 将会同步更新 property [profile]
*/
suspend
fun
updateProfile
():
Profile
=
bot
.
withSession
{
_profile
=
RequestProfileDetailsPacket
(
bot
.
qqAccount
,
id
,
sessionKey
)
.
sendAndExpect
<
RequestProfileDetailsResponse
,
Profile
>
{
it
.
profile
}
return
_profile
!!
}
override
fun
toString
():
String
=
"QQ(${this.id})"
}
/**
/**
*
群成员
*
可修改联系人列表. 只会在内部使用.
*/
*/
class
Member
internal
constructor
(
bot
:
Bot
,
id
:
UInt
,
val
group
:
Group
)
:
QQ
(
bot
,
id
)
{
internal
class
MutableContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
by
mutableMapOf
()
init
{
\ No newline at end of file
TODO
(
"Group member implementation"
)
}
override
fun
toString
():
String
=
"Member(${this.id})"
}
/**
* 群成员的权限
*/
enum
class
MemberPermission
{
/**
* 群主
*/
OWNER
,
/**
* 管理员
*/
OPERATOR
,
/**
* 一般群成员
*/
MEMBER
;
}
/**
* 个人资料
*/
@Suppress
(
"PropertyName"
)
data class
Profile
(
val
qq
:
UInt
,
val
nickname
:
String
,
val
englishName
:
String
?,
val
chineseName
:
String
?,
val
qAge
:
Int
?,
// q 龄
val
zipCode
:
String
?,
val
phone
:
String
?,
val
gender
:
Gender
,
val
birthday
:
Date
?,
val
personalStatement
:
String
?,
// 个人说明
val
school
:
String
?,
val
homepage
:
String
?,
val
email
:
String
?,
val
company
:
String
?
)
{
override
fun
toString
():
String
=
"Profile(qq=$qq, "
+
"nickname=$nickname, "
+
"gender=$gender, "
+
(
englishName
?.
let
{
"englishName=$englishName, "
}
?:
""
)
+
(
chineseName
?.
let
{
"chineseName=$chineseName, "
}
?:
""
)
+
(
qAge
?.
toString
()
?.
let
{
"qAge=$qAge, "
}
?:
""
)
+
(
zipCode
?.
let
{
"zipCode=$zipCode, "
}
?:
""
)
+
(
phone
?.
let
{
"phone=$phone, "
}
?:
""
)
+
(
birthday
?.
toString
()
?.
let
{
"birthday=$birthday, "
}
?:
""
)
+
(
personalStatement
?.
let
{
"personalStatement=$personalStatement, "
}
?:
""
)
+
(
school
?.
let
{
"school=$school, "
}
?:
""
)
+
(
homepage
?.
let
{
"homepage=$homepage, "
}
?:
""
)
+
(
email
?.
let
{
"email=$email, "
}
?:
""
)
+
(
company
?.
let
{
"company=$company,"
}
?:
""
)
+
")"
// 最终会是 ", )", 但这并不影响什么.
}
/**
* 性别
*/
enum
class
Gender
{
SECRET
,
MALE
,
FEMALE
;
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
0 → 100644
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.utils.internal.PositiveNumbers
import
net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
/**
* 群.
*
* Group ID 与 Group Number 并不是同一个值.
* - Group Number([Group.id]) 是通常使用的群号码.(在 QQ 客户端中可见)
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
* @author Him188moe
*/
interface
Group
:
Contact
{
val
internalId
:
GroupInternalId
val
member
:
ContactList
<
Member
>
suspend
fun
getMember
(
id
:
UInt
):
Member
}
/**
* 一般的用户可见的 ID.
* 在 TIM/QQ 客户端中所看到的的号码均是这个 ID.
*
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
*
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
*/
inline
class
GroupId
(
inline
val
value
:
UInt
)
/**
* 将 [this] 转为 [GroupId].
*/
fun
UInt
.
groupId
():
GroupId
=
GroupId
(
this
)
/**
* 将无符号整数格式的 [Long] 转为 [GroupId].
*
* 注: 在 Java 中常用 [Long] 来表示 [UInt]
*/
fun
@
receiver
:
PositiveNumbers
Long
.
groupId
():
GroupId
=
GroupId
(
this
.
coerceAtLeastOrFail
(
0
).
toUInt
())
/**
* 一些群 API 使用的 ID. 在使用时会特别注明
*
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
*
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
*/
inline
class
GroupInternalId
(
inline
val
value
:
UInt
)
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
0 → 100644
View file @
b797ef3c
package
net.mamoe.mirai.contact
/**
* 群成员.
*
* 使用 [QQ.equals]. 因此同 ID 的群成员和 QQ 是 `==` 的
*/
interface
Member
:
QQ
,
Contact
{
/**
* 所在的群
*/
val
group
:
Group
}
/**
* 群成员的权限
*/
enum
class
MemberPermission
{
/**
* 群主
*/
OWNER
,
/**
* 管理员
*/
OPERATOR
,
/**
* 一般群成员
*/
MEMBER
;
}
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
0 → 100644
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
import
kotlinx.coroutines.Deferred
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.data.Profile
import
net.mamoe.mirai.network.BotSession
/**
* QQ 对象.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
* 它不能被直接构造. 任何时候都应从 [Bot.qq], [Bot.ContactSystem.getQQ], [BotSession.qq] 或事件中获取.
*
* 对于同一个 [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
*/
interface
QQ
:
Contact
{
/**
* 用户资料.
*/
val
profile
:
Deferred
<
Profile
>
/**
* 更新个人资料.
* 将会同步更新 property [profile]
*/
suspend
fun
updateProfile
():
Profile
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/data/Profile.kt
0 → 100644
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact.data
import
com.soywiz.klock.Date
/**
* 个人资料
*/
@Suppress
(
"PropertyName"
)
data class
Profile
(
val
qq
:
UInt
,
val
nickname
:
String
,
val
englishName
:
String
?,
val
chineseName
:
String
?,
val
qAge
:
Int
?,
// q 龄
val
zipCode
:
String
?,
val
phone
:
String
?,
val
gender
:
Gender
,
val
birthday
:
Date
?,
val
personalStatement
:
String
?,
// 个人说明
val
school
:
String
?,
val
homepage
:
String
?,
val
email
:
String
?,
val
company
:
String
?
)
{
override
fun
toString
():
String
=
"Profile(qq=$qq, "
+
"nickname=$nickname, "
+
"gender=$gender, "
+
(
englishName
?.
let
{
"englishName=$englishName, "
}
?:
""
)
+
(
chineseName
?.
let
{
"chineseName=$chineseName, "
}
?:
""
)
+
(
qAge
?.
toString
()
?.
let
{
"qAge=$qAge, "
}
?:
""
)
+
(
zipCode
?.
let
{
"zipCode=$zipCode, "
}
?:
""
)
+
(
phone
?.
let
{
"phone=$phone, "
}
?:
""
)
+
(
birthday
?.
toString
()
?.
let
{
"birthday=$birthday, "
}
?:
""
)
+
(
personalStatement
?.
let
{
"personalStatement=$personalStatement, "
}
?:
""
)
+
(
school
?.
let
{
"school=$school, "
}
?:
""
)
+
(
homepage
?.
let
{
"homepage=$homepage, "
}
?:
""
)
+
(
email
?.
let
{
"email=$email, "
}
?:
""
)
+
(
company
?.
let
{
"company=$company,"
}
?:
""
)
+
")"
// 最终会是 ", )", 但这并不影响什么.
}
/**
* 性别
*/
enum
class
Gender
{
SECRET
,
MALE
,
FEMALE
;
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
0 → 100644
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
,
"MemberVisibilityCanBePrivate"
)
package
net.mamoe.mirai.contact.internal
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.sync.Mutex
import
kotlinx.coroutines.sync.withLock
import
net.mamoe.mirai.*
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.contact.data.Profile
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.MessageChain
import
net.mamoe.mirai.message.singleChain
import
net.mamoe.mirai.network.protocol.tim.packet.action.RequestProfileDetailsPacket
import
net.mamoe.mirai.network.protocol.tim.packet.action.RequestProfileDetailsResponse
import
net.mamoe.mirai.network.protocol.tim.packet.action.SendFriendMessagePacket
import
net.mamoe.mirai.network.protocol.tim.packet.action.SendGroupMessagePacket
import
net.mamoe.mirai.network.sessionKey
import
net.mamoe.mirai.utils.SuspendLazy
internal
sealed
class
ContactImpl
:
Contact
{
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
//这两个方法应写为扩展函数, 但为方便 import 还是写在这里
override
suspend
fun
sendMessage
(
plain
:
String
)
=
sendMessage
(
plain
.
singleChain
())
override
suspend
fun
sendMessage
(
message
:
Message
)
=
sendMessage
(
message
.
singleChain
())
}
@Suppress
(
"MemberVisibilityCanBePrivate"
,
"CanBeParameter"
)
internal
class
GroupImpl
internal
constructor
(
override
val
bot
:
Bot
,
val
groupId
:
GroupId
)
:
ContactImpl
(),
Group
{
override
val
id
:
UInt
get
()
=
groupId
.
value
override
val
internalId
=
GroupId
(
id
).
toInternalId
()
private
val
_members
:
MutableContactList
<
Member
>
=
MutableContactList
()
override
val
member
:
ContactList
<
Member
>
=
ContactList
(
_members
)
private
val
membersLock
:
Mutex
=
Mutex
()
override
suspend
fun
getMember
(
id
:
UInt
):
Member
=
if
(
_members
.
containsKey
(
id
))
_members
[
id
]
!!
else
membersLock
.
withLock
{
_members
.
getOrPut
(
id
)
{
MemberImpl
(
bot
,
bot
.
getQQ
(
id
),
this
)
}
}
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
sendPacket
(
SendGroupMessagePacket
(
bot
.
qqAccount
,
internalId
,
bot
.
sessionKey
,
message
))
}
override
fun
toString
():
String
=
"Group(${this.id})"
}
internal
class
QQImpl
internal
constructor
(
override
val
bot
:
Bot
,
override
val
id
:
UInt
)
:
ContactImpl
(),
QQ
{
private
var
_profile
:
Profile
?
=
null
private
val
_initialProfile
by
bot
.
network
.
SuspendLazy
{
updateProfile
()
}
override
val
profile
:
Deferred
<
Profile
>
get
()
=
if
(
_profile
==
null
)
_initialProfile
else
CompletableDeferred
(
_profile
!!
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
=
bot
.
sendPacket
(
SendFriendMessagePacket
(
bot
.
qqAccount
,
id
,
bot
.
sessionKey
,
message
))
/**
* 更新个人资料.
* 将会同步更新 property [profile]
*/
override
suspend
fun
updateProfile
():
Profile
=
bot
.
withSession
{
_profile
=
RequestProfileDetailsPacket
(
bot
.
qqAccount
,
id
,
sessionKey
)
.
sendAndExpect
<
RequestProfileDetailsResponse
,
Profile
>
{
it
.
profile
}
return
_profile
!!
}
override
fun
toString
():
String
=
"QQ(${this.id})"
}
/**
* 群成员
*/
internal
class
MemberImpl
(
override
val
bot
:
Bot
,
private
val
delegate
:
QQ
,
override
val
group
:
Group
)
:
Member
,
ContactImpl
()
{
override
val
profile
:
Deferred
<
Profile
>
get
()
=
delegate
.
profile
override
val
id
:
UInt
get
()
=
delegate
.
id
override
suspend
fun
updateProfile
():
Profile
=
delegate
.
updateProfile
()
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
=
delegate
.
sendMessage
(
message
)
override
fun
toString
():
String
=
"Member(${this.id})"
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
View file @
b797ef3c
...
@@ -170,8 +170,6 @@ inline class ImageId0x06(override inline val value: String) : ImageId {
...
@@ -170,8 +170,6 @@ inline class ImageId0x06(override inline val value: String) : ImageId {
/**
/**
* 一般是群的图片的 id.
* 一般是群的图片的 id.
*
* @param md5 用于下载图片时提交
*/
*/
class
ImageId0x03
constructor
(
override
inline
val
value
:
String
,
inline
val
uniqueId
:
UInt
,
inline
val
height
:
Int
,
inline
val
width
:
Int
)
:
ImageId
{
class
ImageId0x03
constructor
(
override
inline
val
value
:
String
,
inline
val
uniqueId
:
UInt
,
inline
val
height
:
Int
,
inline
val
width
:
Int
)
:
ImageId
{
override
fun
toString
():
String
=
"ImageId(value=$value, uniqueId=${uniqueId}, height=$height, width=$width)"
override
fun
toString
():
String
=
"ImageId(value=$value, uniqueId=${uniqueId}, height=$height, width=$width)"
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/Profile.kt
View file @
b797ef3c
...
@@ -4,8 +4,8 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
...
@@ -4,8 +4,8 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
import
com.soywiz.klock.Date
import
com.soywiz.klock.Date
import
kotlinx.io.core.*
import
kotlinx.io.core.*
import
net.mamoe.mirai.contact.Gender
import
net.mamoe.mirai.contact.
data.
Gender
import
net.mamoe.mirai.contact.Profile
import
net.mamoe.mirai.contact.
data.
Profile
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.packet.*
import
net.mamoe.mirai.network.protocol.tim.packet.*
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.*
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt
View file @
b797ef3c
...
@@ -64,7 +64,6 @@ object EventPacketFactory : PacketFactory<Packet, SessionKey>(SessionKey) {
...
@@ -64,7 +64,6 @@ object EventPacketFactory : PacketFactory<Packet, SessionKey>(SessionKey) {
}
}
}
}
operator
fun
invoke
(
operator
fun
invoke
(
id
:
PacketId
,
id
:
PacketId
,
sequenceId
:
UShort
,
sequenceId
:
UShort
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt
0 → 100644
View file @
b797ef3c
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.protocol.tim.packet.event
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
/**
* 成员被踢出
*/
data class
MemberKickEvent
(
val
member
:
Member
)
:
EventPacket
@PacketVersion
(
date
=
"2019.11.20"
,
timVersion
=
"2.3.2 (21173)"
)
object
MemberKickEventPacketFactory
:
KnownEventParserAndHandler
<
MemberKickEvent
>(
0
x0022u
)
{
override
suspend
fun
ByteReadPacket
.
parse
(
bot
:
Bot
,
identity
:
EventPacketIdentity
):
MemberKickEvent
{
TODO
()
// return MemberKickEvent()
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/PasswordSubmission.kt
View file @
b797ef3c
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
package
net.mamoe.mirai.network.protocol.tim.packet.login
package
net.mamoe.mirai.network.protocol.tim.packet.login
import
kotlinx.io.core.*
import
kotlinx.io.core.*
import
net.mamoe.mirai.contact.Gender
import
net.mamoe.mirai.contact.
data.
Gender
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.packet.*
import
net.mamoe.mirai.network.protocol.tim.packet.*
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
View file @
b797ef3c
...
@@ -61,6 +61,7 @@ class ExternalImage(
...
@@ -61,6 +61,7 @@ class ExternalImage(
suspend
fun
ExternalImage
.
sendTo
(
contact
:
Contact
)
=
when
(
contact
)
{
suspend
fun
ExternalImage
.
sendTo
(
contact
:
Contact
)
=
when
(
contact
)
{
is
Group
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
is
Group
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
is
QQ
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
is
QQ
->
contact
.
uploadImage
(
this
).
sendTo
(
contact
)
else
->
assertUnreachable
()
}
}
/**
/**
...
@@ -72,6 +73,7 @@ suspend fun ExternalImage.sendTo(contact: Contact) = when (contact) {
...
@@ -72,6 +73,7 @@ suspend fun ExternalImage.sendTo(contact: Contact) = when (contact) {
suspend
fun
ExternalImage
.
upload
(
contact
:
Contact
):
Image
=
when
(
contact
)
{
suspend
fun
ExternalImage
.
upload
(
contact
:
Contact
):
Image
=
when
(
contact
)
{
is
Group
->
contact
.
uploadImage
(
this
).
image
()
is
Group
->
contact
.
uploadImage
(
this
).
image
()
is
QQ
->
contact
.
uploadImage
(
this
).
image
()
is
QQ
->
contact
.
uploadImage
(
this
).
image
()
else
->
assertUnreachable
()
}
}
/**
/**
...
...
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