fix: sticker panel save pic
This commit is contained in:
@@ -238,6 +238,7 @@ dependencies {
|
||||
implementation(libs.byte.buddy)
|
||||
implementation(libs.dalvik.dx)
|
||||
ksp(libs.sealedEnum.ksp)
|
||||
implementation(libs.google.protobuf)
|
||||
}
|
||||
|
||||
val adb: String = androidComponents.sdkComponents.adb.get().asFile.absolutePath
|
||||
|
||||
141
app/src/main/java/cc/hicore/Utils/FunProtoData.java
Normal file
141
app/src/main/java/cc/hicore/Utils/FunProtoData.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package cc.hicore.Utils;
|
||||
|
||||
import com.google.protobuf.CodedInputStream;
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import io.github.qauxv.util.Log;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class FunProtoData {
|
||||
private final HashMap<Integer, List<Object>> values = new HashMap<>();
|
||||
public void fromJSON(JSONObject json){
|
||||
try {
|
||||
Iterator<String> key_it = json.keys();
|
||||
while (key_it.hasNext()){
|
||||
String key = key_it.next();
|
||||
int k = Integer.parseInt(key);
|
||||
Object value = json.get(key);
|
||||
if (value instanceof JSONObject){
|
||||
FunProtoData newProto = new FunProtoData();
|
||||
newProto.fromJSON((JSONObject) value);
|
||||
putValue(k, newProto);
|
||||
}else if (value instanceof JSONArray){
|
||||
JSONArray arr = (JSONArray) value;
|
||||
for (int i=0;i < arr.length(); i++){
|
||||
Object arr_obj = arr.get(i);
|
||||
if (arr_obj instanceof JSONObject){
|
||||
FunProtoData newProto = new FunProtoData();
|
||||
newProto.fromJSON((JSONObject) arr_obj);
|
||||
putValue(k, newProto);
|
||||
}else {
|
||||
putValue(k, arr_obj);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
putValue(k, value);
|
||||
}
|
||||
}
|
||||
}catch (Exception ignored){ }
|
||||
}
|
||||
private void putValue(int key, Object value){
|
||||
List<Object> list = values.computeIfAbsent(key, k -> new ArrayList<>());
|
||||
list.add(value);
|
||||
}
|
||||
public void fromBytes(byte[] b) throws IOException {
|
||||
CodedInputStream in = CodedInputStream.newInstance(b);
|
||||
while (in.getBytesUntilLimit() > 0){
|
||||
int tag = in.readTag();
|
||||
int fieldNumber = tag >>> 3;
|
||||
int wireType = tag & 7;
|
||||
if (wireType == 4 || wireType == 3 || wireType > 5) throw new IOException("Unexpected wireType: "+wireType);
|
||||
switch (wireType){
|
||||
case 0:
|
||||
putValue(fieldNumber, in.readInt64());
|
||||
break;
|
||||
case 1:
|
||||
putValue(fieldNumber, in.readRawVarint64());
|
||||
break;
|
||||
case 2:
|
||||
byte[] subBytes = in.readByteArray();
|
||||
try {
|
||||
FunProtoData sub_data = new FunProtoData();
|
||||
sub_data.fromBytes(subBytes);
|
||||
putValue(fieldNumber, sub_data);
|
||||
}catch (Exception e){
|
||||
putValue(fieldNumber, new String(subBytes));
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
putValue(fieldNumber, in.readFixed32());
|
||||
break;
|
||||
default:
|
||||
putValue(fieldNumber,"Unknown wireType: "+wireType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public JSONObject toJSON()throws Exception{
|
||||
JSONObject obj = new JSONObject();
|
||||
for (Integer k_index : values.keySet()){
|
||||
List<?> list = values.get(k_index);
|
||||
if (list.size() > 1){
|
||||
JSONArray arr = new JSONArray();
|
||||
for (Object o : list){
|
||||
arr.put(valueToText(o));
|
||||
}
|
||||
obj.put(String.valueOf(k_index), arr);
|
||||
}else {
|
||||
for (Object o : list){
|
||||
obj.put(String.valueOf(k_index), valueToText(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
private Object valueToText(Object value) throws Exception {
|
||||
if (value instanceof FunProtoData){
|
||||
FunProtoData data = (FunProtoData) value;
|
||||
return data.toJSON();
|
||||
}else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
public byte[] toBytes(){
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
CodedOutputStream out = CodedOutputStream.newInstance(bos);
|
||||
try {
|
||||
for (Integer k_index : values.keySet()){
|
||||
List<?> list = values.get(k_index);
|
||||
for (Object o : list){
|
||||
if (o instanceof Long){
|
||||
long l = (long) o;
|
||||
out.writeInt64(k_index , l);
|
||||
}else if (o instanceof String){
|
||||
String s = (String) o;
|
||||
out.writeByteArray(k_index , s.getBytes());
|
||||
}else if (o instanceof FunProtoData){
|
||||
FunProtoData data = (FunProtoData) o;
|
||||
byte[] subBytes = data.toBytes();
|
||||
out.writeByteArray(k_index , subBytes);
|
||||
}else if (o instanceof Integer){
|
||||
int i = (int) o;
|
||||
out.writeInt32(k_index, i);
|
||||
}else {
|
||||
Log.w("FunProtoData.toBytes "+ "Unknown type: " + o.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
return bos.toByteArray();
|
||||
}catch (Exception e){
|
||||
XLog.e("FunProtoData", "toBytes", e);
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,10 @@ import android.widget.ImageView;
|
||||
import androidx.annotation.NonNull;
|
||||
import cc.hicore.QApp.QAppUtils;
|
||||
import cc.hicore.ReflectUtil.MRes;
|
||||
import cc.hicore.ReflectUtil.XField;
|
||||
import cc.hicore.ReflectUtil.XMethod;
|
||||
import cc.hicore.Utils.FunConf;
|
||||
import cc.hicore.Utils.FunProtoData;
|
||||
import cc.hicore.Utils.XLog;
|
||||
import cc.hicore.hook.stickerPanel.ICreator;
|
||||
import cc.hicore.hook.stickerPanel.PanelUtils;
|
||||
@@ -38,6 +40,8 @@ import cc.hicore.message.chat.SessionHooker;
|
||||
import cc.hicore.message.chat.SessionUtils;
|
||||
import cc.ioctl.util.HookUtils;
|
||||
import cc.ioctl.util.Reflex;
|
||||
import com.tencent.qphone.base.remote.FromServiceMsg;
|
||||
import com.tencent.qphone.base.remote.ToServiceMsg;
|
||||
import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgService;
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement;
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord;
|
||||
@@ -63,8 +67,10 @@ import io.github.qauxv.util.dexkit.Guild_Emo_Btn_Create_QQNT;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import kotlin.Unit;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@FunctionHookEntry
|
||||
@UiItemAgentEntry
|
||||
@@ -78,6 +84,8 @@ public class StickerPanelEntryHooker extends CommonSwitchFunctionHook implements
|
||||
Guild_Emo_Btn_Create_QQNT.INSTANCE
|
||||
});
|
||||
}
|
||||
public static String rkey_group;
|
||||
public static String rkey_private;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@@ -193,9 +201,9 @@ public class StickerPanelEntryHooker extends CommonSwitchFunctionHook implements
|
||||
}else {
|
||||
if (originUrl.startsWith("/download")){
|
||||
if (originUrl.contains("appid=1406")){
|
||||
urls.add("https://multimedia.nt.qq.com.cn" + originUrl + "&rkey=CAQSKDOc_jvbthUjAatuFPQIo-x9wwcDhDGd8SOEu5FyJWNxNMabJTTRpO8");
|
||||
urls.add("https://multimedia.nt.qq.com.cn" + originUrl + rkey_group);
|
||||
}else {
|
||||
urls.add("https://multimedia.nt.qq.com.cn" + originUrl + "&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64");
|
||||
urls.add("https://multimedia.nt.qq.com.cn" + originUrl + rkey_private);
|
||||
}
|
||||
}else {
|
||||
urls.add("https://gchat.qpic.cn"+picElement.getOriginImageUrl());
|
||||
@@ -261,9 +269,47 @@ public class StickerPanelEntryHooker extends CommonSwitchFunctionHook implements
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
//Hook for rkey
|
||||
|
||||
HookUtils.hookBeforeIfEnabled(this, XMethod.clz("mqq.app.msghandle.MsgRespHandler").name("dispatchRespMsg").ignoreParam().get(), param -> {
|
||||
ToServiceMsg serviceMsg = XField.obj(param.args[1]).name("toServiceMsg").get();
|
||||
FromServiceMsg fromServiceMsg = XField.obj(param.args[1]).name("fromServiceMsg").get();
|
||||
|
||||
if ("OidbSvcTrpcTcp.0x9067_202".equals(fromServiceMsg.getServiceCmd())){
|
||||
FunProtoData data = new FunProtoData();
|
||||
data.fromBytes(getUnpPackage(fromServiceMsg.getWupBuffer()));
|
||||
|
||||
JSONObject obj = data.toJSON();
|
||||
rkey_group = obj.getJSONObject("4")
|
||||
.getJSONObject("4")
|
||||
.getJSONArray("1")
|
||||
.getJSONObject(0).getString("1");
|
||||
|
||||
rkey_private = obj.getJSONObject("4")
|
||||
.getJSONObject("4")
|
||||
.getJSONArray("1")
|
||||
.getJSONObject(1).getString("1");
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static byte[] getUnpPackage(byte[] b){
|
||||
if (b == null){
|
||||
return null;
|
||||
}
|
||||
if (b.length < 4){
|
||||
return b;
|
||||
}
|
||||
if (b[0] == 0){
|
||||
return Arrays.copyOfRange(b, 4, b.length);
|
||||
}else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
@@ -43,6 +43,7 @@ byte-buddy = { module = "net.bytebuddy:byte-buddy", version = "1.14.14" }
|
||||
dalvik-dx = { module = "com.jakewharton.android.repackaged:dalvik-dx", version = "14.0.0_r21" }
|
||||
flatbuffers-java = { module = "com.google.flatbuffers:flatbuffers-java", version = "23.5.26" }
|
||||
davemorrissey-subsampling-scale-image-view = { module = "com.davemorrissey.labs:subsampling-scale-image-view-androidx", version = "3.10.0" }
|
||||
google-protobuf = { module = "com.google.protobuf:protobuf-java", version = "4.26.1" }
|
||||
|
||||
[plugins]
|
||||
changelog = { id = "org.jetbrains.changelog", version = "2.2.0" }
|
||||
|
||||
Reference in New Issue
Block a user