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
fdb3be94
Commit
fdb3be94
authored
Oct 18, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve performance
parent
24404f9a
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
279 additions
and
243 deletions
+279
-243
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/internal/MessageDataInternal.kt
...n/net.mamoe.mirai/message/internal/MessageDataInternal.kt
+11
-9
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
...nMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
+9
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
...c/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
+12
-10
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
....mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
+13
-17
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/ActionPacketHandler.kt
...mirai/network/protocol/tim/handler/ActionPacketHandler.kt
+6
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/DataPacketSocketAdapter.kt
...i/network/protocol/tim/handler/DataPacketSocketAdapter.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/EventPacketHandler.kt
....mirai/network/protocol/tim/handler/EventPacketHandler.kt
+3
-8
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/TemporaryPacketHandler.kt
...ai/network/protocol/tim/handler/TemporaryPacketHandler.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
.../net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
+6
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Packet.kt
...lin/net.mamoe.mirai/network/protocol/tim/packet/Packet.kt
+2
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerEvent.kt
...et.mamoe.mirai/network/protocol/tim/packet/ServerEvent.kt
+14
-7
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
...t.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
+2
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
...et.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
+53
-14
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
...otocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
+6
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
...net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
+4
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ServerLoginResponse.kt
.../network/protocol/tim/packet/login/ServerLoginResponse.kt
+4
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Session.kt
....mamoe.mirai/network/protocol/tim/packet/login/Session.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
...onMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
+4
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
.../src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/LoginConfiguration.kt
...onMain/kotlin/net.mamoe.mirai/utils/LoginConfiguration.kt
+0
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
+9
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformSocket.kt
...commonMain/kotlin/net.mamoe.mirai/utils/PlatformSocket.kt
+0
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
+12
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/VarDelegates.kt
...c/commonMain/kotlin/net.mamoe.mirai/utils/VarDelegates.kt
+22
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
.../src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
+3
-10
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/UnsolvedImage.kt
...c/jvmMain/kotlin/net/mamoe/mirai/message/UnsolvedImage.kt
+0
-73
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/PacketInternalJvm.kt
...oe/mirai/network/protocol/tim/packet/PacketInternalJvm.kt
+2
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
...mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
+0
-3
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ImageNetworkUtils.kt
...jvmMain/kotlin/net/mamoe/mirai/utils/ImageNetworkUtils.kt
+0
-37
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
+10
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformSocketJvm.kt
...jvmMain/kotlin/net/mamoe/mirai/utils/PlatformSocketJvm.kt
+2
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+56
-0
mirai-debug/src/main/java/PacketDebuger.kt
mirai-debug/src/main/java/PacketDebuger.kt
+1
-2
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
+3
-7
No files found.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/internal/MessageDataInternal.kt
View file @
fdb3be94
...
...
@@ -24,15 +24,17 @@ internal fun IoBuffer.parsePlainText(): PlainText {
internal
fun
IoBuffer
.
parseMessageImage0x06
():
Image
{
discardExact
(
1
)
this
.
debugPrint
(
"好友的图片"
)
//MiraiLogger.logDebug(this.toUHexString())
val
filenameLength
=
readShort
()
val
suffix
=
readString
(
filenameLength
).
substringAfter
(
"."
)
discardExact
(
this
@
parseMessageImage0x06
.
readRemaining
-
37
-
1
-
filenameLength
-
2
)
val
imageId
=
readString
(
36
)
MiraiLogger
.
logDebug
(
imageId
)
discardExact
(
1
)
//0x41
return
Image
(
"{$imageId}.$suffix"
)
with
(
this
.
debugPrint
(
"好友的图片"
))
{
//MiraiLogger.logDebug(this.toUHexString())
val
filenameLength
=
readShort
()
val
suffix
=
readString
(
filenameLength
).
substringAfter
(
"."
)
discardExact
(
this
.
readRemaining
-
37
-
1
-
filenameLength
-
2
-
8
-
4
)
val
imageId
=
readString
(
36
)
MiraiLogger
.
logDebug
(
"imageId=$imageId"
)
//todo ID似乎错了??
discardExact
(
1
)
//0x41
return
Image
(
"{$imageId}.$suffix"
)
}
}
internal
fun
IoBuffer
.
parseMessageImage0x03
():
Image
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
View file @
fdb3be94
package
net.mamoe.mirai.network
import
kotlinx.coroutines.*
import
kotlinx.coroutines.CancellationException
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.cancelChildren
import
kotlinx.io.core.Closeable
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.BotSocketAdapter
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.LoginHandler
...
...
@@ -27,6 +29,7 @@ import kotlin.coroutines.ContinuationInterceptor
*
* A BotNetworkHandler is used to connect with Tencent servers.
*/
@Suppress
(
"PropertyName"
)
interface
BotNetworkHandler
<
Socket
:
DataPacketSocketAdapter
>
:
Closeable
{
/**
* [BotNetworkHandler] 的协程作用域.
...
...
@@ -38,11 +41,11 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : Closeable {
* - SKey 刷新 [ClientSKeyRefreshmentRequestPacket]
* - 所有数据包处理和发送
*
* [BotNetworkHandler.close] 时将会 [取消][
CoroutineScope.cancel
] 所有此作用域下的协程
* [BotNetworkHandler.close] 时将会 [取消][
kotlin.coroutines.CoroutineContext.cancelChildren
] 所有此作用域下的协程
*/
val
NetworkScope
:
CoroutineScope
va
r
socket
:
Socket
va
l
socket
:
Socket
/**
* 得到 [PacketHandler].
...
...
@@ -57,9 +60,10 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : Closeable {
suspend
fun
login
(
configuration
:
LoginConfiguration
):
LoginResult
/**
* 添加一个临时包处理器
* 添加一个临时包处理器
, 并发送相应的包
*
* @see [TemporaryPacketHandler]
* @see [BotSession.sendAndExpect] 发送并期待一个包
* @see [TemporaryPacketHandler] 临时包处理器
*/
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
View file @
fdb3be94
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
)
package
net.mamoe.mirai.network
import
kotlinx.coroutines.CompletableJob
...
...
@@ -50,7 +52,7 @@ class BotSession(
*
* 实现方法:
* ```kotlin
* session.
expectPacke
t<ServerPacketXXX> {
* session.
sendAndExpec
t<ServerPacketXXX> {
* toSend { ClientPacketXXX(...) }
* onExpect {//it: ServerPacketXXX
*
...
...
@@ -62,7 +64,7 @@ class BotSession(
* @param handlerTemporary 处理器.
*/
//@JvmSynthetic
suspend
inline
fun
<
reified
P
:
ServerPacket
>
expectPacke
t
(
handlerTemporary
:
TemporaryPacketHandler
<
P
>.()
->
Unit
):
CompletableJob
{
suspend
inline
fun
<
reified
P
:
ServerPacket
>
sendAndExpec
t
(
handlerTemporary
:
TemporaryPacketHandler
<
P
>.()
->
Unit
):
CompletableJob
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
).
also
(
handlerTemporary
))
return
job
...
...
@@ -71,28 +73,28 @@ class BotSession(
/**
* 发送一个数据包, 并期待接受一个特定的 [ServerPacket].
* 发送成功后, 该方法会等待收到 [ServerPacket] 直到超时.
* 由于包名可能过长, 可使用 `DataPacketSocketAdapter.
expectPacke
t(PacketProcessor)` 替代.
* 由于包名可能过长, 可使用 `DataPacketSocketAdapter.
sendAndExpec
t(PacketProcessor)` 替代.
*
* 实现方法:
* ```kotlin
*
session.expectPacket<ServerPacketXXX>(ClientPacketXXX(...)) {//it: ServerPacketXXX
*
*
ClientPacketXXX(...).sendAndExpect<ServerPacketXXX> {
*
//it: ServerPacketXXX
* }
* ```
*
* @param P 期待的包
* @param toSend 将要发送的包
* @param handler 处理期待的包
*/
//@JvmSynthetic
suspend
inline
fun
<
reified
P
:
ServerPacket
>
expectPacket
(
toSend
:
ClientPacket
,
noinline
handler
:
suspend
(
P
)
->
Unit
):
CompletableJob
{
suspend
inline
fun
<
reified
P
:
ServerPacket
>
ClientPacket
.
sendAndExpect
(
noinline
handler
:
suspend
(
P
)
->
Unit
):
CompletableJob
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
).
also
{
it
.
toSend
(
t
oSend
)
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
@BotSession
).
also
{
it
.
toSend
(
t
his
)
it
.
onExpect
(
handler
)
})
return
job
}
suspend
inline
fun
ClientPacket
.
send
()
=
socket
.
sendPacket
(
this
)
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
View file @
fdb3be94
...
...
@@ -30,6 +30,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
override
val
NetworkScope
:
CoroutineScope
=
CoroutineScope
(
Dispatchers
.
Default
)
override
lateinit
var
socket
:
BotSocketAdapter
private
set
internal
val
temporaryPacketHandlers
=
mutableListOf
<
TemporaryPacketHandler
<
*
>>()
private
val
handlersLock
=
Mutex
()
...
...
@@ -73,6 +74,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
add
(
EventPacketHandler
(
session
).
asNode
(
EventPacketHandler
))
add
(
ActionPacketHandler
(
session
).
asNode
(
ActionPacketHandler
))
bot
.
logger
.
logPurple
(
"Successfully logged in"
)
}
private
lateinit
var
sessionKey
:
ByteArray
...
...
@@ -110,9 +112,10 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
try
{
channel
.
read
(
buffer
)
//JVM: withContext(IO)
}
catch
(
e
:
ReadPacketInternalException
)
{
}
catch
(
e
:
Exception
)
{
e
.
log
()
//read failed, continue and reread
continue
}
catch
(
e
:
Throwable
)
{
e
.
log
()
//other unexpected exceptions caught.
continue
}
...
...
@@ -123,11 +126,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
NetworkScope
.
launch
{
try
{
//
Ensure the packet is consumed totally so that all
buffers are released
//
`.use`: Ensure that the packet is consumed totally so that all the
buffers are released
ByteReadPacket
(
buffer
,
IoBuffer
.
Pool
).
use
{
distributePacket
(
it
.
parseServerPacket
(
buffer
.
readRemaining
))
}
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Throwable
)
{
e
.
log
()
}
}
...
...
@@ -168,6 +171,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
try
{
packet
.
decode
()
}
catch
(
e
:
Exception
)
{
e
.
log
()
bot
.
printPacketDebugging
(
packet
)
packet
.
close
()
throw
e
...
...
@@ -238,9 +242,6 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
bot
.
logger
.
logError
(
"Caught SendPacketInternalException: ${e.cause?.message}"
)
bot
.
reinitializeNetworkHandler
(
configuration
)
return
@
withContext
}
catch
(
e
:
Throwable
)
{
e
.
log
()
return
@
withContext
}
finally
{
buffer
.
release
(
IoBuffer
.
Pool
)
}
...
...
@@ -338,7 +339,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
is
ServerLoginResponseCaptchaInitPacket
->
{
//[token00BA]来源之一: 验证码
this
.
token00BA
=
packet
.
token00BA
this
.
captchaCache
=
packet
.
verifyCode
Part1
this
.
captchaCache
=
packet
.
captcha
Part1
if
(
packet
.
unknownBoolean
==
true
)
{
this
.
captchaSectionId
=
1
...
...
@@ -390,12 +391,14 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
privateKey
=
privateKey
,
token0825
=
token0825
,
token00BA
=
packet
.
tokenUnknown
?:
token00BA
,
randomDeviceName
=
socket
.
configuration
.
randomDeviceName
randomDeviceName
=
socket
.
configuration
.
randomDeviceName
,
tlv0006
=
packet
.
tlv0006
))
}
is
ServerSessionKeyResponsePacket
->
{
sessionKey
=
packet
.
sessionKey
bot
.
logger
.
logPurple
(
"sessionKey = ${sessionKey.toUHexString()}"
)
heartbeatJob
=
NetworkScope
.
launch
{
while
(
socket
.
isOpen
)
{
...
...
@@ -412,14 +415,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
is
ServerLoginSuccessPacket
->
{
BotLoginSucceedEvent
(
bot
).
broadcast
()
//登录成功后会收到大量上次的消息, 忽略掉 todo 优化
NetworkScope
.
launch
{
delay
(
3000
)
this
@TIMBotNetworkHandler
[
EventPacketHandler
].
ignoreMessage
=
false
}
onLoggedIn
(
sessionKey
)
this
.
close
()
//The LoginHandler is useless since then
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/ActionPacketHandler.kt
View file @
fdb3be94
...
...
@@ -16,6 +16,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResp
import
net.mamoe.mirai.network.protocol.tim.packet.login.ClientSKeyRefreshmentRequestPacket
import
net.mamoe.mirai.network.protocol.tim.packet.login.ClientSKeyRequestPacket
import
net.mamoe.mirai.network.protocol.tim.packet.login.ServerSKeyResponsePacket
import
net.mamoe.mirai.utils.log
/**
* 动作: 获取好友列表, 点赞, 踢人等.
...
...
@@ -64,7 +65,11 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
sKeyRefresherJob
=
session
.
scope
.
launch
{
while
(
session
.
isOpen
)
{
delay
(
1800000
)
session
.
socket
.
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
session
.
bot
.
account
.
account
,
session
.
sessionKey
))
try
{
session
.
socket
.
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
session
.
bot
.
account
.
account
,
session
.
sessionKey
))
}
catch
(
e
:
Throwable
)
{
e
.
log
()
}
}
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/DataPacketSocketAdapter.kt
View file @
fdb3be94
...
...
@@ -41,7 +41,7 @@ interface DataPacketSocketAdapter : Closeable {
*
* 可通过 hook 事件 [ServerPacketReceivedEvent] 来获取服务器返回.
*
* @see [BotSession.
expectPacke
t] kotlin DSL
* @see [BotSession.
sendAndExpec
t] kotlin DSL
*/
suspend
fun
sendPacket
(
packet
:
ClientPacket
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/EventPacketHandler.kt
View file @
fdb3be94
...
...
@@ -26,9 +26,6 @@ import net.mamoe.mirai.utils.MiraiLogger
class
EventPacketHandler
(
session
:
BotSession
)
:
PacketHandler
(
session
)
{
companion
object
Key
:
PacketHandler
.
Key
<
EventPacketHandler
>
internal
var
ignoreMessage
:
Boolean
=
true
override
suspend
fun
onPacketReceived
(
packet
:
ServerPacket
):
Unit
=
with
(
session
)
{
when
(
packet
)
{
is
ServerGroupUploadFileEventPacket
->
{
...
...
@@ -36,14 +33,12 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
}
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
return
FriendMessageEvent
(
bot
,
bot
.
getQQ
(
packet
.
qq
),
packet
.
message
).
broadcast
()
if
(
!
packet
.
isPrevious
)
{
FriendMessageEvent
(
bot
,
bot
.
getQQ
(
packet
.
qq
),
packet
.
message
).
broadcast
()
}
}
is
ServerGroupMessageEventPacket
->
{
if
(
ignoreMessage
)
return
if
(
packet
.
qq
.
toLong
()
==
bot
.
account
.
account
)
return
GroupMessageEvent
(
bot
,
bot
.
getGroupByNumber
(
packet
.
groupNumber
),
bot
.
getQQ
(
packet
.
qq
),
packet
.
message
).
broadcast
()
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/TemporaryPacketHandler.kt
View file @
fdb3be94
...
...
@@ -17,11 +17,11 @@ import kotlin.reflect.KClass
* }
* ```
*
* @see BotSession.
expectPacke
t
* @see BotSession.
sendAndExpec
t
*/
class
TemporaryPacketHandler
<
P
:
ServerPacket
>(
private
val
expectationClass
:
KClass
<
P
>,
private
val
deferred
:
CompletableJob
,
private
val
job
:
CompletableJob
,
private
val
fromSession
:
BotSession
)
{
private
lateinit
var
toSend
:
ClientPacket
...
...
@@ -54,7 +54,7 @@ class TemporaryPacketHandler<P : ServerPacket>(
kotlin
.
runCatching
{
@Suppress
(
"UNCHECKED_CAST"
)
expect
(
packet
as
P
)
}.
onFailure
{
deferred
.
completeExceptionally
(
it
)
}.
onSuccess
{
deferred
.
complete
()
}
}.
onFailure
{
job
.
completeExceptionally
(
it
)
}.
onSuccess
{
job
.
complete
()
}
return
true
}
return
false
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
View file @
fdb3be94
...
...
@@ -5,7 +5,9 @@ package net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeQQ
@PacketId
(
0
x00_58u
)
class
ClientHeartbeatPacket
(
...
...
@@ -13,9 +15,9 @@ class ClientHeartbeatPacket(
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeQQ
(
bot
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
this
.
encryptAndWrite
(
sessionKey
)
{
writeQQ
(
bot
)
writeHex
(
TIMProtocol
.
fixVer
)
encryptAndWrite
(
sessionKey
)
{
writeHex
(
"00 01 00 01"
)
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Packet.kt
View file @
fdb3be94
...
...
@@ -2,17 +2,16 @@
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.Closeable
import
net.mamoe.mirai.utils.toUHexString
/**
* 数据包.
*/
abstract
class
Packet
:
Closeable
{
abstract
class
Packet
{
/**
* 2 Ubyte
*/
open
val
id
:
UShort
=
(
this
::
class
.
annotations
.
firstOrNull
{
it
is
PacketId
}
as
?
PacketId
)
?.
value
?:
error
(
"Annotation PacketId not found"
)
open
val
id
:
UShort
by
lazy
{
(
this
::
class
.
annotations
.
firstOrNull
{
it
is
PacketId
}
as
?
PacketId
)
?.
value
?:
error
(
"Annotation PacketId not found"
)
}
/**
* 包序列 id. 唯一
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerEvent.kt
View file @
fdb3be94
...
...
@@ -26,13 +26,20 @@ fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) =
writeFully
(
uniqueId
)
}
fun
<
S
:
ServerEventPacket
>
S
.
applyId
(
id
:
UShort
):
S
{
this
.
id
=
id
return
this
}
/**
* Packet id: `00 CE` or `00 17`
*
* @author Him188moe
*/
abstract
class
ServerEventPacket
(
input
:
ByteReadPacket
,
val
eventIdentity
:
EventPacketIdentity
)
:
ServerPacket
(
input
)
{
class
Raw
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
override
var
id
:
UShort
=
0
u
class
Raw
(
input
:
ByteReadPacket
,
override
val
id
:
UShort
)
:
ServerPacket
(
input
)
{
fun
distribute
():
ServerEventPacket
=
with
(
input
)
{
val
eventIdentity
=
EventPacketIdentity
(
from
=
readUInt
(),
...
...
@@ -65,7 +72,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
println
(
readUByte
().
toUInt
())
//todo 错了. 可能是 00 79 才是.
return
@
with
ServerFriendTypingCanceledPacket
(
input
,
eventIdentity
)
ServerFriendTypingCanceledPacket
(
input
,
eventIdentity
)
/*
if (readUByte().toUInt() == 0x37u) ServerFriendTypingStartedPacket(input, eventIdentity)
else /*0x22*/ ServerFriendTypingCanceledPacket(input, eventIdentity)*/
...
...
@@ -81,8 +88,8 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
}.
applyId
(
id
).
applySequence
(
sequenceId
)
}
class
Encrypted
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
sessionKey
:
ByteArray
):
Raw
=
Raw
(
this
.
decryptBy
(
sessionKey
)
).
applyId
(
id
).
applySequence
(
sequenceId
)
class
Encrypted
(
input
:
ByteReadPacket
,
override
var
id
:
UShort
,
override
var
sequenceId
:
UShort
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
sessionKey
:
ByteArray
):
Raw
=
Raw
(
this
.
decryptBy
(
sessionKey
)
,
id
).
applySequence
(
sequenceId
)
}
}
...
...
@@ -185,8 +192,8 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
senderName
=
map
.
getValue
(
18
).
read
{
val
tlv
=
readTLVMap
(
true
)
tlv
.
printTLVMap
(
"子map"
)
//群主的18: 05 00 04 00 00 00 03 08 00 04 00 00 00 04 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08
//
//
群主的18: 05 00 04 00 00 00 03 08 00 04 00 00 00 04 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08
//群主的 子map= {5=00 00 00 03, 8=00 00 00 04, 1=48 69 6D 31 38 38 6D 6F 65, 3=04, 4=00 00 00 08}
when
{
tlv
.
containsKey
(
0
x01
)
->
String
(
tlv
.
getValue
(
0
x01
))
tlv
.
containsKey
(
0
x02
)
->
String
(
tlv
.
getValue
(
0
x02
))
...
...
@@ -202,7 +209,7 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
//刚刚的消息: 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD 11 F4 B2 F2 1A E7 1F C4 F1 3F 23 FB 74 80 42 64 00 0B 78 1A 5D A3 26 C1 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A3 26 C1 AA 34 08 42 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00
fun
main
()
{
println
(
"0
8 02 1A 12 08 95 02 10 90 04 40 D6 DE 8C ED 05 48 CF B5 90 D6 02 08 DD F1 92 B7 07 10 DD F1 92 B7 07 1A 14 08 00 10 05 18 D6 DE 8C ED 05 20 02 28 FF FF FF FF 0F 32
00"
.
hexToBytes
().
stringOf
())
println
(
"0
1 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 20 BF 02 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03
00"
.
hexToBytes
().
stringOf
())
}
fun
main2
()
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
View file @
fdb3be94
...
...
@@ -16,7 +16,8 @@ import kotlin.properties.Delegates
* @see parseServerPacket
*/
abstract
class
ServerPacket
(
val
input
:
ByteReadPacket
)
:
Packet
(),
Closeable
{
override
var
id
:
UShort
=
super
.
id
override
val
id
:
UShort
by
lazy
{
super
.
id
}
override
var
sequenceId
:
UShort
by
Delegates
.
notNull
()
open
fun
decode
()
{
...
...
@@ -28,11 +29,6 @@ abstract class ServerPacket(val input: ByteReadPacket) : Packet(), Closeable {
override
fun
toString
():
String
=
this
.
packetToString
()
}
fun
<
S
:
ServerPacket
>
S
.
applyId
(
id
:
UShort
):
S
{
this
.
id
=
id
return
this
}
fun
<
S
:
ServerPacket
>
S
.
applySequence
(
sequenceId
:
UShort
):
S
{
this
.
sequenceId
=
sequenceId
return
this
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
View file @
fdb3be94
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"unused"
)
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.utils.gotoWhere
import
net.mamoe.mirai.utils.toReadPacket
expect
class
PlatformImage
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.account
import
net.mamoe.mirai.network.protocol.tim.handler.ActionPacketHandler
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.utils.*
@PacketId
(
0
x03_88u
)
expect
class
ClientTryGetImageIDPacket
(
botNumber
:
Long
,
sessionKey
:
ByteArray
,
...
...
@@ -16,19 +20,18 @@ expect class ClientTryGetImageIDPacket(
image
:
PlatformImage
)
:
ClientPacket
abstract
class
ServerTryGetImageIDResponsePacket
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
@PacketId
(
0
x03_88u
)
sealed
class
ServerTryGetImageIDResponsePacket
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
@PacketId
(
0
x03_88u
)
class
Encrypted
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerTryGetImageIDResponsePacket
{
val
data
=
this
.
decryptAsByteArray
(
sessionKey
)
println
(
data
.
size
)
println
(
data
.
size
)
println
(
"ServerTryGetImageIDResponsePacket.size="
+
data
.
size
)
if
(
data
.
size
==
209
)
{
return
ServerTryGetImageIDSuccessPacket
(
data
.
toReadPacket
()).
applySequence
(
sequenceId
)
}
return
ServerTryGetImageIDFailedPacket
(
data
.
toReadPacket
())
return
ServerTryGetImageIDFailedPacket
(
data
.
toReadPacket
())
.
applySequence
(
sequenceId
)
}
}
}
...
...
@@ -36,12 +39,14 @@ abstract class ServerTryGetImageIDResponsePacket(input: ByteReadPacket) : Server
/**
* 服务器未存有图片, 返回一个 key 用于客户端上传
*/
@PacketId
(
0
x03_88u
)
class
ServerTryGetImageIDSuccessPacket
(
input
:
ByteReadPacket
)
:
ServerTryGetImageIDResponsePacket
(
input
)
{
lateinit
var
uKey
:
ByteArray
override
fun
decode
()
{
this
.
input
.
gotoWhere
(
ubyteArrayOf
(
0
x42u
,
0
x80u
,
0
x01u
))
this
.
input
.
gotoWhere
(
ubyteArrayOf
(
0
x42u
,
0
x80u
,
0
x01u
))
//todo 优化
uKey
=
this
.
input
.
readBytes
(
128
)
DebugLogger
.
logPurple
(
"获得 uKey(128)=${uKey.toUHexString()}"
)
}
}
...
...
@@ -49,7 +54,41 @@ class ServerTryGetImageIDSuccessPacket(input: ByteReadPacket) : ServerTryGetImag
* 服务器已经存有这个图片
*/
class
ServerTryGetImageIDFailedPacket
(
input
:
ByteReadPacket
)
:
ServerTryGetImageIDResponsePacket
(
input
)
{
override
fun
decode
()
{
override
fun
decode
()
:
Unit
=
with
(
input
)
{
readRemainingBytes
().
debugPrint
(
"ServerTryGetImageIDFailedPacket的body"
)
}
}
suspend
fun
Group
.
uploadImage
(
imageId
:
String
,
image
:
PlatformImage
)
{
this
.
bot
.
network
[
ActionPacketHandler
].
session
.
uploadGroupImage
(
number
,
imageId
,
image
)
}
suspend
fun
QQ
.
uploadImage
(
imageId
:
String
,
image
:
PlatformImage
)
{
TODO
()
}
suspend
fun
BotSession
.
uploadGroupImage
(
groupNumberOrAccount
:
Long
,
imageId
:
String
,
image
:
PlatformImage
)
{
ClientTryGetImageIDPacket
(
account
,
sessionKey
,
groupNumberOrAccount
,
image
).
sendAndExpect
<
ServerTryGetImageIDResponsePacket
>
{
when
(
it
)
{
is
ServerTryGetImageIDFailedPacket
->
{
//服务器已存有图片
}
is
ServerTryGetImageIDSuccessPacket
->
{
val
data
=
image
.
toByteArray
()
httpPostGroupImage
(
uKeyHex
=
it
.
uKey
.
toUHexString
(
""
),
botNumber
=
bot
.
qqAccount
,
fileSize
=
data
.
size
,
imageData
=
data
,
groupCode
=
groupNumberOrAccount
)
//todo HTTP upload image.
}
}
}.
join
()
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
View file @
fdb3be94
...
...
@@ -7,19 +7,22 @@ import kotlinx.io.core.writeUByte
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.PacketId
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.OnlineStatus
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeQQ
/**
* 改变在线状态: "我在线上", "隐身" 等
*/
@PacketId
(
0
x00_ECu
)
class
ClientChangeOnlineStatusPacket
(
private
val
qq
:
Long
,
private
val
bot
:
Long
,
private
val
sessionKey
:
ByteArray
,
private
val
loginStatus
:
OnlineStatus
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
bot
)
this
.
writeHex
(
TIMProtocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
writeHex
(
"01 00"
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
View file @
fdb3be94
...
...
@@ -45,8 +45,10 @@ class ServerSKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
override
fun
decode
()
=
with
(
input
)
{
discardExact
(
4
)
sKey
=
this
.
readString
(
10
)
//todo test
MiraiLogger
.
logDebug
(
"SKey=$sKey"
)
//debugDiscardExact(2)
sKey
=
this
.
readString
(
10
)
DebugLogger
.
logPurple
(
"SKey=$sKey"
)
DebugLogger
.
logPurple
(
"Skey包后面${this.readRemainingBytes().toUHexString()}"
)
}
@PacketId
(
0
x00_1Du
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ServerLoginResponse.kt
View file @
fdb3be94
...
...
@@ -16,8 +16,6 @@ class ServerLoginResponseFailedPacket(val loginResult: LoginResult, input: ByteR
/**
* 服务器进行加密后返回 privateKey
*
* @author NaturalHG
*/
@PacketId
(
0
x08_36u
)
class
ServerLoginResponseKeyExchangePacket
(
input
:
ByteReadPacket
)
:
ServerLoginResponsePacket
(
input
)
{
...
...
@@ -29,7 +27,7 @@ class ServerLoginResponseKeyExchangePacket(input: ByteReadPacket) : ServerLoginR
@Tested
override
fun
decode
()
{
this
.
input
.
discardExact
(
5
)
//01 00 1E 00 10
privateKeyUpdate
=
this
.
input
.
readBytes
(
0
x10
)
//22
privateKeyUpdate
=
this
.
input
.
readBytes
(
0
x10
)
this
.
input
.
discardExact
(
4
)
//00 06 00 78
tlv0006
=
this
.
input
.
readIoBuffer
(
0
x78
)
...
...
@@ -127,7 +125,7 @@ class ServerLoginResponseSuccessPacket(input: ByteReadPacket) : ServerLoginRespo
@PacketId
(
0
x08_36u
)
class
ServerLoginResponseCaptchaInitPacket
(
input
:
ByteReadPacket
)
:
ServerLoginResponsePacket
(
input
)
{
lateinit
var
verifyCode
Part1
:
IoBuffer
lateinit
var
captcha
Part1
:
IoBuffer
lateinit
var
token00BA
:
ByteArray
var
unknownBoolean
:
Boolean
?
=
null
...
...
@@ -136,8 +134,8 @@ class ServerLoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginR
override
fun
decode
()
{
this
.
input
.
discardExact
(
78
)
//println(this.input.readRemainingBytes().toUHexString())
val
verifyCode
Length
=
this
.
input
.
readShort
()
//2bytes
this
.
verifyCodePart1
=
this
.
input
.
readIoBuffer
(
verifyCode
Length
)
val
captcha
Length
=
this
.
input
.
readShort
()
//2bytes
this
.
captchaPart1
=
this
.
input
.
readIoBuffer
(
captcha
Length
)
this
.
input
.
discardExact
(
1
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Session.kt
View file @
fdb3be94
...
...
@@ -9,14 +9,14 @@ import net.mamoe.mirai.utils.*
@PacketId
(
0
x08_28u
)
class
ClientSessionRequestPacket
(
private
val
qq
:
Long
,
private
val
bot
:
Long
,
private
val
serverIp
:
String
,
private
val
token38
:
IoBuffer
,
private
val
token88
:
IoBuffer
,
private
val
encryptionKey
:
IoBuffer
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
bot
)
this
.
writeHex
(
"02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A"
)
this
.
writeHex
(
"00 38"
)
this
.
writeFully
(
token38
)
...
...
@@ -31,7 +31,7 @@ class ClientSessionRequestPacket(
writeHex
(
"00 36 00 12 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00"
)
writeHex
(
TIMProtocol
.
constantData1
)
writeHex
(
TIMProtocol
.
constantData2
)
writeQQ
(
qq
)
writeQQ
(
bot
)
writeHex
(
"00 00 00 00 00 1F 00 22 00 01"
)
writeHex
(
"1A 68 73 66 E4 BA 79 92 CC C2 D4 EC 14 7C 8B AF 43 B0 62 FB 65 58 A9 EB 37 55 1D 26 13 A8 E5 3D"
)
//device ID
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
View file @
fdb3be94
...
...
@@ -69,12 +69,12 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
}
0
x08_28u
->
ServerSessionKeyResponsePacket
.
Encrypted
(
this
)
0
x00_EC_u
->
Server
SKeyResponse
Packet
(
this
)
0
x00_EC_u
->
Server
LoginSuccess
Packet
(
this
)
0
x00_1D_u
->
ServerSKeyResponsePacket
.
Encrypted
(
this
)
0
x00_5C_u
->
ServerAccountInfoResponsePacket
.
Encrypted
(
this
)
0
x00_58_u
->
ServerHeartbeatResponsePacket
(
this
)
0
x00_BA_u
->
ServerCaptchaPacket
.
Encrypted
(
this
)
0
x00_CE_u
,
0
x00_17_u
->
ServerEventPacket
.
Raw
.
Encrypted
(
this
)
0
x00_CE_u
,
0
x00_17_u
->
ServerEventPacket
.
Raw
.
Encrypted
(
this
,
id
,
sequenceId
)
0
x00_81_u
->
ServerFieldOnlineStatusChangedPacket
.
Encrypted
(
this
)
0
x00_CD_u
->
ServerSendFriendMessageResponsePacket
(
this
)
0
x00_02_u
->
ServerSendGroupMessageResponsePacket
(
this
)
...
...
@@ -82,7 +82,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
0
x03_88_u
->
ServerTryGetImageIDResponsePacket
.
Encrypted
(
this
)
else
->
UnknownServerPacket
.
Encrypted
(
this
,
id
,
sequenceId
)
}.
apply
Id
(
id
).
apply
Sequence
(
sequenceId
)
}.
applySequence
(
sequenceId
)
}
fun
Input
.
readIP
():
String
=
buildString
(
4
+
3
)
{
...
...
@@ -145,6 +145,7 @@ fun Input.readLVNumber(): Number {
//@JvmSynthetic
@Deprecated
(
"Low efficiency"
,
ReplaceWith
(
""
))
fun
<
I
:
Input
>
I
.
gotoWhere
(
matcher
:
UByteArray
):
I
{
@Suppress
(
"DEPRECATION"
)
return
this
.
gotoWhere
(
matcher
.
toByteArray
())
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
View file @
fdb3be94
...
...
@@ -15,19 +15,19 @@ internal fun ByteArray.debugPrint(name: String): ByteArray {
return
this
}
@Deprecated
(
"Low
Efficiency
"
,
ReplaceWith
(
""
))
@Deprecated
(
"Low
efficiency, only for debug purpose
"
,
ReplaceWith
(
""
))
internal
fun
IoBuffer
.
debugPrint
(
name
:
String
):
IoBuffer
{
val
readBytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
name
+
"="
+
readBytes
.
toUHexString
())
return
readBytes
.
toIoBuffer
()
}
@Deprecated
(
"Low
Efficiency
"
,
ReplaceWith
(
"discardExact(n)"
))
@Deprecated
(
"Low
efficiency, only for debug purpose
"
,
ReplaceWith
(
"discardExact(n)"
))
internal
fun
Input
.
debugDiscardExact
(
n
:
Number
,
name
:
String
=
""
)
{
DebugLogger
.
logPurple
(
"Discarded($n) $name="
+
this
.
readBytes
(
n
.
toInt
()).
toUHexString
())
}
@Deprecated
(
"Low
Efficiency
"
,
ReplaceWith
(
""
))
@Deprecated
(
"Low
efficiency, only for debug purpose
"
,
ReplaceWith
(
""
))
internal
fun
ByteReadPacket
.
debugPrint
(
name
:
String
=
""
):
ByteReadPacket
{
val
bytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
"ByteReadPacket $name="
+
bytes
.
toUHexString
())
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/LoginConfigur
e
.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/LoginConfigur
ation
.kt
View file @
fdb3be94
File moved
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
0 → 100644
View file @
fdb3be94
package
net.mamoe.mirai.utils
import
kotlin.jvm.JvmOverloads
expect
class
PlatformImage
@JvmOverloads
expect
fun
PlatformImage
.
toByteArray
(
formatName
:
String
=
"JPG"
):
ByteArray
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/
SocketBridge
.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/
PlatformSocket
.kt
View file @
fdb3be94
File moved
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtil.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtil
s
.kt
View file @
fdb3be94
...
...
@@ -31,4 +31,15 @@ expect fun solveIpAddress(hostname: String): String
/**
* Localhost 解析
*/
expect
fun
localIpAddress
():
String
\ No newline at end of file
expect
fun
localIpAddress
():
String
/**
* 上传群图片
*/
expect
suspend
fun
httpPostGroupImage
(
uKeyHex
:
String
,
fileSize
:
Int
,
botNumber
:
Long
,
groupCode
:
Long
,
imageData
:
ByteArray
):
Boolean
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/VarDelegates.kt
0 → 100644
View file @
fdb3be94
package
net.mamoe.mirai.utils
import
kotlin.properties.Delegates
import
kotlin.properties.ReadWriteProperty
import
kotlin.reflect.KProperty
fun
<
T
:
Any
>
Delegates
.
notNullBy
(
initializer
:
()
->
T
):
ReadWriteProperty
<
Any
?
,
T
>
=
NotNullVarWithDefault
(
lazy
(
initializer
=
initializer
))
class
NotNullVarWithDefault
<
T
:
Any
>(
private
val
initializer
:
Lazy
<
T
>
)
:
ReadWriteProperty
<
Any
?
,
T
>
{
private
var
value
:
T
?
=
null
override
fun
getValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>):
T
{
return
value
?:
initializer
.
value
}
override
fun
setValue
(
thisRef
:
Any
?,
property
:
KProperty
<
*
>,
value
:
T
)
{
this
.
value
=
value
}
}
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
View file @
fdb3be94
...
...
@@ -35,7 +35,6 @@ actual sealed class Contact actual constructor(bot: Bot, number: Long) : Platfor
*/
fun
blockingSendMessage
(
message
:
Message
)
=
runBlocking
{
sendMessage
(
message
)
}
/**
* 阻塞发送一个消息. 仅应在 Java 使用
*/
...
...
@@ -44,23 +43,17 @@ actual sealed class Contact actual constructor(bot: Bot, number: Long) : Platfor
/**
* 异步发送一个消息. 仅应在 Java 使用
*/
fun
asyncSendMessage
(
chain
:
MessageChain
)
{
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
chain
)
}
}
fun
asyncSendMessage
(
chain
:
MessageChain
)
=
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
chain
)
}
/**
* 异步发送一个消息. 仅应在 Java 使用
*/
fun
asyncSendMessage
(
message
:
Message
)
{
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
message
)
}
}
fun
asyncSendMessage
(
message
:
Message
)
=
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
message
)
}
/**
* 异步发送一个消息. 仅应在 Java 使用
*/
fun
asyncSendMessage
(
plain
:
String
)
{
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
plain
)
}
}
fun
asyncSendMessage
(
plain
:
String
)
=
bot
.
network
.
NetworkScope
.
launch
{
sendMessage
(
plain
)
}
}
/**
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/UnsolvedImage.kt
deleted
100644 → 0
View file @
24404f9a
package
net.mamoe.mirai.message
import
kotlinx.coroutines.CompletableJob
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.protocol.tim.packet.ClientTryGetImageIDPacketJvm
import
net.mamoe.mirai.network.protocol.tim.packet.ServerTryGetImageIDFailedPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerTryGetImageIDResponsePacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerTryGetImageIDSuccessPacket
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.utils.ImageNetworkUtils
import
net.mamoe.mirai.utils.md5
import
net.mamoe.mirai.utils.toByteArray
import
net.mamoe.mirai.utils.toUHexString
import
java.awt.image.BufferedImage
import
java.io.File
import
java.net.URL
import
javax.imageio.ImageIO
/**
* 不确定是否存在于服务器的 [Image].
* 必须在发送之前 [UnsolvedImage.upload] 或 [Contact.uploadImage], 否则会发送失败.
*
* @suppress todo 重新设计
* @author Him188moe
*/
class
UnsolvedImage
(
private
val
filename
:
String
,
val
image
:
BufferedImage
)
{
constructor
(
imageFile
:
File
)
:
this
(
imageFile
.
name
,
ImageIO
.
read
(
imageFile
))
constructor
(
url
:
URL
)
:
this
(
File
(
url
.
file
))
suspend
fun
upload
(
session
:
BotSession
,
contact
:
Contact
):
CompletableJob
{
return
session
.
expectPacket
<
ServerTryGetImageIDResponsePacket
>
{
toSend
{
ClientTryGetImageIDPacketJvm
(
session
.
bot
.
qqAccount
,
session
.
sessionKey
,
contact
.
number
,
image
)
}
onExpect
{
when
(
it
)
{
is
ServerTryGetImageIDFailedPacket
->
{
//已经存在于服务器了
}
is
ServerTryGetImageIDSuccessPacket
->
{
val
data
=
image
.
toByteArray
()
withContext
(
Dispatchers
.
IO
)
{
if
(!
ImageNetworkUtils
.
postImage
(
it
.
uKey
.
toUHexString
(),
data
.
size
,
session
.
bot
.
qqAccount
,
contact
.
number
,
data
))
{
throw
RuntimeException
(
"cannot upload image"
)
}
}
}
}
}
}
}
fun
toImage
():
Image
{
return
Image
(
getImageId
(
filename
))
}
companion
object
{
@JvmStatic
fun
getImageId
(
filename
:
String
):
String
{
val
md5
=
md5
(
filename
)
return
"{"
+
md5
.
copyOfRange
(
0
,
4
).
toUHexString
(
""
)
+
"-"
.
plus
(
md5
.
copyOfRange
(
4
,
6
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
6
,
8
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
8
,
10
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
10
,
16
).
toUHexString
(
""
))
+
"}."
+
if
(
filename
.
endsWith
(
".jpeg"
))
"jpg"
else
filename
.
substringAfter
(
"."
,
"jpg"
)
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/PacketInternalJvm.kt
View file @
fdb3be94
...
...
@@ -4,7 +4,6 @@ package net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.internal.DangerousInternalIoApi
import
net.mamoe.mirai.utils.toUHexString
import
java.lang.reflect.Field
...
...
@@ -37,7 +36,8 @@ private object IgnoreIdList : List<String> by listOf(
"EMPTY_ID_HEX"
,
"input"
,
"output"
,
"UninitializedByteReadPacket"
"UninitializedByteReadPacket"
,
"sessionKey"
)
internal
actual
fun
Packet
.
packetToString
():
String
=
PacketNameFormatter
.
adjustName
(
this
::
class
.
simpleName
+
"(${this.idHexString})"
)
+
this
::
class
.
java
.
allDeclaredFields
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
View file @
fdb3be94
...
...
@@ -5,9 +5,6 @@ package net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.utils.*
import
java.awt.image.BufferedImage
actual
typealias
PlatformImage
=
BufferedImage
actual
typealias
ClientTryGetImageIDPacket
=
ClientTryGetImageIDPacketJvm
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ImageNetworkUtils.kt
deleted
100644 → 0
View file @
24404f9a
package
net.mamoe.mirai.utils
import
java.awt.image.BufferedImage
import
java.io.ByteArrayOutputStream
import
java.io.IOException
import
java.net.HttpURLConnection
import
java.net.URL
import
javax.imageio.ImageIO
/**
* @author NaturalHG
*/
object
ImageNetworkUtils
{
@Throws
(
IOException
::
class
)
fun
postImage
(
uKeyHex
:
String
,
fileSize
:
Int
,
botNumber
:
Long
,
groupCode
:
Long
,
img
:
ByteArray
):
Boolean
{
//http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group
val
builder
=
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
+
"&ukey="
+
uKeyHex
.
replace
(
" "
,
""
)
+
"&filezise="
+
fileSize
+
"&range="
+
"0"
+
"&uin="
+
botNumber
+
"&groupcode="
+
groupCode
val
conn
=
URL
(
builder
).
openConnection
()
as
HttpURLConnection
conn
.
setRequestProperty
(
"User-Agent"
,
"QQClient"
)
conn
.
setRequestProperty
(
"Content-Length"
,
""
+
fileSize
)
conn
.
requestMethod
=
"POST"
conn
.
doOutput
=
true
conn
.
outputStream
.
write
(
img
)
conn
.
connect
()
return
conn
.
responseCode
==
200
}
}
fun
BufferedImage
.
toByteArray
():
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"JPG"
,
it
);
it
.
toByteArray
()
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
0 → 100644
View file @
fdb3be94
package
net.mamoe.mirai.utils
import
java.awt.image.BufferedImage
import
java.io.ByteArrayOutputStream
import
javax.imageio.ImageIO
actual
typealias
PlatformImage
=
BufferedImage
@JvmOverloads
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"JPG"
,
it
);
it
.
toByteArray
()
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
SocketBridge
Jvm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/
PlatformSocket
Jvm.kt
View file @
fdb3be94
...
...
@@ -14,6 +14,7 @@ actual class PlatformDatagramChannel actual constructor(serverHost: String, serv
private
val
serverAddress
:
InetSocketAddress
=
InetSocketAddress
(
serverHost
,
serverPort
.
toInt
())
private
val
channel
:
DatagramChannel
=
DatagramChannel
.
open
().
connect
(
serverAddress
)
@Throws
(
ReadPacketInternalException
::
class
)
actual
suspend
fun
read
(
buffer
:
IoBuffer
)
=
withContext
(
Dispatchers
.
IO
)
{
try
{
(
channel
as
ReadableByteChannel
).
read
(
buffer
)
...
...
@@ -22,6 +23,7 @@ actual class PlatformDatagramChannel actual constructor(serverHost: String, serv
}
}
@Throws
(
SendPacketInternalException
::
class
)
actual
suspend
fun
send
(
buffer
:
IoBuffer
)
=
withContext
(
Dispatchers
.
IO
)
{
buffer
.
readDirect
{
try
{
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Platform
Bridge
Jvm.kt
→
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Platform
Utils
Jvm.kt
View file @
fdb3be94
package
net.mamoe.mirai.utils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
org.jsoup.Connection
import
org.jsoup.Jsoup
import
java.net.InetAddress
import
java.security.MessageDigest
import
java.util.zip.CRC32
...
...
@@ -15,4 +19,38 @@ actual fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD5
actual
fun
solveIpAddress
(
hostname
:
String
):
String
=
InetAddress
.
getByName
(
hostname
).
hostAddress
actual
fun
localIpAddress
():
String
=
InetAddress
.
getLocalHost
().
hostAddress
\ No newline at end of file
actual
fun
localIpAddress
():
String
=
InetAddress
.
getLocalHost
().
hostAddress
actual
suspend
fun
httpPostGroupImage
(
uKeyHex
:
String
,
fileSize
:
Int
,
botNumber
:
Long
,
groupCode
:
Long
,
imageData
:
ByteArray
):
Boolean
=
Jsoup
.
connect
(
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
+
"&ukey="
+
uKeyHex
.
replace
(
" "
,
""
)
+
"&filezise="
+
fileSize
+
"&range="
+
"0"
+
"&uin="
+
botNumber
+
"&groupcode="
+
groupCode
)
.
userAgent
(
"QQClient"
)
.
header
(
"Content-Length"
,
fileSize
.
toString
())
.
requestBody
(
String
(
imageData
))
.
method
(
Connection
.
Method
.
POST
)
.
ignoreContentType
(
true
)
.
let
{
withContext
(
Dispatchers
.
IO
)
{
it
.
execute
()
}
}
/*
val conn = URL(builder).openConnection() as HttpURLConnection
conn.setRequestProperty("User-Agent", "QQClient")
conn.setRequestProperty("Content-Length", "" + fileSize)
conn.requestMethod = "POST"
conn.doOutput = true
conn.outputStream.write(img)
conn.connect()*/
.
statusCode
()
==
200
\ No newline at end of file
mirai-debug/src/main/java/PacketDebuger.kt
View file @
fdb3be94
...
...
@@ -76,7 +76,6 @@ object Main {
}
}
/**
* 可从 TIM 内存中读取
*
...
...
@@ -89,7 +88,7 @@ object Main {
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
* 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey`
*/
val
sessionKey
:
ByteArray
=
"
9E A6 16 46 FF 15 FB 73 2F 31 0D 7E CB C4 E6 49
"
.
hexToBytes
()
val
sessionKey
:
ByteArray
=
"
F1 68 24 ED A8 6D 33 6E 5C B7 E0 F4 45 77 21 04
"
.
hexToBytes
()
fun
dataReceived
(
data
:
ByteArray
)
{
println
(
"--------------"
)
...
...
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
View file @
fdb3be94
package
demo1
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.withContext
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.event.events.FriendMessageEvent
...
...
@@ -17,14 +16,11 @@ import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import
net.mamoe.mirai.utils.BotAccount
import
net.mamoe.mirai.utils.Console
import
net.mamoe.mirai.utils.MiraiLogger
import
kotlin.coroutines.coroutineContext
import
kotlin.system.exitProcess
import
kotlin.system.measureTimeMillis
suspend
fun
main
()
{
val
bot
=
Bot
(
BotAccount
(
//填写你的账号
account
=
290377258
1
,
password
=
"
zxc12345
6"
account
=
199470102
1
,
password
=
"
asdhim18866
6"
),
Console
())
bot
.
login
{
...
...
@@ -79,7 +75,7 @@ suspend fun main() {
subscribeAll
<
FriendMessageEvent
>
{
always
{
//获取第一个纯文本消息
val
firstText
=
it
.
message
.
first
<
PlainText
>()
val
firstText
=
it
.
message
.
first
OrNull
<
PlainText
>()
}
}
...
...
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