mirror of
https://github.com/mamoe/mirai.git
synced 2024-12-31 07:07:01 +08:00
Simplify DeviceInfo (#655)
* Simplify DeviceInfo * Place random string helper properly * Make DeviceInfo::random java-friendly
This commit is contained in:
parent
54df8d63aa
commit
bb3d039bf8
@ -53,7 +53,7 @@ public expect open class BotConfiguration() : BotConfigurationBase {
|
||||
public fun randomDeviceInfo()
|
||||
|
||||
/**
|
||||
* 使用特定由 [DeviceInfoData] 序列化产生的 JSON 的设备信息
|
||||
* 使用特定由 [DeviceInfo] 序列化产生的 JSON 的设备信息
|
||||
*
|
||||
* @see deviceInfo
|
||||
*/
|
||||
@ -251,5 +251,5 @@ internal val deviceInfoStub: (Context) -> DeviceInfo = {
|
||||
MiraiLogger.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.")
|
||||
@Suppress("DEPRECATION")
|
||||
MiraiLogger.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information")
|
||||
SystemDeviceInfo()
|
||||
DeviceInfo.random()
|
||||
}
|
@ -9,124 +9,106 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.io.core.toByteArray
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import net.mamoe.mirai.utils.internal.getRandomByteArray
|
||||
import net.mamoe.mirai.utils.internal.getRandomIntString
|
||||
import net.mamoe.mirai.utils.internal.getRandomString
|
||||
import net.mamoe.mirai.utils.internal.md5
|
||||
import kotlin.jvm.JvmStatic
|
||||
|
||||
/**
|
||||
* 设备信息. 可通过继承 [SystemDeviceInfo] 来在默认的基础上修改
|
||||
*/
|
||||
public abstract class DeviceInfo {
|
||||
@Transient
|
||||
public abstract val context: Context
|
||||
|
||||
public abstract val display: ByteArray
|
||||
public abstract val product: ByteArray
|
||||
public abstract val device: ByteArray
|
||||
public abstract val board: ByteArray
|
||||
|
||||
public abstract val brand: ByteArray
|
||||
public abstract val model: ByteArray
|
||||
public abstract val bootloader: ByteArray
|
||||
public abstract val fingerprint: ByteArray
|
||||
public abstract val bootId: ByteArray
|
||||
|
||||
public abstract val procVersion: ByteArray
|
||||
public abstract val baseBand: ByteArray
|
||||
|
||||
public abstract val version: Version
|
||||
|
||||
public abstract val simInfo: ByteArray
|
||||
|
||||
public abstract val osType: ByteArray
|
||||
|
||||
public abstract val macAddress: ByteArray
|
||||
|
||||
public abstract val wifiBSSID: ByteArray?
|
||||
public abstract val wifiSSID: ByteArray?
|
||||
|
||||
public abstract val imsiMd5: ByteArray
|
||||
public abstract val imei: String
|
||||
|
||||
@Serializable
|
||||
public class DeviceInfo(
|
||||
public val display: ByteArray,
|
||||
public val product: ByteArray,
|
||||
public val device: ByteArray,
|
||||
public val board: ByteArray,
|
||||
public val brand: ByteArray,
|
||||
public val model: ByteArray,
|
||||
public val bootloader: ByteArray,
|
||||
public val fingerprint: ByteArray,
|
||||
public val bootId: ByteArray,
|
||||
public val procVersion: ByteArray,
|
||||
public val baseBand: ByteArray,
|
||||
public val version: Version,
|
||||
public val simInfo: ByteArray,
|
||||
public val osType: ByteArray,
|
||||
public val macAddress: ByteArray,
|
||||
public val wifiBSSID: ByteArray?,
|
||||
public val wifiSSID: ByteArray?,
|
||||
public val imsiMd5: ByteArray,
|
||||
public val imei: String,
|
||||
public val apn: ByteArray
|
||||
) {
|
||||
public val androidId: ByteArray get() = display
|
||||
public val ipAddress: ByteArray get() = byteArrayOf(192.toByte(), 168.toByte(), 1, 123)
|
||||
|
||||
public abstract val androidId: ByteArray
|
||||
@Serializable
|
||||
public class Version(
|
||||
public val incremental: ByteArray = "5891938".toByteArray(),
|
||||
public val release: ByteArray = "10".toByteArray(),
|
||||
public val codename: ByteArray = "REL".toByteArray(),
|
||||
public val sdk: Int = 29
|
||||
)
|
||||
|
||||
public abstract val apn: ByteArray
|
||||
|
||||
public fun generateDeviceInfoData(): ByteArray {
|
||||
@Serializable
|
||||
class DevInfo(
|
||||
@ProtoNumber(1) val bootloader: ByteArray,
|
||||
@ProtoNumber(2) val procVersion: ByteArray,
|
||||
@ProtoNumber(3) val codename: ByteArray,
|
||||
@ProtoNumber(4) val incremental: ByteArray,
|
||||
@ProtoNumber(5) val fingerprint: ByteArray,
|
||||
@ProtoNumber(6) val bootId: ByteArray,
|
||||
@ProtoNumber(7) val androidId: ByteArray,
|
||||
@ProtoNumber(8) val baseBand: ByteArray,
|
||||
@ProtoNumber(9) val innerVersion: ByteArray
|
||||
)
|
||||
|
||||
return ProtoBuf.encodeToByteArray(
|
||||
DevInfo.serializer(), DevInfo(
|
||||
bootloader,
|
||||
procVersion,
|
||||
version.codename,
|
||||
version.incremental,
|
||||
fingerprint,
|
||||
bootId,
|
||||
androidId,
|
||||
baseBand,
|
||||
version.incremental
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
public fun random(): DeviceInfo {
|
||||
return DeviceInfo(
|
||||
display = "MIRAI.${getRandomString(6, '0'..'9')}.001".toByteArray(),
|
||||
product = "mirai".toByteArray(),
|
||||
device = "mirai".toByteArray(),
|
||||
board = "mirai".toByteArray(),
|
||||
brand = "mamoe".toByteArray(),
|
||||
model = "mirai".toByteArray(),
|
||||
bootloader = "unknown".toByteArray(),
|
||||
fingerprint = "mamoe/mirai/mirai:10/MIRAI.200122.001/${getRandomIntString(7)}:user/release-keys".toByteArray(),
|
||||
bootId = ExternalImage.generateUUID(getRandomByteArray(16).md5()).toByteArray(),
|
||||
procVersion = "Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)".toByteArray(),
|
||||
baseBand = byteArrayOf(),
|
||||
version = Version(),
|
||||
simInfo = "T-Mobile".toByteArray(),
|
||||
osType = "android".toByteArray(),
|
||||
macAddress = "02:00:00:00:00:00".toByteArray(),
|
||||
wifiBSSID = "02:00:00:00:00:00".toByteArray(),
|
||||
wifiSSID = "<unknown ssid>".toByteArray(),
|
||||
imsiMd5 = getRandomByteArray(16).md5(),
|
||||
imei = getRandomIntString(15),
|
||||
apn = "wifi".toByteArray()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
public interface Version {
|
||||
public val incremental: ByteArray
|
||||
public val release: ByteArray
|
||||
public val codename: ByteArray
|
||||
public val sdk: Int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
public class DeviceInfoData(
|
||||
public override val display: ByteArray,
|
||||
public override val product: ByteArray,
|
||||
public override val device: ByteArray,
|
||||
public override val board: ByteArray,
|
||||
public override val brand: ByteArray,
|
||||
public override val model: ByteArray,
|
||||
public override val bootloader: ByteArray,
|
||||
public override val fingerprint: ByteArray,
|
||||
public override val bootId: ByteArray,
|
||||
public override val procVersion: ByteArray,
|
||||
public override val baseBand: ByteArray,
|
||||
public override val version: VersionData,
|
||||
public override val simInfo: ByteArray,
|
||||
public override val osType: ByteArray,
|
||||
public override val macAddress: ByteArray,
|
||||
public override val wifiBSSID: ByteArray?,
|
||||
public override val wifiSSID: ByteArray?,
|
||||
public override val imsiMd5: ByteArray,
|
||||
public override val imei: String,
|
||||
public override val apn: ByteArray
|
||||
) : DeviceInfo() {
|
||||
@Transient
|
||||
public override lateinit var context: Context
|
||||
|
||||
public override val androidId: ByteArray get() = display
|
||||
|
||||
public fun DeviceInfo.generateDeviceInfoData(): ByteArray {
|
||||
@Serializable
|
||||
public class VersionData(
|
||||
public override val incremental: ByteArray = SystemDeviceInfo.Version.incremental,
|
||||
public override val release: ByteArray = SystemDeviceInfo.Version.release,
|
||||
public override val codename: ByteArray = SystemDeviceInfo.Version.codename,
|
||||
public override val sdk: Int = SystemDeviceInfo.Version.sdk
|
||||
) : Version
|
||||
class DevInfo(
|
||||
@ProtoNumber(1) val bootloader: ByteArray,
|
||||
@ProtoNumber(2) val procVersion: ByteArray,
|
||||
@ProtoNumber(3) val codename: ByteArray,
|
||||
@ProtoNumber(4) val incremental: ByteArray,
|
||||
@ProtoNumber(5) val fingerprint: ByteArray,
|
||||
@ProtoNumber(6) val bootId: ByteArray,
|
||||
@ProtoNumber(7) val androidId: ByteArray,
|
||||
@ProtoNumber(8) val baseBand: ByteArray,
|
||||
@ProtoNumber(9) val innerVersion: ByteArray
|
||||
)
|
||||
|
||||
return ProtoBuf.encodeToByteArray(
|
||||
DevInfo.serializer(), DevInfo(
|
||||
bootloader,
|
||||
procVersion,
|
||||
version.codename,
|
||||
version.incremental,
|
||||
fingerprint,
|
||||
bootId,
|
||||
androidId,
|
||||
baseBand,
|
||||
version.incremental
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
/**
|
||||
* 通过本机信息来获取设备信息.
|
||||
*
|
||||
* Android: 获取手机信息, 与 QQ 官方相同.
|
||||
* JVM: 部分为常量, 部分为随机
|
||||
*/
|
||||
public expect open class SystemDeviceInfo : DeviceInfo {
|
||||
public constructor()
|
||||
public constructor(context: Context)
|
||||
|
||||
public object Version : DeviceInfo.Version
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils.internal
|
||||
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextInt
|
||||
|
||||
|
||||
/**
|
||||
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() }
|
||||
|
||||
/**
|
||||
* 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int): String =
|
||||
getRandomString(length, *defaultRanges)
|
||||
|
||||
private val defaultRanges: Array<CharRange> = arrayOf('a'..'z', 'A'..'Z', '0'..'9')
|
||||
private val intCharRanges: Array<CharRange> = arrayOf('0'..'9')
|
||||
/**
|
||||
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int, charRange: CharRange): String =
|
||||
CharArray(length) { charRange.random() }.concatToString()
|
||||
|
||||
/**
|
||||
* 根据所给 [charRanges] 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int, vararg charRanges: CharRange): String =
|
||||
CharArray(length) { charRanges[Random.Default.nextInt(0..charRanges.lastIndex)].random() }.concatToString()
|
||||
|
||||
|
||||
@JvmSynthetic
|
||||
internal fun getRandomIntString(length: Int): String =
|
||||
getRandomString(length, *intCharRanges)
|
@ -57,14 +57,14 @@ public actual open class BotConfiguration : BotConfigurationBase() { // open for
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用特定由 [DeviceInfoData] 序列化产生的 JSON 的设备信息
|
||||
* 使用特定由 [DeviceInfo] 序列化产生的 JSON 的设备信息
|
||||
*
|
||||
* @see deviceInfo
|
||||
*/
|
||||
@SinceMirai("1.2.0")
|
||||
public actual fun loadDeviceInfoJson(json: String) {
|
||||
deviceInfo = { context ->
|
||||
this.json.decodeFromString(DeviceInfoData.serializer(), json).also { it.context = context }
|
||||
this.json.decodeFromString(DeviceInfo.serializer(), json)
|
||||
}
|
||||
}
|
||||
|
||||
|
25
mirai-core-api/src/jvmMain/kotlin/utils/DeviceInfoUtils.kt
Normal file
25
mirai-core-api/src/jvmMain/kotlin/utils/DeviceInfoUtils.kt
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
|
||||
*/
|
||||
public fun File.loadAsDeviceInfo(json: Json): DeviceInfo {
|
||||
if (!this.exists() || this.length() == 0L) {
|
||||
return DeviceInfo.random().also {
|
||||
this.writeText(json.encodeToString(DeviceInfo.serializer(), it))
|
||||
}
|
||||
}
|
||||
return json.decodeFromString(DeviceInfo.serializer(), this.readText())
|
||||
}
|
@ -154,7 +154,7 @@ public actual abstract class LoginSolver {
|
||||
|
||||
internal fun BotConfiguration.getFileBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? {
|
||||
return {
|
||||
File(filename).loadAsDeviceInfo(json, it)
|
||||
File(filename).loadAsDeviceInfo(json)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.io.core.toByteArray
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.utils.internal.md5
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextInt
|
||||
|
||||
/**
|
||||
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
|
||||
*/
|
||||
public fun File.loadAsDeviceInfo(json: Json, context: Context = ContextImpl()): DeviceInfo {
|
||||
if (!this.exists() || this.length() == 0L) {
|
||||
return SystemDeviceInfo(context).also {
|
||||
this.writeText(json.encodeToString(SystemDeviceInfo.serializer(), it))
|
||||
}
|
||||
}
|
||||
return json.decodeFromString(DeviceInfoData.serializer(), this.readText()).also {
|
||||
it.context = context
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
public actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
|
||||
public actual constructor(context: Context) : this() {
|
||||
this.context = context
|
||||
}
|
||||
|
||||
@Transient
|
||||
public final override lateinit var context: Context
|
||||
|
||||
public override val display: ByteArray = "MIRAI.${getRandomString(6, '0'..'9')}.001".toByteArray()
|
||||
public override val product: ByteArray = "mirai".toByteArray()
|
||||
public override val device: ByteArray = "mirai".toByteArray()
|
||||
public override val board: ByteArray = "mirai".toByteArray()
|
||||
public override val brand: ByteArray = "mamoe".toByteArray()
|
||||
public override val model: ByteArray = "mirai".toByteArray()
|
||||
public override val bootloader: ByteArray = "unknown".toByteArray()
|
||||
public override val fingerprint: ByteArray =
|
||||
"mamoe/mirai/mirai:10/MIRAI.200122.001/${getRandomString(7, '0'..'9')}:user/release-keys".toByteArray()
|
||||
public override val bootId: ByteArray = ExternalImage.generateUUID(getRandomByteArray(16).md5()).toByteArray()
|
||||
public override val procVersion: ByteArray =
|
||||
"Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)".toByteArray()
|
||||
public override val baseBand: ByteArray = byteArrayOf()
|
||||
public override val version: Version = Version
|
||||
public override val simInfo: ByteArray = "T-Mobile".toByteArray()
|
||||
public override val osType: ByteArray = "android".toByteArray()
|
||||
public override val macAddress: ByteArray = "02:00:00:00:00:00".toByteArray()
|
||||
public override val wifiBSSID: ByteArray? = "02:00:00:00:00:00".toByteArray()
|
||||
public override val wifiSSID: ByteArray? = "<unknown ssid>".toByteArray()
|
||||
public override val imsiMd5: ByteArray = getRandomByteArray(16).md5()
|
||||
public override val imei: String = getRandomString(15, '0'..'9')
|
||||
public override val androidId: ByteArray get() = display
|
||||
public override val apn: ByteArray = "wifi".toByteArray()
|
||||
|
||||
@Serializable
|
||||
public actual object Version : DeviceInfo.Version {
|
||||
public override val incremental: ByteArray = "5891938".toByteArray()
|
||||
public override val release: ByteArray = "10".toByteArray()
|
||||
public override val codename: ByteArray = "REL".toByteArray()
|
||||
public override val sdk: Int = 29
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() }
|
||||
|
||||
/**
|
||||
* 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int): String =
|
||||
getRandomString(length, *defaultRanges)
|
||||
|
||||
private val defaultRanges: Array<CharRange> = arrayOf('a'..'z', 'A'..'Z', '0'..'9')
|
||||
|
||||
/**
|
||||
* 根据所给 [charRange] 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int, charRange: CharRange): String =
|
||||
String(CharArray(length) { charRange.random() })
|
||||
|
||||
/**
|
||||
* 根据所给 [charRanges] 随机生成长度为 [length] 的 [String].
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun getRandomString(length: Int, vararg charRanges: CharRange): String =
|
||||
String(CharArray(length) { charRanges[Random.Default.nextInt(0..charRanges.lastIndex)].random() })
|
@ -264,7 +264,7 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
context,
|
||||
account,
|
||||
bot = @Suppress("LeakingThis") this as QQAndroidBot,
|
||||
device = configuration.deviceInfo?.invoke(context) ?: SystemDeviceInfo(context)
|
||||
device = configuration.deviceInfo?.invoke(context) ?: DeviceInfo.random()
|
||||
)
|
||||
internal var firstLoginSucceed: Boolean = false
|
||||
|
||||
|
@ -75,7 +75,7 @@ internal open class QQAndroidClient(
|
||||
context: Context,
|
||||
val account: BotAccount,
|
||||
val ecdh: ECDH = ECDH(),
|
||||
val device: DeviceInfo = SystemDeviceInfo(context),
|
||||
val device: DeviceInfo,
|
||||
bot: QQAndroidBot
|
||||
) {
|
||||
@Suppress("INVISIBLE_MEMBER")
|
||||
|
@ -21,6 +21,7 @@ import net.mamoe.mirai.internal.utils.guidFlag
|
||||
import net.mamoe.mirai.internal.utils.io.*
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import net.mamoe.mirai.utils.error
|
||||
import net.mamoe.mirai.utils.generateDeviceInfoData
|
||||
|
||||
internal class WtLogin {
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user