Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions app/src/main/java/moe/ono/creator/GetChannelArkDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/**
* License
* 本文件及代码仅供 cwuom/ono 使用
* 基于 cwuom/ono 开发的开源项目需保证文件中声明本信息
* 禁止 私有项目、闭源项目和以收费形式二次分发的项目 使用
*/

package moe.ono.creator;

import static moe.ono.util.Session.getCurrentChatType;
import static moe.ono.util.Session.getCurrentPeerID;
import static moe.ono.util.analytics.ActionReporter.reportVisitor;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;

import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import com.lxj.xpopup.core.BottomPopupView;
import com.lxj.xpopup.util.XPopupUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Base64;
import java.util.Objects;

import moe.ono.R;
import moe.ono.hooks.base.util.Toasts;
import moe.ono.hooks.item.developer.GetCookie;
import moe.ono.ui.CommonContextWrapper;
import moe.ono.util.AppRuntimeHelper;
import moe.ono.util.Logger;
import moe.ono.util.Session;
import moe.ono.util.SyncUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

@SuppressLint("ResourceType")
public class GetChannelArkDialog extends BottomPopupView {
private static BasePopupView popupView;

public GetChannelArkDialog(@NonNull Context context) {
super(context);
}

public static void createView(Context context) {
Context fixContext = CommonContextWrapper.createAppCompatContext(context);
XPopup.Builder NewPop = new XPopup.Builder(fixContext).moveUpToKeyboard(true).isDestroyOnDismiss(true);
NewPop.maxHeight((int) (XPopupUtils.getScreenHeight(context) * .7f));
NewPop.popupHeight((int) (XPopupUtils.getScreenHeight(context) * .63f));


reportVisitor(AppRuntimeHelper.getAccount(), "CreateView-GetChannelArkDialog");

popupView = NewPop.asCustom(new GetChannelArkDialog(fixContext));
popupView.show();
}

@SuppressLint("SetTextI18n")
@Override
protected void onCreate() {
super.onCreate();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
Button btnSend = findViewById(R.id.btn_send);
TextView tvTarget = findViewById(R.id.tv_target);

EditText title = findViewById(R.id.ark_title);
EditText desc = findViewById(R.id.ark_desc);
EditText jump_url = findViewById(R.id.jump_url);
EditText ark_preview_url = findViewById(R.id.ark_preview_url);
EditText ark_tag_name = findViewById(R.id.ark_tag_name);
EditText ark_tag_icon = findViewById(R.id.ark_tag_icon);
EditText ark_prompt = findViewById(R.id.ark_prompt);

title.setVisibility(VISIBLE);
desc.setVisibility(VISIBLE);
jump_url.setVisibility(VISIBLE);
ark_preview_url.setVisibility(VISIBLE);
ark_tag_name.setVisibility(VISIBLE);
ark_tag_icon.setVisibility(VISIBLE);
ark_prompt.setVisibility(VISIBLE);

title.clearFocus();
desc.clearFocus();
jump_url.clearFocus();
ark_preview_url.clearFocus();
ark_tag_name.clearFocus();
ark_tag_icon.clearFocus();
ark_prompt.clearFocus();

int chat_type = getCurrentChatType();
if (chat_type == 1) {
tvTarget.setText("当前会话: " + getCurrentPeerID() + " | " + "好友");
} else if (chat_type == 2) {
tvTarget.setText("当前会话: " + getCurrentPeerID() + " | " + "群聊");
} else {
tvTarget.setText("当前会话: " + getCurrentPeerID() + " | " + "未知");
}

btnSend.setOnClickListener(v -> {
try {
String cookie = GetCookie.Companion.getCookie("qun.qq.com");
assert cookie != null;
String gtk = GetCookie.Companion.getBknByCookie(cookie);

OkHttpClient client = new OkHttpClient();
String json = "{\n" +
" \"appId\": \"com.tencent.tuwen.lua\",\n" +
" \"bizSrc\": \"guild.share\",\n" +
" \"prompt\": \""+((ark_prompt.getText().toString().isEmpty()) ? title.getText().toString() : ark_prompt.getText().toString())+"\",\n" +
" \"meta\": \"{\\\"news\\\":{\\\"title\\\":\\\""+title.getText().toString()+"\\\",\\\"desc\\\":\\\""+desc.getText().toString()+"\\\",\\\"tag\\\":\\\""+((ark_tag_name.getText().toString().isEmpty()) ? "QQ频道" : ark_tag_name.getText().toString())+"\\\",\\\"tagIcon\\\":\\\""+((ark_tag_icon.getText().toString().isEmpty()) ? "https://tianxuan.gtimg.cn/47329_bd95e16e/assets/guild-icon.png" : ark_tag_icon.getText().toString())+"\\\",\\\"preview\\\":\\\""+ark_preview_url.getText().toString()+"\\\",\\\"jumpUrl\\\":\\\""+jump_url.getText().toString()+"\\\"}}\"\n" +
"}";
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, mediaType);
Request request = new Request.Builder().url("https://qun.qq.com/qunng/http2rpc/gotrpc/auth/trpc.group_pro.guild_activity.Components/GetArkMsgWithSign?bkn=" + gtk)
.header("Host", "qun.qq.com")
.header("User-Agent", "24117RK2CC Build/AQ3A.240829.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/139.0.7258.143 Mobile Safari/537.36 V1_AND_SQ_9.1.35_8708_YYB_D QQ/9.1.35.22670 NetType/WIFI WebP/0.4.1 AppId/537265587 Pixel/1440 StatusBarHeight/138 SimpleUISwitch/0 QQTheme/1103 StudyMode/0 CurrentMode/0 CurrentFontScale/1.0 GlobalDensityScale/0.96 AllowLandscape/false InMagicWin/0")
.header("X-Request-With", "com.tencent.mobileqq")
.header("Cookie", cookie)
.header("x-oidb", "{\"uint32_service_type\":2,\"uint32_command\":\"0x9064\"}")
.header("Referer", "https://qun.qq.com/qunng/guild/tianxuan/p/53049_a53f0edz?traceTint=tianxuan_copy")
.post(body)
.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
SyncUtils.runOnUiThread(() -> Toasts.error(v.getContext(), "网络错误"));
}

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
try {
if (!response.isSuccessful()) {
SyncUtils.runOnUiThread(() -> Toasts.error(v.getContext(), "请求失败: " + response.code()));
return;
}

assert response.body() != null;
String result = response.body().string();

SyncUtils.runOnUiThread(() -> {
JSONObject json = null;
try {
json = new JSONObject(result);
} catch (JSONException e) {
Toasts.error(v.getContext(), "JSON 解析失败");
}
assert json != null;
String base64 = Objects.requireNonNull(json.optJSONObject("data")).optString("signed_ark");
byte[] decodedBytes = Base64.getDecoder().decode(base64);
String ark = new String(decodedBytes);
try {
PacketHelperDialog.send_ark_msg(ark, Session.getContact());
} catch (JSONException e) {
Toasts.error(v.getContext(), "发送失败");
}
});
} catch (Exception e) {
Logger.e(e);
}
}
});
} catch (Exception e) {
Logger.e(e);
}

