From 539a300946ab1af178bca2f8d9c67ce274b60558 Mon Sep 17 00:00:00 2001 From: RTAkland Date: Sun, 30 Aug 2026 22:09:27 +0800 Subject: [PATCH] Rename module name and add dm-codec module to serialization/deserialization dm message --- .gitignore | 1 + LICENSE | 201 +++++++++++++ README.md | 27 ++ bl-client/build.gradle.kts | 2 +- .../kotlin/cn/rtast/bldm/client/bldm.kt | 22 +- {bl-core => bl-codec}/build.gradle.kts | 0 .../codec}/annotations/InternalBldmApi.kt | 2 +- .../kotlin/cn/rtast/bldm/codec}/constant.kt | 2 +- .../cn/rtast/bldm/codec}/data/DMServerConf.kt | 2 +- .../cn/rtast/bldm/codec}/data/RealRoomId.kt | 2 +- .../cn/rtast/bldm/codec}/data/UserNavData.kt | 4 +- .../bldm/codec}/data/protocol/AuthPayload.kt | 2 +- .../codec}/data/protocol/PacketMetadata.kt | 2 +- .../codec/data/protocol/RawDanmuMessage.kt | 6 +- .../cn/rtast/bldm/codec}/protocol/Packet.kt | 2 +- .../rtast/bldm/codec}/protocol/PacketType.kt | 2 +- .../bldm/codec}/protocol/ProtocolVersion.kt | 2 +- .../codec/protocol/codec}/PacketDecoder.kt | 18 +- .../codec/protocol/codec}/PacketEncoder.kt | 12 +- .../codec}/protocol/event/PacketEvents.kt | 8 +- .../bldm/codec}/util/AutoIncrementInt.kt | 2 +- .../rtast/bldm/codec}/util/_cookie_parser.kt | 2 +- .../kotlin/cn/rtast/bldm/codec}/util/_md5.kt | 2 +- .../kotlin/cn/rtast/bldm/codec}/util/json.kt | 10 +- .../kotlin/cn/rtast/bldm/codec}/util/zlib.kt | 2 +- .../src/commonTest/kotlin/test/TestMd5.kt | 0 .../src/commonTest/kotlin/test/TestWbiSign.kt | 2 +- .../cn/rtast/bldm/codec}/util/zlib.jvm.kt | 2 +- .../cn/rtast/bldm/codec}/util/zlib.native.kt | 2 +- bl-dm-codec/README.md | 3 + bl-dm-codec/build.gradle.kts | 28 ++ .../cn/rtast/bldm/dm/codec/InteractWordV2.kt | 43 +++ .../cn/rtast/bldm/dm/codec/OnlineRankCount.kt | 18 ++ .../cn/rtast/bldm/dm/codec/OnlineRankV3.kt | 70 +++++ .../cn/rtast/bldm/dm/codec/RawDanmuMessage.kt | 282 ++++++++++++++++++ .../bldm/dm/codec/ReverseEnginedProtobuf.kt | 16 + .../cn/rtast/bldm/dm/codec/SendGiftV2.kt | 61 ++++ .../cn/rtast/bldm/dm/codec/WatchedChange.kt | 29 ++ .../bldm/dm/codec/_ReversedProtobufClass.kt | 13 + .../cn/rtast/bldm/dm/codec/util/_base64.kt | 13 + .../cn/rtast/bldm/dm/codec/util/_protobuf.kt | 17 ++ settings.gradle.kts | 5 +- 42 files changed, 886 insertions(+), 55 deletions(-) create mode 100644 LICENSE create mode 100644 README.md rename {bl-core => bl-codec}/build.gradle.kts (100%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/annotations/InternalBldmApi.kt (87%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/constant.kt (93%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/data/DMServerConf.kt (95%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/data/RealRoomId.kt (91%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/data/UserNavData.kt (97%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/data/protocol/AuthPayload.kt (93%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/data/protocol/PacketMetadata.kt (85%) rename bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/DanmuMessage.kt => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/RawDanmuMessage.kt (58%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/protocol/Packet.kt (98%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/protocol/PacketType.kt (91%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/protocol/ProtocolVersion.kt (89%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec}/PacketDecoder.kt (77%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec}/PacketEncoder.kt (69%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/protocol/event/PacketEvents.kt (65%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/util/AutoIncrementInt.kt (90%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/util/_cookie_parser.kt (95%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/util/_md5.kt (88%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/util/json.kt (68%) rename {bl-core/src/commonMain/kotlin/cn/rtast/bldm/core => bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec}/util/zlib.kt (80%) rename {bl-core => bl-codec}/src/commonTest/kotlin/test/TestMd5.kt (100%) rename {bl-core => bl-codec}/src/commonTest/kotlin/test/TestWbiSign.kt (91%) rename {bl-core/src/jvmMain/kotlin/cn/rtast/bldm/core => bl-codec/src/jvmMain/kotlin/cn/rtast/bldm/codec}/util/zlib.jvm.kt (94%) rename {bl-core/src/nativeMain/kotlin/cn/rtast/bldm/core => bl-codec/src/nativeMain/kotlin/cn/rtast/bldm/codec}/util/zlib.native.kt (98%) create mode 100644 bl-dm-codec/README.md create mode 100644 bl-dm-codec/build.gradle.kts create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/InteractWordV2.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankCount.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankV3.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/RawDanmuMessage.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/ReverseEnginedProtobuf.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/SendGiftV2.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/WatchedChange.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/_ReversedProtobufClass.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_base64.kt create mode 100644 bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_protobuf.kt diff --git a/.gitignore b/.gitignore index 77bc300..9a6cfe6 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ bin/ .DS_Store /.idea/ /bl-client/src/commonTest/resources/cookie.txt +/bl-client/src/commonTest/resources/res.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..143b6be --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 RTAkland + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..787fb42 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# bldm + +Kotlin Multiplatform library. + +BiliBili live danmu parser API and client. + +Supported platforms: + +- linuxX64 +- linuxArm64 +- macosArm64 +- mingwX64 +- jvm - jvm 11 or later + +# Use case + +## Client + +[TestClient.kt](bl-client/src/commonTest/kotlin/test/TestClient.kt) + +## Raw parser + +[bldm.kt](bl-client/src/commonMain/kotlin/cn/rtast/bldm/client/bldm.kt) + +# Open Source + +Licensed under [Apache-2.0](LICENSE) \ No newline at end of file diff --git a/bl-client/build.gradle.kts b/bl-client/build.gradle.kts index 935f321..396a53c 100644 --- a/bl-client/build.gradle.kts +++ b/bl-client/build.gradle.kts @@ -17,7 +17,7 @@ kotlin { sourceSets { val ktorVersion = "3.5.2" commonMain.dependencies { - api(project(":bl-core")) + api(project(":bl-codec")) implementation("io.ktor:ktor-client-core:$ktorVersion") implementation("io.ktor:ktor-client-websockets:$ktorVersion") } diff --git a/bl-client/src/commonMain/kotlin/cn/rtast/bldm/client/bldm.kt b/bl-client/src/commonMain/kotlin/cn/rtast/bldm/client/bldm.kt index be8772c..68398b1 100644 --- a/bl-client/src/commonMain/kotlin/cn/rtast/bldm/client/bldm.kt +++ b/bl-client/src/commonMain/kotlin/cn/rtast/bldm/client/bldm.kt @@ -9,17 +9,17 @@ package cn.rtast.bldm.client -import cn.rtast.bldm.core.BLDMConstants -import cn.rtast.bldm.core.annotations.InternalBldmApi -import cn.rtast.bldm.core.data.DMServerConf -import cn.rtast.bldm.core.data.RealRoomId -import cn.rtast.bldm.core.data.UserNavData -import cn.rtast.bldm.core.protocol.Packet -import cn.rtast.bldm.core.protocol.PacketDecoder -import cn.rtast.bldm.core.protocol.PacketEncoder -import cn.rtast.bldm.core.protocol.event.PacketEvents -import cn.rtast.bldm.core.util._fromJson -import cn.rtast.bldm.core.util.parseBuvidAndUid +import cn.rtast.bldm.codec.BLDMConstants +import cn.rtast.bldm.codec.annotations.InternalBldmApi +import cn.rtast.bldm.codec.data.DMServerConf +import cn.rtast.bldm.codec.data.RealRoomId +import cn.rtast.bldm.codec.data.UserNavData +import cn.rtast.bldm.codec.protocol.Packet +import cn.rtast.bldm.codec.protocol.codec.PacketDecoder +import cn.rtast.bldm.codec.protocol.codec.PacketEncoder +import cn.rtast.bldm.codec.protocol.event.PacketEvents +import cn.rtast.bldm.codec.util._fromJson +import cn.rtast.bldm.codec.util.parseBuvidAndUid import io.ktor.client.plugins.websocket.* import io.ktor.client.request.* import io.ktor.client.statement.* diff --git a/bl-core/build.gradle.kts b/bl-codec/build.gradle.kts similarity index 100% rename from bl-core/build.gradle.kts rename to bl-codec/build.gradle.kts diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/annotations/InternalBldmApi.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/annotations/InternalBldmApi.kt similarity index 87% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/annotations/InternalBldmApi.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/annotations/InternalBldmApi.kt index f044f1f..b2d3411 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/annotations/InternalBldmApi.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/annotations/InternalBldmApi.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.annotations +package cn.rtast.bldm.codec.annotations @RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Retention(AnnotationRetention.BINARY) diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/constant.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/constant.kt similarity index 93% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/constant.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/constant.kt index 41cc8d8..41069c8 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/constant.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/constant.kt @@ -4,7 +4,7 @@ * Date: 2026/8/29 */ -package cn.rtast.bldm.core +package cn.rtast.bldm.codec public object BLDMConstants { public const val REAL_ROOM_ID_URL: String = "https://api.live.bilibili.com/room/v1/Room/room_init?id=" diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/DMServerConf.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/DMServerConf.kt similarity index 95% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/DMServerConf.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/DMServerConf.kt index bbd9d52..92ab17a 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/DMServerConf.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/DMServerConf.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.data +package cn.rtast.bldm.codec.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/RealRoomId.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/RealRoomId.kt similarity index 91% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/RealRoomId.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/RealRoomId.kt index 3faca7b..a1bf1a4 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/RealRoomId.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/RealRoomId.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.data +package cn.rtast.bldm.codec.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/UserNavData.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/UserNavData.kt similarity index 97% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/UserNavData.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/UserNavData.kt index 32162ca..77ea550 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/UserNavData.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/UserNavData.kt @@ -7,9 +7,9 @@ @file:OptIn(ExperimentalUnsignedTypes::class) -package cn.rtast.bldm.core.data +package cn.rtast.bldm.codec.data -import cn.rtast.bldm.core.util.digest +import cn.rtast.bldm.codec.util.digest import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlin.time.Clock diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/AuthPayload.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/AuthPayload.kt similarity index 93% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/AuthPayload.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/AuthPayload.kt index 9292e5f..94320ff 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/AuthPayload.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/AuthPayload.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.data.protocol +package cn.rtast.bldm.codec.data.protocol import kotlinx.serialization.Serializable diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/PacketMetadata.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/PacketMetadata.kt similarity index 85% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/PacketMetadata.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/PacketMetadata.kt index 1cb9fa9..49382da 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/PacketMetadata.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/PacketMetadata.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.data.protocol +package cn.rtast.bldm.codec.data.protocol import kotlinx.serialization.Serializable diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/DanmuMessage.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/RawDanmuMessage.kt similarity index 58% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/DanmuMessage.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/RawDanmuMessage.kt index 625e278..3c72a0a 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/data/protocol/DanmuMessage.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/data/protocol/RawDanmuMessage.kt @@ -5,11 +5,9 @@ */ -package cn.rtast.bldm.core.data.protocol +package cn.rtast.bldm.codec.data.protocol import kotlinx.serialization.Serializable @Serializable -public data class DanmuMessage( - val content: String -) \ No newline at end of file +public data class RawDanmuMessage(val content: String) \ No newline at end of file diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/Packet.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/Packet.kt similarity index 98% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/Packet.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/Packet.kt index af9e924..db5ea16 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/Packet.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/Packet.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.protocol +package cn.rtast.bldm.codec.protocol import kotlinx.io.Buffer import kotlinx.io.readByteArray diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketType.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/PacketType.kt similarity index 91% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketType.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/PacketType.kt index e2baa3a..4b3a068 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketType.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/PacketType.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.protocol +package cn.rtast.bldm.codec.protocol public enum class PacketType(public val pkCode: Int) { AUTH(7), diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/ProtocolVersion.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/ProtocolVersion.kt similarity index 89% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/ProtocolVersion.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/ProtocolVersion.kt index 6927aff..9c3a01e 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/ProtocolVersion.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/ProtocolVersion.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.protocol +package cn.rtast.bldm.codec.protocol internal enum class ProtocolVersion(val proto: Short) { Raw(0), Zlib(2); diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketDecoder.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketDecoder.kt similarity index 77% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketDecoder.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketDecoder.kt index bcf59d1..bc9e802 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketDecoder.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketDecoder.kt @@ -4,13 +4,15 @@ * Date: 2026/8/30 */ -package cn.rtast.bldm.core.protocol +package cn.rtast.bldm.codec.protocol.codec -import cn.rtast.bldm.core.data.protocol.DanmuMessage -import cn.rtast.bldm.core.protocol.ProtocolVersion.Raw -import cn.rtast.bldm.core.protocol.ProtocolVersion.Zlib -import cn.rtast.bldm.core.protocol.event.PacketEvents -import cn.rtast.bldm.core.util.zlibDecompress +import cn.rtast.bldm.codec.data.protocol.RawDanmuMessage +import cn.rtast.bldm.codec.protocol.PacketType +import cn.rtast.bldm.codec.protocol.ProtocolVersion +import cn.rtast.bldm.codec.protocol.ProtocolVersion.Raw +import cn.rtast.bldm.codec.protocol.ProtocolVersion.Zlib +import cn.rtast.bldm.codec.protocol.event.PacketEvents +import cn.rtast.bldm.codec.util.zlibDecompress import kotlinx.io.Buffer import kotlinx.io.readByteArray @@ -60,7 +62,7 @@ public class PacketDecoder(eventsBuilder: PacketEvents.() -> Unit) { } } - private fun decodeDanmuMessage(bytes: ByteArray): DanmuMessage { - return DanmuMessage(bytes.decodeToString()) + private fun decodeDanmuMessage(bytes: ByteArray): RawDanmuMessage { + return RawDanmuMessage(bytes.decodeToString()) } } \ No newline at end of file diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketEncoder.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketEncoder.kt similarity index 69% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketEncoder.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketEncoder.kt index 8e926df..074000a 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/PacketEncoder.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/codec/PacketEncoder.kt @@ -7,12 +7,14 @@ @file:OptIn(InternalBldmApi::class) -package cn.rtast.bldm.core.protocol +package cn.rtast.bldm.codec.protocol.codec -import cn.rtast.bldm.core.annotations.InternalBldmApi -import cn.rtast.bldm.core.data.protocol.AuthPayload -import cn.rtast.bldm.core.util.AutoIncrementInt -import cn.rtast.bldm.core.util._encodeJson +import cn.rtast.bldm.codec.annotations.InternalBldmApi +import cn.rtast.bldm.codec.data.protocol.AuthPayload +import cn.rtast.bldm.codec.protocol.Packet +import cn.rtast.bldm.codec.protocol.PacketType +import cn.rtast.bldm.codec.util.AutoIncrementInt +import cn.rtast.bldm.codec.util._encodeJson public class PacketEncoder { public companion object { diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/event/PacketEvents.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/event/PacketEvents.kt similarity index 65% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/event/PacketEvents.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/event/PacketEvents.kt index c849008..99098c0 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/protocol/event/PacketEvents.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/protocol/event/PacketEvents.kt @@ -5,16 +5,16 @@ */ -package cn.rtast.bldm.core.protocol.event +package cn.rtast.bldm.codec.protocol.event -import cn.rtast.bldm.core.data.protocol.DanmuMessage +import cn.rtast.bldm.codec.data.protocol.RawDanmuMessage public class PacketEvents { - internal var messageHandler: ((DanmuMessage) -> Unit)? = null + internal var messageHandler: ((RawDanmuMessage) -> Unit)? = null internal var heartbeatHandler: (() -> Unit)? = null internal var authReplyHandler: (() -> Unit)? = null - public fun onMessage(block: (DanmuMessage) -> Unit) { + public fun onMessage(block: (RawDanmuMessage) -> Unit) { messageHandler = block } diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/AutoIncrementInt.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/AutoIncrementInt.kt similarity index 90% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/AutoIncrementInt.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/AutoIncrementInt.kt index 28e2328..1cd2be3 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/AutoIncrementInt.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/AutoIncrementInt.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util import kotlin.reflect.KProperty diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_cookie_parser.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_cookie_parser.kt similarity index 95% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_cookie_parser.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_cookie_parser.kt index 90d968e..fe02e10 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_cookie_parser.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_cookie_parser.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util /** * get buvid and uid from a cookie diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_md5.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_md5.kt similarity index 88% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_md5.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_md5.kt index e7a4441..63eac9a 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/_md5.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/_md5.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util import org.kotlincrypto.hash.md.MD5 diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/json.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/json.kt similarity index 68% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/json.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/json.kt index 7e8184f..009fe99 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/json.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/json.kt @@ -6,15 +6,21 @@ @file:Suppress("FunctionName") -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util -import cn.rtast.bldm.core.annotations.InternalBldmApi +import cn.rtast.bldm.codec.annotations.InternalBldmApi import kotlinx.serialization.json.Json +internal val dmMessageParser = Json { + ignoreUnknownKeys = true + classDiscriminator = "cmd" +} + @InternalBldmApi @Suppress("ObjectPropertyName") public val _json: Json = Json { ignoreUnknownKeys = true + isLenient = true } @InternalBldmApi diff --git a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/zlib.kt b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/zlib.kt similarity index 80% rename from bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/zlib.kt rename to bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/zlib.kt index 82b5757..87e94ad 100644 --- a/bl-core/src/commonMain/kotlin/cn/rtast/bldm/core/util/zlib.kt +++ b/bl-codec/src/commonMain/kotlin/cn/rtast/bldm/codec/util/zlib.kt @@ -5,6 +5,6 @@ */ -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util internal expect fun ByteArray.zlibDecompress(): ByteArray \ No newline at end of file diff --git a/bl-core/src/commonTest/kotlin/test/TestMd5.kt b/bl-codec/src/commonTest/kotlin/test/TestMd5.kt similarity index 100% rename from bl-core/src/commonTest/kotlin/test/TestMd5.kt rename to bl-codec/src/commonTest/kotlin/test/TestMd5.kt diff --git a/bl-core/src/commonTest/kotlin/test/TestWbiSign.kt b/bl-codec/src/commonTest/kotlin/test/TestWbiSign.kt similarity index 91% rename from bl-core/src/commonTest/kotlin/test/TestWbiSign.kt rename to bl-codec/src/commonTest/kotlin/test/TestWbiSign.kt index 22333fa..890f1b3 100644 --- a/bl-core/src/commonTest/kotlin/test/TestWbiSign.kt +++ b/bl-codec/src/commonTest/kotlin/test/TestWbiSign.kt @@ -7,7 +7,7 @@ package test -import cn.rtast.bldm.core.data.UserNavData +import cn.rtast.bldm.codec.data.UserNavData import kotlin.test.Test class TestWbiSign { diff --git a/bl-core/src/jvmMain/kotlin/cn/rtast/bldm/core/util/zlib.jvm.kt b/bl-codec/src/jvmMain/kotlin/cn/rtast/bldm/codec/util/zlib.jvm.kt similarity index 94% rename from bl-core/src/jvmMain/kotlin/cn/rtast/bldm/core/util/zlib.jvm.kt rename to bl-codec/src/jvmMain/kotlin/cn/rtast/bldm/codec/util/zlib.jvm.kt index 9b08830..2e15bc6 100644 --- a/bl-core/src/jvmMain/kotlin/cn/rtast/bldm/core/util/zlib.jvm.kt +++ b/bl-codec/src/jvmMain/kotlin/cn/rtast/bldm/codec/util/zlib.jvm.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util import java.io.ByteArrayOutputStream import java.util.zip.Inflater diff --git a/bl-core/src/nativeMain/kotlin/cn/rtast/bldm/core/util/zlib.native.kt b/bl-codec/src/nativeMain/kotlin/cn/rtast/bldm/codec/util/zlib.native.kt similarity index 98% rename from bl-core/src/nativeMain/kotlin/cn/rtast/bldm/core/util/zlib.native.kt rename to bl-codec/src/nativeMain/kotlin/cn/rtast/bldm/codec/util/zlib.native.kt index 03f7810..a51b62f 100644 --- a/bl-core/src/nativeMain/kotlin/cn/rtast/bldm/core/util/zlib.native.kt +++ b/bl-codec/src/nativeMain/kotlin/cn/rtast/bldm/codec/util/zlib.native.kt @@ -6,7 +6,7 @@ @file:OptIn(ExperimentalForeignApi::class) -package cn.rtast.bldm.core.util +package cn.rtast.bldm.codec.util import kotlinx.cinterop.* import platform.zlib.* diff --git a/bl-dm-codec/README.md b/bl-dm-codec/README.md new file mode 100644 index 0000000..73ea527 --- /dev/null +++ b/bl-dm-codec/README.md @@ -0,0 +1,3 @@ +dm codec + +WIP \ No newline at end of file diff --git a/bl-dm-codec/build.gradle.kts b/bl-dm-codec/build.gradle.kts new file mode 100644 index 0000000..af7a795 --- /dev/null +++ b/bl-dm-codec/build.gradle.kts @@ -0,0 +1,28 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + kotlin("multiplatform") + kotlin("plugin.serialization") +} + +kotlin { + explicitApi() + + linuxX64() + linuxArm64() + macosArm64() + mingwX64() + jvm { compilerOptions.jvmTarget = JvmTarget.JVM_11 } + + sourceSets { + commonMain.dependencies { + api(project(":bl-codec")) + api("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.11.0") + } + + commonTest.dependencies { + implementation(kotlin("test")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0") + } + } +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/InteractWordV2.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/InteractWordV2.kt new file mode 100644 index 0000000..2b48906 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/InteractWordV2.kt @@ -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 { + @Serializable + public data class InteractWordPbPayload( + val uid: Long, + val unameBytes: Map, + val actionType: Int, + val roomId: Long, + val timestampSec: Long, + val timestampMs: Long, + val identityType: Int, + val unameColor: String, + val sourceBytes: Map, + 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, + ) +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankCount.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankCount.kt new file mode 100644 index 0000000..647e96d --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankCount.kt @@ -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, +) \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankV3.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankV3.kt new file mode 100644 index 0000000..ab5d0f4 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/OnlineRankV3.kt @@ -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 { + @Serializable + public data class ReversedProtobuf( + /** + * rank type + * `online_rank` + */ + val rankType: String, + val userRankInfo: List, + ) + + @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, + ) +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/RawDanmuMessage.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/RawDanmuMessage.kt new file mode 100644 index 0000000..05762a6 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/RawDanmuMessage.kt @@ -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, + ) + } + + @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, + @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, + ) + } +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/ReverseEnginedProtobuf.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/ReverseEnginedProtobuf.kt new file mode 100644 index 0000000..e7d8a50 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/ReverseEnginedProtobuf.kt @@ -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 \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/SendGiftV2.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/SendGiftV2.kt new file mode 100644 index 0000000..fce60b3 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/SendGiftV2.kt @@ -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 { + @Serializable + public data class ReversedProtobuf( + val comboId: Long, + val senderNameBytes: Map, + val senderFace: String, + val giftDetail: GiftDetail, + val status: Int, + val senderInfo: SenderInfo, + ) + + @Serializable + public data class GiftDetail( + val giftId: Int, + val giftNameBytes: Map, + val price: Int, + val coinType: String, + val timestamp: Long, + val comboCount: Int, + val batchComboId: String, + val batchNum: Int, + val totalCoin: Int, + val actionBytes: Map, + 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, + ) +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/WatchedChange.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/WatchedChange.kt new file mode 100644 index 0000000..68305cc --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/WatchedChange.kt @@ -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, +) \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/_ReversedProtobufClass.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/_ReversedProtobufClass.kt new file mode 100644 index 0000000..0d56de0 --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/_ReversedProtobufClass.kt @@ -0,0 +1,13 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/8/30 + */ + +package cn.rtast.bldm.dm.codec + +@Suppress("ClassName") +public interface _ReversedProtobufClass { + public val origin: String + public val reversed: T +} \ No newline at end of file diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_base64.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_base64.kt new file mode 100644 index 0000000..3a28a6e --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_base64.kt @@ -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() diff --git a/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_protobuf.kt b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_protobuf.kt new file mode 100644 index 0000000..31d573b --- /dev/null +++ b/bl-dm-codec/src/commonMain/kotlin/cn/rtast/bldm/dm/codec/util/_protobuf.kt @@ -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 ByteArray.fromProtobuf(): T = + ProtoBuf.decodeFromByteArray(this) \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 7747fad..58027b6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,5 @@ rootProject.name = "bldm" -include(":bl-core") -include(":bl-client") \ No newline at end of file +include(":bl-codec") +include(":bl-client") +include(":bl-dm-codec") \ No newline at end of file