Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
Shamrock: 开源开发许可证
Browse files Browse the repository at this point in the history
Signed-off-by: 白池 <whitechi73@outlook.com>
  • Loading branch information
whitechi73 committed Feb 22, 2024
1 parent 8762966 commit 4d5c054
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 23 deletions.
Binary file added .github/jetbrains-variant-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

[![][contrib-image]][contrib-link]

## 鸣谢

感谢[**JetBrains**](https://www.jetbrains.com/zh-cn/community/opensource/#support)提供的开源开发许可证,JetBrains 通过为核心项目贡献者免费提供一套一流的开发者工具来支持非商业开源项目。

[<img src=".github/jetbrains-variant-3.png" width="200"/>](https://www.jetbrains.com/zh-cn/community/opensource/#support)

[banner]: https://socialify.git.ci/whitechi73/OpenShamrock/image?description=1&forks=1&issues=1&logo=https%3A%2F%2Fwhitechi73.github.io%2FOpenShamrock%2Fshamrock.jpg&pattern=Plus&pulls=1&stargazers=1&theme=Auto

[actions]: https://img.shields.io/github/actions/workflow/status/whitechi73/OpenShamrock/build-apk.yml?style=for-the-badge
Expand Down Expand Up @@ -102,3 +108,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
[contrib-image]: https://contrib.rocks/image?repo=whitechi73/OpenShamrock

[contrib-link]: https://github.com/whitechi73/OpenShamrock/graphs/contributors

Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,24 @@ public static class ReqBody extends MessageMicro<ReqBody> {
// public final PBUInt32Field service_id = PBField.initUInt32(0);
// public final PBStringField xml = PBField.initString("");
//};
//public oidb_cmd0xb77$MiniAppMsgBody mini_app_msg_body = new oidb_cmd0xb77$MiniAppMsgBody();
public MiniAppMsgBody mini_app_msg_body = new MiniAppMsgBody();
public final PBUInt64Field recv_guild_id = PBField.initUInt64(0);
}

public static class MiniAppMsgBody extends MessageMicro<MiniAppMsgBody> {
//static final MessageMicro.FieldMap __fieldMap__ = MessageMicro.initFieldMap(
// new int[]{8, 18, 26, 32, 42, 50, 82}, new String[]{"mini_app_appid", "mini_app_path", "web_page_url", "mini_app_type", "title", "desc", "json_str"}

//, new Object[]{0L, "", "", 0, "", "", ""}, oidb_cmd0xb77$MiniAppMsgBody.class);
public final PBUInt64Field mini_app_appid = PBField.initUInt64(0);
public final PBStringField mini_app_path = PBField.initString("");
public final PBStringField web_page_url = PBField.initString("");
public final PBUInt32Field mini_app_type = PBField.initUInt32(0);
public final PBStringField title = PBField.initString("");
public final PBStringField desc = PBField.initString("");
public final PBStringField json_str = PBField.initString("");
}

public static class ArkMsgBody extends MessageMicro<ArkMsgBody> {
public final PBStringField app = PBField.initString("");
public final PBStringField view = PBField.initString("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,12 @@ internal object PacketSvc: BaseSvc() {
fakeReceive("trpc.msg.olpush.OlPushService.MsgPush", 10000, ProtoBuf.encodeToByteArray(msgPush))
return withTimeoutOrNull(5000L) {
suspendCancellableCoroutine {
AioListener.messageLessListenerMap[msgSeq] = {
AioListener.registerTemporaryMsgListener(msgSeq) {
it.resume(this.msgId)
}
it.invokeOnCancellation {
AioListener.unregisterTemporaryMsgListener(msgSeq)
}
}
} ?: -1L
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package moe.fuqiuluo.qqinterface.servlet.ark
sealed class ArkAppInfo(
val appId: Long,
val version: String,
val packageName: String,
val signature: String,
val miniAppId: Long = 0
) {
data object QQMusic: ArkAppInfo(
appId = 100497308,
version = "0.0.0",
packageName = "com.tencent.qqmusic",
signature = "cbd27cd7c861227d013a25b2d10f0799"
)
data object NetEaseMusic: ArkAppInfo(
appId = 100495085,
version = "0.0.0",
packageName = "com.netease.cloudmusic",
signature = "da6b069da1e2982db3e386233f68d76d"
)

data object DanMaKu: ArkAppInfo(
appId = 100951776,
version = "0.0.0",
packageName = "tv.danmaku.bili",
signature = "7194d531cbe7960a22007b9f6bdaa38b",
miniAppId = 1109937557
)
}
63 changes: 53 additions & 10 deletions xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/ark/ArkMsg.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package moe.fuqiuluo.qqinterface.servlet.ark

import com.tencent.mobileqq.pb.ByteStringMicro
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.remote.service.listener.AioListener
import tencent.im.oidb.cmd0xb77.oidb_cmd0xb77

sealed class ArkAppInfo(
val appId: Long,
val version: String,
val packageName: String,
val signature: String
) {
object QQMusic: ArkAppInfo(100497308, "0.0.0", "com.tencent.qqmusic", "cbd27cd7c861227d013a25b2d10f0799")
object NeteaseMusic: ArkAppInfo(100495085, "0.0.0", "com.netease.cloudmusic", "da6b069da1e2982db3e386233f68d76d")
}
import kotlin.coroutines.resume
import kotlin.time.Duration.Companion.seconds

internal object ArkMsgSvc: BaseSvc() {
fun tryShareMusic(
Expand Down Expand Up @@ -54,4 +52,49 @@ internal object ArkMsgSvc: BaseSvc() {
}
sendOidb("OidbSvc.0xb77_9", 0xb77, 9, req.toByteArray())
}

suspend fun tryShareJsonMessage(
jsonString: String,
arkAppInfo: ArkAppInfo = ArkAppInfo.DanMaKu,
): Result<String> {
val msgSeq = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEC2C).qqMsgId
val req = oidb_cmd0xb77.ReqBody()
req.appid.set(arkAppInfo.appId)
req.app_type.set(1)
req.msg_style.set(10)
req.client_info.set(oidb_cmd0xb77.ClientInfo().also {
it.platform.set(1)
it.sdk_version.set(arkAppInfo.version)
it.android_package_name.set(arkAppInfo.packageName)
it.android_signature.set(arkAppInfo.signature)
})
req.ext_info.set(oidb_cmd0xb77.ExtInfo().also {
it.tag_name.set(ByteStringMicro.copyFromUtf8("shamrock"))
it.msg_seq.set(msgSeq)
})
req.send_type.set(0)
req.recv_uin.set(TicketSvc.getLongUin())
req.mini_app_msg_body.set(oidb_cmd0xb77.MiniAppMsgBody().also {
it.mini_app_appid.set(arkAppInfo.miniAppId)
it.mini_app_path.set("pages")
it.web_page_url.set("https://im.qq.com/index/")
it.title.set("title")
it.desc.set("desc")
it.json_str.set(jsonString)
})
sendOidb("OidbSvc.0xb77_9", 0xb77, 9, req.toByteArray())
val signedJson: String = withTimeoutOrNull(5.seconds) {
suspendCancellableCoroutine {
AioListener.registerTemporaryMsgListener(msgSeq) {
it.resume(elements.first {
it.elementType == MsgConstant.KELEMTYPEARKSTRUCT
}.arkElement.bytesData)
}
it.invokeOnCancellation {
AioListener.unregisterTemporaryMsgListener(msgSeq)
}
}
} ?: return Result.failure(Exception("unable to sign json"))
return Result.success(signedJson)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package moe.fuqiuluo.qqinterface.servlet.ark

import kotlinx.serialization.Serializable

@Serializable
internal data class Region(
val adcode: Int,
val province: String?,
val city: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.*
import java.lang.Exception

@Serializable
internal data class Region(
val adcode: Int,
val province: String?,
val city: String?
)

internal object WeatherSvc {
suspend fun fetchWeatherCard(code: Int): Result<JsonObject> {
val cookie = TicketSvc.getCookie("mp.qq.com")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ internal object MusicHelper {
chatType,
peerId,
msgId,
ArkAppInfo.NeteaseMusic,
ArkAppInfo.NetEaseMusic,
title.ifBlank { name },
singerName,
jumpUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ internal class ActionSession {
return params[key].asBooleanOrNull ?: default as Boolean
}

fun getJsonElement(key: String): JsonElement {
return params[key]!!
}

fun getJsonElementOrNull(key: String): JsonElement? {
return params[key]
}

fun getObject(key: String): JsonObject {
return params[key].asJsonObject
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package moe.fuqiuluo.shamrock.remote.action.handlers

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.ark.ArkMsgSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.symbols.OneBotHandler

@OneBotHandler("sign_ark_message")
internal object SignArkMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val json = if(session.isString("json")) session.getString("json")
else session.getJsonElement("json").toString()
return invoke(json, session.echo)
}

suspend operator fun invoke(json: String, echo: JsonElement = EmptyJsonString): String {
/*
ArkMsgSvc.tryShareJsonMessage(json).onSuccess {
return ok(SignArkMessageResult(it), echo = echo)
}.onFailure {
return error(it.message ?: it.toString(), echo)
}*/
return logic("logic error", echo)
}

@Serializable
data class SignArkMessageResult(
val result: String
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,33 @@ import moe.fuqiuluo.shamrock.tools.fetchGetOrThrow
import moe.fuqiuluo.shamrock.tools.fetchOrNull
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray
import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
import moe.fuqiuluo.shamrock.tools.fetchPostJsonString
import moe.fuqiuluo.shamrock.tools.fetchPostOrNull
import moe.fuqiuluo.shamrock.tools.fetchPostOrThrow
import moe.fuqiuluo.shamrock.tools.getOrPost
import moe.fuqiuluo.shamrock.tools.isJsonArray
import moe.fuqiuluo.shamrock.tools.isJsonData
import moe.fuqiuluo.shamrock.tools.isJsonObject
import moe.fuqiuluo.shamrock.tools.isJsonString
import moe.fuqiuluo.shamrock.tools.jsonArray
import moe.fuqiuluo.shamrock.tools.respond

fun Routing.messageAction() {
route("/sign_ark_message") {
get {
val json = fetchGetOrThrow("json")
call.respondText(SignArkMessage(json), ContentType.Application.Json)
}
post {
val json = if (isJsonData() && (isJsonObject("json") || isJsonArray("json")))
fetchPostJsonElement("json").toString()
else fetchPostOrThrow("json")
call.respondText(SignArkMessage(json), ContentType.Application.Json)
}
}

route("/send_group_forward_(msg|message)".toRegex()) {
post {
val groupId = fetchPostOrNull("group_id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import kotlin.collections.HashMap

internal object AioListener : IKernelMsgListener {
// 通过MSG SEQ临时监听器
internal val messageLessListenerMap = Collections.synchronizedMap(HashMap<Long, MsgRecord.() -> Unit>())
private val tempMessageListenerMap = Collections.synchronizedMap(HashMap<Long, suspend MsgRecord.() -> Unit>())

override fun onRecvMsg(msgList: ArrayList<MsgRecord>) {
if (msgList.isEmpty()) return
Expand All @@ -37,13 +37,26 @@ internal object AioListener : IKernelMsgListener {
}
}

fun registerTemporaryMsgListener(
msgSeq: Long,
listener: suspend MsgRecord.() -> Unit
) {
LogCenter.log({ "注册临时消息监听器: $msgSeq" }, Level.DEBUG)
tempMessageListenerMap[msgSeq] = listener
}

fun unregisterTemporaryMsgListener(msgSeq: Long) {
tempMessageListenerMap.remove(msgSeq)
}

private suspend fun handleMsg(record: MsgRecord) {
try {
messageLessListenerMap.firstNotNullOfOrNull {
tempMessageListenerMap.firstNotNullOfOrNull {
if (it.key == record.msgSeq) it else null
}?.let {
it.value(record)
messageLessListenerMap.remove(it.key)
tempMessageListenerMap.remove(it.key)
return
}
if (record.msgSeq < 0) return

Expand Down

0 comments on commit 4d5c054

Please sign in to comment.