mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: 臨時メッセージ
Signed-off-by: WhiteChi <whitechi73@outlook.com>
This commit is contained in:
parent
52b8db70be
commit
e41b7515d3
@ -44,8 +44,6 @@ public final class Contact implements IKernelModel, Serializable {
|
|||||||
|
|
||||||
public Contact(int i2, String str, String str2) {
|
public Contact(int i2, String str, String str2) {
|
||||||
this.serialVersionUID = 1L;
|
this.serialVersionUID = 1L;
|
||||||
this.peerUid = "";
|
|
||||||
this.guildId = "";
|
|
||||||
this.chatType = i2;
|
this.chatType = i2;
|
||||||
this.peerUid = str;
|
this.peerUid = str;
|
||||||
this.guildId = str2;
|
this.guildId = str2;
|
||||||
|
@ -7,7 +7,6 @@ import com.tencent.qqnt.msg.api.IMsgService
|
|||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
@ -103,10 +102,15 @@ internal object MsgSvc: BaseSvc() {
|
|||||||
*
|
*
|
||||||
* Aio 腾讯内部命名 All In One
|
* Aio 腾讯内部命名 All In One
|
||||||
*/
|
*/
|
||||||
suspend fun sendToAio(chatType: Int, peedId: String, message: JsonArray): Pair<Long, Int> {
|
suspend fun sendToAio(
|
||||||
|
chatType: Int,
|
||||||
|
peedId: String,
|
||||||
|
message: JsonArray,
|
||||||
|
fromId: String = peedId
|
||||||
|
): Pair<Long, Int> {
|
||||||
//LogCenter.log(message.toString(), Level.ERROR)
|
//LogCenter.log(message.toString(), Level.ERROR)
|
||||||
//callback.msgHash = result.second 什么垃圾代码,万一cb比你快,你不就寄了?
|
//callback.msgHash = result.second 什么垃圾代码,万一cb比你快,你不就寄了?
|
||||||
return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0))
|
return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0), fromId)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageCallback(
|
class MessageCallback(
|
||||||
|
@ -23,7 +23,13 @@ import moe.fuqiuluo.shamrock.tools.jsonArray
|
|||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
internal object MessageHelper {
|
internal object MessageHelper {
|
||||||
suspend fun sendMessageWithoutMsgId(chatType: Int, peerId: String, message: JsonArray, callback: IOperateCallback): Pair<Long, Int> {
|
suspend fun sendMessageWithoutMsgId(
|
||||||
|
chatType: Int,
|
||||||
|
peerId: String,
|
||||||
|
message: JsonArray,
|
||||||
|
callback: IOperateCallback,
|
||||||
|
fromId: String = peerId
|
||||||
|
): Pair<Long, Int> {
|
||||||
val uniseq = generateMsgId(chatType)
|
val uniseq = generateMsgId(chatType)
|
||||||
var nonMsg: Boolean
|
var nonMsg: Boolean
|
||||||
val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also {
|
val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also {
|
||||||
@ -39,7 +45,7 @@ internal object MessageHelper {
|
|||||||
callback.msgHash = uniseq.first
|
callback.msgHash = uniseq.first
|
||||||
}
|
}
|
||||||
service.sendMsg(
|
service.sendMsg(
|
||||||
generateContact(chatType, peerId),
|
generateContact(chatType, peerId, fromId),
|
||||||
uniseq.second,
|
uniseq.second,
|
||||||
msg as ArrayList<MsgElement>,
|
msg as ArrayList<MsgElement>,
|
||||||
callback
|
callback
|
||||||
@ -51,7 +57,7 @@ internal object MessageHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
||||||
val peerId = if (MsgConstant.KCHATTYPEC2C == chatType) {
|
val peerId = if (MsgConstant.KCHATTYPEC2C == chatType || MsgConstant.KCHATTYPETEMPC2CFROMGROUP == chatType) {
|
||||||
ContactHelper.getUidByUinAsync(id.toLong())
|
ContactHelper.getUidByUinAsync(id.toLong())
|
||||||
} else id
|
} else id
|
||||||
return Contact(chatType, peerId, subId)
|
return Contact(chatType, peerId, subId)
|
||||||
@ -107,6 +113,7 @@ internal object MessageHelper {
|
|||||||
val key = when (chatType) {
|
val key = when (chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> "grp$msgId"
|
MsgConstant.KCHATTYPEGROUP -> "grp$msgId"
|
||||||
MsgConstant.KCHATTYPEC2C -> "c2c$msgId"
|
MsgConstant.KCHATTYPEC2C -> "c2c$msgId"
|
||||||
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> "tmpgrp$msgId"
|
||||||
else -> error("不支持的消息来源类型 | generateMsgIdHash: $chatType")
|
else -> error("不支持的消息来源类型 | generateMsgIdHash: $chatType")
|
||||||
}
|
}
|
||||||
return abs(key.hashCode())
|
return abs(key.hashCode())
|
||||||
|
@ -10,7 +10,7 @@ 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, message, autoEscape, session.echo)
|
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, autoEscape, echo = session.echo)
|
||||||
} else {
|
} else {
|
||||||
val message = session.getArray("message")
|
val message = session.getArray("message")
|
||||||
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, session.echo)
|
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, session.echo)
|
||||||
|
@ -19,13 +19,13 @@ internal object SendMessage: IActionHandler() {
|
|||||||
override suspend fun internalHandle(session: ActionSession): String {
|
override suspend fun internalHandle(session: ActionSession): String {
|
||||||
val detailType = session.getStringOrNull("detail_type") ?: session.getStringOrNull("message_type")
|
val detailType = session.getStringOrNull("detail_type") ?: session.getStringOrNull("message_type")
|
||||||
try {
|
try {
|
||||||
val chatType = detailType?.let {
|
var chatType = detailType?.let {
|
||||||
MessageHelper.obtainMessageTypeByDetailType(it)
|
MessageHelper.obtainMessageTypeByDetailType(it)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
if (session.has("group_id")) {
|
if (session.has("user_id")) {
|
||||||
MsgConstant.KCHATTYPEGROUP
|
|
||||||
} else if (session.has("user_id")) {
|
|
||||||
MsgConstant.KCHATTYPEC2C
|
MsgConstant.KCHATTYPEC2C
|
||||||
|
} else if (session.has("group_id")) {
|
||||||
|
MsgConstant.KCHATTYPEGROUP
|
||||||
} else {
|
} else {
|
||||||
return noParam("detail_type/message_type", session.echo)
|
return noParam("detail_type/message_type", session.echo)
|
||||||
}
|
}
|
||||||
@ -35,13 +35,21 @@ internal object SendMessage: IActionHandler() {
|
|||||||
MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo)
|
MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo)
|
||||||
else -> error("unknown chat type: $chatType")
|
else -> error("unknown chat type: $chatType")
|
||||||
}
|
}
|
||||||
|
var fromId = peerId
|
||||||
|
if (chatType == MsgConstant.KCHATTYPEC2C) {
|
||||||
|
val groupId = session.getStringOrNull("group_id")
|
||||||
|
if (groupId != null) {
|
||||||
|
chatType = MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
||||||
|
fromId = groupId
|
||||||
|
}
|
||||||
|
}
|
||||||
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, session.echo)
|
invoke(chatType, peerId, message, autoEscape, echo = session.echo, fromId = fromId)
|
||||||
} else {
|
} else {
|
||||||
val message = session.getArray("message")
|
val message = session.getArray("message")
|
||||||
invoke(chatType, peerId, message, session.echo)
|
invoke(chatType, peerId, message, session.echo, fromId = fromId)
|
||||||
}
|
}
|
||||||
} catch (e: ParamsException) {
|
} catch (e: ParamsException) {
|
||||||
return noParam(e.message!!, session.echo)
|
return noParam(e.message!!, session.echo)
|
||||||
@ -56,20 +64,21 @@ internal object SendMessage: IActionHandler() {
|
|||||||
peerId: String,
|
peerId: String,
|
||||||
message: String,
|
message: String,
|
||||||
autoEscape: Boolean,
|
autoEscape: Boolean,
|
||||||
|
fromId: String = peerId,
|
||||||
echo: JsonElement = EmptyJsonString
|
echo: JsonElement = EmptyJsonString
|
||||||
): String {
|
): String {
|
||||||
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
|
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
|
||||||
// return logic("contact is not found", echo = echo)
|
// return logic("contact is not found", echo = echo)
|
||||||
//}
|
//}
|
||||||
val result = if (autoEscape) {
|
val result = if (autoEscape) {
|
||||||
MsgSvc.sendToAio(chatType, peerId, arrayListOf(message).json)
|
MsgSvc.sendToAio(chatType, peerId, arrayListOf(message).json, fromId = fromId)
|
||||||
} else {
|
} else {
|
||||||
val msg = MessageHelper.decodeCQCode(message)
|
val msg = MessageHelper.decodeCQCode(message)
|
||||||
if (msg.isEmpty()) {
|
if (msg.isEmpty()) {
|
||||||
LogCenter.log("CQ码不合法", Level.WARN)
|
LogCenter.log("CQ码不合法", Level.WARN)
|
||||||
return logic("CQCode is illegal", echo)
|
return logic("CQCode is illegal", echo)
|
||||||
} else {
|
} else {
|
||||||
MsgSvc.sendToAio(chatType, peerId, msg)
|
MsgSvc.sendToAio(chatType, peerId, msg, fromId = fromId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok(MessageResult(
|
return ok(MessageResult(
|
||||||
@ -80,12 +89,12 @@ internal object SendMessage: IActionHandler() {
|
|||||||
|
|
||||||
// 消息段格式消息
|
// 消息段格式消息
|
||||||
suspend operator fun invoke(
|
suspend operator fun invoke(
|
||||||
chatType: Int, peerId: String, message: JsonArray, echo: JsonElement = EmptyJsonString
|
chatType: Int, peerId: String, message: JsonArray, echo: JsonElement = EmptyJsonString, fromId: String = peerId
|
||||||
): String {
|
): String {
|
||||||
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
|
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
|
||||||
// return logic("contact is not found", echo = echo)
|
// return logic("contact is not found", echo = echo)
|
||||||
//}
|
//}
|
||||||
val result = MsgSvc.sendToAio(chatType, peerId, message)
|
val result = MsgSvc.sendToAio(chatType, peerId, message, fromId = fromId)
|
||||||
return ok(MessageResult(
|
return ok(MessageResult(
|
||||||
msgId = result.second,
|
msgId = result.second,
|
||||||
time = result.first * 0.001
|
time = result.first * 0.001
|
||||||
|
@ -7,13 +7,15 @@ import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
|||||||
internal object SendPrivateMessage: IActionHandler() {
|
internal object SendPrivateMessage: IActionHandler() {
|
||||||
override suspend fun internalHandle(session: ActionSession): String {
|
override suspend fun internalHandle(session: ActionSession): String {
|
||||||
val userId = session.getString("user_id")
|
val userId = session.getString("user_id")
|
||||||
|
val groupId = session.getStringOrNull("group_id")
|
||||||
|
val chatTYpe = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
||||||
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.KCHATTYPEC2C, userId, message, autoEscape, session.echo)
|
SendMessage(chatTYpe, userId, message, autoEscape, echo = session.echo, fromId = groupId ?: userId)
|
||||||
} else {
|
} else {
|
||||||
val message = session.getArray("message")
|
val message = session.getArray("message")
|
||||||
SendMessage(MsgConstant.KCHATTYPEC2C, userId, message, session.echo)
|
SendMessage(chatTYpe, userId, message, session.echo, fromId = groupId ?: userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +82,16 @@ fun Routing.messageAction() {
|
|||||||
route("/send_private_(msg|message)".toRegex()) {
|
route("/send_private_(msg|message)".toRegex()) {
|
||||||
get {
|
get {
|
||||||
val userId = fetchGetOrThrow("user_id")
|
val userId = fetchGetOrThrow("user_id")
|
||||||
|
val groupId = fetchGetOrNull("group_id")
|
||||||
val message = fetchGetOrThrow("message")
|
val message = fetchGetOrThrow("message")
|
||||||
val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false
|
val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false
|
||||||
call.respondText(SendMessage(MsgConstant.KCHATTYPEC2C, userId, message, autoEscape))
|
call.respondText(SendMessage(
|
||||||
|
chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP,
|
||||||
|
peerId = userId,
|
||||||
|
message = message,
|
||||||
|
autoEscape = autoEscape,
|
||||||
|
fromId = groupId ?: userId
|
||||||
|
))
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
val userId = fetchPostOrThrow("user_id")
|
val userId = fetchPostOrThrow("user_id")
|
||||||
|
@ -14,6 +14,7 @@ import moe.fuqiuluo.shamrock.remote.service.data.push.MsgSubType
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.MsgType
|
import moe.fuqiuluo.shamrock.remote.service.data.push.MsgType
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
|
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageEvent
|
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageEvent
|
||||||
|
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeEvent
|
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeEvent
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType
|
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
|
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
|
||||||
@ -92,7 +93,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
|
|||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
rawMsg: String,
|
rawMsg: String,
|
||||||
msgHash: Int,
|
msgHash: Int,
|
||||||
postType: PostType = PostType.Msg
|
postType: PostType = PostType.Msg,
|
||||||
|
tempSource: MessageTempSource = MessageTempSource.Unknown
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val uin = app.longAccountUin
|
val uin = app.longAccountUin
|
||||||
transMessageEvent(record,
|
transMessageEvent(record,
|
||||||
@ -119,7 +121,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
|
|||||||
role = MemberRole.Member,
|
role = MemberRole.Member,
|
||||||
title = "",
|
title = "",
|
||||||
level = "",
|
level = "",
|
||||||
)
|
),
|
||||||
|
tmpSource = tempSource.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
|
@ -56,9 +56,23 @@ internal data class MessageEvent (
|
|||||||
@SerialName("message") val message: JsonElement,
|
@SerialName("message") val message: JsonElement,
|
||||||
@SerialName("raw_message") val rawMessage: String,
|
@SerialName("raw_message") val rawMessage: String,
|
||||||
@SerialName("font") val font: Int,
|
@SerialName("font") val font: Int,
|
||||||
@SerialName("sender") val sender: Sender
|
@SerialName("sender") val sender: Sender,
|
||||||
|
@SerialName("temp_source") val tmpSource: Int = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum class MessageTempSource(val id: Int) {
|
||||||
|
Group(0),
|
||||||
|
Consultation(1),
|
||||||
|
Seek(2),
|
||||||
|
QQMovie(3),
|
||||||
|
HotChat(4),
|
||||||
|
VerifyMsg(6),
|
||||||
|
Discussion(7),
|
||||||
|
Dating(8),
|
||||||
|
Contact(9),
|
||||||
|
Unknown(-1),
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal data class Anonymous(
|
internal data class Anonymous(
|
||||||
@SerialName("name") val name: String
|
@SerialName("name") val name: String
|
||||||
|
@ -12,6 +12,7 @@ import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
|
import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
|
||||||
|
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
|
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
@ -71,6 +72,24 @@ internal object AioListener: IKernelMsgListener {
|
|||||||
LogCenter.log("私聊消息推送失败 -> MessageTransmitter", Level.WARN)
|
LogCenter.log("私聊消息推送失败 -> MessageTransmitter", Level.WARN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
||||||
|
if (!ShamrockConfig.allowTempSession()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCenter.log("私聊临时消息(private = ${record.senderUin}, id = $msgHash, msg = $rawMsg)")
|
||||||
|
ShamrockConfig.getPrivateRule()?.let { rule ->
|
||||||
|
if (rule.black?.contains(record.peerUin) == true) return
|
||||||
|
if (rule.white?.contains(record.peerUin) == false) return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!GlobalEventTransmitter.MessageTransmitter.transPrivateMessage(
|
||||||
|
record, record.elements, rawMsg, msgHash, tempSource = MessageTempSource.Group
|
||||||
|
)) {
|
||||||
|
LogCenter.log("私聊临时消息推送失败 -> MessageTransmitter", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> LogCenter.log("不支持PUSH事件: ${record.chatType}")
|
else -> LogCenter.log("不支持PUSH事件: ${record.chatType}")
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
@ -109,6 +128,11 @@ internal object AioListener: IKernelMsgListener {
|
|||||||
GlobalEventTransmitter.MessageTransmitter
|
GlobalEventTransmitter.MessageTransmitter
|
||||||
.transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent)
|
.transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent)
|
||||||
}
|
}
|
||||||
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
||||||
|
if (!ShamrockConfig.allowTempSession()) return@launch
|
||||||
|
GlobalEventTransmitter.MessageTransmitter
|
||||||
|
.transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent, MessageTempSource.Group)
|
||||||
|
}
|
||||||
else -> LogCenter.log("不支持SELF PUSH事件: ${record.chatType}")
|
else -> LogCenter.log("不支持SELF PUSH事件: ${record.chatType}")
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user