Rename module name and add dm-codec module to serialization/deserialization dm message
This commit is contained in:
42 files changed
+886
-55
No files matched your search
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
public data class InteractWordV2(
|
||||
override val origin: String,
|
||||
@ReverseEnginedProtobuf override val reversed: InteractWordPbPayload,
|
||||
val dmScore: Int,
|
||||
) : _ReversedProtobufClass<InteractWordV2.InteractWordPbPayload> {
|
||||
@Serializable
|
||||
public data class InteractWordPbPayload(
|
||||
val uid: Long,
|
||||
val unameBytes: Map<String, Int>,
|
||||
val actionType: Int,
|
||||
val roomId: Long,
|
||||
val timestampSec: Long,
|
||||
val timestampMs: Long,
|
||||
val identityType: Int,
|
||||
val unameColor: String,
|
||||
val sourceBytes: Map<String, Int>,
|
||||
val msgId: ULong,
|
||||
val userInfo: UserInfo,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UserInfo(
|
||||
val uid: Long,
|
||||
val userDetail: UserDetail,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UserDetail(
|
||||
val faceUrl: String,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
public data class OnlineRankCount(
|
||||
val count: Int,
|
||||
val countText: String,
|
||||
val onlineCount: Int,
|
||||
val onlineCountText: String,
|
||||
)
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* this data class defined
|
||||
*/
|
||||
@Serializable
|
||||
public data class OnlineRankV3(
|
||||
override val origin: String,
|
||||
@ReverseEnginedProtobuf override val reversed: ReversedProtobuf,
|
||||
) : _ReversedProtobufClass<OnlineRankV3.ReversedProtobuf> {
|
||||
@Serializable
|
||||
public data class ReversedProtobuf(
|
||||
/**
|
||||
* rank type
|
||||
* `online_rank`
|
||||
*/
|
||||
val rankType: String,
|
||||
val userRankInfo: List<UserRankInfo>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UserRankInfo(
|
||||
val uid: Long,
|
||||
val avatarUrl: String,
|
||||
val scoreInfo: UserScore,
|
||||
val nickname: String,
|
||||
val rank: Int,
|
||||
val accountDetail: AccountDetail,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UserScore(
|
||||
val score: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class AccountDetail(
|
||||
val uid: Long,
|
||||
val profile: ProfileCard,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class ProfileCard(
|
||||
val nickname: String,
|
||||
val faceUrl: String,
|
||||
val avatarMedia: MediaInfo,
|
||||
val iconMedia: MediaInfo,
|
||||
val extraFlags: ExtraFlags,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class MediaInfo(
|
||||
val nickname: String,
|
||||
val avatarUrl: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class ExtraFlags(
|
||||
val flagValue: Long,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@Serializable
|
||||
public sealed class RawDanmuMessage {
|
||||
@Serializable
|
||||
@SerialName("STOP_LIVE_ROOM_LIST")
|
||||
public data class RawStopLiveRoomListMsg(val data: Data) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
@SerialName("room_id_list")
|
||||
val roomIdList: List<Long>,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("INTERACT_WORD_V2")
|
||||
public data class RawInteractWordV2(val data: Data) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
@SerialName("dmscore")
|
||||
val dmScore: Int,
|
||||
/**
|
||||
* base64 encoded protobuf content
|
||||
*/
|
||||
val pb: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("LIKE_INFO_V3_CLICK")
|
||||
public data class RawLikeInfoV3ClickMsg(val data: Data) : RawDanmuMessage() {
|
||||
|
||||
@Serializable
|
||||
public data class Data(
|
||||
@SerialName("contribution_info")
|
||||
val contributionInfo: ContributionInfo,
|
||||
val dmscore: Int,
|
||||
@SerialName("fans_medal")
|
||||
val fansMedal: FansMedal,
|
||||
@SerialName("group_medal")
|
||||
val groupMedal: String?,
|
||||
val identities: List<Int>,
|
||||
@SerialName("is_mystery")
|
||||
val isMystery: Boolean,
|
||||
@SerialName("like_icon")
|
||||
val likeIcon: String,
|
||||
@SerialName("like_text")
|
||||
val likeText: String,
|
||||
@SerialName("msg_type")
|
||||
val msgType: Int,
|
||||
@SerialName("show_area")
|
||||
val showArea: Int,
|
||||
val uid: Long,
|
||||
val uinfo: UInfo,
|
||||
val uname: String,
|
||||
@SerialName("uname_color")
|
||||
val unameColor: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class ContributionInfo(
|
||||
val grade: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class FansMedal(
|
||||
@SerialName("anchor_roomid")
|
||||
val anchorRoomid: Long,
|
||||
@SerialName("guard_level")
|
||||
val guardLevel: Int,
|
||||
@SerialName("icon_id")
|
||||
val iconId: Int,
|
||||
@SerialName("is_lighted")
|
||||
val isLighted: Int,
|
||||
@SerialName("medal_color")
|
||||
val medalColor: Long,
|
||||
@SerialName("medal_color_border")
|
||||
val medalColorBorder: Long,
|
||||
@SerialName("medal_color_end")
|
||||
val medalColorEnd: Long,
|
||||
@SerialName("medal_color_start")
|
||||
val medalColorStart: Long,
|
||||
@SerialName("medal_level")
|
||||
val medalLevel: Int,
|
||||
@SerialName("medal_name")
|
||||
val medalName: String,
|
||||
val score: Long,
|
||||
val special: String,
|
||||
@SerialName("target_id")
|
||||
val targetId: Long,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UInfo(
|
||||
val anon: String?,
|
||||
val base: BaseInfo?,
|
||||
val guard: String?,
|
||||
@SerialName("guard_leader")
|
||||
val guardLeader: String?,
|
||||
val medal: String?,
|
||||
val title: String?,
|
||||
@SerialName("uhead_frame")
|
||||
val uheadFrame: String?,
|
||||
val uid: Long,
|
||||
val wealth: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class BaseInfo(
|
||||
val face: String,
|
||||
@SerialName("is_mystery")
|
||||
val isMystery: Boolean,
|
||||
val name: String,
|
||||
@SerialName("name_color")
|
||||
val nameColor: Int,
|
||||
@SerialName("name_color_str")
|
||||
val nameColorStr: String,
|
||||
@SerialName("official_info")
|
||||
val officialInfo: OfficialInfo,
|
||||
@SerialName("origin_info")
|
||||
val originInfo: OriginInfo,
|
||||
@SerialName("risk_ctrl_info")
|
||||
val riskCtrlInfo: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class OfficialInfo(
|
||||
val desc: String,
|
||||
val role: Int,
|
||||
val title: String,
|
||||
val type: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class OriginInfo(
|
||||
val face: String,
|
||||
val name: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("RECALL_DANMU_MSG")
|
||||
public data class RawRecallDanmuMsg(
|
||||
val data: Data,
|
||||
) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
@SerialName("recall_type")
|
||||
val recallType: Int,
|
||||
@SerialName("target_id")
|
||||
val targetId: Long,
|
||||
val uinfo: UInfo,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class UInfo(
|
||||
val uid: Long,
|
||||
val base: String?,
|
||||
val medal: String?,
|
||||
val wealth: String?,
|
||||
val title: String?,
|
||||
val guard: String?,
|
||||
@SerialName("uhead_frame")
|
||||
val uheadFrame: String?,
|
||||
@SerialName("guard_leader")
|
||||
val guardLeader: String?,
|
||||
val anon: String?,
|
||||
@SerialName("bubble_box")
|
||||
val bubbleBox: String?,
|
||||
@SerialName("dm_config")
|
||||
val dmConfig: String?,
|
||||
@SerialName("name_color")
|
||||
val nameColor: String?,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("ONLINE_RANK_COUNT")
|
||||
public data class RawOnlineRankCount(
|
||||
val data: Data,
|
||||
) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
val count: Int,
|
||||
@SerialName("count_text")
|
||||
val countText: String,
|
||||
@SerialName("online_count")
|
||||
val onlineCount: Int,
|
||||
@SerialName("online_count_text")
|
||||
val onlineCountText: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("SEND_GIFT_V2")
|
||||
public data class RawSendGiftV2(
|
||||
val danmu: Danmu,
|
||||
val data: Data,
|
||||
) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Danmu(
|
||||
/**
|
||||
* live room area id
|
||||
*/
|
||||
val area: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class Data(
|
||||
/**
|
||||
* maybe means `高能积分`
|
||||
* depends on gift values
|
||||
*/
|
||||
@SerialName("dmscore")
|
||||
val dmScore: Int,
|
||||
/**
|
||||
* base64 encoded protobuf content
|
||||
*/
|
||||
val pb: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("LIKE_INFO_V3_UPDATE")
|
||||
public data class RawLikeInfoV3Update(val data: Data) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
/**
|
||||
* total like count
|
||||
*/
|
||||
@SerialName("click_count")
|
||||
val clickCount: Int,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("ONLINE_RANK_V3")
|
||||
public data class RawOnlineRankV3(val data: Data) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
/**
|
||||
* base64 encoded protobuf content
|
||||
*/
|
||||
val pb: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("WATCHED_CHANGE")
|
||||
public data class RawWatchedChange(
|
||||
val data: Data,
|
||||
) : RawDanmuMessage() {
|
||||
@Serializable
|
||||
public data class Data(
|
||||
/**
|
||||
* example `305251371`
|
||||
*/
|
||||
val num: Long,
|
||||
/**
|
||||
* example `30525.1万`
|
||||
*/
|
||||
@SerialName("text_small")
|
||||
val textSmall: String,
|
||||
/**
|
||||
* example `30525.1万人看过`
|
||||
*/
|
||||
@SerialName("text_large")
|
||||
val textLarge: String,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
/**
|
||||
* mark a class or property as derived through protobuf reverse engineering
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
|
||||
public annotation class ReverseEnginedProtobuf
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
public data class SendGiftV2(
|
||||
override val origin: String,
|
||||
@ReverseEnginedProtobuf override val reversed: ReversedProtobuf,
|
||||
val area: Int,
|
||||
val dmScore: Int,
|
||||
) : _ReversedProtobufClass<SendGiftV2.ReversedProtobuf> {
|
||||
@Serializable
|
||||
public data class ReversedProtobuf(
|
||||
val comboId: Long,
|
||||
val senderNameBytes: Map<String, Int>,
|
||||
val senderFace: String,
|
||||
val giftDetail: GiftDetail,
|
||||
val status: Int,
|
||||
val senderInfo: SenderInfo,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class GiftDetail(
|
||||
val giftId: Int,
|
||||
val giftNameBytes: Map<String, Int>,
|
||||
val price: Int,
|
||||
val coinType: String,
|
||||
val timestamp: Long,
|
||||
val comboCount: Int,
|
||||
val batchComboId: String,
|
||||
val batchNum: Int,
|
||||
val totalCoin: Int,
|
||||
val actionBytes: Map<String, Int>,
|
||||
val anchorInfo: AnchorInfo,
|
||||
val giftAssets: GiftAssets,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class AnchorInfo(
|
||||
val anchorUid: Long,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class GiftAssets(
|
||||
val icon: String,
|
||||
val webp: String,
|
||||
val gif: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class SenderInfo(
|
||||
val comboId: Long,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
public data class WatchedChange(
|
||||
/**
|
||||
* number of watched
|
||||
*/
|
||||
val num: Long,
|
||||
/**
|
||||
* short formatted number
|
||||
*/
|
||||
@SerialName("text_small")
|
||||
val textSmall: String,
|
||||
/**
|
||||
* long formatted number
|
||||
*/
|
||||
@SerialName("text_large")
|
||||
val textLarge: String,
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
package cn.rtast.bldm.dm.codec
|
||||
|
||||
@Suppress("ClassName")
|
||||
public interface _ReversedProtobufClass<T> {
|
||||
public val origin: String
|
||||
public val reversed: T
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.dm.codec.util
|
||||
|
||||
import kotlin.io.encoding.Base64
|
||||
|
||||
internal fun String.decodeBase64ToByteArray(): ByteArray = Base64.decode(this.encodeToByteArray())
|
||||
internal fun String.decodeBase64ToString(): String = Base64.decode(this.encodeToByteArray()).decodeToString()
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
@file:OptIn(ExperimentalSerializationApi::class)
|
||||
|
||||
package cn.rtast.bldm.dm.codec.util
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.decodeFromByteArray
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
|
||||
internal inline fun <reified T> ByteArray.fromProtobuf(): T =
|
||||
ProtoBuf.decodeFromByteArray(this)
|
||||
Reference in New Issue
Block a user