mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: support requestUploadGroupPic
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
68ea62ea0b
commit
720313124c
21
app/proguard-rules.pro
vendored
21
app/proguard-rules.pro
vendored
@ -199,17 +199,36 @@
|
|||||||
|
|
||||||
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
|
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
|
||||||
|
|
||||||
-keep class moe.fuqiuluo.** { *; }
|
-keep class moe.fuqiuluo.shamrock.app.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.ui.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.MainActivity { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.MainActivityKt { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.Manifest { *; }
|
||||||
|
|
||||||
|
-keep class moe.fuqiuluo.shamrock.xposed.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.helper.** { *; }
|
||||||
|
|
||||||
|
# tencent interfaces rules
|
||||||
-keep class com.tencent.** { *; }
|
-keep class com.tencent.** { *; }
|
||||||
-keep class com.qq.** { *; }
|
-keep class com.qq.** { *; }
|
||||||
-keep class com.google.gson.** { *; }
|
-keep class com.google.gson.** { *; }
|
||||||
-keep class de.** { *; }
|
-keep class de.** { *; }
|
||||||
|
-keep class epic.** { *; }
|
||||||
|
-keep class friendlist.** { *; }
|
||||||
|
-keep class KQQ.** { *; }
|
||||||
-keep class mqq.** { *; }
|
-keep class mqq.** { *; }
|
||||||
|
-keep class msf.** { *; }
|
||||||
|
-keep class oicq.** { *; }
|
||||||
-keep class QQService.** { *; }
|
-keep class QQService.** { *; }
|
||||||
-keep class SummaryCard.** { *; }
|
-keep class SummaryCard.** { *; }
|
||||||
-keep class tencent.** { *; }
|
-keep class tencent.** { *; }
|
||||||
|
-keep class VIP.** { *; }
|
||||||
|
|
||||||
-keepclassmembers class * {
|
-keepclassmembers class * {
|
||||||
native <methods>;
|
native <methods>;
|
||||||
}
|
}
|
||||||
-keep class io.netty.** { *; }
|
-keep class io.netty.** { *; }
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ data class NotOnlineImage(
|
|||||||
@ProtoNumber(7) val picMd5: ByteArray? = null,
|
@ProtoNumber(7) val picMd5: ByteArray? = null,
|
||||||
@ProtoNumber(8) val picHeight: UInt? = null,
|
@ProtoNumber(8) val picHeight: UInt? = null,
|
||||||
@ProtoNumber(9) val picWidth: UInt? = null,
|
@ProtoNumber(9) val picWidth: UInt? = null,
|
||||||
@ProtoNumber(10) val resId: ByteArray? = null,
|
@ProtoNumber(10) val resId: ByteArray? = null, // md5 + ".jpg"
|
||||||
@ProtoNumber(11) val flag: ByteArray? = null,
|
@ProtoNumber(11) val flag: ByteArray? = null,
|
||||||
@ProtoNumber(12) val thumbUrl: String? = null,
|
@ProtoNumber(12) val thumbUrl: String? = null,
|
||||||
@ProtoNumber(13) val original: UInt? = null,
|
@ProtoNumber(13) val original: UInt? = null,
|
||||||
|
63
protobuf/src/main/java/protobuf/oidb/cmd0x388/Cmd0x388Req.kt
Normal file
63
protobuf/src/main/java/protobuf/oidb/cmd0x388/Cmd0x388Req.kt
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package protobuf.oidb.cmd0x388
|
||||||
|
|
||||||
|
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Cmd0x388ReqBody(
|
||||||
|
@ProtoNumber(1) var netType: Int = 0,
|
||||||
|
@ProtoNumber(2) var subCmd: Int = 0,
|
||||||
|
@ProtoNumber(3) var msgTryUpImg: ArrayList<TryUpImgReq>? = null,
|
||||||
|
// @ProtoNumber(4) var rpt_msg_getimg_url_req: ArrayList<GetImgUrlReq>? = null,
|
||||||
|
@ProtoNumber(5) var msgTryUpPttReq: ArrayList<TryUpPttReq>? = null,
|
||||||
|
// @ProtoNumber(6) var msgGetPttUrlReq: ArrayList<GetPttUrlReq>? = null,
|
||||||
|
@ProtoNumber(7) var commandId: Int = 0,
|
||||||
|
// @ProtoNumber(8) var rpt_msg_del_img_req: ArrayList<DelImgReq>? = null,
|
||||||
|
@ProtoNumber(1001) var extension: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
): Protobuf<Cmd0x388ReqBody>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TryUpImgReq(
|
||||||
|
@ProtoNumber(1) var groupCode: Long = 0,
|
||||||
|
@ProtoNumber(2) var srcUin: Long = 0,
|
||||||
|
@ProtoNumber(3) var fileId: Long? = null,
|
||||||
|
@ProtoNumber(4) var fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(5) var fileSize: Long = 0,
|
||||||
|
@ProtoNumber(6) var fileName: String = "",
|
||||||
|
@ProtoNumber(7) var srcTerm: Int = 0,
|
||||||
|
@ProtoNumber(8) var platformType: Int = 0,
|
||||||
|
@ProtoNumber(9) var buType: Int = 0,
|
||||||
|
@ProtoNumber(10) var picWidth: Int = 0,
|
||||||
|
@ProtoNumber(11) var picHeight: Int = 0,
|
||||||
|
@ProtoNumber(12) var picType: Int = 0,
|
||||||
|
@ProtoNumber(13) var buildVer: String = "",
|
||||||
|
@ProtoNumber(14) var innerIp: Int = 0,
|
||||||
|
@ProtoNumber(15) var appPicType: Int = 0,
|
||||||
|
@ProtoNumber(16) var originalPic: Int = 0,
|
||||||
|
@ProtoNumber(17) var fileIndex: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(18) var dstUin: Long = 0,
|
||||||
|
@ProtoNumber(19) var srvUpload: Int? = null,
|
||||||
|
@ProtoNumber(20) var transferUrl: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TryUpPttReq(
|
||||||
|
@ProtoNumber(1) var groupCode: Long = 0,
|
||||||
|
@ProtoNumber(2) var srcUin: Long = 0,
|
||||||
|
@ProtoNumber(3) var fileId: Long = 0,
|
||||||
|
@ProtoNumber(4) var fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(5) var fileSize: Long = 0,
|
||||||
|
@ProtoNumber(6) var fileName: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(7) var srcTerm: Int = 0,
|
||||||
|
@ProtoNumber(8) var platformType: Int = 0,
|
||||||
|
@ProtoNumber(9) var buType: Int = 0,
|
||||||
|
@ProtoNumber(10) var buildVer: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(11) var innerIp: Int = 0,
|
||||||
|
@ProtoNumber(12) var voiceLength: Int = 0,
|
||||||
|
@ProtoNumber(13) var newUpChan: Boolean = false,
|
||||||
|
@ProtoNumber(14) var codec: Int = 0,
|
||||||
|
@ProtoNumber(15) var voiceType: Int = 0,
|
||||||
|
@ProtoNumber(16) var buId: Int = 0,
|
||||||
|
)
|
78
protobuf/src/main/java/protobuf/oidb/cmd0x388/Cmd0x388Rsp.kt
Normal file
78
protobuf/src/main/java/protobuf/oidb/cmd0x388/Cmd0x388Rsp.kt
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
|
package protobuf.oidb.cmd0x388
|
||||||
|
|
||||||
|
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Cmd0x388RspBody(
|
||||||
|
@ProtoNumber(1) var clientIp: UInt = 0u,
|
||||||
|
@ProtoNumber(2) var subCmd: UInt = 0u,
|
||||||
|
@ProtoNumber(3) var msgTryUpImgRsp: ArrayList<TryUpImgRsp>? = null,
|
||||||
|
@ProtoNumber(5) var msgTryUpPttRsp: ArrayList<TryUpPttRsp>? = null,
|
||||||
|
): Protobuf<Cmd0x388RspBody>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TryUpPttRsp(
|
||||||
|
@ProtoNumber(1) var fileId: Long = 0,
|
||||||
|
@ProtoNumber(2) var result: Int = 0,
|
||||||
|
@ProtoNumber(3) var failMsg: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(4) var fileExit: Boolean = false,
|
||||||
|
@ProtoNumber(5) var upIp: List<Int>? = null,
|
||||||
|
@ProtoNumber(6) var upPort: List<Int>? = null,
|
||||||
|
@ProtoNumber(7) var upUkey: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(8) var fileid: Long = 0,
|
||||||
|
@ProtoNumber(9) var upOffset: Long = 0,
|
||||||
|
@ProtoNumber(10) var blockSize: Long = 0,
|
||||||
|
@ProtoNumber(11) var fileKey: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(12) var channelType: Int = 0,
|
||||||
|
@ProtoNumber(26) var msgUpIp6: ArrayList<IPv6Info>? = null,
|
||||||
|
@ProtoNumber(27) var clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
): Protobuf<TryUpPttRsp>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TryUpImgRsp(
|
||||||
|
@ProtoNumber(1) var extFileId: ULong = 0u, // 没有实际作用
|
||||||
|
@ProtoNumber(2) var result: UInt = 0u,
|
||||||
|
@ProtoNumber(3) var faiMsg: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(4) var fileExist: Boolean = false,
|
||||||
|
@ProtoNumber(5) var msgImgInfo: ImgInfo? = null, // 里面只是一堆垃圾
|
||||||
|
@ProtoNumber(6) var upIp: ArrayList<Long>? = null,
|
||||||
|
@ProtoNumber(7) var upPort: ArrayList<Int>? = null,
|
||||||
|
@ProtoNumber(8) var ukey: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(9) var fileId: Long = 0,
|
||||||
|
@ProtoNumber(10) var upOffset: ULong = 0u,
|
||||||
|
@ProtoNumber(11) var blockSize: Long = 0,
|
||||||
|
@ProtoNumber(12) var bool_new_big_chan: Boolean = false,
|
||||||
|
@ProtoNumber(26) var rpt_msg_up_ip6: ArrayList<IPv6Info>? = null,
|
||||||
|
@ProtoNumber(27) var client_ip6: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(1001) var msg_info4busi: TryUpInfo4Busi? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TryUpInfo4Busi(
|
||||||
|
@ProtoNumber(1) var down_domain: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(2) var thumb_down_url: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(3) var original_down_url: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(4) var big_down_url: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(5) var file_resid: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class IPv6Info(
|
||||||
|
@ProtoNumber(1) var ip6: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(2) var port: UInt = 0u,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ImgInfo(
|
||||||
|
@ProtoNumber(1) var file_md5: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(2) var file_type: UInt = 0u,
|
||||||
|
@ProtoNumber(3) var file_size: ULong = 0u,
|
||||||
|
@ProtoNumber(4) var file_width: UInt = 0u,
|
||||||
|
@ProtoNumber(5) var file_height: UInt = 0u,
|
||||||
|
)
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.tencent.mobileqq.data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MessageForPic extends MessageRecord {
|
||||||
|
public String SpeedInfo;
|
||||||
|
public String actMsgContentValue;
|
||||||
|
public String action;
|
||||||
|
public String bigMsgUrl;
|
||||||
|
public String bigThumbMsgUrl;
|
||||||
|
public int busiType;
|
||||||
|
public int fileSizeFlag;
|
||||||
|
public long groupFileID;
|
||||||
|
public long height;
|
||||||
|
public int imageType;
|
||||||
|
public boolean isInMixedMsg;
|
||||||
|
public boolean isMixed;
|
||||||
|
public boolean isRead;
|
||||||
|
public boolean isShareAppActionMsg;
|
||||||
|
public String localUUID;
|
||||||
|
public int mCurrlength;
|
||||||
|
public int mDownloadLength;
|
||||||
|
public long mPresendTransferedSize;
|
||||||
|
public int mShowLength;
|
||||||
|
public String md5;
|
||||||
|
//@RecordForTest
|
||||||
|
// public msg_ctrl$MsgCtrl msgCtrl;
|
||||||
|
public int msgVia;
|
||||||
|
public int ntChatType;
|
||||||
|
public String ntPeerUid;
|
||||||
|
public String path;
|
||||||
|
//public PicMessageExtraData picExtraData;
|
||||||
|
public int picExtraFlag;
|
||||||
|
public Object picExtraObject;
|
||||||
|
public int previewed;
|
||||||
|
public String rawMsgUrl;
|
||||||
|
/// public ReportInfo reportInfo;
|
||||||
|
//public MsgRecordParams rootMsgRecordParams;
|
||||||
|
public String serverStoreSource;
|
||||||
|
public long shareAppID;
|
||||||
|
public long size;
|
||||||
|
public long subTypeId;
|
||||||
|
public int thumbHeight;
|
||||||
|
public String thumbMsgUrl;
|
||||||
|
public int thumbWidth;
|
||||||
|
//public ThumbWidthHeightDP thumbWidthHeightDP;
|
||||||
|
public int type;
|
||||||
|
public String uuid;
|
||||||
|
public long width;
|
||||||
|
public boolean isDownStatusReady = false;
|
||||||
|
public int subMsgId = 0;
|
||||||
|
public int isReport = 0;
|
||||||
|
public int subVersion = 5;
|
||||||
|
public int preDownState = -1;
|
||||||
|
public int preDownNetworkType = -1;
|
||||||
|
public long DSKey = 0;
|
||||||
|
public int mNotPredownloadReason = 0;
|
||||||
|
public int subThumbWidth = -1;
|
||||||
|
public int subThumbHeight = -1;
|
||||||
|
public int aiofileType = -1;
|
||||||
|
public int subMsgType = -1;
|
||||||
|
public boolean bEnableEnc = false;
|
||||||
|
public int thumbSize = -1;
|
||||||
|
public boolean isBlessPic = false;
|
||||||
|
public boolean sync2Story = false;
|
||||||
|
public boolean isQzonePic = false;
|
||||||
|
public boolean isStoryPhoto = false;
|
||||||
|
public long replyRealSourceMsgId = -1;
|
||||||
|
|
||||||
|
public String toLogString() {
|
||||||
|
return "path:" + this.path + ",uuid:" + this.uuid + ",md5:" + this.md5 + ",size:" + this.size + ",groupFileID:" + this.groupFileID;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package com.tencent.mobileqq.transfile;
|
package com.tencent.mobileqq.transfile;
|
||||||
|
|
||||||
public class BaseTransProcessor {
|
import com.tencent.mobileqq.utils.httputils.IHttpCommunicatorListener;
|
||||||
|
|
||||||
|
public class BaseTransProcessor implements IHttpCommunicatorListener {
|
||||||
public FileMsg file;
|
public FileMsg file;
|
||||||
|
|
||||||
public long getFileStatus() {
|
public long getFileStatus() {
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.tencent.mobileqq.transfile;
|
||||||
|
|
||||||
|
public class BaseUploadProcessor extends BaseTransProcessor {
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
package com.tencent.mobileqq.transfile;
|
package com.tencent.mobileqq.transfile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class FileMsg {
|
public class FileMsg {
|
||||||
public static final int STATUS_FILE_EXPIRED = 5002;
|
public static final int STATUS_FILE_EXPIRED = 5002;
|
||||||
public static final int STATUS_FILE_TRANSFERING = 5000;
|
public static final int STATUS_FILE_TRANSFERING = 5000;
|
||||||
@ -107,4 +111,58 @@ public class FileMsg {
|
|||||||
public static final int UIN_BUDDY = 0;
|
public static final int UIN_BUDDY = 0;
|
||||||
public static final int UIN_DISCUSS = 2;
|
public static final int UIN_DISCUSS = 2;
|
||||||
public static final int UIN_TROOP = 1;
|
public static final int UIN_TROOP = 1;
|
||||||
|
|
||||||
|
public String domain;
|
||||||
|
public String downDomain;
|
||||||
|
public long endTime;
|
||||||
|
public int errorCode;
|
||||||
|
public String errorMessage;
|
||||||
|
public File file;
|
||||||
|
public long fileID;
|
||||||
|
public String fileKey;
|
||||||
|
public String fileMd5;
|
||||||
|
public String filePath;
|
||||||
|
public long fileSize;
|
||||||
|
public int fileType;
|
||||||
|
public String fileUrl;
|
||||||
|
public String forwardTaskKey;
|
||||||
|
public String friendUin;
|
||||||
|
public int isRead;
|
||||||
|
public boolean isStreamMode;
|
||||||
|
public int lastStatus;
|
||||||
|
public byte[] localFileMd5;
|
||||||
|
public String logTag;
|
||||||
|
public long mSecMsgId;
|
||||||
|
public long mSubMsgId;
|
||||||
|
public String mUin;
|
||||||
|
public String msgImageData;
|
||||||
|
public String msgTime;
|
||||||
|
public String orgiDownUrl;
|
||||||
|
public String peerUin;
|
||||||
|
public int picScale;
|
||||||
|
public long picThumbSize;
|
||||||
|
public BaseTransProcessor processor;
|
||||||
|
public boolean processorDoReportSelf;
|
||||||
|
public int pttSlicePos;
|
||||||
|
public String pttSliceText;
|
||||||
|
public OutputStream revStream;
|
||||||
|
public String selfUin;
|
||||||
|
public InputStream sendStream;
|
||||||
|
public String serverPath;
|
||||||
|
public long startTime;
|
||||||
|
public int status;
|
||||||
|
public long stepUrlCost;
|
||||||
|
public String suffixType;
|
||||||
|
public String thumbDownUrl;
|
||||||
|
public String thumbPath;
|
||||||
|
public String thumbUrl;
|
||||||
|
public String tmpFilePath;
|
||||||
|
public byte[] transferData;
|
||||||
|
public long transferedSize;
|
||||||
|
public String uKey;
|
||||||
|
public int uinType;
|
||||||
|
public long uniseq;
|
||||||
|
public String[] urls;
|
||||||
|
public byte[] userInfo;
|
||||||
|
public String uuidPath;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
package com.tencent.mobileqq.transfile;
|
package com.tencent.mobileqq.transfile;
|
||||||
|
|
||||||
public class GroupPicUploadProcessor {
|
import com.tencent.mobileqq.utils.httputils.IHttpCommunicatorListener;
|
||||||
|
|
||||||
|
public class GroupPicUploadProcessor extends BaseUploadProcessor {
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,8 @@ public final class PicElement implements IKernelModel {
|
|||||||
this.isFlashPic = bool;
|
this.isFlashPic = bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStoreID(int i2) {
|
||||||
|
}
|
||||||
public void setMd5HexStr(String str) {
|
public void setMd5HexStr(String str) {
|
||||||
this.md5HexStr = str;
|
this.md5HexStr = str;
|
||||||
}
|
}
|
||||||
|
178
xposed/proguard-rules.pro
vendored
178
xposed/proguard-rules.pro
vendored
@ -19,181 +19,3 @@
|
|||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
|
||||||
# Never inline methods, but allow shrinking and obfuscation.
|
|
||||||
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.ViewCompat$Api* {
|
|
||||||
<methods>;
|
|
||||||
}
|
|
||||||
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.WindowInsetsCompat$*Impl* {
|
|
||||||
<methods>;
|
|
||||||
}
|
|
||||||
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.app.NotificationCompat$*$Api*Impl {
|
|
||||||
<methods>;
|
|
||||||
}
|
|
||||||
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.os.UserHandleCompat$Api*Impl {
|
|
||||||
<methods>;
|
|
||||||
}
|
|
||||||
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.widget.EdgeEffectCompat$Api*Impl {
|
|
||||||
<methods>;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep metadata about inner emulated classes. This helps with
|
|
||||||
# reflection on older platforms, but can be omitted if the
|
|
||||||
# metadata usage is not present in the app.
|
|
||||||
|
|
||||||
-keepclassmembers class * {
|
|
||||||
** CREATOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep the special static methods that are required in all enumeration
|
|
||||||
# classes.
|
|
||||||
-keepclassmembers enum * {
|
|
||||||
public static **[] values();
|
|
||||||
public static ** valueOf(java.lang.String);
|
|
||||||
}
|
|
||||||
|
|
||||||
-keep public class androidx.appcompat.widget.** { *; }
|
|
||||||
-keep public class androidx.appcompat.app.** { *; }
|
|
||||||
-keep public class androidx.appcompat.view.menu.** { *; }
|
|
||||||
|
|
||||||
# Ensure that reflectively-loaded inflater is not obfuscated. This can be
|
|
||||||
# removed when we stop supporting AAPT1 builds.
|
|
||||||
-keepnames class androidx.appcompat.app.AppCompatViewInflater
|
|
||||||
# aapt is not able to read app::actionViewClass and app:actionProviderClass to produce proguard
|
|
||||||
# keep rules. Add a commonly used SearchView to the keep list until b/109831488 is resolved.
|
|
||||||
-keep class androidx.appcompat.widget.SearchView { <init>(...); }
|
|
||||||
|
|
||||||
# CoordinatorLayout resolves the behaviors of its child components with reflection.
|
|
||||||
-keep public class * extends androidx.coordinatorlayout.widget.CoordinatorLayout$Behavior {
|
|
||||||
public <init>(android.content.Context, android.util.AttributeSet);
|
|
||||||
public <init>();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Make sure we keep annotations for CoordinatorLayout's DefaultBehavior
|
|
||||||
-keepattributes RuntimeVisible*Annotation*
|
|
||||||
|
|
||||||
-if class androidx.appcompat.app.AppCompatViewInflater
|
|
||||||
-keep class com.google.android.material.theme.MaterialComponentsViewInflater {
|
|
||||||
<init>();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep `Companion` object fields of serializable classes.
|
|
||||||
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
|
|
||||||
-if @kotlinx.serialization.Serializable class **
|
|
||||||
-keepclassmembers class <1> {
|
|
||||||
static <1>$Companion Companion;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
|
|
||||||
-if @kotlinx.serialization.Serializable class ** {
|
|
||||||
static **$* *;
|
|
||||||
}
|
|
||||||
-keepclassmembers class <2>$<3> {
|
|
||||||
kotlinx.serialization.KSerializer serializer(...);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep `INSTANCE.serializer()` of serializable objects.
|
|
||||||
-if @kotlinx.serialization.Serializable class ** {
|
|
||||||
public static ** INSTANCE;
|
|
||||||
}
|
|
||||||
-keepclassmembers class <1> {
|
|
||||||
public static <1> INSTANCE;
|
|
||||||
kotlinx.serialization.KSerializer serializer(...);
|
|
||||||
}
|
|
||||||
|
|
||||||
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
|
|
||||||
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
|
|
||||||
|
|
||||||
# Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes
|
|
||||||
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
|
|
||||||
-dontnote kotlinx.serialization.**
|
|
||||||
|
|
||||||
# Serialization core uses `java.lang.ClassValue` for caching inside these specified classes.
|
|
||||||
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
|
|
||||||
# However, since in this case they will not be used, we can disable these warnings
|
|
||||||
-dontwarn kotlinx.serialization.internal.ClassValueReferences
|
|
||||||
|
|
||||||
# Rule to save runtime annotations on serializable class.
|
|
||||||
# If the R8 full mode is used, annotations are removed from classes-files.
|
|
||||||
#
|
|
||||||
# For the annotation serializer, it is necessary to read the `Serializable` annotation inside the serializer<T>() function - if it is present,
|
|
||||||
# then `SealedClassSerializer` is used, if absent, then `PolymorphicSerializer'.
|
|
||||||
#
|
|
||||||
# When using R8 full mode, all interfaces will be serialized using `PolymorphicSerializer`.
|
|
||||||
#
|
|
||||||
# see https://github.com/Kotlin/kotlinx.serialization/issues/2050
|
|
||||||
|
|
||||||
-if @kotlinx.serialization.Serializable class **
|
|
||||||
-keep, allowshrinking, allowoptimization, allowobfuscation, allowaccessmodification class <1>
|
|
||||||
|
|
||||||
# Entry point for retaining MainDispatcherLoader which uses a ServiceLoader.
|
|
||||||
-keep class kotlinx.coroutines.Dispatchers {
|
|
||||||
** getMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Entry point for retaining CoroutineExceptionHandlerImpl.handlers which uses a ServiceLoader.
|
|
||||||
-keep class kotlinx.coroutines.CoroutineExceptionHandlerKt {
|
|
||||||
void handleCoroutineException(...);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Entry point for the rest of coroutines machinery
|
|
||||||
-keep class kotlinx.coroutines.BuildersKt {
|
|
||||||
** runBlocking(...);
|
|
||||||
** launch(...);
|
|
||||||
}
|
|
||||||
|
|
||||||
# We are cheating a bit by not having android.jar on R8's library classpath. Ignore those warnings.
|
|
||||||
-ignorewarnings
|
|
||||||
|
|
||||||
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
|
|
||||||
-keep class kotlinx.coroutines.android.AndroidExceptionPreHandler {*;}
|
|
||||||
|
|
||||||
# Statically turn off all debugging facilities and assertions
|
|
||||||
-keepclassmembers class io.ktor.** { volatile <fields>; }
|
|
||||||
-keep class io.ktor.** { *; }
|
|
||||||
-keep class kotlinx.coroutines.** { *; }
|
|
||||||
-dontwarn kotlinx.atomicfu.**
|
|
||||||
-dontwarn io.netty.**
|
|
||||||
-dontwarn com.typesafe.**
|
|
||||||
-assumenosideeffects class * implements org.slf4j.Logger {
|
|
||||||
public *** trace(...);
|
|
||||||
public *** debug(...);
|
|
||||||
public *** info(...);
|
|
||||||
public *** warn(...);
|
|
||||||
public *** error(...);
|
|
||||||
}
|
|
||||||
-keep class kotlin.reflect.jvm.internal.** { *; }
|
|
||||||
|
|
||||||
-keep class com.arthenica.ffmpegkit.FFmpegKitConfig {
|
|
||||||
native <methods>;
|
|
||||||
void log(long, int, byte[]);
|
|
||||||
void statistics(long, int, float, float, long , int, double, double);
|
|
||||||
int safOpen(int);
|
|
||||||
int safClose(int);
|
|
||||||
}
|
|
||||||
|
|
||||||
-keep class com.arthenica.ffmpegkit.AbiDetect {
|
|
||||||
native <methods>;
|
|
||||||
}
|
|
||||||
|
|
||||||
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
|
|
||||||
|
|
||||||
-keep class moe.fuqiuluo.** { *; }
|
|
||||||
-keep class com.tencent.** { *; }
|
|
||||||
-keep class com.qq.** { *; }
|
|
||||||
-keep class com.google.gson.** { *; }
|
|
||||||
-keep class de.** { *; }
|
|
||||||
-keep class mqq.** { *; }
|
|
||||||
-keep class QQService.** { *; }
|
|
||||||
-keep class SummaryCard.** { *; }
|
|
||||||
-keep class tencent.** { *; }
|
|
||||||
|
|
||||||
-keepclassmembers class * {
|
|
||||||
native <methods>;
|
|
||||||
}
|
|
||||||
-keep class io.netty.** { *; }
|
|
||||||
|
|
||||||
-keep class moe.fuqiuluo.** implements com.tencent.qqnt.kernel.nativeinterface.** {
|
|
||||||
*;
|
|
||||||
}
|
|
||||||
|
@ -3,6 +3,7 @@ package moe.fuqiuluo.qqinterface.servlet.msg.maker
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.tencent.mobileqq.app.QQAppInterface
|
import com.tencent.mobileqq.app.QQAppInterface
|
||||||
|
import com.tencent.mobileqq.data.MessageForPic
|
||||||
import com.tencent.mobileqq.emoticon.QQSysFaceUtil
|
import com.tencent.mobileqq.emoticon.QQSysFaceUtil
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
@ -57,37 +58,37 @@ import kotlin.random.nextInt
|
|||||||
|
|
||||||
internal typealias IMsgElementMaker = suspend (Int, Long, String, JsonObject) -> Result<MsgElement>
|
internal typealias IMsgElementMaker = suspend (Int, Long, String, JsonObject) -> Result<MsgElement>
|
||||||
|
|
||||||
internal object MsgElementMaker {
|
internal object NtMsgElementMaker {
|
||||||
private val makerMap = hashMapOf(
|
private val makerMap = hashMapOf(
|
||||||
"text" to MsgElementMaker::createTextElem,
|
"text" to NtMsgElementMaker::createTextElem,
|
||||||
"face" to MsgElementMaker::createFaceElem,
|
"face" to NtMsgElementMaker::createFaceElem,
|
||||||
"pic" to MsgElementMaker::createImageElem,
|
"pic" to NtMsgElementMaker::createImageElem,
|
||||||
"image" to MsgElementMaker::createImageElem,
|
"image" to NtMsgElementMaker::createImageElem,
|
||||||
"voice" to MsgElementMaker::createRecordElem,
|
"voice" to NtMsgElementMaker::createRecordElem,
|
||||||
"record" to MsgElementMaker::createRecordElem,
|
"record" to NtMsgElementMaker::createRecordElem,
|
||||||
"at" to MsgElementMaker::createAtElem,
|
"at" to NtMsgElementMaker::createAtElem,
|
||||||
"video" to MsgElementMaker::createVideoElem,
|
"video" to NtMsgElementMaker::createVideoElem,
|
||||||
"markdown" to MsgElementMaker::createMarkdownElem,
|
"markdown" to NtMsgElementMaker::createMarkdownElem,
|
||||||
"dice" to MsgElementMaker::createDiceElem,
|
"dice" to NtMsgElementMaker::createDiceElem,
|
||||||
"rps" to MsgElementMaker::createRpsElem,
|
"rps" to NtMsgElementMaker::createRpsElem,
|
||||||
"poke" to MsgElementMaker::createPokeElem,
|
"poke" to NtMsgElementMaker::createPokeElem,
|
||||||
"anonymous" to MsgElementMaker::createAnonymousElem,
|
"anonymous" to NtMsgElementMaker::createAnonymousElem,
|
||||||
"share" to MsgElementMaker::createShareElem,
|
"share" to NtMsgElementMaker::createShareElem,
|
||||||
"contact" to MsgElementMaker::createContactElem,
|
"contact" to NtMsgElementMaker::createContactElem,
|
||||||
"location" to MsgElementMaker::createLocationElem,
|
"location" to NtMsgElementMaker::createLocationElem,
|
||||||
"music" to MsgElementMaker::createMusicElem,
|
"music" to NtMsgElementMaker::createMusicElem,
|
||||||
"reply" to MsgElementMaker::createReplyElem,
|
"reply" to NtMsgElementMaker::createReplyElem,
|
||||||
"touch" to MsgElementMaker::createTouchElem,
|
"touch" to NtMsgElementMaker::createTouchElem,
|
||||||
"weather" to MsgElementMaker::createWeatherElem,
|
"weather" to NtMsgElementMaker::createWeatherElem,
|
||||||
"json" to MsgElementMaker::createJsonElem,
|
"json" to NtMsgElementMaker::createJsonElem,
|
||||||
"new_dice" to MsgElementMaker::createNewDiceElem,
|
"new_dice" to NtMsgElementMaker::createNewDiceElem,
|
||||||
"new_rps" to MsgElementMaker::createNewRpsElem,
|
"new_rps" to NtMsgElementMaker::createNewRpsElem,
|
||||||
"basketball" to MsgElementMaker::createBasketballElem,
|
"basketball" to NtMsgElementMaker::createBasketballElem,
|
||||||
//"node" to MessageMaker::createNodeElem,
|
//"node" to MessageMaker::createNodeElem,
|
||||||
//"multi_msg" to MessageMaker::createLongMsgStruct,
|
//"multi_msg" to MessageMaker::createLongMsgStruct,
|
||||||
"bubble_face" to MsgElementMaker::createBubbleFaceElem,
|
"bubble_face" to NtMsgElementMaker::createBubbleFaceElem,
|
||||||
"button" to MsgElementMaker::createInlineKeywordElem,
|
"button" to NtMsgElementMaker::createInlineKeywordElem,
|
||||||
"inline_keyboard" to MsgElementMaker::createInlineKeywordElem
|
"inline_keyboard" to NtMsgElementMaker::createInlineKeywordElem
|
||||||
)
|
)
|
||||||
|
|
||||||
operator fun get(type: String): IMsgElementMaker? = makerMap[type]
|
operator fun get(type: String): IMsgElementMaker? = makerMap[type]
|
||||||
@ -1006,6 +1007,10 @@ internal object MsgElementMaker {
|
|||||||
pic.picSubType = data["subType"].asIntOrNull ?: 0
|
pic.picSubType = data["subType"].asIntOrNull ?: 0
|
||||||
pic.isFlashPic = isFlash
|
pic.isFlashPic = isFlash
|
||||||
|
|
||||||
|
//if (PlatformUtils.getQQVersionCode() >= PlatformUtils.QQ_9_0_8_VER && !ShamrockConfig.enableOldBDH()) {
|
||||||
|
// pic.storeID = 1
|
||||||
|
//}
|
||||||
|
|
||||||
elem.picElement = pic
|
elem.picElement = pic
|
||||||
|
|
||||||
return Result.success(elem)
|
return Result.success(elem)
|
@ -1,5 +1,7 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.data.MessageRecord
|
||||||
|
|
||||||
internal enum class ContactType {
|
internal enum class ContactType {
|
||||||
TROOP,
|
TROOP,
|
||||||
PRIVATE,
|
PRIVATE,
|
||||||
@ -8,12 +10,20 @@ internal enum class ContactType {
|
|||||||
internal interface TransTarget {
|
internal interface TransTarget {
|
||||||
val id: String
|
val id: String
|
||||||
val type: ContactType
|
val type: ContactType
|
||||||
|
|
||||||
|
val mRec: MessageRecord?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Troop(override val id: String): TransTarget {
|
internal class Troop(
|
||||||
|
override val id: String,
|
||||||
|
override val mRec: MessageRecord? = null
|
||||||
|
): TransTarget {
|
||||||
override val type: ContactType = ContactType.TROOP
|
override val type: ContactType = ContactType.TROOP
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Private(override val id: String): TransTarget {
|
internal class Private(
|
||||||
|
override val id: String,
|
||||||
|
override val mRec: MessageRecord? = null
|
||||||
|
): TransTarget {
|
||||||
override val type: ContactType = ContactType.PRIVATE
|
override val type: ContactType = ContactType.PRIVATE
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,18 @@
|
|||||||
|
|
||||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.transfile.BaseTransProcessor
|
||||||
import com.tencent.mobileqq.transfile.FileMsg
|
import com.tencent.mobileqq.transfile.FileMsg
|
||||||
import com.tencent.mobileqq.transfile.TransferRequest
|
import com.tencent.mobileqq.transfile.TransferRequest
|
||||||
import com.tencent.mobileqq.transfile.api.ITransFileController
|
import com.tencent.mobileqq.transfile.api.ITransFileController
|
||||||
|
import com.tencent.mobileqq.utils.httputils.IHttpCommunicatorListener
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
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 kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
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
|
||||||
@ -81,6 +84,7 @@ internal abstract class FileTransfer {
|
|||||||
}
|
}
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
|
lateinit var processor: IHttpCommunicatorListener
|
||||||
while (
|
while (
|
||||||
//service.findProcessor(
|
//service.findProcessor(
|
||||||
// transferRequest.keyForTransfer // uin + uniseq
|
// transferRequest.keyForTransfer // uin + uniseq
|
||||||
@ -89,8 +93,13 @@ internal abstract class FileTransfer {
|
|||||||
// 如果上传处理器依旧存在,说明没有上传成功
|
// 如果上传处理器依旧存在,说明没有上传成功
|
||||||
&& service.isWorking.get()
|
&& service.isWorking.get()
|
||||||
) {
|
) {
|
||||||
|
processor = service.findProcessor(runtime.currentAccountUin, transferRequest.mUniseq)
|
||||||
delay(100)
|
delay(100)
|
||||||
}
|
}
|
||||||
|
if (processor is BaseTransProcessor && processor.file != null) {
|
||||||
|
val fileMsg = processor.file
|
||||||
|
LogCenter.log("[OldBDH] 资源上传结束(fileId = ${fileMsg.fileID}, fileKey = ${fileMsg.fileKey}, path = ${fileMsg.filePath})")
|
||||||
|
}
|
||||||
continuation.resume(true)
|
continuation.resume(true)
|
||||||
}
|
}
|
||||||
// 实现取消上传器
|
// 实现取消上传器
|
||||||
|
@ -0,0 +1,224 @@
|
|||||||
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
|
import kotlinx.atomicfu.atomic
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
||||||
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
|
import protobuf.auto.toByteArray
|
||||||
|
import protobuf.oidb.TrpcOidb
|
||||||
|
import protobuf.oidb.cmd0x11c5.ClientMeta
|
||||||
|
import protobuf.oidb.cmd0x11c5.CodecConfigReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.CommonHead
|
||||||
|
import protobuf.oidb.cmd0x11c5.DownloadExt
|
||||||
|
import protobuf.oidb.cmd0x11c5.DownloadReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.FileInfo
|
||||||
|
import protobuf.oidb.cmd0x11c5.FileType
|
||||||
|
import protobuf.oidb.cmd0x11c5.IndexNode
|
||||||
|
import protobuf.oidb.cmd0x11c5.MultiMediaReqHead
|
||||||
|
import protobuf.oidb.cmd0x11c5.NtV2RichMediaReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.NtV2RichMediaRsp
|
||||||
|
import protobuf.oidb.cmd0x11c5.SceneInfo
|
||||||
|
import protobuf.oidb.cmd0x11c5.UploadInfo
|
||||||
|
import protobuf.oidb.cmd0x11c5.UploadReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.VideoDownloadExt
|
||||||
|
import protobuf.oidb.cmd0x388.Cmd0x388ReqBody
|
||||||
|
import protobuf.oidb.cmd0x388.Cmd0x388RspBody
|
||||||
|
import protobuf.oidb.cmd0x388.TryUpImgReq
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.random.nextUInt
|
||||||
|
import kotlin.random.nextULong
|
||||||
|
|
||||||
|
internal object NtV2RichMediaSvc: BaseSvc() {
|
||||||
|
private val requestIdSeq = atomic(2L)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取NT图片的RKEY
|
||||||
|
*/
|
||||||
|
suspend fun getNtPicRKey(
|
||||||
|
fileId: String,
|
||||||
|
md5: String,
|
||||||
|
sha: String,
|
||||||
|
fileSize: ULong,
|
||||||
|
width: UInt,
|
||||||
|
height: UInt,
|
||||||
|
sceneBuilder: suspend SceneInfo.() -> Unit
|
||||||
|
): Result<String> {
|
||||||
|
runCatching {
|
||||||
|
val req = NtV2RichMediaReq(
|
||||||
|
head = MultiMediaReqHead(
|
||||||
|
commonHead = CommonHead(
|
||||||
|
requestId = requestIdSeq.incrementAndGet().toULong(),
|
||||||
|
cmd = 200u
|
||||||
|
),
|
||||||
|
sceneInfo = SceneInfo(
|
||||||
|
requestType = 2u,
|
||||||
|
businessType = 1u,
|
||||||
|
).apply {
|
||||||
|
sceneBuilder()
|
||||||
|
},
|
||||||
|
clientMeta = ClientMeta(2u)
|
||||||
|
),
|
||||||
|
download = DownloadReq(
|
||||||
|
IndexNode(
|
||||||
|
FileInfo(
|
||||||
|
fileSize = fileSize,
|
||||||
|
md5 = md5.lowercase(),
|
||||||
|
sha1 = sha.lowercase(),
|
||||||
|
name = "${md5}.jpg",
|
||||||
|
fileType = FileType(
|
||||||
|
fileType = 1u,
|
||||||
|
picFormat = 1000u,
|
||||||
|
videoFormat = 0u,
|
||||||
|
voiceFormat = 0u
|
||||||
|
),
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
time = 0u,
|
||||||
|
original = 1u
|
||||||
|
),
|
||||||
|
fileUuid = fileId,
|
||||||
|
storeId = 1u,
|
||||||
|
uploadTime = 0u,
|
||||||
|
ttl = 0u,
|
||||||
|
subType = 0u,
|
||||||
|
storeAppId = 0u
|
||||||
|
),
|
||||||
|
DownloadExt(
|
||||||
|
video = VideoDownloadExt(
|
||||||
|
busiType = 0u,
|
||||||
|
subBusiType = 0u,
|
||||||
|
msgCodecConfig = CodecConfigReq(
|
||||||
|
platformChipinfo = "",
|
||||||
|
osVer = "",
|
||||||
|
deviceName = ""
|
||||||
|
),
|
||||||
|
flag = 1u
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).toByteArray()
|
||||||
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)?.slice(4)
|
||||||
|
buffer?.decodeProtobuf<TrpcOidb>()?.buffer?.decodeProtobuf<NtV2RichMediaRsp>()?.download?.rkeyParam?.let {
|
||||||
|
return Result.success(it)
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
return Result.failure(it)
|
||||||
|
}
|
||||||
|
return Result.failure(Exception("unable to get c2c nt pic"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求上传Nt图片
|
||||||
|
*/
|
||||||
|
suspend fun requestUploadNtPic(
|
||||||
|
file: File,
|
||||||
|
md5: String,
|
||||||
|
sha: String,
|
||||||
|
name: String,
|
||||||
|
width: UInt,
|
||||||
|
height: UInt,
|
||||||
|
sceneBuilder: suspend SceneInfo.() -> Unit
|
||||||
|
) {
|
||||||
|
val req = NtV2RichMediaReq(
|
||||||
|
head = MultiMediaReqHead(
|
||||||
|
commonHead = CommonHead(
|
||||||
|
requestId = requestIdSeq.incrementAndGet().toULong(),
|
||||||
|
cmd = 100u
|
||||||
|
),
|
||||||
|
sceneInfo = SceneInfo(
|
||||||
|
requestType = 2u,
|
||||||
|
businessType = 1u,
|
||||||
|
).apply {
|
||||||
|
sceneBuilder()
|
||||||
|
},
|
||||||
|
clientMeta = ClientMeta(2u)
|
||||||
|
),
|
||||||
|
upload = UploadReq(
|
||||||
|
listOf(UploadInfo(
|
||||||
|
FileInfo(
|
||||||
|
fileSize = file.length().toULong(),
|
||||||
|
md5 = md5,
|
||||||
|
sha1 = sha,
|
||||||
|
name = name,
|
||||||
|
fileType = FileType(
|
||||||
|
fileType = 1u,
|
||||||
|
picFormat = 1000u,
|
||||||
|
videoFormat = 0u,
|
||||||
|
voiceFormat = 0u
|
||||||
|
),
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
time = 0u,
|
||||||
|
original = 1u
|
||||||
|
),
|
||||||
|
subFileType = 0u
|
||||||
|
)),
|
||||||
|
tryFastUploadCompleted = true,
|
||||||
|
srvSendMsg = false,
|
||||||
|
clientRandomId = Random.nextULong(),
|
||||||
|
compatQMsgSceneType = 1u,
|
||||||
|
clientSeq = Random.nextUInt(),
|
||||||
|
noNeedCompatMsg = true
|
||||||
|
)
|
||||||
|
).toByteArray()
|
||||||
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_100", 4549, 100, req, true)?.slice(4)
|
||||||
|
val rsp = buffer?.decodeProtobuf<TrpcOidb>()?.buffer?.decodeProtobuf<NtV2RichMediaRsp>()
|
||||||
|
LogCenter.log("requestUploadPic => rsp: $rsp")
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun requestUploadGroupPic(
|
||||||
|
groupId: ULong,
|
||||||
|
md5: String,
|
||||||
|
fileSize: ULong,
|
||||||
|
width: UInt,
|
||||||
|
height: UInt,
|
||||||
|
): Result<TryUpPicData> {
|
||||||
|
return runCatching {
|
||||||
|
val rspBuffer = sendBufferAW("ImgStore.GroupPicUp", true, Cmd0x388ReqBody(
|
||||||
|
netType = 3,
|
||||||
|
subCmd = 1,
|
||||||
|
msgTryUpImg = arrayListOf(
|
||||||
|
TryUpImgReq(
|
||||||
|
groupCode = groupId.toLong(),
|
||||||
|
srcUin = TicketSvc.getLongUin(),
|
||||||
|
fileMd5 = md5.hex2ByteArray(),
|
||||||
|
fileSize = fileSize.toLong(),
|
||||||
|
fileName = "$md5.jpg",
|
||||||
|
srcTerm = 2,
|
||||||
|
platformType = 9,
|
||||||
|
buType = 212,
|
||||||
|
picWidth = width.toInt(),
|
||||||
|
picHeight = height.toInt(),
|
||||||
|
picType = 1000,
|
||||||
|
buildVer = "1.0.0",
|
||||||
|
originalPic = 1,
|
||||||
|
fileIndex = byteArrayOf(),
|
||||||
|
srvUpload = 0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
).toByteArray())!!
|
||||||
|
val rsp = rspBuffer.decodeProtobuf<Cmd0x388RspBody>()
|
||||||
|
.msgTryUpImgRsp!!.first()
|
||||||
|
TryUpPicData(
|
||||||
|
uKey = rsp.ukey,
|
||||||
|
exist = rsp.fileExist,
|
||||||
|
fileId = rsp.fileId.toULong(),
|
||||||
|
upIp = rsp.upIp,
|
||||||
|
upPort = rsp.upPort
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class TryUpPicData(
|
||||||
|
val uKey: ByteArray,
|
||||||
|
val exist: Boolean,
|
||||||
|
val fileId: ULong,
|
||||||
|
var upIp: ArrayList<Long>? = null,
|
||||||
|
var upPort: ArrayList<Int>? = null,
|
||||||
|
)
|
||||||
|
}
|
@ -10,6 +10,7 @@ import kotlinx.atomicfu.atomic
|
|||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey
|
||||||
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
@ -53,8 +54,6 @@ private const val MULTIMEDIA_DOMAIN = "multimedia.nt.qq.com.cn"
|
|||||||
private const val C2C_PIC = "c2cpicdw.qpic.cn"
|
private const val C2C_PIC = "c2cpicdw.qpic.cn"
|
||||||
|
|
||||||
internal object RichProtoSvc: BaseSvc() {
|
internal object RichProtoSvc: BaseSvc() {
|
||||||
private val requestId = atomic(2L)
|
|
||||||
|
|
||||||
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
|
||||||
msgCmd = 1200,
|
msgCmd = 1200,
|
||||||
@ -279,81 +278,6 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
return "https://$domain/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2"
|
return "https://$domain/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNtPicRKey(
|
|
||||||
fileId: String,
|
|
||||||
md5: String,
|
|
||||||
sha: String,
|
|
||||||
fileSize: ULong,
|
|
||||||
width: UInt,
|
|
||||||
height: UInt,
|
|
||||||
sceneBuilder: suspend SceneInfo.() -> Unit
|
|
||||||
): Result<String> {
|
|
||||||
runCatching {
|
|
||||||
val req = run {
|
|
||||||
NtV2RichMediaReq(
|
|
||||||
head = MultiMediaReqHead(
|
|
||||||
commonHead = CommonHead(
|
|
||||||
requestId = requestId.incrementAndGet().toULong(),
|
|
||||||
cmd = 200u
|
|
||||||
),
|
|
||||||
sceneInfo = SceneInfo(
|
|
||||||
requestType = 2u,
|
|
||||||
businessType = 1u,
|
|
||||||
).apply {
|
|
||||||
sceneBuilder()
|
|
||||||
},
|
|
||||||
clientMeta = ClientMeta(2u)
|
|
||||||
),
|
|
||||||
download = DownloadReq(
|
|
||||||
IndexNode(
|
|
||||||
FileInfo(
|
|
||||||
fileSize = fileSize,
|
|
||||||
md5 = md5.lowercase(),
|
|
||||||
sha1 = sha.lowercase(),
|
|
||||||
name = "${md5}.jpg",
|
|
||||||
fileType = FileType(
|
|
||||||
fileType = 1u,
|
|
||||||
picFormat = 1000u,
|
|
||||||
videoFormat = 0u,
|
|
||||||
voiceFormat = 0u
|
|
||||||
),
|
|
||||||
width = width,
|
|
||||||
height = height,
|
|
||||||
time = 0u,
|
|
||||||
original = 1u
|
|
||||||
),
|
|
||||||
fileUuid = fileId,
|
|
||||||
storeId = 1u,
|
|
||||||
uploadTime = 0u,
|
|
||||||
ttl = 0u,
|
|
||||||
subType = 0u,
|
|
||||||
storeAppId = 0u
|
|
||||||
),
|
|
||||||
DownloadExt(
|
|
||||||
video = VideoDownloadExt(
|
|
||||||
busiType = 0u,
|
|
||||||
subBusiType = 0u,
|
|
||||||
msgCodecConfig = CodecConfigReq(
|
|
||||||
platformChipinfo = "",
|
|
||||||
osVer = "",
|
|
||||||
deviceName = ""
|
|
||||||
),
|
|
||||||
flag = 1u
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}.toByteArray()
|
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)?.slice(4)
|
|
||||||
buffer?.decodeProtobuf<TrpcOidb>()?.buffer?.decodeProtobuf<NtV2RichMediaRsp>()?.download?.rkeyParam?.let {
|
|
||||||
return Result.success(it)
|
|
||||||
}
|
|
||||||
}.onFailure {
|
|
||||||
return Result.failure(it)
|
|
||||||
}
|
|
||||||
return Result.failure(Exception("unable to get c2c nt pic"))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getC2CVideoDownUrl(
|
suspend fun getC2CVideoDownUrl(
|
||||||
peerId: String,
|
peerId: String,
|
||||||
md5: ByteArray,
|
md5: ByteArray,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.data.MessageForPic
|
||||||
import com.tencent.mobileqq.data.MessageForShortVideo
|
import com.tencent.mobileqq.data.MessageForShortVideo
|
||||||
|
import com.tencent.mobileqq.data.MessageRecord
|
||||||
import com.tencent.mobileqq.transfile.FileMsg
|
import com.tencent.mobileqq.transfile.FileMsg
|
||||||
import com.tencent.mobileqq.transfile.TransferRequest
|
import com.tencent.mobileqq.transfile.TransferRequest
|
||||||
import moe.fuqiuluo.shamrock.utils.MD5
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
@ -11,16 +13,15 @@ import moe.fuqiuluo.shamrock.helper.TransfileHelper
|
|||||||
internal object Transfer: FileTransfer() {
|
internal object Transfer: FileTransfer() {
|
||||||
private val ROUTE = mapOf<ContactType, Map<ResourceType, suspend TransTarget.(Resource) -> Boolean>>(
|
private val ROUTE = mapOf<ContactType, Map<ResourceType, suspend TransTarget.(Resource) -> Boolean>>(
|
||||||
ContactType.TROOP to mapOf(
|
ContactType.TROOP to mapOf(
|
||||||
Picture to { uploadGroupPic(id, (it as PictureResource).src) },
|
Picture to { uploadGroupPic(id, (it as PictureResource).src, mRec) },
|
||||||
Voice to { uploadGroupVoice(id, (it as VoiceResource).src) },
|
Voice to { uploadGroupVoice(id, (it as VoiceResource).src) },
|
||||||
Video to { uploadGroupVideo(id, (it as VideoResource).src, it.thumb) },
|
Video to { uploadGroupVideo(id, (it as VideoResource).src, it.thumb) },
|
||||||
|
|
||||||
),
|
),
|
||||||
ContactType.PRIVATE to mapOf(
|
ContactType.PRIVATE to mapOf(
|
||||||
Picture to { uploadC2CPic(id, (it as PictureResource).src) },
|
Picture to { uploadC2CPic(id, (it as PictureResource).src, mRec) },
|
||||||
Voice to { uploadC2CVoice(id, (it as VoiceResource).src) },
|
Voice to { uploadC2CVoice(id, (it as VoiceResource).src) },
|
||||||
Video to { uploadC2CVideo(id, (it as VideoResource).src, it.thumb) },
|
Video to { uploadC2CVideo(id, (it as VideoResource).src, it.thumb) },
|
||||||
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ internal object Transfer: FileTransfer() {
|
|||||||
suspend fun uploadC2CPic(
|
suspend fun uploadC2CPic(
|
||||||
peerId: String,
|
peerId: String,
|
||||||
file: File,
|
file: File,
|
||||||
|
record: MessageRecord? = null,
|
||||||
wait: Boolean = true
|
wait: Boolean = true
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return transC2CResource(peerId, file, FileMsg.TRANSFILE_TYPE_PIC, SEND_MSG_BUSINESS_TYPE_PIC_CAMERA, wait) {
|
return transC2CResource(peerId, file, FileMsg.TRANSFILE_TYPE_PIC, SEND_MSG_BUSINESS_TYPE_PIC_CAMERA, wait) {
|
||||||
@ -93,22 +95,24 @@ internal object Transfer: FileTransfer() {
|
|||||||
it.mExtraObj = picUpExtraInfo
|
it.mExtraObj = picUpExtraInfo
|
||||||
it.mIsPresend = true
|
it.mIsPresend = true
|
||||||
it.delayShowProgressTimeInMs = 2000
|
it.delayShowProgressTimeInMs = 2000
|
||||||
|
it.mRec = record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun uploadGroupPic(
|
suspend fun uploadGroupPic(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
file: File,
|
file: File,
|
||||||
|
record: MessageRecord? = null,
|
||||||
wait: Boolean = true
|
wait: Boolean = true
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return transTroopResource(groupId, file, FileMsg.TRANSFILE_TYPE_PIC, SEND_MSG_BUSINESS_TYPE_PIC_CAMERA, wait) {
|
return transTroopResource(groupId, file, FileMsg.TRANSFILE_TYPE_PIC, SEND_MSG_BUSINESS_TYPE_PIC_CAMERA, wait) {
|
||||||
val picUpExtraInfo = TransferRequest.PicUpExtraInfo()
|
val picUpExtraInfo = TransferRequest.PicUpExtraInfo()
|
||||||
//picUpExtraInfo.mIsRaw = !TransfileHelper.isGifFile(file)
|
|
||||||
picUpExtraInfo.mIsRaw = false
|
picUpExtraInfo.mIsRaw = false
|
||||||
picUpExtraInfo.mUinType = FileMsg.UIN_TROOP
|
picUpExtraInfo.mUinType = FileMsg.UIN_TROOP
|
||||||
it.mPicSendSource = 8
|
it.mPicSendSource = 8
|
||||||
it.delayShowProgressTimeInMs = 2000
|
it.delayShowProgressTimeInMs = 2000
|
||||||
it.mExtraObj = picUpExtraInfo
|
it.mExtraObj = picUpExtraInfo
|
||||||
|
it.mRec = record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import kotlinx.serialization.json.JsonObject
|
|||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
||||||
import moe.fuqiuluo.qqinterface.servlet.msg.maker.MessageElementMaker
|
import moe.fuqiuluo.qqinterface.servlet.msg.maker.MessageElementMaker
|
||||||
import moe.fuqiuluo.qqinterface.servlet.msg.maker.MsgElementMaker
|
import moe.fuqiuluo.qqinterface.servlet.msg.maker.NtMsgElementMaker
|
||||||
import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
||||||
import moe.fuqiuluo.shamrock.helper.db.MessageMapping
|
import moe.fuqiuluo.shamrock.helper.db.MessageMapping
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
|
import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
|
||||||
@ -29,6 +29,7 @@ import moe.fuqiuluo.shamrock.tools.jsonArray
|
|||||||
import protobuf.message.Elem
|
import protobuf.message.Elem
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal object MessageHelper {
|
internal object MessageHelper {
|
||||||
suspend fun sendMessageWithoutMsgId(
|
suspend fun sendMessageWithoutMsgId(
|
||||||
@ -66,12 +67,15 @@ internal object MessageHelper {
|
|||||||
suspend fun resendMsg(contact: Contact, msgId: Long, retryCnt: Int, msgHashId: Int): Result<SendMsgResult> {
|
suspend fun resendMsg(contact: Contact, msgId: Long, retryCnt: Int, msgHashId: Int): Result<SendMsgResult> {
|
||||||
if (retryCnt < 0) return Result.failure(SendMsgException("消息发送超时次数过多"))
|
if (retryCnt < 0) return Result.failure(SendMsgException("消息发送超时次数过多"))
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
val result = withTimeoutOrNull(15000) {
|
val result = withTimeoutOrNull(15.seconds) {
|
||||||
if (suspendCancellableCoroutine {
|
val resendRet = suspendCancellableCoroutine {
|
||||||
service.resendMsg(contact, msgId) { result, _ ->
|
service.resendMsg(contact, msgId) { result, _ ->
|
||||||
it.resume(result)
|
it.resume(result)
|
||||||
}
|
}
|
||||||
} != 0) {
|
}
|
||||||
|
if (resendRet != 0 &&
|
||||||
|
resendRet != 4 // 使用OldBDH 100%触发
|
||||||
|
) {
|
||||||
resendMsg(contact, msgId, retryCnt - 1, msgHashId)
|
resendMsg(contact, msgId, retryCnt - 1, msgHashId)
|
||||||
} else {
|
} else {
|
||||||
Result.success(SendMsgResult(msgHashId, msgId, System.currentTimeMillis()))
|
Result.success(SendMsgResult(msgHashId, msgId, System.currentTimeMillis()))
|
||||||
@ -294,7 +298,7 @@ internal object MessageHelper {
|
|||||||
var hasActionMsg = false
|
var hasActionMsg = false
|
||||||
messageList.forEach {
|
messageList.forEach {
|
||||||
val msg = it.jsonObject
|
val msg = it.jsonObject
|
||||||
val maker = MsgElementMaker[msg["type"].asString]
|
val maker = NtMsgElementMaker[msg["type"].asString]
|
||||||
if (maker != null) {
|
if (maker != null) {
|
||||||
try {
|
try {
|
||||||
val data = msg["data"].asJsonObjectOrNull ?: EmptyJsonObject
|
val data = msg["data"].asJsonObjectOrNull ?: EmptyJsonObject
|
||||||
|
@ -15,13 +15,13 @@ internal object SendGroupMessage: IActionHandler() {
|
|||||||
return if (session.isString("message")) {
|
return if (session.isString("message")) {
|
||||||
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
|
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
|
||||||
val message = session.getString("message")
|
val message = session.getString("message")
|
||||||
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, autoEscape, echo = session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
|
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, autoEscape, echo = session.echo, retryCnt = retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
} else if (session.isObject("message")) {
|
} else if (session.isObject("message")) {
|
||||||
val message = session.getObject("message")
|
val message = session.getObject("message")
|
||||||
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), listOf( message ).jsonArray, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
|
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), listOf( message ).jsonArray, session.echo, retryCnt = retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
} else {
|
} else {
|
||||||
val message = session.getArray("message")
|
val message = session.getArray("message")
|
||||||
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
|
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, session.echo, retryCnt = retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ internal object SendMessage: IActionHandler() {
|
|||||||
return if (session.isString("message")) {
|
return if (session.isString("message")) {
|
||||||
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
|
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
|
||||||
val message = session.getString("message")
|
val message = session.getString("message")
|
||||||
invoke(chatType, peerId, message, autoEscape, echo = session.echo, fromId = fromId, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
|
invoke(chatType, peerId, message, autoEscape, echo = session.echo, fromId = fromId, retryCnt = retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
} else if (session.isArray("message")) {
|
} else if (session.isArray("message")) {
|
||||||
val message = session.getArray("message")
|
val message = session.getArray("message")
|
||||||
invoke(chatType, peerId, message, session.echo, fromId = fromId, retryCnt ?: 3, recallDuration = recallDuration)
|
invoke(chatType, peerId, message, session.echo, fromId = fromId, retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
} else {
|
} else {
|
||||||
val message = session.getObject("message")
|
val message = session.getObject("message")
|
||||||
invoke(chatType, peerId, listOf( message ).jsonArray, session.echo, fromId = fromId, retryCnt ?: 3, recallDuration = recallDuration)
|
invoke(chatType, peerId, listOf( message ).jsonArray, session.echo, fromId = fromId, retryCnt ?: 5, recallDuration = recallDuration)
|
||||||
}
|
}
|
||||||
} catch (e: ParamsException) {
|
} catch (e: ParamsException) {
|
||||||
return noParam(e.message!!, session.echo)
|
return noParam(e.message!!, session.echo)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote.action.handlers
|
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||||
|
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||||
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
import moe.fuqiuluo.symbols.OneBotHandler
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.message.*
|
import protobuf.message.*
|
||||||
@ -21,8 +23,13 @@ internal object SendMsgByResid : IActionHandler() {
|
|||||||
override suspend fun internalHandle(session: ActionSession): String {
|
override suspend fun internalHandle(session: ActionSession): String {
|
||||||
val resid = session.getString("resid")
|
val resid = session.getString("resid")
|
||||||
val peerId = session.getString("peer")
|
val peerId = session.getString("peer")
|
||||||
|
val msgType = session.getStringOrNull("message_type") ?: "group"
|
||||||
|
return invoke(peerId, resid, msgType, session.echo)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend operator fun invoke(peerId: String, resId: String, type: String, echo: JsonElement = EmptyJsonString): String {
|
||||||
val req = PbSendMsgReq(
|
val req = PbSendMsgReq(
|
||||||
routingHead = when (session.getStringOrNull("message_type")) {
|
routingHead = when (type) {
|
||||||
"group" ->RoutingHead(grp = Grp(peerId.toUInt()))
|
"group" ->RoutingHead(grp = Grp(peerId.toUInt()))
|
||||||
"private" ->RoutingHead( c2c = C2C(peerId.toUInt()))
|
"private" ->RoutingHead( c2c = C2C(peerId.toUInt()))
|
||||||
else ->RoutingHead( grp = Grp(peerId.toUInt()))
|
else ->RoutingHead( grp = Grp(peerId.toUInt()))
|
||||||
@ -34,7 +41,7 @@ internal object SendMsgByResid : IActionHandler() {
|
|||||||
Elem(
|
Elem(
|
||||||
generalFlags = GeneralFlags(
|
generalFlags = GeneralFlags(
|
||||||
longTextFlag = 1u,
|
longTextFlag = 1u,
|
||||||
longTextResid = resid.toByteArray()
|
longTextResid = resId.toByteArray()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -45,6 +52,6 @@ internal object SendMsgByResid : IActionHandler() {
|
|||||||
msgVia = 0u
|
msgVia = 0u
|
||||||
)
|
)
|
||||||
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
|
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
|
||||||
return ok("ok", session.echo)
|
return ok("ok", echo)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ internal object SendPrivateMessage : IActionHandler() {
|
|||||||
autoEscape = autoEscape,
|
autoEscape = autoEscape,
|
||||||
echo = session.echo,
|
echo = session.echo,
|
||||||
fromId = groupId?.toString() ?: userId.toString(),
|
fromId = groupId?.toString() ?: userId.toString(),
|
||||||
retryCnt = retryCnt ?: 3,
|
retryCnt = retryCnt ?: 5,
|
||||||
recallDuration = recallDuration
|
recallDuration = recallDuration
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -34,7 +34,7 @@ internal object SendPrivateMessage : IActionHandler() {
|
|||||||
message = if (session.isArray("message")) session.getArray("message") else listOf(session.getObject("message")).jsonArray,
|
message = if (session.isArray("message")) session.getArray("message") else listOf(session.getObject("message")).jsonArray,
|
||||||
echo = session.echo,
|
echo = session.echo,
|
||||||
fromId = groupId?.toString() ?: userId.toString(),
|
fromId = groupId?.toString() ?: userId.toString(),
|
||||||
retryCnt = retryCnt ?: 3,
|
retryCnt = retryCnt ?: 5,
|
||||||
recallDuration = recallDuration
|
recallDuration = recallDuration
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,8 @@ internal class XposedEntry: IXposedHookLoadPackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun execStartupInit(ctx: Context) {
|
private fun execStartupInit(ctx: Context) {
|
||||||
|
log("Shamrock: Executing startup init: $ctx")
|
||||||
|
|
||||||
if (sec_static_stage_inited) return
|
if (sec_static_stage_inited) return
|
||||||
|
|
||||||
val classLoader = ctx.classLoader.also { requireNotNull(it) }
|
val classLoader = ctx.classLoader.also { requireNotNull(it) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user