mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Merge branch 'master' of github.com:whitechi73/OpenShamrock
This commit is contained in:
commit
1593d973a0
13
.github/FUNDING.yml
vendored
Normal file
13
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: shamrock320 # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
@ -24,7 +24,7 @@ android {
|
|||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 33
|
targetSdk = 33
|
||||||
versionCode = (System.currentTimeMillis() / 1000).toInt()
|
versionCode = (System.currentTimeMillis() / 1000).toInt()
|
||||||
versionName = "1.0.5-dev" + gitCommitHash()
|
versionName = "1.0.6-dev" + gitCommitHash()
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
@ -66,6 +66,7 @@ android {
|
|||||||
create("app") {
|
create("app") {
|
||||||
dimension = "mode"
|
dimension = "mode"
|
||||||
ndk {
|
ndk {
|
||||||
|
println("Full architecture and full compilation.")
|
||||||
abiFilters.add("arm64-v8a")
|
abiFilters.add("arm64-v8a")
|
||||||
abiFilters.add("x86_64")
|
abiFilters.add("x86_64")
|
||||||
}
|
}
|
||||||
@ -73,12 +74,14 @@ android {
|
|||||||
create("arm64") {
|
create("arm64") {
|
||||||
dimension = "mode"
|
dimension = "mode"
|
||||||
ndk {
|
ndk {
|
||||||
|
println("Full compilation of arm64 architecture")
|
||||||
abiFilters.add("arm64-v8a")
|
abiFilters.add("arm64-v8a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
create("x64") {
|
create("x64") {
|
||||||
dimension = "mode"
|
dimension = "mode"
|
||||||
ndk {
|
ndk {
|
||||||
|
println("Full compilation of x64 architecture")
|
||||||
abiFilters.add("x86_64")
|
abiFilters.add("x86_64")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
/* compiled from: P */
|
|
||||||
/* loaded from: classes2.dex */
|
|
||||||
public final class GroupFileCommonResult {
|
public final class GroupFileCommonResult {
|
||||||
String clientWording;
|
String clientWording;
|
||||||
int retCode;
|
int retCode;
|
||||||
@ -29,8 +27,6 @@ public final class GroupFileCommonResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GroupFileCommonResult(int i2, String str, String str2) {
|
public GroupFileCommonResult(int i2, String str, String str2) {
|
||||||
this.retMsg = "";
|
|
||||||
this.clientWording = "";
|
|
||||||
this.retCode = i2;
|
this.retCode = i2;
|
||||||
this.retMsg = str;
|
this.retMsg = str;
|
||||||
this.clientWording = str2;
|
this.clientWording = str2;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
public interface IDeleteGroupFileCallback {
|
public interface IDeleteGroupFileCallback {
|
||||||
void onResult(int i2, String str, DeleteGroupFileResult deleteGroupFileResult);
|
void onResult(int code, String why, DeleteGroupFileResult result);
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ public interface IKernelRichMediaService {
|
|||||||
|
|
||||||
void cancelTransferTask(Contact contact, ArrayList<Long> arrayList, ArrayList<Integer> arrayList2, IOperateTransferInfoCallback iOperateTransferInfoCallback);
|
void cancelTransferTask(Contact contact, ArrayList<Long> arrayList, ArrayList<Integer> arrayList2, IOperateTransferInfoCallback iOperateTransferInfoCallback);
|
||||||
|
|
||||||
void deleteGroupFile(long j2, String str, int i2, IDeleteGroupFileCallback iDeleteGroupFileCallback);
|
void deleteGroupFile(long groupCode, String fileUid, int bizId, IDeleteGroupFileCallback cb);
|
||||||
|
|
||||||
void deleteTransferInfo(Contact contact, ArrayList<Long> arrayList, IOperateTransferInfoCallback iOperateTransferInfoCallback);
|
void deleteTransferInfo(Contact contact, ArrayList<Long> arrayList, IOperateTransferInfoCallback iOperateTransferInfoCallback);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.proto.protobufOf
|
import moe.fuqiuluo.proto.protobufOf
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
@ -37,9 +38,9 @@ internal abstract class BaseSvc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendOidbAW(cmd: String, cmdId: Int, serviceId: Int, data: ByteArray, trpc: Boolean = false, timeout: Long = 5000L): ByteArray? {
|
suspend fun sendOidbAW(cmd: String, cmdId: Int, serviceId: Int, data: ByteArray, trpc: Boolean = false, timeout: Long = 5000L): ByteArray? {
|
||||||
return withTimeoutOrNull(timeout) {
|
|
||||||
suspendCoroutine { continuation ->
|
|
||||||
val seq = MsfCore.getNextSeq()
|
val seq = MsfCore.getNextSeq()
|
||||||
|
return withTimeoutOrNull(timeout) {
|
||||||
|
suspendCancellableCoroutine { continuation ->
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
||||||
val buffer = it.getByteArrayExtra("buffer")!!
|
val buffer = it.getByteArrayExtra("buffer")!!
|
||||||
@ -49,13 +50,16 @@ internal abstract class BaseSvc {
|
|||||||
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
|
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
|
||||||
else sendOidb(cmd, cmdId, serviceId, data, seq)
|
else sendOidb(cmd, cmdId, serviceId, data, seq)
|
||||||
}
|
}
|
||||||
|
}.also {
|
||||||
|
if (it == null)
|
||||||
|
DynamicReceiver.unregister(seq)
|
||||||
}?.copyOf()
|
}?.copyOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray, timeout: Long = 5000L): ByteArray? {
|
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray, timeout: Long = 5000L): ByteArray? {
|
||||||
return withTimeoutOrNull<ByteArray?>(timeout) {
|
|
||||||
suspendCoroutine { continuation ->
|
|
||||||
val seq = MsfCore.getNextSeq()
|
val seq = MsfCore.getNextSeq()
|
||||||
|
return withTimeoutOrNull<ByteArray?>(timeout) {
|
||||||
|
suspendCancellableCoroutine { continuation ->
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
||||||
val buffer = it.getByteArrayExtra("buffer")!!
|
val buffer = it.getByteArrayExtra("buffer")!!
|
||||||
@ -64,6 +68,9 @@ internal abstract class BaseSvc {
|
|||||||
sendBuffer(cmd, isPb, data, seq)
|
sendBuffer(cmd, isPb, data, seq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}.also {
|
||||||
|
if (it == null)
|
||||||
|
DynamicReceiver.unregister(seq)
|
||||||
}?.copyOf()
|
}?.copyOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet
|
package moe.fuqiuluo.qqinterface.servlet
|
||||||
|
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.DeleteGroupFileResult
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.GroupFileCommonResult
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.IDeleteGroupFileCallback
|
||||||
import io.ktor.util.Deflate
|
import io.ktor.util.Deflate
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import moe.fuqiuluo.proto.protobufOf
|
import moe.fuqiuluo.proto.protobufOf
|
||||||
@ -12,8 +17,11 @@ import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
|
|||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.tools.toHexString
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
internal object FileSvc: BaseSvc() {
|
internal object FileSvc: BaseSvc() {
|
||||||
fun createFileFolder(groupId: String, folderName: String) {
|
fun createFileFolder(groupId: String, folderName: String) {
|
||||||
@ -38,6 +46,21 @@ internal object FileSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteGroupFile(groupId: String, bizId: Int, fileUid: String) {
|
fun deleteGroupFile(groupId: String, bizId: Int, fileUid: String) {
|
||||||
|
/*
|
||||||
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
|
val sessionService = kernelService.wrapperSession
|
||||||
|
val richMediaService = sessionService.richMediaService
|
||||||
|
|
||||||
|
val result = withTimeoutOrNull(3000L) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
richMediaService.deleteGroupFile(groupId.toLong(), fileUid, bizId) { code, _, result ->
|
||||||
|
it.resume(code to result.result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (result == null) Result.failure(RuntimeException("delete group file timeout")) else Result.success(result)*/
|
||||||
|
// 调用QQ内部实现会导致闪退!
|
||||||
sendOidb("OidbSvc.0x6d6_3", 1750, 3, protobufOf(
|
sendOidb("OidbSvc.0x6d6_3", 1750, 3, protobufOf(
|
||||||
4 to mapOf(
|
4 to mapOf(
|
||||||
1 to groupId.toLong(),
|
1 to groupId.toLong(),
|
||||||
|
@ -143,13 +143,15 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
element: MsgElement
|
element: MsgElement
|
||||||
): MessageSegment {
|
): MessageSegment {
|
||||||
val video = element.videoElement
|
val video = element.videoElement
|
||||||
|
val md5 = video.fileName.split(".")[0]
|
||||||
|
|
||||||
return MessageSegment(
|
return MessageSegment(
|
||||||
type = "video",
|
type = "video",
|
||||||
data = hashMapOf(
|
data = hashMapOf(
|
||||||
"file" to video.fileName,
|
"file" to video.fileName,
|
||||||
"url" to when(chatType) {
|
"url" to when(chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", video.fileName, video.fileUuid)
|
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", video.fileName, video.fileUuid)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
||||||
else -> unknownChatType(chatType)
|
else -> unknownChatType(chatType)
|
||||||
}
|
}
|
||||||
).also {
|
).also {
|
||||||
|
@ -63,24 +63,30 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
suspend fun getC2CFileDownUrl(
|
suspend fun getC2CFileDownUrl(
|
||||||
fileId: String,
|
fileId: String,
|
||||||
subId: String,
|
subId: String,
|
||||||
|
retryCnt: Int = 0
|
||||||
): String {
|
): String {
|
||||||
val uid = ContactHelper.getUidByUinAsync(app.currentUin.toLong())
|
val buffer = sendOidbAW("OidbSvc.0xe37_1200", 3639, 1200, protobufOf(
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xe37_1200", 3639, 1200, protobufOf(
|
|
||||||
1 to 1200,
|
1 to 1200,
|
||||||
2 to 1 /* QRoute.api(IAudioHelperApi::class.java).genDebugSeq().toInt() */, /* seq */
|
2 to 1 /* QRoute.api(IAudioHelperApi::class.java).genDebugSeq().toInt() */, /* seq */
|
||||||
14 to mapOf(
|
14 to mapOf(
|
||||||
10 to uid,
|
10 to app.longAccountUin,
|
||||||
20 to fileId,
|
20 to fileId,
|
||||||
30 to 2, /* ver */
|
30 to 2, /* ver */
|
||||||
60 to subId,
|
60 to subId,
|
||||||
601 to 0
|
601 to 0
|
||||||
),
|
),
|
||||||
101 to 3,
|
101 to 3, // uint32_business_id
|
||||||
102 to 104, /* client_type */
|
102 to 104, /* client_type */
|
||||||
200 to 1, /* url_type */
|
200 to 1, /* uint32_flag_support_mediaplatform */
|
||||||
99999 to 90200 to 1
|
99999 to mapOf(
|
||||||
).toByteArray(), trpc = true)
|
90200 to 1 // uint32_download_url_type
|
||||||
|
)
|
||||||
|
).toByteArray())
|
||||||
|
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
|
if (retryCnt < 3) {
|
||||||
|
return getC2CFileDownUrl(fileId, subId, retryCnt + 1)
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
} else {
|
} else {
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = oidb_sso.OIDBSSOPkg()
|
||||||
|
@ -14,10 +14,30 @@ internal object DeleteGroupFile: IActionHandler() {
|
|||||||
return invoke(groupId, fileId, busid, session.echo)
|
return invoke(groupId, fileId, busid, session.echo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
suspend operator fun invoke(
|
||||||
|
groupId: String,
|
||||||
|
fileId: String,
|
||||||
|
bizId: Int,
|
||||||
|
echo: JsonElement = EmptyJsonString
|
||||||
|
): String {
|
||||||
|
val result = FileSvc.deleteGroupFile(groupId, bizId, fileId)
|
||||||
|
if(result.isFailure) {
|
||||||
|
return error(result.exceptionOrNull()?.message ?: "删除群文件失败", echo)
|
||||||
|
}
|
||||||
|
val commonResult = result.getOrThrow()
|
||||||
|
if (commonResult.first != 0 || commonResult.second.retCode != 0) {
|
||||||
|
return error(commonResult.second.clientWording, echo)
|
||||||
|
}
|
||||||
|
return ok("成功", echo)
|
||||||
|
}
|
||||||
|
*/
|
||||||
operator fun invoke(groupId: String, fileId: String, bizId: Int, echo: JsonElement = EmptyJsonString): String {
|
operator fun invoke(groupId: String, fileId: String, bizId: Int, echo: JsonElement = EmptyJsonString): String {
|
||||||
FileSvc.deleteGroupFile(groupId, bizId, fileId)
|
FileSvc.deleteGroupFile(groupId, bizId, fileId)
|
||||||
return ok("成功", echo)
|
return ok("成功", echo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val requiredParams: Array<String> = arrayOf("group_id", "file_id", "busid")
|
||||||
|
|
||||||
override fun path(): String = "delete_group_file"
|
override fun path(): String = "delete_group_file"
|
||||||
}
|
}
|
@ -17,10 +17,12 @@ import moe.fuqiuluo.shamrock.remote.config.ECHO_KEY
|
|||||||
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
|
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.IndexData
|
import moe.fuqiuluo.shamrock.remote.entries.IndexData
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.Status
|
import moe.fuqiuluo.shamrock.remote.entries.Status
|
||||||
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonObject
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement
|
import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
|
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
|
||||||
|
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObjectOrNull
|
||||||
import moe.fuqiuluo.shamrock.tools.isJsonArray
|
import moe.fuqiuluo.shamrock.tools.isJsonArray
|
||||||
import moe.fuqiuluo.shamrock.tools.isJsonObject
|
import moe.fuqiuluo.shamrock.tools.isJsonObject
|
||||||
import moe.fuqiuluo.shamrock.tools.isJsonString
|
import moe.fuqiuluo.shamrock.tools.isJsonString
|
||||||
@ -55,7 +57,7 @@ fun Routing.echoVersion() {
|
|||||||
}
|
}
|
||||||
call.attributes.put(ECHO_KEY, echo)
|
call.attributes.put(ECHO_KEY, echo)
|
||||||
|
|
||||||
val params = fetchPostJsonObject("params")
|
val params = fetchPostJsonObjectOrNull("params") ?: EmptyJsonObject
|
||||||
|
|
||||||
val handler = ActionManager[action]
|
val handler = ActionManager[action]
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
|
@ -69,8 +69,8 @@ internal class WebSocketService(host: String, port: Int): WebSocketTransmitServl
|
|||||||
}
|
}
|
||||||
val path = URI.create(handshake.resourceDescriptor).path
|
val path = URI.create(handshake.resourceDescriptor).path
|
||||||
if (path != "/api") {
|
if (path != "/api") {
|
||||||
pushMetaLifecycle()
|
|
||||||
eventReceivers.add(conn)
|
eventReceivers.add(conn)
|
||||||
|
pushMetaLifecycle()
|
||||||
}
|
}
|
||||||
LogCenter.log({ "WSServer连接(${conn.remoteSocketAddress.address.hostAddress}:${conn.remoteSocketAddress.port}$path)" }, Level.WARN)
|
LogCenter.log({ "WSServer连接(${conn.remoteSocketAddress.address.hostAddress}:${conn.remoteSocketAddress.port}$path)" }, Level.WARN)
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ internal abstract class WebSocketTransmitServlet(
|
|||||||
}
|
}
|
||||||
val action = actionObject["action"].asString
|
val action = actionObject["action"].asString
|
||||||
val echo = actionObject["echo"] ?: EmptyJsonString
|
val echo = actionObject["echo"] ?: EmptyJsonString
|
||||||
val params = actionObject["params"].asJsonObject
|
val params = actionObject["params"].asJsonObjectOrNull ?: EmptyJsonObject
|
||||||
|
|
||||||
val handler = ActionManager[action]
|
val handler = ActionManager[action]
|
||||||
handler?.handle(ActionSession(params, echo))
|
handler?.handle(ActionSession(params, echo))
|
||||||
|
@ -55,7 +55,7 @@ internal object PrimitiveListener {
|
|||||||
) return
|
) return
|
||||||
val msgType = pb[1, 2, 1].asInt
|
val msgType = pb[1, 2, 1].asInt
|
||||||
var subType = 0
|
var subType = 0
|
||||||
if (pb.has(1, 2, 3)) {
|
if (pb.has(1, 2, 3) && pb.has(1, 2, 2)) {
|
||||||
subType = pb[1, 2, 2].asInt
|
subType = pb[1, 2, 2].asInt
|
||||||
}
|
}
|
||||||
val msgTime = pb[1, 2, 6].asLong
|
val msgTime = pb[1, 2, 6].asLong
|
||||||
|
@ -20,13 +20,10 @@ import kotlinx.serialization.json.JsonPrimitive
|
|||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import moe.fuqiuluo.shamrock.helper.ParamsException
|
import moe.fuqiuluo.shamrock.helper.ParamsException
|
||||||
import io.ktor.http.HttpMethod
|
import io.ktor.http.HttpMethod
|
||||||
import io.ktor.http.decodeURLPart
|
|
||||||
import io.ktor.http.parseUrlEncodedParameters
|
import io.ktor.http.parseUrlEncodedParameters
|
||||||
import io.ktor.server.request.httpMethod
|
import io.ktor.server.request.httpMethod
|
||||||
import io.ktor.server.routing.route
|
import io.ktor.server.routing.route
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.CommonResult
|
import moe.fuqiuluo.shamrock.remote.entries.CommonResult
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
|
import moe.fuqiuluo.shamrock.remote.entries.EmptyObject
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.Status
|
import moe.fuqiuluo.shamrock.remote.entries.Status
|
||||||
@ -38,9 +35,9 @@ import moe.fuqiuluo.shamrock.remote.entries.Status
|
|||||||
annotation class ShamrockDsl
|
annotation class ShamrockDsl
|
||||||
|
|
||||||
|
|
||||||
private val isJsonKey = AttributeKey<Boolean>("isJson")
|
private val keyIsJson = AttributeKey<Boolean>("isJson")
|
||||||
private val jsonKey = AttributeKey<JsonObject>("paramsJson")
|
private val keyJsonObject = AttributeKey<JsonObject>("paramsJson")
|
||||||
private val partsKey = AttributeKey<Parameters>("paramsParts")
|
private val keyParts = AttributeKey<Parameters>("paramsParts")
|
||||||
|
|
||||||
suspend fun ApplicationCall.fetch(key: String): String {
|
suspend fun ApplicationCall.fetch(key: String): String {
|
||||||
val isPost = request.httpMethod == HttpMethod.Post
|
val isPost = request.httpMethod == HttpMethod.Post
|
||||||
@ -94,23 +91,23 @@ fun ApplicationCall.isJsonData(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun ApplicationCall.fetchPostOrNull(key: String): String? {
|
suspend fun ApplicationCall.fetchPostOrNull(key: String): String? {
|
||||||
if (attributes.contains(jsonKey)) {
|
if (attributes.contains(keyJsonObject)) {
|
||||||
return attributes[jsonKey][key].asStringOrNull
|
return attributes[keyJsonObject][key].asStringOrNull
|
||||||
}
|
}
|
||||||
if (attributes.contains(partsKey)) {
|
if (attributes.contains(keyParts)) {
|
||||||
return attributes[partsKey][key]
|
return attributes[keyParts][key]
|
||||||
}
|
}
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
if (isJsonData()) {
|
if (isJsonData()) {
|
||||||
Json.parseToJsonElement(receiveText()).jsonObject.also {
|
Json.parseToJsonElement(receiveText()).jsonObject.also {
|
||||||
attributes.put(jsonKey, it)
|
attributes.put(keyJsonObject, it)
|
||||||
attributes.put(isJsonKey, true)
|
attributes.put(keyIsJson, true)
|
||||||
}[key].asStringOrNull
|
}[key].asStringOrNull
|
||||||
} else if (
|
} else if (
|
||||||
ContentType.Application.FormUrlEncoded == request.contentType()
|
ContentType.Application.FormUrlEncoded == request.contentType()
|
||||||
) {
|
) {
|
||||||
receiveParameters().also {
|
receiveParameters().also {
|
||||||
attributes.put(partsKey, it)
|
attributes.put(keyParts, it)
|
||||||
}[key]
|
}[key]
|
||||||
} else {
|
} else {
|
||||||
receiveTextAsUnknown(key)
|
receiveTextAsUnknown(key)
|
||||||
@ -124,13 +121,13 @@ private suspend fun ApplicationCall.receiveTextAsUnknown(key: String): String? {
|
|||||||
return receiveText().let { text ->
|
return receiveText().let { text ->
|
||||||
if (text.startsWith("{") && text.endsWith("}")) {
|
if (text.startsWith("{") && text.endsWith("}")) {
|
||||||
Json.parseToJsonElement(text).jsonObject.also {
|
Json.parseToJsonElement(text).jsonObject.also {
|
||||||
attributes.put(jsonKey, it)
|
attributes.put(keyJsonObject, it)
|
||||||
attributes.put(isJsonKey, true)
|
attributes.put(keyIsJson, true)
|
||||||
}[key].asStringOrNull
|
}[key].asStringOrNull
|
||||||
} else {
|
} else {
|
||||||
text.parseUrlEncodedParameters().also {
|
text.parseUrlEncodedParameters().also {
|
||||||
attributes.put(partsKey, it)
|
attributes.put(keyParts, it)
|
||||||
attributes.put(isJsonKey, false)
|
attributes.put(keyIsJson, false)
|
||||||
}[key]
|
}[key]
|
||||||
}
|
}
|
||||||
} // receiveText
|
} // receiveText
|
||||||
@ -170,17 +167,17 @@ suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostOrThrow(key: String)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun PipelineContext<Unit, ApplicationCall>.isJsonData(): Boolean {
|
fun PipelineContext<Unit, ApplicationCall>.isJsonData(): Boolean {
|
||||||
return ContentType.Application.Json == call.request.contentType() || call.attributes[isJsonKey]
|
return ContentType.Application.Json == call.request.contentType() || (keyIsJson in call.attributes && call.attributes[keyIsJson])
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Boolean {
|
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Boolean {
|
||||||
if (!isJsonData()) return true
|
if (!isJsonData()) return true
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (keyJsonObject in call.attributes) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
call.attributes.put(isJsonKey, true)
|
call.attributes.put(keyIsJson, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key] is JsonPrimitive
|
return data[key] is JsonPrimitive
|
||||||
@ -188,11 +185,11 @@ suspend fun PipelineContext<Unit, ApplicationCall>.isJsonString(key: String): Bo
|
|||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Boolean {
|
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Boolean {
|
||||||
if (!isJsonData()) return false
|
if (!isJsonData()) return false
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key] is JsonObject
|
return data[key] is JsonObject
|
||||||
@ -200,56 +197,68 @@ suspend fun PipelineContext<Unit, ApplicationCall>.isJsonObject(key: String): Bo
|
|||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonArray(key: String): Boolean {
|
suspend fun PipelineContext<Unit, ApplicationCall>.isJsonArray(key: String): Boolean {
|
||||||
if (!isJsonData()) return false
|
if (!isJsonData()) return false
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key] is JsonArray
|
return data[key] is JsonArray
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonString(key: String): String {
|
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonString(key: String): String {
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key].asString
|
return data[key].asString
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonElement(key: String): JsonElement {
|
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonElement(key: String): JsonElement {
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key]!!
|
return data[key]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObject(key: String): JsonObject {
|
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObject(key: String): JsonObject {
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key].asJsonObject
|
return data[key].asJsonObject
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonArray(key: String): JsonArray {
|
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObjectOrNull(key: String): JsonObject? {
|
||||||
val data = if (call.attributes.contains(jsonKey)) {
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
call.attributes[jsonKey]
|
call.attributes[keyJsonObject]
|
||||||
} else {
|
} else {
|
||||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
call.attributes.put(jsonKey, it)
|
call.attributes.put(keyJsonObject, it)
|
||||||
call.attributes.put(isJsonKey, true)
|
}
|
||||||
|
}
|
||||||
|
return data[key].asJsonObjectOrNull
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonArray(key: String): JsonArray {
|
||||||
|
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||||
|
call.attributes[keyJsonObject]
|
||||||
|
} else {
|
||||||
|
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||||
|
call.attributes.put(keyJsonObject, it)
|
||||||
|
call.attributes.put(keyIsJson, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data[key].asJsonArray
|
return data[key].asJsonArray
|
||||||
|
Loading…
x
Reference in New Issue
Block a user