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
55e6c934
Commit
55e6c934
authored
Jan 28, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
JceStruct serialization
parent
2f4a4a48
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
881 additions
and
1523 deletions
+881
-1523
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceInput.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceInput.kt
+0
-510
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceOutput.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceOutput.kt
+0
-292
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceStruct.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceStruct.kt
+1
-3
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
.../kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
+653
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt
...moe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt
+19
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
...oe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
+37
-36
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt
...lin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt
+0
-12
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
...ndroid/network/protocol/packet/chat/receive/MessageSvc.kt
+4
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
...ai/qqandroid/network/protocol/packet/login/LoginPacket.kt
+5
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/Register.kt
...mirai/qqandroid/network/protocol/packet/login/Register.kt
+69
-67
mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt
....mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt
+40
-0
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt
...n/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt
+1
-1
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverAndroid.kt
...tlin/net/mamoe/mirai/utils/DefaultCaptchaSolverAndroid.kt
+0
-8
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt
...idMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt
+26
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt
...n/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt
+1
-1
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
+0
-287
mirai-debug/src/test/kotlin/jceTest/JceOutputTest.kt
mirai-debug/src/test/kotlin/jceTest/JceOutputTest.kt
+0
-295
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
...roid/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
+23
-6
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceInput.kt
deleted
100644 → 0
View file @
2f4a4a48
This diff is collapsed.
Click to expand it.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceOutput.kt
deleted
100644 → 0
View file @
2f4a4a48
package
net.mamoe.mirai.qqandroid.io
import
kotlinx.io.charsets.Charset
import
kotlinx.io.core.*
import
kotlin.experimental.or
import
kotlin.reflect.KClass
@PublishedApi
internal
val
CharsetGBK
=
Charset
.
forName
(
"GBK"
)
@PublishedApi
internal
val
CharsetUTF8
=
Charset
.
forName
(
"UTF8"
)
inline
fun
buildJcePacket
(
stringCharset
:
Charset
=
CharsetGBK
,
block
:
JceOutput
.()
->
Unit
):
ByteReadPacket
{
return
JceOutput
(
stringCharset
).
apply
(
block
).
build
()
}
inline
fun
BytePacketBuilder
.
writeJcePacket
(
stringCharset
:
Charset
=
CharsetGBK
,
block
:
JceOutput
.()
->
Unit
)
{
return
this
.
writePacket
(
buildJcePacket
(
stringCharset
,
block
))
}
fun
jceStruct
(
tag
:
Int
,
struct
:
JceStruct
):
ByteArray
{
return
buildJcePacket
{
writeJceStruct
(
struct
,
tag
)
}.
readBytes
()
}
fun
<
K
,
V
>
jceMap
(
tag
:
Int
,
vararg
entries
:
Pair
<
K
,
V
>):
ByteArray
{
return
buildJcePacket
{
writeMap
(
mapOf
(*
entries
),
tag
)
}.
readBytes
()
}
/**
*
* From: com.qq.taf.jce.JceOutputStream
*/
@Suppress
(
"unused"
,
"MemberVisibilityCanBePrivate"
)
@UseExperimental
(
ExperimentalIoApi
::
class
)
class
JceOutput
(
private
val
stringCharset
:
Charset
=
CharsetGBK
)
{
private
val
output
:
BytePacketBuilder
=
BytePacketBuilder
()
fun
build
():
ByteReadPacket
=
output
.
build
()
fun
close
()
=
output
.
close
()
fun
flush
()
=
output
.
flush
()
fun
writeByte
(
v
:
Byte
,
tag
:
Int
)
{
if
(
v
.
toInt
()
==
0
)
{
writeHead
(
ZERO_TYPE
,
tag
)
}
else
{
writeHead
(
BYTE
,
tag
)
output
.
writeByte
(
v
)
}
}
fun
writeDouble
(
v
:
Double
,
tag
:
Int
)
{
writeHead
(
DOUBLE
,
tag
)
output
.
writeDouble
(
v
)
}
fun
writeFloat
(
v
:
Float
,
tag
:
Int
)
{
writeHead
(
FLOAT
,
tag
)
output
.
writeFloat
(
v
)
}
fun
writeFully
(
src
:
ByteArray
,
tag
:
Int
)
{
writeHead
(
SIMPLE_LIST
,
tag
)
writeHead
(
BYTE
,
0
)
writeInt
(
src
.
size
,
0
)
output
.
writeFully
(
src
)
}
fun
writeFully
(
src
:
DoubleArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeDouble
(
it
,
0
)
}
}
fun
writeFully
(
src
:
FloatArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeFloat
(
it
,
0
)
}
}
fun
writeFully
(
src
:
IntArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeInt
(
it
,
0
)
}
}
fun
writeFully
(
src
:
LongArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeLong
(
it
,
0
)
}
}
fun
writeFully
(
src
:
ShortArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeShort
(
it
,
0
)
}
}
fun
writeFully
(
src
:
BooleanArray
,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeBoolean
(
it
,
0
)
}
}
fun
<
T
>
writeFully
(
src
:
Array
<
T
>,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
writeInt
(
src
.
size
,
0
)
src
.
forEach
{
writeObject
(
it
,
0
)
}
}
fun
writeInt
(
v
:
Int
,
tag
:
Int
)
{
if
(
v
in
Short
.
MIN_VALUE
..
Short
.
MAX_VALUE
)
{
writeShort
(
v
.
toShort
(),
tag
)
}
else
{
writeHead
(
INT
,
tag
)
output
.
writeInt
(
v
)
}
}
fun
writeLong
(
v
:
Long
,
tag
:
Int
)
{
if
(
v
in
Int
.
MIN_VALUE
..
Int
.
MAX_VALUE
)
{
writeInt
(
v
.
toInt
(),
tag
)
}
else
{
writeHead
(
LONG
,
tag
)
output
.
writeLong
(
v
)
}
}
fun
writeShort
(
v
:
Short
,
tag
:
Int
)
{
if
(
v
in
Byte
.
MIN_VALUE
..
Byte
.
MAX_VALUE
)
{
writeByte
(
v
.
toByte
(),
tag
)
}
else
{
writeHead
(
SHORT
,
tag
)
output
.
writeShort
(
v
)
}
}
fun
writeBoolean
(
v
:
Boolean
,
tag
:
Int
)
{
this
.
writeByte
(
if
(
v
)
1
else
0
,
tag
)
}
fun
writeString
(
v
:
String
,
tag
:
Int
)
{
val
array
=
v
.
toByteArray
(
stringCharset
)
if
(
array
.
size
>
255
)
{
writeHead
(
STRING4
,
tag
)
output
.
writeInt
(
array
.
size
)
output
.
writeFully
(
array
)
}
else
{
writeHead
(
STRING1
,
tag
)
output
.
writeByte
(
array
.
size
.
toByte
())
output
.
writeFully
(
array
)
}
}
fun
<
K
,
V
>
writeMap
(
map
:
Map
<
K
,
V
>,
tag
:
Int
)
{
writeHead
(
MAP
,
tag
)
if
(
map
.
isEmpty
())
{
writeInt
(
0
,
0
)
}
else
{
writeInt
(
map
.
size
,
0
)
map
.
forEach
{
(
key
,
value
)
->
writeObject
(
key
,
0
)
writeObject
(
value
,
1
)
}
}
}
fun
writeCollection
(
collection
:
Collection
<
*
>?,
tag
:
Int
)
{
writeHead
(
LIST
,
tag
)
if
(
collection
==
null
||
collection
.
isEmpty
())
{
writeInt
(
0
,
0
)
}
else
{
writeInt
(
collection
.
size
,
0
)
collection
.
forEach
{
writeObject
(
it
,
0
)
}
}
}
fun
writeJceStruct
(
v
:
JceStruct
,
tag
:
Int
)
{
writeHead
(
STRUCT_BEGIN
,
tag
)
v
.
writeTo
(
this
)
writeHead
(
STRUCT_END
,
0
)
}
fun
<
T
>
writeObject
(
v
:
T
,
tag
:
Int
)
{
when
(
v
)
{
is
Byte
->
writeByte
(
v
,
tag
)
is
Short
->
writeShort
(
v
,
tag
)
is
Int
->
writeInt
(
v
,
tag
)
is
Long
->
writeLong
(
v
,
tag
)
is
Float
->
writeFloat
(
v
,
tag
)
is
Double
->
writeDouble
(
v
,
tag
)
is
JceStruct
->
writeJceStruct
(
v
,
tag
)
is
ByteArray
->
writeFully
(
v
,
tag
)
is
Collection
<
*
>
->
writeCollection
(
v
,
tag
)
is
Boolean
->
writeBoolean
(
v
,
tag
)
is
Map
<
*
,
*
>
->
writeMap
(
v
,
tag
)
is
IntArray
->
writeFully
(
v
,
tag
)
is
ShortArray
->
writeFully
(
v
,
tag
)
is
BooleanArray
->
writeFully
(
v
,
tag
)
is
LongArray
->
writeFully
(
v
,
tag
)
is
FloatArray
->
writeFully
(
v
,
tag
)
is
DoubleArray
->
writeFully
(
v
,
tag
)
is
Array
<
*
>
->
writeFully
(
v
,
tag
)
is
String
->
writeString
(
v
,
tag
)
//
// is ByteReadPacket -> ByteArrayPool.useInstance {
// v.readAvailable(it)
// writeFully(it, tag)
// }
else
->
error
(
"unsupported type: ${v.getClassName()}"
)
}
}
fun
write
(
v
:
Int
,
tag
:
Int
)
=
writeInt
(
v
,
tag
)
fun
write
(
v
:
Byte
,
tag
:
Int
)
=
writeByte
(
v
,
tag
)
fun
write
(
v
:
Short
,
tag
:
Int
)
=
writeShort
(
v
,
tag
)
fun
write
(
v
:
Long
,
tag
:
Int
)
=
writeLong
(
v
,
tag
)
fun
write
(
v
:
Float
,
tag
:
Int
)
=
writeFloat
(
v
,
tag
)
fun
write
(
v
:
Double
,
tag
:
Int
)
=
writeDouble
(
v
,
tag
)
fun
write
(
v
:
String
,
tag
:
Int
)
=
writeString
(
v
,
tag
)
fun
write
(
v
:
Boolean
,
tag
:
Int
)
=
writeBoolean
(
v
,
tag
)
fun
write
(
v
:
Collection
<
*
>,
tag
:
Int
)
=
writeCollection
(
v
,
tag
)
fun
write
(
v
:
Map
<
*
,
*
>,
tag
:
Int
)
=
writeMap
(
v
,
tag
)
fun
write
(
v
:
ByteArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
IntArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
BooleanArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
LongArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
ShortArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
Array
<
*
>,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
FloatArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
fun
write
(
v
:
DoubleArray
,
tag
:
Int
)
=
writeFully
(
v
,
tag
)
@PublishedApi
internal
companion
object
{
const
val
BYTE
:
Int
=
0
const
val
DOUBLE
:
Int
=
5
const
val
FLOAT
:
Int
=
4
const
val
INT
:
Int
=
2
const
val
JCE_MAX_STRING_LENGTH
=
104857600
const
val
LIST
:
Int
=
9
const
val
LONG
:
Int
=
3
const
val
MAP
:
Int
=
8
const
val
SHORT
:
Int
=
1
const
val
SIMPLE_LIST
:
Int
=
13
const
val
STRING1
:
Int
=
6
const
val
STRING4
:
Int
=
7
const
val
STRUCT_BEGIN
:
Int
=
10
const
val
STRUCT_END
:
Int
=
11
const
val
ZERO_TYPE
:
Int
=
12
private
fun
Any
?.
getClassName
():
KClass
<
out
Any
>
=
if
(
this
==
null
)
Unit
::
class
else this::class
}
@
PublishedApi
internal
fun
writeHead
(
type
:
Int
,
tag
:
Int
)
{
if
(
tag
<
15
)
{
this
.
output
.
writeByte
(((
tag
shl
4
)
or
type
).
toByte
())
return
}
if
(
tag
<
256
)
{
this
.
output
.
writeByte
((
type
.
toByte
()
or
0
xF0
.
toByte
()))
this
.
output
.
writeByte
(
tag
.
toByte
())
return
}
throw
JceEncodeException
(
"tag is too large: $tag"
)
}
}
class
JceEncodeException
(
message
:
String
)
:
RuntimeException
(
message
)
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/JceStruct.kt
View file @
55e6c934
package
net.mamoe.mirai.qqandroid.io
interface
JceStruct
{
}
\ No newline at end of file
interface
JceStruct
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce
Encoder
.kt
→
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
View file @
55e6c934
This diff is collapsed.
Click to expand it.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt
View file @
55e6c934
package
net.mamoe.mirai.qqandroid.network.protocol.jce
import
kotlinx.serialization.Polymorphic
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.UseSerializers
import
net.mamoe.mirai.qqandroid.io.JceStruct
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
private
val
EMPTY_MAP
=
mapOf
<
String
,
String
>()
private
val
EMPTY_SBUFFER_MAP
=
mapOf
<
Int
,
ByteArray
>()
...
...
@@ -15,8 +18,23 @@ class RequestPacket(
@SerialId
(
4
)
val
iRequestId
:
Int
=
0
,
@SerialId
(
5
)
val
sServantName
:
String
=
""
,
@SerialId
(
6
)
val
sFuncName
:
String
=
""
,
@SerialId
(
7
)
val
sBuffer
:
Map
<
Int
,
ByteArray
>
=
EMPTY_SBUFFER_MAP
,
@SerialId
(
7
)
val
sBuffer
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@SerialId
(
8
)
val
iTimeout
:
Int
=
0
,
@SerialId
(
9
)
val
context
:
Map
<
String
,
String
>
=
EMPTY_MAP
,
@SerialId
(
10
)
val
status
:
Map
<
String
,
String
>
=
EMPTY_MAP
)
:
JceStruct
@Serializable
class
RequestDataVersion3
(
@SerialId
(
0
)
val
map
:
Map
<
String
,
ByteArray
>
)
:
JceStruct
@Serializable
class
RequestDataVersion2
(
@SerialId
(
0
)
val
map
:
Map
<
String
,
Map
<
String
,
ByteArray
>>
)
:
JceStruct
@Serializable
class
RequestDataStructSvcReqRegister
(
@SerialId
(
0
)
val
struct
:
SvcReqRegister
)
:
JceStruct
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
View file @
55e6c934
package
net.mamoe.mirai.qqandroid.network.protocol.jce
import
kotlinx.serialization.Polymorphic
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.qqandroid.io.JceStruct
@Serializable
class
SvcReqRegister
(
@SerialId
(
6
)
var
bIsOnline
:
Byte
=
0
,
@SerialId
(
34
)
var
bIsSetStatus
:
Byte
=
0
,
@SerialId
(
7
)
var
bIsShowOnlin
e
:
Byte
=
0
,
@SerialId
(
8
)
var
bKikPC
:
Byte
=
0
,
@SerialId
(
9
)
var
bKikWeak
:
Byte
=
0
,
@SerialId
(
5
)
va
r
bOnlinePush
:
Byte
=
0
,
@SerialId
(
22
)
var
bOpenPush
:
Byte
=
1
,
@SerialId
(
14
)
var
bRegTyp
e
:
Byte
=
0
,
@SerialId
(
36
)
var
bSetMute
:
Byte
=
0
,
@SerialId
(
18
)
var
bSlientPush
:
Byte
=
0
,
@SerialId
(
33
)
var
bytes_0x769_reqbody
:
ByteArray
?
=
null
,
@SerialId
(
2
)
var
cConnType
:
Byte
=
0
,
@SerialId
(
12
)
va
r
cNetType
:
Byte
=
0
,
@SerialId
(
23
)
var
iLargeSeq
:
Long
=
0L
,
@SerialId
(
24
)
var
iLastWatchStartTime
:
Long
=
0L
,
@SerialId
(
1
7
)
var
iLocaleID
:
Int
=
2052
,
@SerialId
(
1
1
)
var
iOSVersion
:
Long
=
0L
,
@SerialId
(
4
)
var
iStatus
:
Int
=
11
,
@SerialId
(
1
)
var
lBid
:
Long
=
0L
,
@SerialId
(
29
)
var
lCpId
:
Long
=
0L
,
@SerialId
(
0
)
var
lUin
:
Long
=
0L
,
@SerialId
(
13
)
var
sBuildVer
:
String
?
=
""
,
@SerialId
(
2
8
)
var
sChannelNo
:
String
?
=
""
,
@SerialId
(
3
)
var
sOther
:
String
=
""
,
@SerialId
(
19
)
var
strDevName
:
String
?
=
null
,
@SerialId
(
2
0
)
var
strDevType
:
String
?
=
null
,
@SerialId
(
32
)
var
strIOSIdfa
:
String
?
=
""
,
@SerialId
(
2
1
)
var
strOSVer
:
String
?
=
null
,
@SerialId
(
30
)
var
strVendorName
:
String
?
=
null
,
@SerialId
(
3
1
)
var
strVendorOS
Name
:
String
?
=
null
,
@SerialId
(
10
)
var
timeStamp
:
Long
=
0L
,
@SerialId
(
27
)
var
uNewSSOIp
:
Long
=
0L
,
@SerialId
(
26
)
var
uOldSSOIp
:
Long
=
0L
,
@SerialId
(
15
)
var
vecDevParam
:
ByteArray
?
=
null
,
@SerialId
(
16
)
var
vecGuid
:
ByteArray
?
=
null
,
@SerialId
(
3
5
)
var
vecServerBuf
:
ByteArray
?
=
null
@SerialId
(
0
)
val
lUin
:
Long
=
0L
,
@SerialId
(
1
)
val
lBid
:
Long
=
0L
,
@SerialId
(
2
)
val
cConnTyp
e
:
Byte
=
0
,
@SerialId
(
3
)
val
sOther
:
String
=
""
,
@SerialId
(
4
)
val
iStatus
:
Int
=
11
,
@SerialId
(
5
)
va
l
bOnlinePush
:
Byte
=
0
,
@SerialId
(
6
)
val
bIsOnline
:
Byte
=
0
,
@SerialId
(
7
)
val
bIsShowOnlin
e
:
Byte
=
0
,
@SerialId
(
8
)
val
bKikPC
:
Byte
=
0
,
@SerialId
(
9
)
val
bKikWeak
:
Byte
=
0
,
@SerialId
(
10
)
val
timeStamp
:
Long
=
0L
,
@SerialId
(
11
)
val
iOSVersion
:
Long
=
0L
,
@SerialId
(
12
)
va
l
cNetType
:
Byte
=
0
,
@SerialId
(
13
)
val
sBuildVer
:
String
?
=
""
,
@SerialId
(
14
)
val
bRegType
:
Byte
=
0
,
@SerialId
(
1
5
)
val
vecDevParam
:
ByteArray
?
=
null
,
@SerialId
(
1
6
)
val
vecGuid
:
ByteArray
?
=
null
,
@SerialId
(
17
)
val
iLocaleID
:
Int
=
2052
,
@SerialId
(
1
8
)
val
bSlientPush
:
Byte
=
0
,
@SerialId
(
19
)
val
strDevName
:
String
?
=
null
,
@SerialId
(
20
)
val
strDevType
:
String
?
=
null
,
@SerialId
(
21
)
val
strOSVer
:
String
?
=
null
,
@SerialId
(
2
2
)
val
bOpenPush
:
Byte
=
1
,
@SerialId
(
23
)
val
iLargeSeq
:
Long
=
0L
,
@SerialId
(
24
)
val
iLastWatchStartTime
:
Long
=
0L
,
@SerialId
(
2
6
)
val
uOldSSOIp
:
Long
=
0L
,
@SerialId
(
27
)
val
uNewSSOIp
:
Long
=
0L
,
@SerialId
(
2
8
)
val
sChannelNo
:
String
?
=
""
,
@SerialId
(
29
)
val
lCpId
:
Long
=
0L
,
@SerialId
(
3
0
)
val
strVendor
Name
:
String
?
=
null
,
@SerialId
(
31
)
val
strVendorOSName
:
String
?
=
null
,
@SerialId
(
32
)
val
strIOSIdfa
:
String
?
=
""
,
@SerialId
(
33
)
val
bytes_0x769_reqbody
:
ByteArray
?
=
null
,
@SerialId
(
34
)
val
bIsSetStatus
:
Byte
=
0
,
@SerialId
(
35
)
val
vecServerBuf
:
ByteArray
?
=
null
,
@SerialId
(
3
6
)
val
bSetMute
:
Byte
=
0
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
)
:
JceStruct
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt
deleted
100644 → 0
View file @
2f4a4a48
package
net.mamoe.mirai.qqandroid.network.protocol.jce
import
kotlinx.io.core.BytePacketBuilder
import
net.mamoe.mirai.qqandroid.io.JceOutput
import
net.mamoe.mirai.qqandroid.io.buildJcePacket
import
net.mamoe.mirai.qqandroid.io.writeJcePacket
inline
fun
BytePacketBuilder
.
writeUniRequestPacket
(
requestPacket
:
RequestPacket
.()
->
Unit
)
{
writeJcePacket
{
RequestPacket
().
apply
(
requestPacket
).
writeTo
(
this
)
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
55e6c934
...
...
@@ -4,7 +4,7 @@ import kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.
JceInput
import
net.mamoe.mirai.qqandroid.io.
serialization.loadAs
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
...
...
@@ -248,7 +248,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
}
private
suspend
fun
ByteReadPacket
.
parseUniResponse
(
bot
:
QQAndroidBot
,
packetFactory
:
PacketFactory
<
*
>,
ssoSequenceId
:
Int
,
consumer
:
PacketConsumer
)
{
val
uni
=
RequestPacket
.
newInstanceFrom
(
JceInput
(
readIoBuffer
(
readInt
()
-
4
)
))
val
uni
=
readBytes
(
readInt
()
-
4
).
loadAs
(
RequestPacket
.
serializer
(
))
PacketLogger
.
verbose
(
uni
.
toString
())
consumer
(
packetFactory
.
decode
(
bot
,
uni
.
sBuffer
.
toReadPacket
()),
uni
.
sServantName
+
"."
+
uni
.
sFuncName
,
ssoSequenceId
)
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
View file @
55e6c934
...
...
@@ -4,6 +4,9 @@ import kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.discardExact
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.Jce
import
net.mamoe.mirai.qqandroid.io.serialization.loadAs
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion2
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion3
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
...
...
@@ -19,7 +22,7 @@ class MessageSvc {
)
val
messageNotification
=
Jce
.
UTF8
.
load
(
RequestPushNotify
.
serializer
(),
req
.
sBuffer
[
0
]
!!
req
.
sBuffer
.
loadAs
(
RequestDataVersion2
.
serializer
()).
map
.
entries
.
first
().
value
.
entries
.
first
().
value
)
println
(
messageNotification
.
contentToString
())
TODO
()
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
View file @
55e6c934
...
...
@@ -219,7 +219,11 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
sealed
class
LoginPacketResponse
:
Packet
{
object
Success
:
LoginPacketResponse
()
object
Success
:
LoginPacketResponse
(){
override
fun
toString
():
String
{
return
"LoginPacketResponse.Success"
}
}
data class
Error
(
val
title
:
String
,
val
message
:
String
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/Register.kt
View file @
55e6c934
package
net.mamoe.mirai.qqandroid.network.protocol.packet.login
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.writeFully
import
kotlinx.serialization.protobuf.ProtoBuf
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.io.jceMap
import
net.mamoe.mirai.qqandroid.io.jceStruct
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataStructSvcReqRegister
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion3
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
import
net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.utils.io.debugPrint
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.localIpAddress
...
...
@@ -55,72 +56,73 @@ class StatSvc {
client
,
subAppId
=
subAppId
,
commandName
=
commandName
,
extraData
=
client
.
wLoginSigInfo
.
tgt
.
toReadPacket
(),
sequenceId
=
sequenceId
)
{
write
UniRequestPacket
{
sServantName
=
"PushService"
sFuncName
=
"SvcReqRegister"
sBuffer
=
jceMap
(
0
,
"SvcReqRegister"
to
jceStruct
(
0
,
SvcReqRegister
().
apply
{
cConnType
=
0
lBid
=
1
or
2
or
4
lUin
=
client
.
uin
iStatus
=
client
.
onlineStatus
.
id
bKikPC
=
0
// 是否把 PC 踢下线
bKikWeak
=
0
timeStamp
=
0
// timeStamp = currentTimeSeconds // millis or seconds??
iLargeSeq
=
1551
// ?
bOpenPush
=
1
iLocaleID
=
2052
bRegType
=
(
if
(
regPushReason
==
RegPushReason
.
appRegister
||
regPushReason
==
RegPushReason
.
fillRegProxy
||
regPushReason
==
RegPushReason
.
createDefaultRegInfo
||
regPushReason
==
RegPushReason
.
setOnlineStatus
)
0
else
1
).
toByte
()
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
()
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
vecGuid
=
client
.
device
.
guid
strDevName
=
client
.
device
.
model
.
encodeToString
()
strDevType
=
client
.
device
.
model
.
encodeToString
()
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
()
write
Fully
(
RequestPacket
(
sServantName
=
"PushService"
,
sFuncName
=
"SvcReqRegister"
,
sBuffer
=
RequestDataVersion3
(
mapOf
(
"SvcReqRegister"
to
RequestDataStructSvcReqRegister
(
SvcReqRegister
(
cConnType
=
0
,
lBid
=
1
or
2
or
4
,
lUin
=
client
.
uin
,
iStatus
=
client
.
onlineStatus
.
id
,
bKikPC
=
0
,
// 是否把 PC 踢下线
bKikWeak
=
0
,
timeStamp
=
0
,
// timeStamp = currentTimeSeconds // millis or seconds??
iLargeSeq
=
1551
,
// ?
bOpenPush
=
1
,
iLocaleID
=
2052
,
bRegType
=
(
if
(
regPushReason
==
RegPushReason
.
appRegister
||
regPushReason
==
RegPushReason
.
fillRegProxy
||
regPushReason
==
RegPushReason
.
createDefaultRegInfo
||
regPushReason
==
RegPushReason
.
setOnlineStatus
)
0
else
1
).
toByte
(),
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
,
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
(),
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
,
vecGuid
=
client
.
device
.
guid
,
strDevName
=
client
.
device
.
model
.
encodeToString
(),
strDevType
=
client
.
device
.
model
.
encodeToString
(),
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
(),
uOldSSOIp
=
0
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
}
strVendorName
=
"MIUI"
strVendorOSName
=
"?ONEPLUS A5000_23_17"
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody
=
ProtoBuf
.
dump
(
Oidb0x769
.
RequestBody
.
serializer
(),
Oidb0x769
.
RequestBody
(
rpt_config_list
=
listOf
(
Oidb0x769
.
ConfigSeq
(
type
=
46
,
version
=
0
),
Oidb0x769
.
ConfigSeq
(
type
=
283
,
version
=
0
uOldSSOIp
=
0
,
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
},
strVendorName
=
"MIUI"
,
strVendorOSName
=
"?ONEPLUS A5000_23_17"
,
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody
=
ProtoBuf
.
dump
(
Oidb0x769
.
RequestBody
.
serializer
(),
Oidb0x769
.
RequestBody
(
rpt_config_list
=
listOf
(
Oidb0x769
.
ConfigSeq
(
type
=
46
,
version
=
0
),
Oidb0x769
.
ConfigSeq
(
type
=
283
,
version
=
0
)
)
)
)
),
bSetMute
=
0
)
)
bSetMute
=
0
}
)
)
}
this
.
writePacket
(
this
.
build
().
debugPrint
(
"sso body"
))
).
toByteArray
(
RequestDataStructSvcReqRegister
.
serializer
())
)
).
toByteArray
(
RequestDataVersion3
.
serializer
())
).
toByteArray
(
RequestPacket
.
serializer
())
)
}
}
...
...
mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/Jce
En
coderTest.kt
→
mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/Jce
De
coderTest.kt
View file @
55e6c934
package
net.mamoe.mirai.qqandroid.io.serialization
import
kotlinx.io.core.readBytes
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.qqandroid.io.CharsetUTF8
import
net.mamoe.mirai.qqandroid.io.JceOutput
import
net.mamoe.mirai.qqandroid.io.JceStruct
import
net.mamoe.mirai.qqandroid.io.buildJcePacket
import
net.mamoe.mirai.utils.io.toUHexString
import
net.mamoe.mirai.utils.cryptor.contentToString
import
kotlin.test.Test
import
kotlin.test.assertEquals
class
Jce
En
coderTest
{
class
Jce
De
coderTest
{
@Serializable
class
TestSimpleJceStruct
(
...
...
@@ -23,51 +18,16 @@ class JceEncoderTest {
@SerialId
(
4
)
val
long
:
Long
=
123
,
@SerialId
(
5
)
val
float
:
Float
=
123f
,
@SerialId
(
6
)
val
double
:
Double
=
123.0
)
:
JceStruct
()
{
override
fun
writeTo
(
builder
:
JceOutput
)
=
builder
.
run
{
writeString
(
"123"
,
0
)
writeByte
(
123
,
1
)
writeShort
(
123
,
2
)
writeInt
(
123
,
3
)
writeLong
(
123
,
4
)
writeFloat
(
123f
,
5
)
writeDouble
(
123.0
,
6
)
}
}
)
:
JceStruct
@Test
fun
testEncoder
()
{
assertEquals
(
buildJcePacket
{
writeString
(
"123"
,
0
)
writeByte
(
123
,
1
)
writeShort
(
123
,
2
)
writeInt
(
123
,
3
)
writeLong
(
123
,
4
)
writeFloat
(
123f
,
5
)
writeDouble
(
123.0
,
6
)
}.
readBytes
().
toUHexString
(),
Jce
.
GBK
.
dump
(
TestSimpleJceStruct
.
serializer
(),
TestSimpleJceStruct
()
).
toUHexString
()
)
println
(
TestComplexJceStruct
().
toByteArray
(
TestComplexJceStruct
.
serializer
()).
loadAs
(
TestComplexJceStruct
.
serializer
()).
contentToString
())
}
@Test
fun
testEncoder2
()
{
assertEquals
(
buildJcePacket
(
stringCharset
=
CharsetUTF8
)
{
writeFully
(
byteArrayOf
(
1
,
2
,
3
),
7
)
writeCollection
(
listOf
(
1
,
2
,
3
),
8
)
writeMap
(
mapOf
(
"哈哈"
to
"嘿嘿"
),
9
)
writeJceStruct
(
TestSimpleJceStruct
(),
10
)
}.
readBytes
().
toUHexString
(),
Jce
.
UTF8
.
dump
(
TestComplexJceStruct
.
serializer
(),
TestComplexJceStruct
()
).
toUHexString
()
)
}
@Serializable
...
...
@@ -76,5 +36,5 @@ class JceEncoderTest {
@SerialId
(
8
)
val
byteList
:
List
<
Byte
>
=
listOf
(
1
,
2
,
3
),
@SerialId
(
9
)
val
map
:
Map
<
String
,
String
>
=
mapOf
(
"哈哈"
to
"嘿嘿"
),
@SerialId
(
10
)
val
nestedJceStruct
:
TestSimpleJceStruct
=
TestSimpleJceStruct
()
)
)
:
JceStruct
}
\ No newline at end of file
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt
View file @
55e6c934
...
...
@@ -389,7 +389,7 @@ internal class TIMPCBotNetworkHandler internal constructor(coroutineContext: Cor
close
()
return
}
val
code
=
configuration
.
loginSolver
(
bot
,
captchaCache
!!
)
val
code
=
configuration
.
loginSolver
.
onSolvePicCaptcha
(
bot
,
captchaCache
!!
)
this
.
captchaCache
=
null
if
(
code
==
null
||
code
.
length
!=
4
)
{
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverAndroid.kt
deleted
100644 → 0
View file @
2f4a4a48
package
net.mamoe.mirai.utils
/**
* 直接抛出异常. 需自行处理验证码, 在 [BotConfiguration.captchaSolver] 中调整
*/
actual
var
DefaultCaptchaSolver
:
CaptchaSolver
=
{
error
(
"No CaptchaSolver found. BotConfiguration.captchaSolver should be assigned manually"
)
}
\ No newline at end of file
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/defaultLoginSolver.kt
0 → 100644
View file @
55e6c934
package
net.mamoe.mirai.utils
import
kotlinx.io.core.IoBuffer
import
net.mamoe.mirai.Bot
/**
* 在各平台实现的默认的验证码处理器.
*/
actual
var
defaultLoginSolver
:
LoginSolver
=
object
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onGetPhoneNumber
():
String
{
error
(
"should be implemented manually by you"
)
}
override
suspend
fun
onGetSMSVerifyCode
():
String
{
error
(
"should be implemented manually by you"
)
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/DefaultCaptchaSolverJvm.kt
View file @
55e6c934
...
...
@@ -28,7 +28,7 @@ import kotlin.coroutines.CoroutineContext
actual
var
defaultLoginSolver
:
LoginSolver
=
DefaultLoginSolver
()
class
DefaultLoginSolver
():
LoginSolver
()
{
class
DefaultLoginSolver
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
loginSolverLock
.
withLock
{
val
tempFile
:
File
=
createTempFile
(
suffix
=
".png"
).
apply
{
deleteOnExit
()
}
...
...
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
deleted
100644 → 0
View file @
2f4a4a48
package
jceTest
import
io.ktor.util.InternalAPI
import
jce.jce.JceInputStream
import
jceTest.JceOutputTest.TestMiraiStruct
import
jceTest.JceOutputTest.TestQQStruct
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.qqandroid.network.io.JceInput
import
net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import
net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.io.toIoBuffer
import
org.junit.Test
private
infix
fun
<
T
>
T
.
shouldEqualTo
(
another
:
T
)
{
if
(
this
is
Array
<
*
>)
{
this
.
contentEquals
(
another
as
Array
<
*
>)
}
else
check
(
this
.
contentToString
()
==
another
.
contentToString
())
{
"""actual: ${this.contentToString()}
|required: ${another.contentToString()}
"""
.
trimMargin
()
}
}
@UseExperimental
(
InternalAPI
::
class
)
private
fun
<
R
>
ByteArray
.
qqJce
(
block
:
JceInputStream
.()
->
R
):
R
{
return
JceInputStream
(
this
).
run
(
block
)
}
private
fun
<
R
>
ByteArray
.
read
(
block
:
JceInput
.()
->
R
):
R
{
return
JceInput
(
this
.
toIoBuffer
()).
run
(
block
)
}
private
fun
ByteReadPacket
.
check
(
block
:
ByteArray
.()
->
Unit
)
{
this
.
readBytes
().
apply
(
block
)
}
internal
class
JceInputTest
{
@Test
fun
readByte
()
=
buildJcePacket
{
writeByte
(
1
,
1
)
}.
check
{
read
{
readByte
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toByte
(),
1
,
true
)
}
}
@Test
fun
readDouble
()
=
buildJcePacket
{
writeDouble
(
1.0
,
1
)
}.
check
{
read
{
readDouble
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toDouble
(),
1
,
true
)
}
}
@Test
fun
readFloat
()
=
buildJcePacket
{
writeFloat
(
1.0f
,
1
)
}.
check
{
read
{
readFloat
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toFloat
(),
1
,
true
)
}
}
@Test
fun
readFully
()
=
buildJcePacket
{
writeFully
(
byteArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readByteArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
byteArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully
()
=
buildJcePacket
{
writeFully
(
shortArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readShortArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
shortArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully1
()
=
buildJcePacket
{
writeFully
(
intArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readIntArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
intArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully2
()
=
buildJcePacket
{
writeFully
(
longArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readLongArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
longArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully3
()
=
buildJcePacket
{
writeFully
(
booleanArrayOf
(
true
,
false
,
true
),
1
)
}.
check
{
read
{
readBooleanArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
booleanArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully4
()
=
buildJcePacket
{
writeFully
(
floatArrayOf
(
1f
,
2f
,
3f
),
1
)
}.
check
{
read
{
readFloatArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
floatArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully5
()
=
buildJcePacket
{
writeFully
(
doubleArrayOf
(
1.0
,
2.0
,
3.0
),
1
)
}.
check
{
read
{
readDoubleArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
doubleArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully6
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
"sss"
,
"哈哈"
),
1
)
}.
check
{
read
{
readSimpleArray
(
""
,
1
)
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
""
),
1
,
true
)
}
}
@Test
fun
testWriteFully7
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
"sss"
,
"哈哈"
),
1
)
}.
check
{
read
{
readArrayOrNull
(
""
,
1
)
!!
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
""
),
1
,
true
)
}
}
@Test
fun
testWriteFully8
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
TestMiraiStruct
(
"Haha"
)),
1
)
}.
check
{
read
{
readJceStructArrayOrNull
(
TestMiraiStruct
,
1
)
!!
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
TestQQStruct
(
"stub"
)),
1
,
true
)
}
}
@Test
fun
readInt
()
=
buildJcePacket
{
writeInt
(
1
,
2
)
}.
check
{
read
{
readInt
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0
,
2
,
true
)
}
}
@Test
fun
readLong
()
=
buildJcePacket
{
writeLong
(
1
,
2
)
}.
check
{
read
{
readLong
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0L
,
2
,
true
)
}
}
@Test
fun
readShort
()
=
buildJcePacket
{
writeShort
(
1
,
2
)
}.
check
{
read
{
readShort
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toShort
(),
2
,
true
)
}
}
@Test
fun
readBoolean
()
=
buildJcePacket
{
writeBoolean
(
true
,
2
)
}.
check
{
read
{
readBoolean
(
2
)
}
shouldEqualTo
qqJce
{
read
(
false
,
2
,
true
)
}
}
@Test
fun
readString
()
=
buildJcePacket
{
writeString
(
"嗨"
,
2
)
}.
check
{
read
{
readString
(
2
)
}
shouldEqualTo
qqJce
{
read
(
""
,
2
,
true
)
}
}
@Test
fun
readMap
()
=
buildJcePacket
{
writeMap
(
mapOf
(
123.0
to
"Hello"
),
3
)
}.
check
{
read
{
readMap
(
0.0
,
""
,
3
)
}
shouldEqualTo
qqJce
{
read
(
mapOf
(
0.0
to
""
),
3
,
true
)
}
}
@Test
fun
readCollection
()
=
buildJcePacket
{
writeCollection
(
listOf
(
"1"
,
"还"
),
3
)
}.
check
{
repeat
(
0
)
{
error
(
"fuck kotlin"
)
}
read
{
readList
(
""
,
3
)
}
shouldEqualTo
qqJce
{
read
(
listOf
(
""
),
3
,
true
)
}
}
@Test
fun
readJceStruct
()
=
buildJcePacket
{
writeJceStruct
(
TestMiraiStruct
(
"123"
),
3
)
}.
check
{
read
{
readJceStruct
(
TestMiraiStruct
,
3
)
}
shouldEqualTo
qqJce
{
read
(
TestQQStruct
(
"stub"
),
3
,
true
)
!!
}
}
@Test
fun
readObject
()
=
buildJcePacket
{
writeObject
(
123
,
3
)
}.
check
{
read
{
readObject
(
123
,
3
)
}
shouldEqualTo
qqJce
{
read
(
123
as
Any
,
3
,
true
)
}
}
}
\ No newline at end of file
mirai-debug/src/test/kotlin/jceTest/JceOutputTest.kt
deleted
100644 → 0
View file @
2f4a4a48
package
jceTest
import
io.ktor.util.InternalAPI
import
jce.jce.JceInputStream
import
jce.jce.JceOutputStream
import
jce.jce.JceStruct
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.qqandroid.network.io.JceInput
import
net.mamoe.mirai.qqandroid.network.io.JceOutput
import
net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import
net.mamoe.mirai.utils.io.toUHexString
import
org.junit.Test
private
infix
fun
ByteReadPacket
.
shouldEqualTo
(
another
:
ByteArray
)
{
this
.
readBytes
().
let
{
check
(
it
.
contentEquals
(
another
))
{
"""actual: ${it.toUHexString()}
|required: ${another.toUHexString()}
"""
.
trimMargin
()
}
}
}
@UseExperimental
(
InternalAPI
::
class
)
private
fun
qqJce
(
block
:
JceOutputStream
.()
->
Unit
):
ByteArray
{
return
JceOutputStream
().
apply
(
block
).
toByteArray
()
}
internal
class
JceOutputTest
{
@Test
fun
writeByte
()
{
buildJcePacket
{
writeByte
(
1
,
1
)
writeByte
(-
128
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1
.
toByte
(),
1
)
write
((-
128
).
toByte
(),
2
)
}
}
@Test
fun
writeDouble
()
{
buildJcePacket
{
writeDouble
(
1.0
,
1
)
writeDouble
(-
128.0
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1
.
toDouble
(),
1
)
write
((-
128
).
toDouble
(),
2
)
}
}
@Test
fun
writeFloat
()
{
buildJcePacket
{
writeFloat
(
1.0f
,
1
)
writeFloat
(-
128.0f
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1
.
toFloat
(),
1
)
write
((-
128
).
toFloat
(),
2
)
}
}
@Test
fun
writeFully
()
{
buildJcePacket
{
writeFully
(
byteArrayOf
(
1
,
2
),
1
)
writeFully
(
byteArrayOf
(
1
,
2
),
2
)
}
shouldEqualTo
qqJce
{
write
(
byteArrayOf
(
1
,
2
),
1
)
write
(
byteArrayOf
(
1
,
2
),
2
)
}
}
@Test
fun
testWriteFully
()
{
buildJcePacket
{
writeFully
(
intArrayOf
(
1
,
2
),
1
)
writeFully
(
intArrayOf
(
1
,
2
),
2
)
}
shouldEqualTo
qqJce
{
write
(
intArrayOf
(
1
,
2
),
1
)
write
(
intArrayOf
(
1
,
2
),
2
)
}
}
@Test
fun
testWriteFully1
()
{
buildJcePacket
{
writeFully
(
shortArrayOf
(
1
,
2
),
1
)
writeFully
(
shortArrayOf
(
1
,
2
),
2
)
}
shouldEqualTo
qqJce
{
write
(
shortArrayOf
(
1
,
2
),
1
)
write
(
shortArrayOf
(
1
,
2
),
2
)
}
}
@Test
fun
testWriteFully2
()
{
buildJcePacket
{
writeFully
(
booleanArrayOf
(
true
,
false
),
1
)
writeFully
(
booleanArrayOf
(
true
,
false
),
2
)
}
shouldEqualTo
qqJce
{
write
(
booleanArrayOf
(
true
,
false
),
1
)
write
(
booleanArrayOf
(
true
,
false
),
2
)
}
}
@Test
fun
testWriteFully3
()
{
buildJcePacket
{
writeFully
(
longArrayOf
(
1
,
2
),
1
)
writeFully
(
longArrayOf
(
1
,
2
),
2
)
}
shouldEqualTo
qqJce
{
write
(
longArrayOf
(
1
,
2
),
1
)
write
(
longArrayOf
(
1
,
2
),
2
)
}
}
@Test
fun
testWriteFully4
()
{
buildJcePacket
{
writeFully
(
floatArrayOf
(
1f
,
2f
),
1
)
writeFully
(
floatArrayOf
(
1f
,
2f
),
2
)
}
shouldEqualTo
qqJce
{
write
(
floatArrayOf
(
1f
,
2f
),
1
)
write
(
floatArrayOf
(
1f
,
2f
),
2
)
}
}
@Test
fun
testWriteFully5
()
{
buildJcePacket
{
writeFully
(
doubleArrayOf
(
1.0
,
2.0
),
1
)
writeFully
(
doubleArrayOf
(
1.0
,
2.0
),
2
)
}
shouldEqualTo
qqJce
{
write
(
doubleArrayOf
(
1.0
,
2.0
),
1
)
write
(
doubleArrayOf
(
1.0
,
2.0
),
2
)
}
}
@Test
fun
testWriteFully6
()
{
buildJcePacket
{
writeFully
(
arrayOf
(
"123"
,
"哈哈"
),
1
)
writeFully
(
arrayOf
(
"123"
,
"哈哈"
),
2
)
}
shouldEqualTo
qqJce
{
write
(
arrayOf
(
"123"
,
"哈哈"
),
1
)
write
(
arrayOf
(
"123"
,
"哈哈"
),
2
)
}
}
@Test
fun
writeInt
()
{
buildJcePacket
{
writeInt
(
1
,
1
)
writeInt
(-
128
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1
,
1
)
write
(-
128
,
2
)
}
}
@Test
fun
writeLong
()
{
buildJcePacket
{
writeLong
(
1
,
1
)
writeLong
(-
128
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1L
,
1
)
write
(-
128L
,
2
)
}
}
@Test
fun
writeShort
()
{
buildJcePacket
{
writeShort
(
1
,
1
)
writeShort
(-
128
,
2
)
}
shouldEqualTo
qqJce
{
write
(
1
.
toShort
(),
1
)
write
((-
128
).
toShort
(),
2
)
}
}
@Test
fun
writeBoolean
()
{
buildJcePacket
{
writeBoolean
(
true
,
1
)
writeBoolean
(
false
,
2
)
}
shouldEqualTo
qqJce
{
write
(
true
,
1
)
write
(
false
,
2
)
}
}
@Test
fun
writeString
()
{
buildJcePacket
{
writeString
(
"1"
,
1
)
writeString
(
"哈啊"
,
2
)
}
shouldEqualTo
qqJce
{
write
(
"1"
,
1
)
write
(
"哈啊"
,
2
)
}
}
@Test
fun
writeMap
()
{
buildJcePacket
{
writeMap
(
mapOf
(
""
to
""
),
1
)
writeMap
(
mapOf
(
""
to
123
),
2
)
writeMap
(
mapOf
(
123.0
to
"Hello"
),
3
)
}
shouldEqualTo
qqJce
{
write
(
mapOf
(
""
to
""
),
1
)
write
(
mapOf
(
""
to
123
),
2
)
write
(
mapOf
(
123.0
to
"Hello"
),
3
)
}
}
@Test
fun
writeCollection
()
{
buildJcePacket
{
writeCollection
(
listOf
(
"啊"
,
"333"
,
"1"
),
1
)
}
shouldEqualTo
qqJce
{
write
(
listOf
(
"啊"
,
"333"
,
"1"
),
1
)
}
}
data class
TestMiraiStruct
(
val
message
:
String
)
:
net
.
mamoe
.
mirai
.
qqandroid
.
network
.
io
.
JceStruct
()
{
override
fun
writeTo
(
builder
:
JceOutput
)
{
builder
.
writeString
(
message
,
0
)
}
companion
object
:
Factory
<
TestMiraiStruct
>
{
override
fun
newInstanceFrom
(
input
:
JceInput
):
TestMiraiStruct
{
return
TestMiraiStruct
(
input
.
readString
(
0
))
}
}
}
class
TestQQStruct
(
private
var
message
:
String
)
:
JceStruct
()
{
constructor
()
:
this
(
""
)
override
fun
readFrom
(
var1
:
JceInputStream
)
{
message
=
var1
.
read
(
""
,
0
,
true
)
}
override
fun
writeTo
(
var1
:
JceOutputStream
)
{
var1
.
write
(
message
,
0
)
}
override
fun
toString
():
String
{
return
"TestMiraiStruct(message=$message)"
}
}
@Test
fun
writeJceStruct
()
{
buildJcePacket
{
writeJceStruct
(
TestMiraiStruct
(
"Hello"
),
0
)
writeJceStruct
(
TestMiraiStruct
(
"嗨"
),
1
)
}
shouldEqualTo
qqJce
{
write
(
TestQQStruct
(
"Hello"
),
0
)
write
(
TestQQStruct
(
"嗨"
),
1
)
}
}
@Test
fun
writeObject
()
{
buildJcePacket
{
writeObject
(
0
.
toByte
(),
1
)
writeObject
(
0
.
toShort
(),
2
)
writeObject
(
0
,
3
)
writeObject
(
0L
,
4
)
writeObject
(
0f
,
5
)
writeObject
(
0.0
,
6
)
writeObject
(
"hello"
,
7
)
writeObject
(
TestMiraiStruct
(
"Hello"
),
8
)
}
shouldEqualTo
qqJce
{
write
(
0
.
toByte
(),
1
)
write
(
0
.
toShort
(),
2
)
write
(
0
,
3
)
write
(
0L
,
4
)
write
(
0f
,
5
)
write
(
0.0
,
6
)
write
(
"hello"
,
7
)
write
(
TestQQStruct
(
"Hello"
),
8
)
}
}
}
\ No newline at end of file
mirai-demos/mirai-demo-android/src/main/kotlin/net/mamoe/mirai/demo/MiraiService.kt
View file @
55e6c934
...
...
@@ -10,11 +10,13 @@ import android.os.IBinder
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.timpc.TIMPC
import
net.mamoe.mirai.utils.LoginFailedException
import
net.mamoe.mirai.utils.LoginSolver
import
java.lang.ref.WeakReference
class
MiraiService
:
Service
()
{
...
...
@@ -42,12 +44,27 @@ class MiraiService : Service() {
private
fun
login
(
qq
:
Long
,
pwd
:
String
)
{
GlobalScope
.
launch
{
mBot
=
TIMPC
.
Bot
(
qq
,
pwd
)
{
captchaSolver
=
{
val
bytes
=
it
.
readBytes
()
val
bitmap
=
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
size
)
mCaptchaDeferred
=
CompletableDeferred
()
mCallback
?.
get
()
?.
onCaptcha
(
bitmap
)
mCaptchaDeferred
.
await
()
loginSolver
=
object
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
val
bytes
=
data
.
readBytes
()
val
bitmap
=
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
size
)
mCaptchaDeferred
=
CompletableDeferred
()
mCallback
?.
get
()
?.
onCaptcha
(
bitmap
)
return
mCaptchaDeferred
.
await
()
}
override
suspend
fun
onSolveSliderCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
TODO
(
"not implemented"
)
}
override
suspend
fun
onGetPhoneNumber
():
String
{
TODO
(
"not implemented"
)
}
override
suspend
fun
onGetSMSVerifyCode
():
String
{
TODO
(
"not implemented"
)
}
}
}.
apply
{
try
{
...
...
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