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
Show 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
package
net.mamoe.mirai.qqandroid.io
interface
JceStruct
{
interface
JceStruct
\ No newline at end of file
}
\ 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
package
net.mamoe.mirai.qqandroid.network.protocol.jce
import
kotlinx.serialization.Polymorphic
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.UseSerializers
import
net.mamoe.mirai.qqandroid.io.JceStruct
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_MAP
=
mapOf
<
String
,
String
>()
private
val
EMPTY_SBUFFER_MAP
=
mapOf
<
Int
,
ByteArray
>()
private
val
EMPTY_SBUFFER_MAP
=
mapOf
<
Int
,
ByteArray
>()
...
@@ -15,8 +18,23 @@ class RequestPacket(
...
@@ -15,8 +18,23 @@ class RequestPacket(
@SerialId
(
4
)
val
iRequestId
:
Int
=
0
,
@SerialId
(
4
)
val
iRequestId
:
Int
=
0
,
@SerialId
(
5
)
val
sServantName
:
String
=
""
,
@SerialId
(
5
)
val
sServantName
:
String
=
""
,
@SerialId
(
6
)
val
sFuncName
:
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
(
8
)
val
iTimeout
:
Int
=
0
,
@SerialId
(
9
)
val
context
:
Map
<
String
,
String
>
=
EMPTY_MAP
,
@SerialId
(
9
)
val
context
:
Map
<
String
,
String
>
=
EMPTY_MAP
,
@SerialId
(
10
)
val
status
:
Map
<
String
,
String
>
=
EMPTY_MAP
@SerialId
(
10
)
val
status
:
Map
<
String
,
String
>
=
EMPTY_MAP
)
:
JceStruct
)
:
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
package
net.mamoe.mirai.qqandroid.network.protocol.jce
import
kotlinx.serialization.Polymorphic
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.qqandroid.io.JceStruct
import
net.mamoe.mirai.qqandroid.io.JceStruct
@Serializable
@Serializable
class
SvcReqRegister
(
class
SvcReqRegister
(
@SerialId
(
6
)
var
bIsOnline
:
Byte
=
0
,
@SerialId
(
0
)
val
lUin
:
Long
=
0L
,
@SerialId
(
34
)
var
bIsSetStatus
:
Byte
=
0
,
@SerialId
(
1
)
val
lBid
:
Long
=
0L
,
@SerialId
(
7
)
var
bIsShowOnlin
e
:
Byte
=
0
,
@SerialId
(
2
)
val
cConnTyp
e
:
Byte
=
0
,
@SerialId
(
8
)
var
bKikPC
:
Byte
=
0
,
@SerialId
(
3
)
val
sOther
:
String
=
""
,
@SerialId
(
9
)
var
bKikWeak
:
Byte
=
0
,
@SerialId
(
4
)
val
iStatus
:
Int
=
11
,
@SerialId
(
5
)
va
r
bOnlinePush
:
Byte
=
0
,
@SerialId
(
5
)
va
l
bOnlinePush
:
Byte
=
0
,
@SerialId
(
22
)
var
bOpenPush
:
Byte
=
1
,
@SerialId
(
6
)
val
bIsOnline
:
Byte
=
0
,
@SerialId
(
14
)
var
bRegTyp
e
:
Byte
=
0
,
@SerialId
(
7
)
val
bIsShowOnlin
e
:
Byte
=
0
,
@SerialId
(
36
)
var
bSetMute
:
Byte
=
0
,
@SerialId
(
8
)
val
bKikPC
:
Byte
=
0
,
@SerialId
(
18
)
var
bSlientPush
:
Byte
=
0
,
@SerialId
(
9
)
val
bKikWeak
:
Byte
=
0
,
@SerialId
(
33
)
var
bytes_0x769_reqbody
:
ByteArray
?
=
null
,
@SerialId
(
10
)
val
timeStamp
:
Long
=
0L
,
@SerialId
(
2
)
var
cConnType
:
Byte
=
0
,
@SerialId
(
11
)
val
iOSVersion
:
Long
=
0L
,
@SerialId
(
12
)
va
r
cNetType
:
Byte
=
0
,
@SerialId
(
12
)
va
l
cNetType
:
Byte
=
0
,
@SerialId
(
23
)
var
iLargeSeq
:
Long
=
0L
,
@SerialId
(
13
)
val
sBuildVer
:
String
?
=
""
,
@SerialId
(
24
)
var
iLastWatchStartTime
:
Long
=
0L
,
@SerialId
(
14
)
val
bRegType
:
Byte
=
0
,
@SerialId
(
1
7
)
var
iLocaleID
:
Int
=
2052
,
@SerialId
(
1
5
)
val
vecDevParam
:
ByteArray
?
=
null
,
@SerialId
(
1
1
)
var
iOSVersion
:
Long
=
0L
,
@SerialId
(
1
6
)
val
vecGuid
:
ByteArray
?
=
null
,
@SerialId
(
4
)
var
iStatus
:
Int
=
11
,
@SerialId
(
17
)
val
iLocaleID
:
Int
=
2052
,
@SerialId
(
1
)
var
lBid
:
Long
=
0L
,
@SerialId
(
1
8
)
val
bSlientPush
:
Byte
=
0
,
@SerialId
(
29
)
var
lCpId
:
Long
=
0L
,
@SerialId
(
19
)
val
strDevName
:
String
?
=
null
,
@SerialId
(
0
)
var
lUin
:
Long
=
0L
,
@SerialId
(
20
)
val
strDevType
:
String
?
=
null
,
@SerialId
(
13
)
var
sBuildVer
:
String
?
=
""
,
@SerialId
(
21
)
val
strOSVer
:
String
?
=
null
,
@SerialId
(
2
8
)
var
sChannelNo
:
String
?
=
""
,
@SerialId
(
2
2
)
val
bOpenPush
:
Byte
=
1
,
@SerialId
(
3
)
var
sOther
:
String
=
""
,
@SerialId
(
23
)
val
iLargeSeq
:
Long
=
0L
,
@SerialId
(
19
)
var
strDevName
:
String
?
=
null
,
@SerialId
(
24
)
val
iLastWatchStartTime
:
Long
=
0L
,
@SerialId
(
2
0
)
var
strDevType
:
String
?
=
null
,
@SerialId
(
2
6
)
val
uOldSSOIp
:
Long
=
0L
,
@SerialId
(
32
)
var
strIOSIdfa
:
String
?
=
""
,
@SerialId
(
27
)
val
uNewSSOIp
:
Long
=
0L
,
@SerialId
(
2
1
)
var
strOSVer
:
String
?
=
null
,
@SerialId
(
2
8
)
val
sChannelNo
:
String
?
=
""
,
@SerialId
(
30
)
var
strVendorName
:
String
?
=
null
,
@SerialId
(
29
)
val
lCpId
:
Long
=
0L
,
@SerialId
(
3
1
)
var
strVendorOS
Name
:
String
?
=
null
,
@SerialId
(
3
0
)
val
strVendor
Name
:
String
?
=
null
,
@SerialId
(
10
)
var
timeStamp
:
Long
=
0L
,
@SerialId
(
31
)
val
strVendorOSName
:
String
?
=
null
,
@SerialId
(
27
)
var
uNewSSOIp
:
Long
=
0L
,
@SerialId
(
32
)
val
strIOSIdfa
:
String
?
=
""
,
@SerialId
(
26
)
var
uOldSSOIp
:
Long
=
0L
,
@SerialId
(
33
)
val
bytes_0x769_reqbody
:
ByteArray
?
=
null
,
@SerialId
(
15
)
var
vecDevParam
:
ByteArray
?
=
null
,
@SerialId
(
34
)
val
bIsSetStatus
:
Byte
=
0
,
@SerialId
(
16
)
var
vecGuid
:
ByteArray
?
=
null
,
@SerialId
(
35
)
val
vecServerBuf
:
ByteArray
?
=
null
,
@SerialId
(
3
5
)
var
vecServerBuf
:
ByteArray
?
=
null
@SerialId
(
3
6
)
val
bSetMute
:
Byte
=
0
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
)
:
JceStruct
)
:
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.*
...
@@ -4,7 +4,7 @@ import kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
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.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
...
@@ -248,7 +248,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
...
@@ -248,7 +248,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
}
}
private
suspend
fun
ByteReadPacket
.
parseUniResponse
(
bot
:
QQAndroidBot
,
packetFactory
:
PacketFactory
<
*
>,
ssoSequenceId
:
Int
,
consumer
:
PacketConsumer
)
{
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
())
PacketLogger
.
verbose
(
uni
.
toString
())
consumer
(
packetFactory
.
decode
(
bot
,
uni
.
sBuffer
.
toReadPacket
()),
uni
.
sServantName
+
"."
+
uni
.
sFuncName
,
ssoSequenceId
)
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
...
@@ -4,6 +4,9 @@ import kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.discardExact
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.Jce
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.jce.RequestPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
...
@@ -19,7 +22,7 @@ class MessageSvc {
...
@@ -19,7 +22,7 @@ class MessageSvc {
)
)
val
messageNotification
=
Jce
.
UTF8
.
load
(
val
messageNotification
=
Jce
.
UTF8
.
load
(
RequestPushNotify
.
serializer
(),
RequestPushNotify
.
serializer
(),
req
.
sBuffer
[
0
]
!!
req
.
sBuffer
.
loadAs
(
RequestDataVersion2
.
serializer
()).
map
.
entries
.
first
().
value
.
entries
.
first
().
value
)
)
println
(
messageNotification
.
contentToString
())
println
(
messageNotification
.
contentToString
())
TODO
()
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
...
@@ -219,7 +219,11 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
sealed
class
LoginPacketResponse
:
Packet
{
sealed
class
LoginPacketResponse
:
Packet
{
object
Success
:
LoginPacketResponse
()
object
Success
:
LoginPacketResponse
(){
override
fun
toString
():
String
{
return
"LoginPacketResponse.Success"
}
}
data class
Error
(
data class
Error
(
val
title
:
String
,
val
title
:
String
,
val
message
:
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
package
net.mamoe.mirai.qqandroid.network.protocol.packet.login
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.writeFully
import
kotlinx.serialization.protobuf.ProtoBuf
import
kotlinx.serialization.protobuf.ProtoBuf
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
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.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.io.jceMap
import
net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataStructSvcReqRegister
import
net.mamoe.mirai.qqandroid.io.jceStruct
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.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.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
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.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
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.network.protocol.packet.writeSsoPacket
import
net.mamoe.mirai.qqandroid.utils.NetworkType
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.encodeToString
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.io.toReadPacket
import
net.mamoe.mirai.utils.localIpAddress
import
net.mamoe.mirai.utils.localIpAddress
...
@@ -55,45 +56,45 @@ class StatSvc {
...
@@ -55,45 +56,45 @@ class StatSvc {
client
,
subAppId
=
subAppId
,
commandName
=
commandName
,
client
,
subAppId
=
subAppId
,
commandName
=
commandName
,
extraData
=
client
.
wLoginSigInfo
.
tgt
.
toReadPacket
(),
sequenceId
=
sequenceId
extraData
=
client
.
wLoginSigInfo
.
tgt
.
toReadPacket
(),
sequenceId
=
sequenceId
)
{
)
{
write
UniRequestPacket
{
write
Fully
(
sServantName
=
"PushService"
RequestPacket
(
sFuncName
=
"SvcReqRegister"
sServantName
=
"PushService"
,
sBuffer
=
jceMap
(
sFuncName
=
"SvcReqRegister"
,
0
,
sBuffer
=
RequestDataVersion3
(
"SvcReqRegister"
to
jceStruct
(
mapOf
(
0
,
"SvcReqRegister"
to
RequestDataStructSvcReqRegister
(
SvcReqRegister
().
apply
{
SvcReqRegister
(
cConnType
=
0
cConnType
=
0
,
lBid
=
1
or
2
or
4
lBid
=
1
or
2
or
4
,
lUin
=
client
.
uin
lUin
=
client
.
uin
,
iStatus
=
client
.
onlineStatus
.
id
iStatus
=
client
.
onlineStatus
.
id
,
bKikPC
=
0
// 是否把 PC 踢下线
bKikPC
=
0
,
// 是否把 PC 踢下线
bKikWeak
=
0
bKikWeak
=
0
,
timeStamp
=
0
timeStamp
=
0
,
// timeStamp = currentTimeSeconds // millis or seconds??
// timeStamp = currentTimeSeconds // millis or seconds??
iLargeSeq
=
1551
// ?
iLargeSeq
=
1551
,
// ?
bOpenPush
=
1
bOpenPush
=
1
,
iLocaleID
=
2052
iLocaleID
=
2052
,
bRegType
=
bRegType
=
(
if
(
regPushReason
==
RegPushReason
.
appRegister
||
(
if
(
regPushReason
==
RegPushReason
.
appRegister
||
regPushReason
==
RegPushReason
.
fillRegProxy
||
regPushReason
==
RegPushReason
.
fillRegProxy
||
regPushReason
==
RegPushReason
.
createDefaultRegInfo
||
regPushReason
==
RegPushReason
.
createDefaultRegInfo
||
regPushReason
==
RegPushReason
.
setOnlineStatus
regPushReason
==
RegPushReason
.
setOnlineStatus
)
0
else
1
).
toByte
()
)
0
else
1
).
toByte
(),
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
,
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
()
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
(),
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
,
vecGuid
=
client
.
device
.
guid
vecGuid
=
client
.
device
.
guid
,
strDevName
=
client
.
device
.
model
.
encodeToString
()
strDevName
=
client
.
device
.
model
.
encodeToString
(),
strDevType
=
client
.
device
.
model
.
encodeToString
()
strDevType
=
client
.
device
.
model
.
encodeToString
(),
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
()
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
(),
uOldSSOIp
=
0
uOldSSOIp
=
0
,
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
}
},
strVendorName
=
"MIUI"
strVendorName
=
"MIUI"
,
strVendorOSName
=
"?ONEPLUS A5000_23_17"
strVendorOSName
=
"?ONEPLUS A5000_23_17"
,
// register 时还需要
// register 时还需要
/*
/*
var44.uNewSSOIp = field_127445;
var44.uNewSSOIp = field_127445;
...
@@ -114,13 +115,14 @@ class StatSvc {
...
@@ -114,13 +115,14 @@ class StatSvc {
)
)
)
)
)
)
)
),
bSetMute
=
0
bSetMute
=
0
}
)
)
).
toByteArray
(
RequestDataStructSvcReqRegister
.
serializer
())
)
).
toByteArray
(
RequestDataVersion3
.
serializer
())
).
toByteArray
(
RequestPacket
.
serializer
())
)
)
}
this
.
writePacket
(
this
.
build
().
debugPrint
(
"sso body"
))
}
}
}
}
...
...
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
package
net.mamoe.mirai.qqandroid.io.serialization
import
kotlinx.io.core.readBytes
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.SerialId
import
kotlinx.serialization.Serializable
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.JceStruct
import
net.mamoe.mirai.qqandroid.io.buildJcePacket
import
net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.test.Test
import
kotlin.test.Test
import
kotlin.test.assertEquals
class
Jce
En
coderTest
{
class
Jce
De
coderTest
{
@Serializable
@Serializable
class
TestSimpleJceStruct
(
class
TestSimpleJceStruct
(
...
@@ -23,51 +18,16 @@ class JceEncoderTest {
...
@@ -23,51 +18,16 @@ class JceEncoderTest {
@SerialId
(
4
)
val
long
:
Long
=
123
,
@SerialId
(
4
)
val
long
:
Long
=
123
,
@SerialId
(
5
)
val
float
:
Float
=
123f
,
@SerialId
(
5
)
val
float
:
Float
=
123f
,
@SerialId
(
6
)
val
double
:
Double
=
123.0
@SerialId
(
6
)
val
double
:
Double
=
123.0
)
:
JceStruct
()
{
)
:
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
)
}
}
@Test
@Test
fun
testEncoder
()
{
fun
testEncoder
()
{
assertEquals
(
println
(
TestComplexJceStruct
().
toByteArray
(
TestComplexJceStruct
.
serializer
()).
loadAs
(
TestComplexJceStruct
.
serializer
()).
contentToString
())
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
()
)
}
}
@Test
@Test
fun
testEncoder2
()
{
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
@Serializable
...
@@ -76,5 +36,5 @@ class JceEncoderTest {
...
@@ -76,5 +36,5 @@ class JceEncoderTest {
@SerialId
(
8
)
val
byteList
:
List
<
Byte
>
=
listOf
(
1
,
2
,
3
),
@SerialId
(
8
)
val
byteList
:
List
<
Byte
>
=
listOf
(
1
,
2
,
3
),
@SerialId
(
9
)
val
map
:
Map
<
String
,
String
>
=
mapOf
(
"哈哈"
to
"嘿嘿"
),
@SerialId
(
9
)
val
map
:
Map
<
String
,
String
>
=
mapOf
(
"哈哈"
to
"嘿嘿"
),
@SerialId
(
10
)
val
nestedJceStruct
:
TestSimpleJceStruct
=
TestSimpleJceStruct
()
@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
...
@@ -389,7 +389,7 @@ internal class TIMPCBotNetworkHandler internal constructor(coroutineContext: Cor
close
()
close
()
return
return
}
}
val
code
=
configuration
.
loginSolver
(
bot
,
captchaCache
!!
)
val
code
=
configuration
.
loginSolver
.
onSolvePicCaptcha
(
bot
,
captchaCache
!!
)
this
.
captchaCache
=
null
this
.
captchaCache
=
null
if
(
code
==
null
||
code
.
length
!=
4
)
{
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
...
@@ -28,7 +28,7 @@ import kotlin.coroutines.CoroutineContext
actual
var
defaultLoginSolver
:
LoginSolver
=
DefaultLoginSolver
()
actual
var
defaultLoginSolver
:
LoginSolver
=
DefaultLoginSolver
()
class
DefaultLoginSolver
():
LoginSolver
()
{
class
DefaultLoginSolver
:
LoginSolver
()
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
loginSolverLock
.
withLock
{
loginSolverLock
.
withLock
{
val
tempFile
:
File
=
createTempFile
(
suffix
=
".png"
).
apply
{
deleteOnExit
()
}
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
...
@@ -10,11 +10,13 @@ import android.os.IBinder
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.launch
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.timpc.TIMPC
import
net.mamoe.mirai.timpc.TIMPC
import
net.mamoe.mirai.utils.LoginFailedException
import
net.mamoe.mirai.utils.LoginFailedException
import
net.mamoe.mirai.utils.LoginSolver
import
java.lang.ref.WeakReference
import
java.lang.ref.WeakReference
class
MiraiService
:
Service
()
{
class
MiraiService
:
Service
()
{
...
@@ -42,12 +44,27 @@ class MiraiService : Service() {
...
@@ -42,12 +44,27 @@ class MiraiService : Service() {
private
fun
login
(
qq
:
Long
,
pwd
:
String
)
{
private
fun
login
(
qq
:
Long
,
pwd
:
String
)
{
GlobalScope
.
launch
{
GlobalScope
.
launch
{
mBot
=
TIMPC
.
Bot
(
qq
,
pwd
)
{
mBot
=
TIMPC
.
Bot
(
qq
,
pwd
)
{
captchaSolver
=
{
loginSolver
=
object
:
LoginSolver
()
{
val
bytes
=
it
.
readBytes
()
override
suspend
fun
onSolvePicCaptcha
(
bot
:
Bot
,
data
:
IoBuffer
):
String
?
{
val
bytes
=
data
.
readBytes
()
val
bitmap
=
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
size
)
val
bitmap
=
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
size
)
mCaptchaDeferred
=
CompletableDeferred
()
mCaptchaDeferred
=
CompletableDeferred
()
mCallback
?.
get
()
?.
onCaptcha
(
bitmap
)
mCallback
?.
get
()
?.
onCaptcha
(
bitmap
)
mCaptchaDeferred
.
await
()
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
{
}.
apply
{
try
{
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