Shamrock: 雑談音声フラッシュバックの修正

This commit is contained in:
WhiteChi 2023-11-04 22:53:01 +08:00
parent 75dc5c0294
commit c8143bcf67
9 changed files with 61 additions and 44 deletions

View File

@ -61,8 +61,8 @@ const std::byte MD5::PADDING[64] = { (byte) 0x80 };
const char MD5::HEX[16] = { const char MD5::HEX[16] = {
'0', '1', '2', '3', '0', '1', '2', '3',
'4', '5', '6', '7', '4', '5', '6', '7',
'8', '9', 'a', 'b', '8', '9', 'A', 'B',
'c', 'd', 'e', 'f' 'C', 'D', 'E', 'F'
}; };

View File

@ -10,7 +10,6 @@ android {
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
} }
@ -36,7 +35,4 @@ dependencies {
implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0") implementation("com.google.android.material:material:1.9.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
} }

View File

@ -8,6 +8,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
import mqq.app.AppRuntime; import mqq.app.AppRuntime;
public class BaseTransFileController implements ITransFileController { public class BaseTransFileController implements ITransFileController {
@Override
public boolean containsProcessor(String name, long uin) {
return false;
}
@Override @Override
public IHttpCommunicatorListener findProcessor(String str) { public IHttpCommunicatorListener findProcessor(String str) {
return null; return null;

View File

@ -14,7 +14,7 @@ public interface ITransFileController extends IRuntimeService {
//@Deprecated //@Deprecated
//void addProcessor(String str, IHttpCommunicatorListener iHttpCommunicatorListener); //void addProcessor(String str, IHttpCommunicatorListener iHttpCommunicatorListener);
//boolean containsProcessor(String str, long j2); boolean containsProcessor(String name, long uin);
IHttpCommunicatorListener findProcessor(String str); IHttpCommunicatorListener findProcessor(String str);

View File

@ -13,7 +13,6 @@ android {
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
externalNativeBuild { externalNativeBuild {
cmake { cmake {
@ -50,6 +49,9 @@ android {
} }
dependencies { dependencies {
compileOnly ("de.robv.android.xposed:api:82")
compileOnly (project(":qqinterface"))
implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0") implementation("com.google.android.material:material:1.9.0")
@ -93,12 +95,5 @@ dependencies {
//ksp("androidx.room:room-compiler:$roomVersion") //ksp("androidx.room:room-compiler:$roomVersion")
// optional - Kotlin Extensions and Coroutines support for Room // optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$roomVersion") implementation("androidx.room:room-ktx:$roomVersion")
compileOnly ("de.robv.android.xposed:api:82")
compileOnly (project(":qqinterface"))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
} }

View File

@ -539,7 +539,7 @@ internal object MessageMaker {
file = FileUtils.parseAndSave(data["url"].asString) file = FileUtils.parseAndSave(data["url"].asString)
} }
if (!file.exists()) { if (!file.exists()) {
throw LogicException("Voice(${file.name}) file is not exists, please check your filename.") return Result.failure(LogicException("Voice(${file.name}) file is not exists, please check your filename."))
} }
val isMagic = data["magic"].asStringOrNull == "1" val isMagic = data["magic"].asStringOrNull == "1"
@ -580,11 +580,14 @@ internal object MessageMaker {
// QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath) // QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath)
//} //}
Transfer with when (chatType) { if(!(Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId) MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId) MsgConstant.KCHATTYPEC2C -> Private(peerId)
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> Private(peerId)
else -> error("Not supported chatType($chatType) for RecordMsg") else -> error("Not supported chatType($chatType) for RecordMsg")
} trans VoiceResource(file) } trans VoiceResource(file))) {
return Result.failure(RuntimeException("上传语音失败: $file"))
}
val elem = MsgElement() val elem = MsgElement()
elem.elementType = MsgConstant.KELEMTYPEPTT elem.elementType = MsgConstant.KELEMTYPEPTT

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.shamrock.utils.MD5 import moe.fuqiuluo.shamrock.utils.MD5
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
import mqq.app.AppRuntime import mqq.app.AppRuntime
@ -73,30 +74,34 @@ internal abstract class FileTransfer {
transferRequest: TransferRequest, transferRequest: TransferRequest,
wait: Boolean wait: Boolean
): Boolean { ): Boolean {
val service = runtime.getRuntimeService(ITransFileController::class.java, "all") return withTimeoutOrNull(60_000) {
if(service.transferAsync(transferRequest)) { val service = runtime.getRuntimeService(ITransFileController::class.java, "all")
if (!wait) { // 如果无需等待直接返回 if(service.transferAsync(transferRequest)) {
return true if (!wait) { // 如果无需等待直接返回
} return@withTimeoutOrNull true
return suspendCancellableCoroutine { continuation -> }
val waiter = GlobalScope.launch { suspendCancellableCoroutine { continuation ->
while ( GlobalScope.launch {
service.findProcessor(transferRequest.keyForTransfer) != null while (
// 如果上传处理器依旧存在,说明没有上传成功 //service.findProcessor(
) { // transferRequest.keyForTransfer // uin + uniseq
delay(100) //) != null
service.containsProcessor(runtime.currentAccountUin, transferRequest.mUniseq)
// 如果上传处理器依旧存在,说明没有上传成功
&& service.isWorking.get()
) {
delay(100)
}
continuation.resume(true)
}
// 实现取消上传器
// 目前没什么用
continuation.invokeOnCancellation {
continuation.resume(false)
} }
continuation.resume(true)
} }
// 实现取消上传器 } else false
// 目前没什么用 } ?: false
continuation.invokeOnCancellation {
waiter.cancel()
continuation.resume(false)
}
}
}
return false
} }
companion object { companion object {

View File

@ -24,12 +24,12 @@ internal object Transfer: FileTransfer() {
) )
suspend fun uploadC2CVideo( suspend fun uploadC2CVideo(
groupId: String, userId: String,
file: File, file: File,
thumb: File, thumb: File,
wait: Boolean = true wait: Boolean = true
): Boolean { ): Boolean {
return transC2CResource(groupId, file, FileMsg.TRANSFILE_TYPE_SHORT_VIDEO_C2C, BUSI_TYPE_SHORT_VIDEO, wait) { return transC2CResource(userId, file, FileMsg.TRANSFILE_TYPE_SHORT_VIDEO_C2C, BUSI_TYPE_SHORT_VIDEO, wait) {
it.mSourceVideoCodecFormat = VIDEO_FORMAT_MP4 it.mSourceVideoCodecFormat = VIDEO_FORMAT_MP4
it.mRec = MessageForShortVideo().also { it.mRec = MessageForShortVideo().also {
it.busiType = BUSI_TYPE_SHORT_VIDEO it.busiType = BUSI_TYPE_SHORT_VIDEO
@ -56,11 +56,11 @@ internal object Transfer: FileTransfer() {
} }
suspend fun uploadC2CVoice( suspend fun uploadC2CVoice(
groupId: String, userId: String,
file: File, file: File,
wait: Boolean = true wait: Boolean = true
): Boolean { ): Boolean {
return transC2CResource(groupId, file, FileMsg.TRANSFILE_TYPE_PTT, 1002, wait) { return transC2CResource(userId, file, FileMsg.TRANSFILE_TYPE_PTT, 1002, wait) {
it.mPttUploadPanel = 3 it.mPttUploadPanel = 3
it.mPttCompressFinish = true it.mPttCompressFinish = true
it.mIsPttPreSend = true it.mIsPttPreSend = true

View File

@ -2,6 +2,7 @@
package moe.fuqiuluo.shamrock.xposed.actions package moe.fuqiuluo.shamrock.xposed.actions
import android.content.Context import android.content.Context
import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import moe.fuqiuluo.shamrock.tools.hookMethod import moe.fuqiuluo.shamrock.tools.hookMethod
@ -12,12 +13,24 @@ class AntiDetection: IAction {
override fun invoke(ctx: Context) { override fun invoke(ctx: Context) {
antiTrace() antiTrace()
antiMemoryWalking() antiMemoryWalking()
antiFindPackage()
} }
val isModuleStack = fun String.(): Boolean { val isModuleStack = fun String.(): Boolean {
return contains("fuqiuluo") || contains("shamrock") || contains("whitechi") || contains("lsposed") || contains("xposed") return contains("fuqiuluo") || contains("shamrock") || contains("whitechi") || contains("lsposed") || contains("xposed")
} }
private fun antiFindPackage() {
//PackageManager::class.java.hookMethod("getApplicationInfo").before {
// val packageName = it.args[0] as String
// if(packageName == "moe.fuqiuluo.shamrock") {
// it.throwable = PackageManager.NameNotFoundException()
// } else if (packageName == "moe.fuqiuluo.shamrock.hided") {
// it.args[0] = "moe.fuqiuluo.shamrock"
// }
//}
}
private fun antiMemoryWalking() { private fun antiMemoryWalking() {
val c = Class.forName("dalvik.system.VMDebug") val c = Class.forName("dalvik.system.VMDebug")
//val startMethodTracingMethod = c.getDeclaredMethod( //val startMethodTracingMethod = c.getDeclaredMethod(