popupView.dismiss();
});
}, 100);


}




@Override
protected void beforeDismiss() {
super.beforeDismiss();
}

@Override
protected void onDismiss() {
super.onDismiss();
}

@Override
protected int getImplLayoutId() {
return R.layout.get_channel_ark;
}
}
77 changes: 77 additions & 0 deletions app/src/main/java/moe/ono/hooks/item/chat/BottomShortcutMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,38 @@ import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.lxj.xpopup.XPopup
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XC_MethodHook.MethodHookParam
import de.robv.android.xposed.XposedHelpers
import moe.ono.R
import moe.ono.bridge.ntapi.ChatTypeConstants
import moe.ono.config.CacheConfig
import moe.ono.config.ConfigManager
import moe.ono.constants.Constants
import moe.ono.creator.FakeFileSender
import moe.ono.creator.GetChannelArkDialog
import moe.ono.creator.PacketHelperDialog
import moe.ono.creator.QQMessageTrackerDialog
import moe.ono.hooks.XHook
import moe.ono.hooks._base.BaseSwitchFunctionHookItem
import moe.ono.hooks._core.annotation.HookItem
import moe.ono.hooks._core.factory.HookItemFactory.getItem
import moe.ono.hooks.base.util.Toasts
import moe.ono.hooks.item.developer.GetBknByCookie
import moe.ono.hooks.item.developer.GetCookie
import moe.ono.hooks.item.developer.QQHookCodec
import moe.ono.hooks.item.developer.QQPacketHelperEntry
import moe.ono.hooks.item.sigma.QQMessageTracker
import moe.ono.reflex.XMethod
import moe.ono.ui.CommonContextWrapper
import moe.ono.util.Initiator
import moe.ono.util.Logger
import moe.ono.util.Session
import moe.ono.util.SyncUtils

