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
|
||||
targetSdk = 33
|
||||
versionCode = (System.currentTimeMillis() / 1000).toInt()
|
||||
versionName = "1.0.5-dev" + gitCommitHash()
|
||||
versionName = "1.0.6-dev" + gitCommitHash()
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
@ -66,6 +66,7 @@ android {
|
||||
create("app") {
|
||||
dimension = "mode"
|
||||
ndk {
|
||||
println("Full architecture and full compilation.")
|
||||
abiFilters.add("arm64-v8a")
|
||||
abiFilters.add("x86_64")
|
||||
}
|
||||
@ -73,12 +74,14 @@ android {
|
||||
create("arm64") {
|
||||
dimension = "mode"
|
||||
ndk {
|
||||
println("Full compilation of arm64 architecture")
|
||||
abiFilters.add("arm64-v8a")
|
||||
}
|
||||
}
|
||||
create("x64") {
|
||||
dimension = "mode"
|
||||
ndk {
|
||||
println("Full compilation of x64 architecture")
|
||||
abiFilters.add("x86_64")
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.tencent.qqnt.kernel.nativeinterface;
|
||||
|
||||
/* compiled from: P */
|
||||
/* loaded from: classes2.dex */
|
||||
public final class GroupFileCommonResult {
|
||||
String clientWording;
|
||||
int retCode;
|
||||
@ -29,8 +27,6 @@ public final class GroupFileCommonResult {
|
||||
}
|
||||
|
||||
public GroupFileCommonResult(int i2, String str, String str2) {
|
||||
this.retMsg = "";
|
||||
this.clientWording = "";
|
||||
this.retCode = i2;
|
||||
this.retMsg = str;
|
||||
this.clientWording = str2;
|
||||
|
@ -1,5 +1,5 @@
|
||||
package com.tencent.qqnt.kernel.nativeinterface;
|
||||
|
||||
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 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);
|
||||
|
||||
|
@ -11,6 +11,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import moe.fuqiuluo.proto.protobufOf
|
||||
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? {
|
||||
val seq = MsfCore.getNextSeq()
|
||||
return withTimeoutOrNull(timeout) {
|
||||
suspendCoroutine { continuation ->
|
||||
val seq = MsfCore.getNextSeq()
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
||||
val buffer = it.getByteArrayExtra("buffer")!!
|
||||
@ -49,13 +50,16 @@ internal abstract class BaseSvc {
|
||||
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
|
||||
else sendOidb(cmd, cmdId, serviceId, data, seq)
|
||||
}
|
||||
}.also {
|
||||
if (it == null)
|
||||
DynamicReceiver.unregister(seq)
|
||||
}?.copyOf()
|
||||
}
|
||||
|
||||
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray, timeout: Long = 5000L): ByteArray? {
|
||||
val seq = MsfCore.getNextSeq()
|
||||
return withTimeoutOrNull<ByteArray?>(timeout) {
|
||||
suspendCoroutine { continuation ->
|
||||
val seq = MsfCore.getNextSeq()
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
||||
val buffer = it.getByteArrayExtra("buffer")!!
|
||||
@ -64,6 +68,9 @@ internal abstract class BaseSvc {
|
||||
sendBuffer(cmd, isPb, data, seq)
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
if (it == null)
|
||||
DynamicReceiver.unregister(seq)
|
||||
}?.copyOf()
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet
|
||||
|
||||
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 kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
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.toHexString
|
||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
||||
import tencent.im.oidb.oidb_sso
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
internal object FileSvc: BaseSvc() {
|
||||
fun createFileFolder(groupId: String, folderName: String) {
|
||||
@ -38,8 +46,23 @@ internal object FileSvc: BaseSvc() {
|
||||
}
|
||||
|
||||
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(
|
||||
4 to mapOf(
|
||||
4 to mapOf(
|
||||
1 to groupId.toLong(),
|
||||
2 to 3,
|
||||
3 to bizId,
|
||||
|
@ -143,13 +143,15 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
||||
element: MsgElement
|
||||
): MessageSegment {
|
||||
val video = element.videoElement
|
||||
val md5 = video.fileName.split(".")[0]
|
||||
|
||||
return MessageSegment(
|
||||
type = "video",
|
||||
data = hashMapOf(
|
||||
"file" to video.fileName,
|
||||
"url" to when(chatType) {
|
||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", video.fileName, video.fileUuid)
|
||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", video.fileName, video.fileUuid)
|
||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
||||
else -> unknownChatType(chatType)
|
||||
}
|
||||
).also {
|
||||
|
@ -63,24 +63,30 @@ internal object RichProtoSvc: BaseSvc() {
|
||||
suspend fun getC2CFileDownUrl(
|
||||
fileId: String,
|
||||
subId: String,
|
||||
retryCnt: Int = 0
|
||||
): String {
|
||||
val uid = ContactHelper.getUidByUinAsync(app.currentUin.toLong())
|
||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xe37_1200", 3639, 1200, protobufOf(
|
||||
val buffer = sendOidbAW("OidbSvc.0xe37_1200", 3639, 1200, protobufOf(
|
||||
1 to 1200,
|
||||
2 to 1 /* QRoute.api(IAudioHelperApi::class.java).genDebugSeq().toInt() */, /* seq */
|
||||
14 to mapOf(
|
||||
10 to uid,
|
||||
10 to app.longAccountUin,
|
||||
20 to fileId,
|
||||
30 to 2, /* ver */
|
||||
60 to subId,
|
||||
601 to 0
|
||||
),
|
||||
101 to 3,
|
||||
101 to 3, // uint32_business_id
|
||||
102 to 104, /* client_type */
|
||||
200 to 1, /* url_type */
|
||||
99999 to 90200 to 1
|
||||
).toByteArray(), trpc = true)
|
||||
200 to 1, /* uint32_flag_support_mediaplatform */
|
||||
99999 to mapOf(
|
||||
90200 to 1 // uint32_download_url_type
|
||||
)
|
||||
).toByteArray())
|
||||
|
||||
if (buffer == null) {
|
||||
if (retryCnt < 3) {
|
||||
return getC2CFileDownUrl(fileId, subId, retryCnt + 1)
|
||||
}
|
||||
return ""
|
||||
} else {
|
||||
val body = oidb_sso.OIDBSSOPkg()
|
||||
|
@ -14,10 +14,30 @@ internal object DeleteGroupFile: IActionHandler() {
|
||||
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 {
|
||||
FileSvc.deleteGroupFile(groupId, bizId, fileId)
|
||||
return ok("成功", echo)
|
||||
}
|
||||
|
||||
override val requiredParams: Array<String> = arrayOf("group_id", "file_id", "busid")
|
||||
|
||||
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.IndexData
|
||||
import moe.fuqiuluo.shamrock.remote.entries.Status
|
||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonObject
|
||||
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
||||
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
||||
import moe.fuqiuluo.shamrock.tools.fetchPostJsonElement
|
||||
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
|
||||
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObjectOrNull
|
||||
import moe.fuqiuluo.shamrock.tools.isJsonArray
|
||||
import moe.fuqiuluo.shamrock.tools.isJsonObject
|
||||
import moe.fuqiuluo.shamrock.tools.isJsonString
|
||||
@ -55,7 +57,7 @@ fun Routing.echoVersion() {
|
||||
}
|
||||
call.attributes.put(ECHO_KEY, echo)
|
||||
|
||||
val params = fetchPostJsonObject("params")
|
||||
val params = fetchPostJsonObjectOrNull("params") ?: EmptyJsonObject
|
||||
|
||||
val handler = ActionManager[action]
|
||||
if (handler == null) {
|
||||
|
@ -69,8 +69,8 @@ internal class WebSocketService(host: String, port: Int): WebSocketTransmitServl
|
||||
}
|
||||
val path = URI.create(handshake.resourceDescriptor).path
|
||||
if (path != "/api") {
|
||||
pushMetaLifecycle()
|
||||
eventReceivers.add(conn)
|
||||
pushMetaLifecycle()
|
||||
}
|
||||
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 echo = actionObject["echo"] ?: EmptyJsonString
|
||||
val params = actionObject["params"].asJsonObject
|
||||
val params = actionObject["params"].asJsonObjectOrNull ?: EmptyJsonObject
|
||||
|
||||
val handler = ActionManager[action]
|
||||
handler?.handle(ActionSession(params, echo))
|
||||
|
@ -55,7 +55,7 @@ internal object PrimitiveListener {
|
||||
) return
|
||||
val msgType = pb[1, 2, 1].asInt
|
||||
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
|
||||
}
|
||||
val msgTime = pb[1, 2, 6].asLong
|
||||
|
@ -20,13 +20,10 @@ import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import moe.fuqiuluo.shamrock.helper.ParamsException
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.decodeURLPart
|
||||
import io.ktor.http.parseUrlEncodedParameters
|
||||
import io.ktor.server.request.httpMethod
|
||||
import io.ktor.server.routing.route
|
||||
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.EmptyObject
|
||||
import moe.fuqiuluo.shamrock.remote.entries.Status
|
||||
@ -38,9 +35,9 @@ import moe.fuqiuluo.shamrock.remote.entries.Status
|
||||
annotation class ShamrockDsl
|
||||
|
||||
|
||||
private val isJsonKey = AttributeKey<Boolean>("isJson")
|
||||
private val jsonKey = AttributeKey<JsonObject>("paramsJson")
|
||||
private val partsKey = AttributeKey<Parameters>("paramsParts")
|
||||
private val keyIsJson = AttributeKey<Boolean>("isJson")
|
||||
private val keyJsonObject = AttributeKey<JsonObject>("paramsJson")
|
||||
private val keyParts = AttributeKey<Parameters>("paramsParts")
|
||||
|
||||
suspend fun ApplicationCall.fetch(key: String): String {
|
||||
val isPost = request.httpMethod == HttpMethod.Post
|
||||
@ -94,23 +91,23 @@ fun ApplicationCall.isJsonData(): Boolean {
|
||||
}
|
||||
|
||||
suspend fun ApplicationCall.fetchPostOrNull(key: String): String? {
|
||||
if (attributes.contains(jsonKey)) {
|
||||
return attributes[jsonKey][key].asStringOrNull
|
||||
if (attributes.contains(keyJsonObject)) {
|
||||
return attributes[keyJsonObject][key].asStringOrNull
|
||||
}
|
||||
if (attributes.contains(partsKey)) {
|
||||
return attributes[partsKey][key]
|
||||
if (attributes.contains(keyParts)) {
|
||||
return attributes[keyParts][key]
|
||||
}
|
||||
return kotlin.runCatching {
|
||||
if (isJsonData()) {
|
||||
Json.parseToJsonElement(receiveText()).jsonObject.also {
|
||||
attributes.put(jsonKey, it)
|
||||
attributes.put(isJsonKey, true)
|
||||
attributes.put(keyJsonObject, it)
|
||||
attributes.put(keyIsJson, true)
|
||||
}[key].asStringOrNull
|
||||
} else if (
|
||||
ContentType.Application.FormUrlEncoded == request.contentType()
|
||||
) {
|
||||
receiveParameters().also {
|
||||
attributes.put(partsKey, it)
|
||||
attributes.put(keyParts, it)
|
||||
}[key]
|
||||
} else {
|
||||
receiveTextAsUnknown(key)
|
||||
@ -124,13 +121,13 @@ private suspend fun ApplicationCall.receiveTextAsUnknown(key: String): String? {
|
||||
return receiveText().let { text ->
|
||||
if (text.startsWith("{") && text.endsWith("}")) {
|
||||
Json.parseToJsonElement(text).jsonObject.also {
|
||||
attributes.put(jsonKey, it)
|
||||
attributes.put(isJsonKey, true)
|
||||
attributes.put(keyJsonObject, it)
|
||||
attributes.put(keyIsJson, true)
|
||||
}[key].asStringOrNull
|
||||
} else {
|
||||
text.parseUrlEncodedParameters().also {
|
||||
attributes.put(partsKey, it)
|
||||
attributes.put(isJsonKey, false)
|
||||
attributes.put(keyParts, it)
|
||||
attributes.put(keyIsJson, false)
|
||||
}[key]
|
||||
}
|
||||
} // receiveText
|
||||
@ -170,17 +167,17 @@ suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostOrThrow(key: String)
|
||||
}
|
||||
|
||||
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 {
|
||||
if (!isJsonData()) return true
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (keyJsonObject in call.attributes) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(isJsonKey, true)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
call.attributes.put(keyIsJson, true)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if (!isJsonData()) return false
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if (!isJsonData()) return false
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
return data[key] is JsonArray
|
||||
}
|
||||
|
||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonString(key: String): String {
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
return data[key].asString
|
||||
}
|
||||
|
||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonElement(key: String): JsonElement {
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
return data[key]!!
|
||||
}
|
||||
|
||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObject(key: String): JsonObject {
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
return data[key].asJsonObject
|
||||
}
|
||||
|
||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonArray(key: String): JsonArray {
|
||||
val data = if (call.attributes.contains(jsonKey)) {
|
||||
call.attributes[jsonKey]
|
||||
suspend fun PipelineContext<Unit, ApplicationCall>.fetchPostJsonObjectOrNull(key: String): JsonObject? {
|
||||
val data = if (call.attributes.contains(keyJsonObject)) {
|
||||
call.attributes[keyJsonObject]
|
||||
} else {
|
||||
Json.parseToJsonElement(call.receiveText()).jsonObject.also {
|
||||
call.attributes.put(jsonKey, it)
|
||||
call.attributes.put(isJsonKey, true)
|
||||
call.attributes.put(keyJsonObject, it)
|
||||
}
|
||||
}
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user