Skip to content

Commit

Permalink
fix: CardMsgSender and AioChatPieClipPasteHook for QQNT
Browse files Browse the repository at this point in the history
  • Loading branch information
klxiaoniu committed Jul 21, 2023
1 parent b83edf5 commit c3b551c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 32 deletions.
4 changes: 3 additions & 1 deletion app/src/main/java/cc/hicore/hook/ReplyMsgWithImg.java
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ protected boolean initOnce() throws Exception {
Log.d("ReplyMsgWithImg PhotoListPanel.a chatPie is null");
return;
}

// TODO: NT版本请用getSessionByAIOParam()
Parcelable sessionInfo = InputButtonHookDispatcher.getSessionInfo(chatPie);
int isTroop = SessionInfoImpl.getUinType(sessionInfo);
if (isTroop == 1 || isTroop == 0) {
Expand Down Expand Up @@ -488,7 +490,7 @@ public static void addEditText(@NonNull EditText ed, @NonNull String text) {
}

@Override
public void onInitBaseChatPie(@NonNull Object baseChatPie, @NonNull ViewGroup aioRootView, @NonNull Parcelable session, @NonNull Context ctx,
public void onInitBaseChatPie(@NonNull Object baseChatPie, @NonNull ViewGroup aioRootView, @Nullable Parcelable session, @NonNull Context ctx,
@NonNull AppRuntime rt) {
mBaseChatPie = new WeakReference<>(Objects.requireNonNull(baseChatPie, "baseChatPie is null"));
EditText input = aioRootView.findViewById(ctx.getResources().getIdentifier("input", "id", ctx.getPackageName()));
Expand Down
14 changes: 7 additions & 7 deletions app/src/main/java/cc/ioctl/hook/msg/AioChatPieClipPasteHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
import androidx.core.view.ViewCompat;
import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat;
import cc.hicore.message.bridge.Chat_facade_bridge;
import cc.ioctl.util.SendCacheUtils;
import cc.ioctl.util.ui.FaultyDialog;
import cc.hicore.message.bridge.Chat_facade_bridge;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import io.github.qauxv.R;
Expand Down Expand Up @@ -150,7 +150,7 @@ protected void afterHookedMethod(MethodHookParam param) {

@Override
public void onInitBaseChatPie(@NonNull Object baseChatPie, @NonNull ViewGroup aioRootView,
@NonNull Parcelable session, @NonNull Context ctx, @NonNull AppRuntime rt) {
@Nullable Parcelable session, @NonNull Context ctx, @NonNull AppRuntime rt) {
int inputTextId = ctx.getResources().getIdentifier("input", "id", ctx.getPackageName());
EditText input = aioRootView.findViewById(inputTextId);
Objects.requireNonNull(input, "onInitBaseChatPie: findViewById R.id.input is null");
Expand All @@ -160,7 +160,7 @@ public void onInitBaseChatPie(@NonNull Object baseChatPie, @NonNull ViewGroup ai
if (item != null && item.getFirst().hasMimeType(MIME_IMAGE)) {
Uri uri = item.getSecond().getUri();
if (uri != null && "content".equals(uri.getScheme())) {
handleSendUriPicture(ctx, session, uri, aioRootView, rt);
handleSendUriPicture(ctx, session == null ? InputButtonHookDispatcher.INSTANCE.getSessionByAIOParam() : session, uri, aioRootView, rt);
return null;
}
}
Expand All @@ -173,7 +173,7 @@ public void onInitBaseChatPie(@NonNull Object baseChatPie, @NonNull ViewGroup ai
if (item != null && item.getFirst().hasMimeType(MIME_IMAGE)) {
Uri uri = item.getSecond().getUri();
if (uri != null && "content".equals(uri.getScheme())) {
handleSendUriPicture(ctx, session, uri, aioRootView, rt);
handleSendUriPicture(ctx, session == null ? InputButtonHookDispatcher.INSTANCE.getSessionByAIOParam() : session, uri, aioRootView, rt);
return true;
}
}
Expand Down Expand Up @@ -206,7 +206,7 @@ private static Pair<ClipDescription, Item> getClipDataItem0(@Nullable ClipData c
}

private static void handleSendUriPicture(@NonNull Context ctx, @NonNull Parcelable session, @NonNull Uri uri,
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
AtomicBoolean cpTimeout = new AtomicBoolean(true);
// call ContentResolver#openInputStream(Uri) asynchronously to avoid blocking UI thread
SyncUtils.async(() -> {
Expand Down Expand Up @@ -237,7 +237,7 @@ private static void handleSendUriPicture(@NonNull Context ctx, @NonNull Parcelab
}

private static void confirmSendMessage(@NonNull Context context, @NonNull Parcelable session, @NonNull byte[] data,
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Expand Down Expand Up @@ -270,7 +270,7 @@ private static void confirmSendMessage(@NonNull Context context, @NonNull Parcel
}

private static void executeSendMessage(@NonNull Context context, @NonNull Parcelable session, @NonNull byte[] data,
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
@NonNull ViewGroup aioRootView, @NonNull AppRuntime rt) {
try {
File file = SendCacheUtils.saveAsCacheFile(context, data);
Chat_facade_bridge.sendPic(session, file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,9 @@ import mqq.app.AppRuntime

interface IBaseChatPieInitDecorator : IBaseChatPieDecorator {
@Throws(Throwable::class)
fun onInitBaseChatPie(baseChatPie: Any, aioRootView: ViewGroup, session: Parcelable, ctx: Context, rt: AppRuntime)
/**
* On NT Version, param session is null, get it by calling InputButtonHookDispatcher.INSTANCE.getSessionByAIOParam().
* DO NOT call it right after onInitBaseChatPie, for it is not initialized before entering an AIO.
*/
fun onInitBaseChatPie(baseChatPie: Any, aioRootView: ViewGroup, session: Parcelable?, ctx: Context, rt: AppRuntime)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
import cc.hicore.QApp.QAppUtils;
import cc.hicore.ReflectUtil.MRes;
import cc.hicore.hook.ReplyMsgWithImg;
import cc.hicore.message.chat.SessionHooker;
import cc.hicore.message.chat.SessionUtils;
import cc.ioctl.hook.experimental.CardMsgSender;
import cc.ioctl.hook.msg.AioChatPieClipPasteHook;
import cc.ioctl.util.HookUtils;
import com.tencent.qqnt.kernel.nativeinterface.Contact;
import io.github.duzhaokun123.hook.SendTTSHook;
import io.github.qauxv.R;
import io.github.qauxv.base.annotation.FunctionHookEntry;
import io.github.qauxv.bridge.AppRuntimeHelper;
import io.github.qauxv.bridge.SessionInfoImpl;
import io.github.qauxv.bridge.ntapi.RelationNTUinAndUidApi;
import io.github.qauxv.hook.BaseHookDispatcher;
import io.github.qauxv.router.decorator.IBaseChatPieDecorator;
import io.github.qauxv.router.decorator.IBaseChatPieInitDecorator;
Expand Down Expand Up @@ -102,51 +106,67 @@ public boolean initOnce() throws Exception {
HookUtils.hookAfterIfEnabled(this, DexKit.requireMethodFromCache(AIO_InputRootInit_QQNT.INSTANCE), 40, param -> {
Button sendBtn = null;
EditText editText = null;
ViewGroup inputRoot = null;
Field[] fs = param.thisObject.getClass().getDeclaredFields();
for (Field f : fs) {
Class<?> type = f.getType();
if (type.equals(Button.class)) {
f.setAccessible(true);
if ("send_btn".equals(MRes.getViewResName((View) f.get(param.thisObject)))) {
sendBtn = (Button) f.get(param.thisObject);
}
sendBtn = (Button) f.get(param.thisObject);
} else if (type.equals(EditText.class)) {
f.setAccessible(true);
editText = (EditText) f.get(param.thisObject);
} else if (type.equals(ViewGroup.class)) {
f.setAccessible(true);
inputRoot = (ViewGroup) f.get(param.thisObject);
}
}

AppRuntime qqApp = AppRuntimeHelper.getAppRuntime();
Objects.requireNonNull(qqApp, "QQAppInterface is null");

if (sendBtn != null && editText != null) {
EditText finalEditText = editText;
Button finalSendBtn = sendBtn;
sendBtn.setOnLongClickListener(v -> {
Context ctx = v.getContext();
String text = finalEditText.getText().toString();
Toasts.info(ctx, text);
// TODO: AIOParam是不是onFunBtnLongClick的第二个参数?以及qqApp参数的获取
// if (((TextView) v).length() == 0) { //|| !CardMsgHook.INSTANCE.isEnabled()
// return false;
// }
// for (IBaseChatPieDecorator decorator : DECORATORS) {
// if (decorator instanceof IInputButtonDecorator) {
// IInputButtonDecorator d = (IInputButtonDecorator) decorator;
// try {
// if (d.isEnabled() && d.onFunBtnLongClick(text, (Parcelable) AIOParam, finalEditText, finalSendBtn, ctx, null)) {
// return true;
// }
// } catch (Throwable e) {
// decorator.traceError(e);
// }
// }
// }
// TODO: BaseChatPie已不存在,onInitBaseChatPie何去何从
for (IBaseChatPieDecorator decorator : DECORATORS) {
if (decorator instanceof IInputButtonDecorator) {
IInputButtonDecorator d = (IInputButtonDecorator) decorator;
try {
if (d.isEnabled() && d.onFunBtnLongClick(text, getSessionByAIOParam(), finalEditText, finalSendBtn, ctx, qqApp)) {
return true;
}
} catch (Throwable e) {
decorator.traceError(e);
}
}
}
return true;
});
} else {
Log.e("send_btn field not found");
Log.e("SendBtn or EditText field not found");
}

// 这样写比较好地兼容了原有代码,但不太像是onInitBaseChatPie的意思了,有待优化
Objects.requireNonNull(inputRoot, "inputRoot is null");
for (IBaseChatPieDecorator baseDecorator : DECORATORS) {
if (baseDecorator instanceof IBaseChatPieInitDecorator) {
IBaseChatPieInitDecorator decorator = (IBaseChatPieInitDecorator) baseDecorator;
try {
if (decorator.isEnabled()) {
decorator.onInitBaseChatPie(param.thisObject, inputRoot, null, inputRoot.getContext(), qqApp);
}
} catch (Throwable e) {
decorator.traceError(e);
}
}
}
});
return true;
}

//Begin: send btn
HookUtils.hookAfterIfEnabled(this, DexKit.requireMethodFromCache(NBaseChatPie_init.INSTANCE), 40,
param -> {
Expand Down Expand Up @@ -259,6 +279,19 @@ public boolean onLongClick(View v) {
return true;
}

/**
* QQNT: Get session info from AIOParam
*/
public Parcelable getSessionByAIOParam() {
Contact c = SessionUtils.AIOParam2Contact(AIOParam);
int type = c.getChatType() - 1; // chatType: 1 for friend, 2 for group
String uin = c.getPeerUid();
if (uin.startsWith("u_")) {
uin = RelationNTUinAndUidApi.getUinFromUid(uin);
}
return SessionInfoImpl.createSessionInfo(uin, type);
}

@Override
public boolean isEnabled() {
for (IBaseChatPieDecorator decorator : DECORATORS) {
Expand Down

0 comments on commit c3b551c

Please sign in to comment.