@SuppressLint("DiscouragedApi")
Expand All @@ -50,6 +57,10 @@ class BottomShortcutMenu : BaseSwitchFunctionHookItem() {
).ignoreParam().get()

hookAfter(method) { param: MethodHookParam ->
if (Session.getContact().chatType != ChatTypeConstants.C2C && Session.getContact().chatType != ChatTypeConstants.GROUP) {
return@hookAfter
}

val imageView = param.result as ImageView
if ("拍照".contentEquals(imageView.contentDescription)) {
imageView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
Expand Down Expand Up @@ -123,6 +134,15 @@ class BottomShortcutMenu : BaseSwitchFunctionHookItem() {
).path
)

val getCookie = ConfigManager.getDefaultConfig().getBooleanOrFalse(Constants.PrekXXX + getItem(
GetCookie::class.java).path)

val getBknByCookie = ConfigManager.getDefaultConfig().getBooleanOrFalse(Constants.PrekXXX + getItem(
GetBknByCookie::class.java).path)

val getChannelArk = ConfigManager.getDefaultConfig().getBooleanOrFalse(Constants.PrekXXX + getItem(
GetChannelArk::class.java).path)

val items = ArrayList<String>()
if (qqPacketHelper) {
items.add("QQPacketHelper")
Expand All @@ -133,6 +153,15 @@ class BottomShortcutMenu : BaseSwitchFunctionHookItem() {
if (qqMessageTracker) {
items.add("已读追踪")
}
if (getCookie) {
items.add("GetCookie")
}
if (getBknByCookie) {
items.add("GetBknByCookie")
}
if (getChannelArk) {
items.add("GetChannelArk")
}

if (getItem(QQHookCodec::class.java).isEnabled) {
if (!messageEncryptor) {
Expand Down Expand Up @@ -186,7 +215,55 @@ class BottomShortcutMenu : BaseSwitchFunctionHookItem() {
).path, false
)
}
"GetCookie" -> {
SyncUtils.runOnUiThread {
val builder = MaterialAlertDialogBuilder(
CommonContextWrapper.createAppCompatContext(view.context)
)

builder.setTitle("请输入域名")

val domain =
EditText(CommonContextWrapper.createAppCompatContext(view.context))
domain.setHint("请输入域名")
domain.setText("qzone.qq.com")

builder.setView(domain)

builder.setNegativeButton("取消") { dialog, i ->
dialog.dismiss()
}
builder.setPositiveButton("确定") { dialog, i ->
GetCookie.getCookie(view.context, domain.text.toString())
}

builder.show()
}
}
"GetBknByCookie" -> {
SyncUtils.runOnUiThread {
val builder = MaterialAlertDialogBuilder(CommonContextWrapper.createAppCompatContext(view.context))

builder.setTitle("请输入 Cookie")

val cookie = EditText(CommonContextWrapper.createAppCompatContext(view.context))
cookie.setHint("请输入 Cookie")

builder.setView(cookie)

builder.setNegativeButton("取消") { dialog, i ->
dialog.dismiss()
}
builder.setPositiveButton("确定") { dialog, i ->
GetBknByCookie.getBkn(CommonContextWrapper.createAppCompatContext(view.context), cookie.text.toString())
}

builder.show()
}
}
"GetChannelArk" -> {
SyncUtils.runOnUiThread { GetChannelArkDialog.createView(view.context) }
}
}
}
.show()
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/moe/ono/hooks/item/chat/GetChannelArk.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package moe.ono.hooks.item.chat;

import android.annotation.SuppressLint;

import androidx.annotation.NonNull;

import moe.ono.hooks._base.BaseSwitchFunctionHookItem;
import moe.ono.hooks._core.annotation.HookItem;

@SuppressLint("DiscouragedApi")
@HookItem(path = "聊天与消息/GetChannelArk", description = "获取频道卡片\n* 需在 快捷菜单 中使用")
public class GetChannelArk extends BaseSwitchFunctionHookItem {

@Override
public void entry(@NonNull ClassLoader classLoader) throws Throwable {

}
}
Loading